| | |
| | | <template> |
| | | <div class="bg-white rounded-lg p-4 flex flex-col w-[340px] gap-4"> |
| | | <div class="bg-white rounded-lg p-4 flex flex-col w-[370px] gap-4"> |
| | | <!-- 头部 --> |
| | | <div class="flex items-center flex-0"> |
| | | <span class="ywifont ywicon-guanbi cursor-pointer mr-1.5" @click="handleClose"></span> |
| | |
| | | <el-tree-select |
| | | v-model="tmpCondition.property" |
| | | :data="propertyGroupList" |
| | | placeholder="请选择属性" |
| | | class="!w-full" |
| | | placeholder="属性" |
| | | class="!w-[120px]" |
| | | clearable |
| | | filterable |
| | | node-key="id" |
| | | default-expand-all |
| | | @change="handlePropertyChange" |
| | | :props="propertyGroupProps" |
| | | popper-class="custom-popper_w-180" |
| | | ></el-tree-select> |
| | | </el-form-item> |
| | | |
| | | <!-- 操作符选择 --> |
| | | <el-form-item prop="operator" class="!mb-0"> |
| | | <el-select v-model="tmpCondition.operator" placeholder="选择操作" class="!w-[100px]"> |
| | | <el-select v-model="tmpCondition.operator" placeholder="操作" class="!w-[100px]"> |
| | | <el-option v-for="op in operators" :key="op.value" :label="op.label" :value="op.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | |
| | | <!-- 值输入 --> |
| | | <el-form-item prop="value" class="!mb-0"> |
| | | <div class="flex items-center"> |
| | | <el-input v-d-input-point v-model="tmpCondition.value" placeholder="输入值" class="!flex-1" /> |
| | | <span class="ml-1 text-gray-500">mm</span> |
| | | <el-input v-model="tmpCondition.value" placeholder="值" class="!flex-1" /> |
| | | <span v-if="propertyMapRow?.[tmpCondition?.property]?.info?.unit" class="ml-1 text-gray-500">{{ |
| | | propertyMapRow?.[tmpCondition?.property]?.info?.unit |
| | | }}</span> |
| | | </div> |
| | | </el-form-item> |
| | | |
| | |
| | | class="flex items-center text-blue-400 py-2 px-4 rounded-md" |
| | | :style="{ borderBottom: index !== queryForm.conditions.length - 1 ? '1px solid #e0e0e0' : 'none' }" |
| | | > |
| | | <span>{{ condition.field }}</span> |
| | | <span>{{ condition.operator }}</span> |
| | | <span>{{ condition.value }}</span> |
| | | <span>{{ `"${propertyMapRow[condition.vprop]?.title}"` }}</span> |
| | | <span> {{ operatorMap[condition.operator]?.label }} </span> |
| | | <span>{{ `"${condition.value}"` }}</span> |
| | | <el-button type="danger" link @click="removeCondition(index)" class="!flex !items-center ml-auto"> |
| | | <span class="ywifont ywicon-shanchu"></span> |
| | | </el-button> |
| | |
| | | </div> |
| | | |
| | | <!-- 结果表格 --> |
| | | <el-table class="flex-auto" :data="tableData" style="width: 100%"> |
| | | <el-table v-loading="tableLoading" class="flex-auto" :data="tableData" style="width: 100%"> |
| | | <el-table-column prop="OTYPE" label="类型" width="120" show-overflow-tooltip /> |
| | | <el-table-column prop="ONAME" label="名称" show-overflow-tooltip /> |
| | | <el-table-column prop="location" label="定位" width="60" fixed="right"> |
| | |
| | | import type { PropType } from 'vue'; |
| | | import { computed, ref } from 'vue'; |
| | | import * as XLSX from 'xlsx'; |
| | | import { advanceSearchMapElementByPost } from '/@/api/map'; |
| | | import type { OLMap } from '/@/model/map/OLMap'; |
| | | import { formatDate } from '/@/utils/formatTime'; |
| | | import { travelTree } from '/@/utils/util'; |
| | | import { deepClone } from '/@/utils/other'; |
| | | |
| | | const props = defineProps({ |
| | | olMap: { |
| | |
| | | }); |
| | | }); |
| | | |
| | | const propertyMapRow = ref(null); |
| | | const propertyGroupProps = { |
| | | label: 'title', |
| | | children: 'prop_list', |
| | |
| | | const groupList = (config?.['sections']?.['WebGIS'] ?? []).map((group) => { |
| | | group.id = group.type; |
| | | group.prop_list = (group?.prop_list ?? []) |
| | | ?.filter((item) => !['OTYPE'].includes(item.vprop)) |
| | | ?.filter((item) => !['OTYPE', 'ONAME'].includes(item.vprop)) |
| | | .map((item) => { |
| | | let info: any = {}; |
| | | if (item.vprop === 'ONAME') { |
| | | info = { |
| | | title: 'ONAME', |
| | | unit: null, |
| | | value: '', |
| | | }; |
| | | } else { |
| | | info = vpropsMap[item.vprop] ?? {}; |
| | | vpropsList.push(item.vprop); |
| | | const title = info.title; |
| | | info = { |
| | | ...info, |
| | | value: null, |
| | | }; |
| | | } |
| | | return { |
| | | id: `${item.type}_${item.vprop}`, |
| | | let info: any = vpropsMap[item.vprop] ?? {}; |
| | | vpropsList.push(item.vprop); |
| | | const title = info.title; |
| | | info = { |
| | | ...info, |
| | | value: null, |
| | | }; |
| | | const row = { |
| | | id: `${item.vprop}`, |
| | | ...item, |
| | | info, |
| | | title: info.title ?? '-', |
| | | }; |
| | | if (!propertyMapRow.value) { |
| | | propertyMapRow.value = {}; |
| | | } |
| | | propertyMapRow.value[row.id] = row; |
| | | return row; |
| | | }); |
| | | return group; |
| | | }); |
| | | return groupList; |
| | | }); |
| | | |
| | | const getRowById = (id: string) => { |
| | | if (!id) return null; |
| | | let row = null; |
| | | travelTree( |
| | | propertyGroupList.value as any[], |
| | | (value) => { |
| | | if (value.id === id) { |
| | | row = value; |
| | | return true; |
| | | } |
| | | }, |
| | | null, |
| | | false, |
| | | 'prop_list' |
| | | ); |
| | | return row; |
| | | }; |
| | | |
| | | // 查询表单 |
| | | const queryForm = ref({ |
| | | otype: '', |
| | |
| | | }); |
| | | |
| | | const tmpConditionRules = { |
| | | field: [{ required: true, message: '请选择属性' }], |
| | | property: [{ required: true, message: '请选择属性' }], |
| | | operator: [{ required: true, message: '请选择操作' }], |
| | | value: [{ required: true, message: '请输入值', trigger: '' }], |
| | | }; |
| | |
| | | { label: '包含', value: 'contains' }, |
| | | ]; |
| | | |
| | | const getOperatorMap = () => { |
| | | const operatorMap = operators.reduce((map, item) => { |
| | | map[item.value] = item; |
| | | return map; |
| | | }, {}); |
| | | return operatorMap; |
| | | }; |
| | | |
| | | const operatorMap = getOperatorMap(); |
| | | |
| | | const tmpConditionFormRef = ref(); |
| | | |
| | | // 添加条件 |
| | |
| | | tmpConditionFormRef.value?.validate().then((isValid) => { |
| | | if (isValid) { |
| | | queryForm.value.conditions.push({ |
| | | field: tmpCondition.value.property, |
| | | vprop: tmpCondition.value.property, |
| | | operator: tmpCondition.value.operator, |
| | | value: tmpCondition.value.value, |
| | | }); |
| | |
| | | const errorMsg = ref('管道口径 大于 100 mm'); |
| | | |
| | | // 表格数据 |
| | | const tableData = ref([ |
| | | { |
| | | OTYPE: 'WDM_JUNCTIONS', |
| | | ONAME: 'A12C16EA-5F57-4805-B4FB-323FA039F9DB', |
| | | WKT: 'SRID=3857;POINT(13278186.889830789 3008601.422306897)', |
| | | }, |
| | | { |
| | | OTYPE: 'WDM_JUNCTIONS', |
| | | ONAME: '6E43EF17-F323-49C7-B959-18BD62DD1531', |
| | | WKT: 'SRID=3857;POINT(13278233.269957816 3006550.7408933467)', |
| | | }, |
| | | { |
| | | OTYPE: 'WDM_JUNCTIONS', |
| | | ONAME: 'B354F8D9-6209-4ACC-A80A-323CDEBA8D10_A', |
| | | WKT: 'SRID=3857;POINT(13286748.002881516 3009644.946623342)', |
| | | }, |
| | | { |
| | | OTYPE: 'WDM_JUNCTIONS', |
| | | ONAME: '7a298481-e662-46b8-8975-77c8ee2323b3_A', |
| | | WKT: 'SRID=3857;POINT(13273178.586931476 3008968.173553084)', |
| | | }, |
| | | { |
| | | OTYPE: 'WDM_JUNCTIONS', |
| | | ONAME: '28B04E28-D2D9-411C-B8DC-E5303663323E', |
| | | WKT: 'SRID=3857;POINT(13278471.946910834 3007984.879801554)', |
| | | }, |
| | | { |
| | | OTYPE: 'WDM_JUNCTIONS', |
| | | ONAME: '41214eab-3d6c-4489-873b-f9c3236a781f', |
| | | WKT: 'SRID=3857;POINT(13272238.408417333 3011269.210506023)', |
| | | }, |
| | | { |
| | | OTYPE: 'WDM_JUNCTIONS', |
| | | ONAME: 'B542F7B4-323B-4719-8129-87FB0E535B0E', |
| | | WKT: 'SRID=3857;POINT(13277316.458261633 3004469.8875761065)', |
| | | }, |
| | | { |
| | | OTYPE: 'WDM_JUNCTIONS', |
| | | ONAME: 'ed1bba62-406b-4834-8786-6392e323da64_A', |
| | | WKT: 'SRID=3857;POINT(13292432.068603484 2998711.659135078)', |
| | | }, |
| | | { |
| | | OTYPE: 'WDM_JUNCTIONS', |
| | | ONAME: '1859ff7f-3237-42f1-b797-b190822b2b0b', |
| | | WKT: 'SRID=3857;POINT(13278834.639353445 3010664.463221053)', |
| | | }, |
| | | { |
| | | OTYPE: 'WDM_JUNCTIONS', |
| | | ONAME: '7df9889b-e406-429e-b2d1-7cc3e3236125', |
| | | WKT: 'SRID=3857;POINT(13272832.912394198 3006125.215556366)', |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | |
| | | // 分页相关 |
| | | const currentPage = ref(1); |
| | | const pageSize = ref(10); |
| | | const jumpPage = ref(1); |
| | | |
| | | const tableLoading = ref(false); |
| | | // 按钮事件处理 |
| | | const handleSearch = () => { |
| | | const handleSearch = async () => { |
| | | // 实现查询逻辑 |
| | | console.log('🚀 ~ selectedSpatialType:', selectedSpatialType.value); |
| | | console.log('🚀 ~ queryForm:', queryForm.value); |
| | | |
| | | let extent; |
| | | switch (selectedSpatialType.value) { |
| | | case 'global': |
| | | break; |
| | | case 'currentView': |
| | | // 获取当前地图视图范围 |
| | | const extent = props.olMap.map.getView().calculateExtent(); |
| | | console.log('当前视图范围:', extent); |
| | | extent = props.olMap.map.getView().calculateExtent(); |
| | | break; |
| | | case 'rectangle': |
| | | extent = props.olMap.drawLayer?.getSource().getExtent(); |
| | | break; |
| | | case 'polygon': |
| | | break; |
| | | } |
| | | const conditions = deepClone(queryForm.value.conditions).map((item) => { |
| | | const id = item.vprop; |
| | | const operate = item.operator; |
| | | const row = getRowById(id); |
| | | Reflect.deleteProperty(item, 'operator'); |
| | | return { |
| | | ...item, |
| | | vprop: row?.vprop, |
| | | operate: operate, |
| | | }; |
| | | }); |
| | | tableLoading.value = true; |
| | | const res = await advanceSearchMapElementByPost({ |
| | | extent, |
| | | max_count: 100, |
| | | time: formatDate(new Date()), |
| | | otype: queryForm.value.otype, |
| | | condtions: JSON.stringify(conditions), |
| | | }) |
| | | .catch(() => { |
| | | tableData.value = []; |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | tableData.value = res.values ?? []; |
| | | }; |
| | | |
| | | const handleLocate = () => { |
| | | // 实现高亮定位逻辑 |
| | | props.olMap.clearObjectSearch(); |
| | | const features = tableData.value.filter((item) => item.WKT).map((item) => { |
| | | return props.olMap.readWKT(item.WKT); |
| | | }); |
| | | const features = tableData.value |
| | | .filter((item) => item.WKT) |
| | | .map((item) => { |
| | | return props.olMap.readWKT(item.WKT); |
| | | }); |
| | | props.olMap.highlightSearch(features); |
| | | // props.olMap.zoomToFeatures(features); |
| | | }; |
| | |
| | | let preSelectedSpatialType = ''; |
| | | // 选择空间范围类型 |
| | | const handleSpatialTypeSelect = (type: string) => { |
| | | if (preSelectedSpatialType === type) return; |
| | | // if (preSelectedSpatialType === type) return; |
| | | selectedSpatialType.value = type; |
| | | // 触发选择事件 |
| | | emit('selectSpatial', type); |
| | |
| | | } |
| | | } |
| | | </style> |
| | | |
| | | <style lang="scss"> |
| | | .custom-popper_w-180 { |
| | | .el-tree { |
| | | width: 180px !important; |
| | | } |
| | | } |
| | | </style> |