Procházet zdrojové kódy

feat(drainage): 排水管网按雨污类型上色筛选,排水分区精简字段

null před 20 hodinami
rodič
revize
b2cbb2ef29

+ 1 - 1
src/components/GisMapCanvas.vue

@@ -186,7 +186,7 @@ function addLine(TdtMap, line) {
     strokeColor: line.color || '#3498db',
     strokeWeight: line.strokeWeight || 6,
     strokeOpacity: line.strokeOpacity ?? 0.92,
-    strokeStyle: 'solid'
+    strokeStyle: line.strokeStyle === 'dashed' ? 'dashed' : 'solid'
   })
   polyline.addEventListener('click', (event) => {
     event?.domEvent?.stopPropagation?.()

+ 10 - 158
src/views/subSystem/drainage/jcsj/psfqgl.vue

@@ -16,8 +16,8 @@
         <el-input v-model="queryParams.name" placeholder="请输入分区名称" clearable style="width: 200px"
           @keyup.enter="handleQuery" />
       </el-form-item>
-      <el-form-item label="地点">
-        <el-input v-model="queryParams.district" placeholder="请输入地点" clearable style="width: 200px"
+      <el-form-item label="地址">
+        <el-input v-model="queryParams.district" placeholder="请输入地址" clearable style="width: 200px"
           @keyup.enter="handleQuery" />
       </el-form-item>
       <el-form-item label="分区类型">
@@ -48,27 +48,8 @@
     <el-table v-loading="loading" :data="filteredList" style="width: 100%" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="分区名称" prop="name" min-width="160" />
-      <el-table-column label="地点" prop="district" min-width="100" />
+      <el-table-column label="地址" prop="district" min-width="180" show-overflow-tooltip />
       <el-table-column label="分区类型" prop="partitionType" min-width="100" />
-      <el-table-column label="数据时间" prop="time" min-width="120" />
-      <el-table-column :label="`排水量(${DRAINAGE_UNIT})`" prop="drainage" min-width="120" align="right">
-        <template #default="{ row }">
-          <span>{{ formatVolume(row.drainage) }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column :label="`积水量(${WATERLOGGING_UNIT})`" prop="waterlogging" min-width="120" align="right">
-        <template #default="{ row }">
-          <span>{{ formatVolume(row.waterlogging) }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column label="积水等级" prop="level" min-width="110" align="center">
-        <template #default="{ row }">
-          <el-tag v-if="hasLevel(row.level)" :type="getLevelTagType(row.level)" effect="light" size="small">
-            {{ getLevelLabel(row.level) }}
-          </el-tag>
-          <span v-else class="text-placeholder">--</span>
-        </template>
-      </el-table-column>
       <el-table-column label="关联设备" min-width="160">
         <template #default="{ row }">
           {{ equipmentNameMap[row.id] || '' }}
@@ -100,7 +81,7 @@
           </el-col>
           <el-col :span="12">
             <div class="info-item">
-              <span class="info-label">地点:</span>
+              <span class="info-label">地址:</span>
               <span class="info-value">{{ currentRow.district }}</span>
             </div>
           </el-col>
@@ -108,33 +89,8 @@
         <el-row :gutter="20">
           <el-col :span="12">
             <div class="info-item">
-              <span class="info-label">数据时间:</span>
-              <span class="info-value">{{ currentRow.time }}</span>
-            </div>
-          </el-col>
-          <el-col :span="12">
-            <div class="info-item">
-              <span class="info-label">排水量:</span>
-              <span class="info-value">{{ formatVolume(currentRow.drainage) }} {{ DRAINAGE_UNIT }}</span>
-            </div>
-          </el-col>
-        </el-row>
-        <el-row :gutter="20">
-          <el-col :span="12">
-            <div class="info-item">
-              <span class="info-label">积水量:</span>
-              <span class="info-value">{{ formatVolume(currentRow.waterlogging) }} {{ WATERLOGGING_UNIT }}</span>
-            </div>
-          </el-col>
-          <el-col :span="12">
-            <div class="info-item">
-              <span class="info-label">积水等级:</span>
-              <span class="info-value">
-                <el-tag v-if="hasLevel(currentRow.level)" :type="getLevelTagType(currentRow.level)" effect="light" size="small">
-                  {{ getLevelLabel(currentRow.level) }}
-                </el-tag>
-                <span v-else class="text-placeholder">--</span>
-              </span>
+              <span class="info-label">分区类型:</span>
+              <span class="info-value">{{ currentRow.partitionType || '--' }}</span>
             </div>
           </el-col>
         </el-row>
@@ -162,7 +118,7 @@
     </el-drawer>
 
     <!-- 新增/修改对话框 -->
-    <el-dialog v-model="editDialogVisible" :title="editDialogTitle" width="800px" :before-close="handleEditClose"
+    <el-dialog v-model="editDialogVisible" :title="editDialogTitle" width="640px" :before-close="handleEditClose"
       @opened="onEditDialogOpened">
       <el-form ref="editFormRef" :model="editForm" :rules="editRules" label-width="100px">
         <el-row :gutter="20">
@@ -171,19 +127,6 @@
               <el-input v-model="editForm.name" placeholder="请输入分区名称" />
             </el-form-item>
           </el-col>
-          <el-col :span="12">
-            <el-form-item label="地点" prop="district">
-              <el-input v-model="editForm.district" placeholder="请输入地点" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="20">
-          <el-col :span="12">
-            <el-form-item label="数据时间" prop="time">
-              <el-date-picker v-model="editForm.time" type="date" placeholder="选择日期" value-format="YYYY-MM-DD"
-                style="width: 100%" />
-            </el-form-item>
-          </el-col>
           <el-col :span="12">
             <el-form-item label="分区类型" prop="partitionType">
               <el-select v-model="editForm.partitionType" placeholder="请选择分区类型" style="width:100%"
@@ -196,25 +139,8 @@
         </el-row>
         <el-row :gutter="20">
           <el-col :span="12">
-            <el-form-item :label="`排水量(${DRAINAGE_UNIT})`" prop="drainage">
-              <el-input-number v-model="editForm.drainage" :precision="2" :min="0" style="width:100%"
-                placeholder="请输入排水量" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item :label="`积水量(${WATERLOGGING_UNIT})`" prop="waterlogging">
-              <el-input-number v-model="editForm.waterlogging" :precision="2" :min="0" style="width:100%"
-                placeholder="请输入积水量" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="20">
-          <el-col :span="12">
-            <el-form-item label="积水等级" prop="level">
-              <el-select v-model="editForm.level" placeholder="请选择积水等级" clearable style="width:100%">
-                <el-option v-for="item in levelOptions" :key="item.value" :label="item.label"
-                  :value="normalizeLevelValue(item.value)" />
-              </el-select>
+            <el-form-item label="地址" prop="district">
+              <el-input v-model="editForm.district" placeholder="请输入地址" />
             </el-form-item>
           </el-col>
         </el-row>
@@ -288,7 +214,6 @@
 <script setup name="Psfqgl">
 import { ref, computed, nextTick, onMounted } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
-import { useDict } from '@/utils/dict'
 import locationIcon from '@/assets/images/location.png'
 import {
   getPartitionPage,
@@ -302,61 +227,6 @@ import {
   getDrainageBoundEquipmentIds
 } from '@/api/drainage'
 
-// ==================== 量纲 + 积水等级字典 ====================
-// 排水量 / 积水量 单位:业务口径若调整,只改这两处,表单、列表、详情同步生效
-const DRAINAGE_UNIT = 'm³'
-const WATERLOGGING_UNIT = 'm³'
-
-// 积水等级字典(sys_dict_type = drainage_waterlogging_level)
-// 与易积水点 waterlogging_level 口径保持一致:0未积水 / 1轻度 / 2中度 / 3严重
-const { drainage_waterlogging_level: levelDict } = useDict('drainage_waterlogging_level')
-
-// 字典表未配置时用内置口径兜底,避免页面无选项
-const LEVEL_FALLBACK = [
-  { label: '未积水', value: '0', elTagType: 'success' },
-  { label: '轻度积水', value: '1', elTagType: 'primary' },
-  { label: '中度积水', value: '2', elTagType: 'warning' },
-  { label: '严重积水', value: '3', elTagType: 'danger' }
-]
-
-const levelOptions = computed(() => {
-  const list = levelDict.value
-  return Array.isArray(list) && list.length ? list : LEVEL_FALLBACK
-})
-
-// 字典值统一成数字,保证 el-select 回显能与后端 Integer 字段匹配
-function normalizeLevelValue(value) {
-  if (value === null || value === undefined || value === '') return value
-  return Number.isNaN(Number(value)) ? value : Number(value)
-}
-
-function hasLevel(value) {
-  return value !== null && value !== undefined && value !== ''
-}
-
-function findLevelOption(value) {
-  const key = String(value)
-  return levelOptions.value.find(item => String(item.value) === key)
-}
-
-function getLevelLabel(value) {
-  const option = findLevelOption(value)
-  return option ? option.label : '--'
-}
-
-// 标签配色由字典 list_class 决定;primary / 空值走默认主题色
-function getLevelTagType(value) {
-  const option = findLevelOption(value)
-  const type = option ? (option.elTagType || option.listClass) : ''
-  return !type || type === 'primary' || type === 'default' ? '' : type
-}
-
-function formatVolume(value) {
-  if (value === null || value === undefined || value === '') return '--'
-  const num = Number(value)
-  return Number.isFinite(num) ? num.toFixed(2) : String(value)
-}
-
 // 地图标记创建(用Label+img代替Marker)
 function createMapMarker(map, bPoint, name, bgColor) {
   const color = bgColor || '#409eff'
@@ -626,19 +496,13 @@ const editForm = ref({
   name: '',
   district: '',
   partitionType: '',
-  time: '',
-  drainage: 0,
-  waterlogging: 0,
-  level: 0,
   longitude: null,
   latitude: null,
   points: ''
 })
 
 const editRules = {
-  name: [{ required: true, message: '请输入分区名称', trigger: 'blur' }],
-  time: [{ required: true, message: '请选择数据时间', trigger: 'change' }],
-  level: [{ required: true, message: '请选择积水等级', trigger: 'change' }]
+  name: [{ required: true, message: '请输入分区名称', trigger: 'blur' }]
 }
 
 // 编辑弹窗地图相关
@@ -659,10 +523,6 @@ function handleAdd() {
     name: '',
     district: '',
     partitionType: '',
-    time: '',
-    drainage: 0,
-    waterlogging: 0,
-    level: 0,
     longitude: null,
     latitude: null,
     points: ''
@@ -678,10 +538,6 @@ function handleEdit(row) {
     name: row.name,
     district: row.district,
     partitionType: row.partitionType,
-    time: row.time,
-    drainage: row.drainage,
-    waterlogging: row.waterlogging,
-    level: hasLevel(row.level) ? normalizeLevelValue(row.level) : 0,
     longitude: row.longitude,
     latitude: row.latitude,
     points: row.points || ''
@@ -1038,10 +894,6 @@ async function submitBind() {
   font-size: 14px;
 }
 
-.text-placeholder {
-  color: #c0c4cc;
-}
-
 .map-section {
   border: 1px solid #e4e7ed;
   border-radius: 4px;

+ 96 - 32
src/views/subSystem/drainage/jcsj/psgwgl.vue

@@ -29,13 +29,17 @@
         </div>
       </div>
       <div class="map-legend">
-        <span class="legend-title">线条颜色:</span>
-        <span v-for="item in statusDict" :key="item.value" class="legend-item">
-          <i :style="{ background: statusColor(item.value) }"></i>{{ item.label }}
+        <span class="legend-title">管线颜色:</span>
+        <span class="legend-item">
+          <i :style="{ background: SEWAGE_COLORS['1'] }"></i>雨水 {{ rainCount }} 条
+        </span>
+        <span class="legend-item">
+          <i :style="{ background: SEWAGE_COLORS['0'] }"></i>污水 {{ sewageCount }} 条
         </span>
         <span class="legend-item">
-          <i style="background: #409eff"></i>未知状态
+          <i :style="{ background: SEWAGE_COLORS.unknown }"></i>未识别 {{ unknownCount }} 条
         </span>
+        <span class="legend-note">维护中 / 异常的管段显示为虚线</span>
       </div>
     </el-card>
 
@@ -49,9 +53,9 @@
           <el-input v-model="query.networkName" placeholder="请输入" clearable style="width: 160px"
             @keyup.enter="handleQuery" />
         </el-form-item>
-        <el-form-item label="等级">
-          <el-select v-model="query.networkLevel" placeholder="请选择" clearable style="width: 140px">
-            <el-option v-for="item in levelDict" :key="item.value" :label="item.label" :value="item.value" />
+        <el-form-item label="管线类型">
+          <el-select v-model="query.sewageType" placeholder="请选择" clearable style="width: 120px">
+            <el-option v-for="item in sewageTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
           </el-select>
         </el-form-item>
         <el-form-item label="管养单位">
@@ -100,11 +104,11 @@
       <el-table v-loading="loading" :data="tableData" style="width: 100%" @row-dblclick="openDetail">
         <el-table-column label="设施编码" prop="networkCode" min-width="120" show-overflow-tooltip />
         <el-table-column label="设施名称" prop="networkName" min-width="150" show-overflow-tooltip />
-        <el-table-column label="等级" width="90" align="center">
+        <el-table-column label="管线类型" width="90" align="center">
           <template #default="{ row }">
-            <el-tag v-if="levelLabel(row.networkLevel)" size="small"
-              :type="levelTagType(row.networkLevel)">{{ levelLabel(row.networkLevel) }}</el-tag>
-            <span v-else class="text-muted">-</span>
+            <el-tag v-if="row.sewageType !== null && row.sewageType !== undefined && row.sewageType !== ''"
+              size="small" :type="sewageTagType(row.sewageType)">{{ sewageLabel(row.sewageType) }}</el-tag>
+            <span v-else class="text-muted">未识别</span>
           </template>
         </el-table-column>
         <el-table-column label="管养单位" prop="managementUnit" min-width="140" show-overflow-tooltip />
@@ -133,10 +137,10 @@
       <el-descriptions :column="2" border class="detail-desc">
         <el-descriptions-item label="设施编码">{{ fmt(detailRow.networkCode) }}</el-descriptions-item>
         <el-descriptions-item label="设施名称">{{ fmt(detailRow.networkName) }}</el-descriptions-item>
-        <el-descriptions-item label="等级">
-          <el-tag v-if="levelLabel(detailRow.networkLevel)" size="small"
-            :type="levelTagType(detailRow.networkLevel)">{{ levelLabel(detailRow.networkLevel) }}</el-tag>
-          <span v-else>-</span>
+        <el-descriptions-item label="管线类型">
+          <el-tag v-if="detailRow.sewageType !== null && detailRow.sewageType !== undefined && detailRow.sewageType !== ''"
+            size="small" :type="sewageTagType(detailRow.sewageType)">{{ sewageLabel(detailRow.sewageType) }}</el-tag>
+          <span v-else>未识别</span>
         </el-descriptions-item>
         <el-descriptions-item label="状态">
           <el-tag size="small" :type="statusTagType(detailRow.status)">{{ statusLabel(detailRow.status) }}</el-tag>
@@ -184,14 +188,28 @@ import {
   getDrainagePipeNetworkFilterOptions
 } from '@/api/drainage'
 
-const { pipe_network_status: statusDict, pipe_network_level: levelDict } =
-  useDict('pipe_network_status', 'pipe_network_level')
+const { pipe_network_status: statusDict, drainage_sewage_type: sewageTypeDict } =
+  useDict('pipe_network_status', 'drainage_sewage_type')
+
+// ==================== 雨污配色(与参考色一致:雨水蓝、污水青) ====================
+// 值取自 pipe_network_base.network_level 注释:0=污水 1=雨水
+const SEWAGE_COLORS = { '0': '#35be83', '1': '#2f9be8', unknown: '#909399' }
+
+/** 雨污下拉项:字典优先,字典未配置时用内置两项兜底,保证筛选不空转 */
+const sewageTypeOptions = computed(() => {
+  const list = sewageTypeDict?.value || []
+  if (list.length) return list
+  return [
+    { label: '雨水', value: '1' },
+    { label: '污水', value: '0' }
+  ]
+})
 
 // ==================== 查询条件 ====================
 const query = ref({
   networkCode: '',
   networkName: '',
-  networkLevel: '',
+  sewageType: '',
   managementUnit: '',
   material: '',
   status: '',
@@ -292,7 +310,7 @@ function resetQuery() {
   query.value = {
     networkCode: '',
     networkName: '',
-    networkLevel: '',
+    sewageType: '',
     managementUnit: '',
     material: '',
     status: '',
@@ -339,13 +357,32 @@ function buildRowPoints(row) {
   return points
 }
 
-/** 状态 → 线条颜色,和列表标签口径一致 */
-const STATUS_COLORS = { '0': '#67c23a', '1': '#e6a23c', '2': '#f56c6c' }
+/** 雨污类型 → 线条颜色(雨水蓝、污水青,未识别灰) */
+function sewageColor(value) {
+  const key = value === null || value === undefined ? '' : String(value)
+  return SEWAGE_COLORS[key] || SEWAGE_COLORS.unknown
+}
 
-function statusColor(value) {
-  return STATUS_COLORS[String(value)] || '#409eff'
+/** 状态 → 线型:维护中/异常走虚线,颜色仍按雨污类型区分 */
+function lineStrokeStyle(status) {
+  return status === null || status === undefined || String(status) === '0' ? 'solid' : 'dashed'
 }
 
+/** 图例条数,按当前地图记录统计(network_level:0=污水 1=雨水) */
+const sewageSummary = computed(() => {
+  const summary = { rain: 0, sewage: 0, unknown: 0 }
+  mapRecords.value.forEach((row) => {
+    const type = row.sewageType === null || row.sewageType === undefined ? '' : String(row.sewageType)
+    if (type === '1') summary.rain += 1
+    else if (type === '0') summary.sewage += 1
+    else summary.unknown += 1
+  })
+  return summary
+})
+const rainCount = computed(() => sewageSummary.value.rain)
+const sewageCount = computed(() => sewageSummary.value.sewage)
+const unknownCount = computed(() => sewageSummary.value.unknown)
+
 const mapLines = computed(() =>
   mapRecords.value
     .map((row) => {
@@ -355,8 +392,9 @@ const mapLines = computed(() =>
         id: row.networkId,
         name: row.networkName || row.networkCode || '排水管线',
         points,
-        color: statusColor(row.status),
+        color: sewageColor(row.sewageType),
         strokeWeight: 5,
+        strokeStyle: lineStrokeStyle(row.status),
         raw: row
       }
     })
@@ -409,7 +447,14 @@ const detailPoints = computed(() => {
 const detailLines = computed(() => {
   const points = buildRowPoints(detailRow.value)
   if (points.length < 2) return []
-  return [{ id: 'detail', name: '管段', points, color: '#409eff', strokeWeight: 6 }]
+  return [{
+    id: 'detail',
+    name: '管段',
+    points,
+    color: sewageColor(detailRow.value.sewageType),
+    strokeWeight: 6,
+    strokeStyle: lineStrokeStyle(detailRow.value.status)
+  }]
 })
 
 /** 地图要素点击:直接打开对应管网详情 */
@@ -460,15 +505,19 @@ function statusTagType(value) {
   return map[String(value)] || 'info'
 }
 
-function levelLabel(value) {
-  return dictItem(levelDict, value)?.label || ''
+/** 雨污类型文案:字典优先,字典未就绪时按编码兜底 */
+function sewageLabel(value) {
+  const label = dictItem(sewageTypeDict, value)?.label
+  if (label) return label
+  if (String(value) === '0') return '污水'
+  if (String(value) === '1') return '雨水'
+  return '未识别'
 }
 
-function levelTagType(value) {
-  const item = dictItem(levelDict, value)
-  const listClass = item?.listClass || item?.elTagType || ''
-  // Element Plus 没有 primary 类型,回落为默认样式
-  return ['success', 'warning', 'danger', 'info'].includes(listClass) ? listClass : ''
+/** 雨污类型标签配色:雨水蓝(primary)、污水青(success) */
+function sewageTagType(value) {
+  const map = { '1': 'primary', '0': 'success' }
+  return map[String(value)] || 'info'
 }
 
 function fmt(value) {
@@ -566,6 +615,21 @@ onMounted(() => {
     }
   }
 
+  .legend-note {
+    color: #a8abb2;
+
+    &::before {
+      content: '';
+      display: inline-block;
+      width: 18px;
+      height: 4px;
+      margin-right: 5px;
+      vertical-align: middle;
+      border-radius: 2px;
+      background: repeating-linear-gradient(90deg, #a8abb2 0 4px, transparent 4px 8px);
+    }
+  }
+
   .filter-card {
     margin-bottom: 16px;
   }