瀏覽代碼

refactor(warning): 重构预警系统数据结构和标签管理

- 移除重复的预警级别和状态标签定义,统一从 statisticsShared 模块导入
- 更新预警类型判断逻辑,使用标准化的标签映射替代硬编码数组
- 优化预警级别显示函数,优先使用后端返回的名称字段
- 修正预警级别代码转换函数,简化逻辑并提高准确性
- 调整预警状态标签映射关系,确保颜色配置正确
- 修改详情视图数据结构,移除预警名称字段并新增设备代码和名称
- 更新搜索过滤逻辑,适配新的数据字段结构
- 在所有统计页面中引入并调用预警引用数据加载函数
- 移除表格中的预警事项列以优化显示布局
- 新增预设样式类用于预警内容的换行和溢出处理
林仔 1 周之前
父節點
當前提交
e41d15c39c
共有 32 個文件被更改,包括 310 次插入 和 428 次删除
  1. 8 5
      src/api/smxyjldczxt/yjxxfb/yjfb.js
  2. 4 0
      src/api/warning/list.js
  3. 5 0
      src/assets/styles/index.scss
  4. 6 9
      src/views/subSystem/lifeCompany/lAlertInformation/LCorrelation.vue
  5. 34 51
      src/views/subSystem/lifeCompany/lAlertInformation/LRelease.vue
  6. 33 92
      src/views/subSystem/lifeCompany/lAlertInformation/LReportUpload.vue
  7. 21 34
      src/views/subSystem/lifeCompany/lAlertInformation/LTobeHandled.vue
  8. 7 6
      src/views/subSystem/lifeCompany/lOverviewWarning/LTodayNot.vue
  9. 4 3
      src/views/subSystem/lifeCompany/lOverviewWarning/Lhistory.vue
  10. 7 7
      src/views/subSystem/lifeCompany/lOverviewWarning/Ltoday.vue
  11. 1 2
      src/views/subSystem/lifeCompany/lOverviewWarning/WarningDetailDrawer.vue
  12. 14 42
      src/views/subSystem/lifeCompany/lOverviewWarning/dashboardShared.js
  13. 4 3
      src/views/subSystem/lifeCompany/lhome/lHome.vue
  14. 1 1
      src/views/subSystem/lifeCompany/lstatistics/LcallEff.vue
  15. 1 1
      src/views/subSystem/lifeCompany/lstatistics/LdisposalAnalysis.vue
  16. 1 1
      src/views/subSystem/lifeCompany/lstatistics/LwarningStatistics.vue
  17. 4 3
      src/views/subSystem/lifeCompany/lstatistics/disposalEfficiency/index.vue
  18. 2 1
      src/views/subSystem/lifeCompany/lstatistics/disposalStatus/index.vue
  19. 11 14
      src/views/subSystem/lifeCompany/lstatistics/industryAnalysis/index.vue
  20. 4 3
      src/views/subSystem/lifeCompany/lstatistics/receiveEfficiency/index.vue
  21. 26 47
      src/views/subSystem/lifeCompany/lstatistics/statisticsShared.js
  22. 3 2
      src/views/subSystem/lifeCompany/lstatistics/today/index.vue
  23. 2 1
      src/views/subSystem/lifeCompany/lstatistics/trend/index.vue
  24. 43 55
      src/views/subSystem/lifeCompany/lwarningInfoCont/LAlertQuery.vue
  25. 23 35
      src/views/subSystem/lifeCompany/lwarningInfoCont/LwarningDisp.vue
  26. 30 4
      src/views/subSystem/lifeCompany/warningWorkflow.js
  27. 2 1
      src/views/subSystem/warningList/codeGenerate/index.vue
  28. 2 1
      src/views/subSystem/warningList/itemDetail/index.vue
  29. 2 1
      src/views/subSystem/warningList/itemManage/index.vue
  30. 2 1
      src/views/subSystem/warningList/itemQuery/index.vue
  31. 2 1
      src/views/subSystem/warningList/reasonManage/index.vue
  32. 1 1
      src/views/subSystem/warningList/shared.js

+ 8 - 5
src/api/smxyjldczxt/yjxxfb/yjfb.js

@@ -60,12 +60,15 @@ export function updateYjxxData(data) {
 }
 
 // 获取字典数据
-export function getAlertTypeDictionaryData(query) {
-  return request({
-    url: '/system/dict/data/list',
-    method: 'get',
-    params: query
+export async function getAlertTypeDictionaryData(query) {
+  const type = query.dictType
+  const response = await request({
+    url: ['alert_type', 'warning_type'].includes(type)
+      ? '/warning/config/types'
+      : '/system/dict/data/type/' + (type === 'warning_level' ? 'alert_level' : type),
+    method: 'get'
   })
+  return { ...response, rows: response.data || [] }
 }
 
 // 预警详情

+ 4 - 0
src/api/warning/list.js

@@ -1,5 +1,9 @@
 import request from '@/utils/request'
 
+export function listWarningTypes() {
+  return request({ url: '/warning/config/types', method: 'get' })
+}
+
 export function listWarningItems(params) {
   return request({
     url: '/warning/item/list',

+ 5 - 0
src/assets/styles/index.scss

@@ -23,6 +23,11 @@
   word-break: break-word;
 }
 
+.warning-content {
+  white-space: pre-wrap;
+  overflow-wrap: anywhere;
+}
+
 @media (max-width: 768px) {
   .detail-drawer,
   .facility-form-drawer {

+ 6 - 9
src/views/subSystem/lifeCompany/lAlertInformation/LCorrelation.vue

@@ -105,7 +105,7 @@
               class="warning-link"
               @click="openWarningDetail(scope.row.linkedWarning.warningId)"
             >
-              {{ scope.row.linkedWarning.warningName }}
+              {{ scope.row.linkedWarning.warningNo }}
             </span>
             <span v-else class="empty-text">-</span>
           </template>
@@ -154,11 +154,11 @@
             <el-option
               v-for="item in availableWarnings"
               :key="item.warningId"
-              :label="item.warningName"
+              :label="item.warningNo"
               :value="item.warningId"
             >
               <div class="warning-option">
-                <span>{{ item.warningName }}</span>
+                <span>{{ item.warningNo }}</span>
                 <el-tag :type="getWarningLevelType(item.warningLevel)">{{ item.warningLevelText }}</el-tag>
               </div>
             </el-option>
@@ -183,7 +183,7 @@
             <el-option
               v-for="item in availableWarnings"
               :key="item.warningId"
-              :label="item.warningName"
+              :label="item.warningNo"
               :value="item.warningId"
             />
           </el-select>
@@ -201,10 +201,8 @@
       <template v-if="warningDetailData.basicInfo">
         <el-descriptions :column="2" border>
           <el-descriptions-item label="预警编号">{{ warningDetailData.basicInfo.warningNo || "-" }}</el-descriptions-item>
-          <el-descriptions-item label="预警名称">{{ warningDetailData.basicInfo.warningName || "-" }}</el-descriptions-item>
           <el-descriptions-item label="告警类型">{{ formatTypeText(warningDetailData.basicInfo.warningType) }}</el-descriptions-item>
           <el-descriptions-item label="预警级别">{{ formatLevelText(warningDetailData.basicInfo.warningLevel) }}</el-descriptions-item>
-          <el-descriptions-item label="预警位置" :span="2">{{ warningDetailData.basicInfo.location || "-" }}</el-descriptions-item>
           <el-descriptions-item label="发布时间">{{ warningDetailData.basicInfo.publishTime || "-" }}</el-descriptions-item>
           <el-descriptions-item label="状态">{{ warningDetailData.basicInfo.status || "-" }}</el-descriptions-item>
           <el-descriptions-item label="内容描述" :span="2">{{ warningDetailData.basicInfo.warningContent || "-" }}</el-descriptions-item>
@@ -344,13 +342,12 @@ function normalizeWarningRow(item) {
   return {
     warningId: item.warningId || item.warning_id,
     warningNo: item.warningNo || item.warning_no,
-    warningName: item.warningName || item.warning_name,
+
     warningType: item.warningType || item.warning_type,
     warningLevel: item.warningLevel || item.warning_level,
     warningLevelText: formatLevelText(item.warningLevel || item.warning_level),
     publishTime: item.publishTime || item.publish_time,
     status: item.status,
-    location: item.location,
     warningContent: item.warningContent || item.warning_content
   };
 }
@@ -411,7 +408,7 @@ async function buildLinkedAlarmMap() {
         if (alarmId) {
           map[alarmId] = {
             warningId: warning.warningId,
-            warningName: warning.warningName,
+
             warningLevel: warning.warningLevel,
             warningLevelText: warning.warningLevelText
           };

+ 34 - 51
src/views/subSystem/lifeCompany/lAlertInformation/LRelease.vue

@@ -16,10 +16,10 @@
 
     <el-card shadow="never" class="page-card">
       <el-form :model="queryParams" :inline="true">
-        <el-form-item label="预警名称">
+        <el-form-item label="预警编号">
           <el-input
-            v-model="queryParams.warningName"
-            placeholder="请输入预警名称"
+            v-model="queryParams.warningNo"
+            placeholder="请输入预警编号"
             clearable
             style="width: 220px"
             @keyup.enter="handleQuery"
@@ -71,7 +71,7 @@
           </template>
         </el-table-column>
         <el-table-column label="预警编号" prop="warningNo" width="180" />
-        <el-table-column label="预警名称" prop="warningName" min-width="180" show-overflow-tooltip />
+
         <el-table-column label="预警类型" prop="warningTypeText" width="120" />
         <el-table-column label="预警级别" width="110" align="center">
           <template #default="scope">
@@ -80,7 +80,9 @@
             </el-tag>
           </template>
         </el-table-column>
-        <el-table-column label="预警位置" prop="location" min-width="180" show-overflow-tooltip />
+        <el-table-column label="关联设备" min-width="180" show-overflow-tooltip>
+          <template #default="{ row }">{{ row.deviceName || row.deviceCode || "-" }}</template>
+        </el-table-column>
         <el-table-column label="发布时间" width="180">
           <template #default="scope">{{ formatDateTime(scope.row.publishTime) }}</template>
         </el-table-column>
@@ -179,34 +181,14 @@
             </el-form-item>
           </el-col>
           <el-col :span="24">
-            <el-form-item label="预警名称" prop="warningName">
-              <el-input v-model="formData.warningName" placeholder="请输入预警名称" maxlength="100" show-word-limit />
-            </el-form-item>
-          </el-col>
-          <el-col :span="24">
-            <el-form-item label="预警位置" prop="location">
-              <el-input v-model="formData.location" placeholder="请输入预警位置" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="24">
-            <el-form-item label="关联设备">
-              <el-input v-model="formData.deviceName" placeholder="点击选择关联设备" readonly @click="openDevicePicker">
+            <el-form-item label="关联设备" prop="deviceCode">
+              <el-input :model-value="formData.deviceName || formData.deviceCode" placeholder="点击选择关联设备" readonly @click="openDevicePicker">
                 <template #append>
                   <el-button :icon="Search" @click="openDevicePicker">选择</el-button>
                 </template>
               </el-input>
             </el-form-item>
           </el-col>
-          <el-col :span="12">
-            <el-form-item label="经度">
-              <el-input v-model="formData.longitude" placeholder="请输入经度" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="纬度">
-              <el-input v-model="formData.latitude" placeholder="请输入纬度" />
-            </el-form-item>
-          </el-col>
           <el-col :span="24">
             <el-form-item label="内容描述" prop="warningContent">
               <el-input
@@ -290,7 +272,6 @@
         <WarningItemSummary :warning="detailData.basicInfo" />
         <el-descriptions :column="2" border>
           <el-descriptions-item label="预警编号">{{ detailData.basicInfo.warningNo || "-" }}</el-descriptions-item>
-          <el-descriptions-item label="预警名称">{{ detailData.basicInfo.warningName || "-" }}</el-descriptions-item>
           <el-descriptions-item label="预警类型">{{ formatTypeText(detailData.basicInfo.warningType) }}</el-descriptions-item>
           <el-descriptions-item label="预警级别">
             <el-tag :type="getLevelTagType(detailData.basicInfo.warningLevel)">
@@ -301,7 +282,6 @@
           <el-descriptions-item label="权属单位">{{ detailData.basicInfo.ownershipUnit || "-" }}</el-descriptions-item>
           <el-descriptions-item label="发布人">{{ detailData.basicInfo.publisher || "-" }}</el-descriptions-item>
           <el-descriptions-item label="处置人">{{ detailData.basicInfo.handler || "-" }}</el-descriptions-item>
-          <el-descriptions-item label="预警位置" :span="2">{{ detailData.basicInfo.location || "-" }}</el-descriptions-item>
           <el-descriptions-item label="关联设备" :span="2">
             <template v-if="detailData.basicInfo.deviceCode || detailData.basicInfo.deviceName">
               {{ detailData.basicInfo.deviceName || "-" }}
@@ -311,7 +291,7 @@
           </el-descriptions-item>
           <el-descriptions-item label="发布时间">{{ formatDateTime(detailData.basicInfo.publishTime) }}</el-descriptions-item>
           <el-descriptions-item label="状态">{{ getStatusText(detailData.basicInfo.status) }}</el-descriptions-item>
-          <el-descriptions-item label="内容描述" :span="2">{{ detailData.basicInfo.warningContent || "-" }}</el-descriptions-item>
+          <el-descriptions-item label="内容描述" :span="2"><span class="warning-content">{{ detailData.basicInfo.warningContent || "-" }}</span></el-descriptions-item>
           <el-descriptions-item label="备注" :span="2">{{ detailData.basicInfo.remark || "-" }}</el-descriptions-item>
         </el-descriptions>
 
@@ -453,12 +433,13 @@
 </template>
 
 <script setup>
+import { useWarningStatuses } from '@/views/subSystem/lifeCompany/warningWorkflow'
+const { warningStatusOptions, databaseStatusLabels } = useWarningStatuses()
 import WarningItemSummary from '../components/WarningItemSummary.vue';
 import {computed, onMounted, reactive, ref, watch} from "vue";
 import {ElMessage, ElMessageBox} from "element-plus";
 import { Search } from "@element-plus/icons-vue";
 import { parseTime } from "@/utils/ruoyi";
-import { warningStatusLabels } from "../warningWorkflow";
 import WarningDisposalReasons from '../components/WarningDisposalReasons.vue';
 import WarningAttachments from "../components/WarningAttachments.vue";
 import { attachmentsForDisposal, unlinkedWarningAttachments } from "../warningAttachments";
@@ -529,7 +510,7 @@ const deptTreeRef = ref();
 const queryParams = reactive({
   pageNum: 1,
   pageSize: 10,
-  warningName: "",
+  warningNo: "",
   warningType: "",
   warningLevel: "",
   dateRange: []
@@ -540,8 +521,8 @@ const formData = reactive(createEmptyForm());
 const formRules = {
   warningType: [{ required: true, message: "请选择预警类型", trigger: "change" }],
   warningLevel: [{ required: true, message: "请选择预警级别", trigger: "change" }],
-  warningName: [{ required: true, message: "请输入预警名称", trigger: "blur" }],
-  location: [{ required: true, message: "请输入预警位置", trigger: "blur" }],
+
+  deviceCode: [{ required: true, whitespace: true, message: "请选择关联设备", trigger: "change" }],
   warningContent: [{ required: true, message: "请输入预警内容描述", trigger: "blur" }]
 };
 
@@ -565,15 +546,14 @@ function createEmptyForm() {
     itemSnapshot: "",
     warningId: "",
     warningNo: "",
-    warningName: "",
+
     warningType: "",
     warningLevel: "",
     warningSpecial: "",
     deviceCode: "",
     deviceName: "",
-    location: "",
-    longitude: "",
-    latitude: "",
+
+
     ownershipUnit: "",
     publisher: "",
     publishTime: "",
@@ -666,7 +646,7 @@ function getLevelTagType(level) {
 }
 
 function getStatusText(status) {
-  return warningStatusLabels[status] || status || "-";
+  return databaseStatusLabels.value[status] || status || "-"
 }
 
 function getStatusTagType(status) {
@@ -687,13 +667,12 @@ function normalizeWarningRow(item) {
   row.itemSnapshot = item.itemSnapshot || item.item_snapshot || "";
   row.warningId = item.warningId || item.warning_id || "";
   row.warningNo = item.warningNo || item.warning_no || "";
-  row.warningName = item.warningName || item.warning_name || "";
+
   row.warningType = item.warningType || item.warning_type || "";
   row.warningLevel = item.warningLevel || item.warning_level || "";
   row.warningSpecial = item.warningSpecial || item.warning_special || "";
-  row.location = item.location || "";
-  row.longitude = item.longitude || "";
-  row.latitude = item.latitude || "";
+
+
   row.ownershipUnit = item.ownershipUnit || item.ownership_unit || "";
   row.publisher = item.publisher || "";
   row.publishTime = item.publishTime || item.publish_time || "";
@@ -793,7 +772,7 @@ async function loadList() {
     const params = {
       pageNum: queryParams.pageNum,
       pageSize: queryParams.pageSize,
-      warningName: queryParams.warningName,
+      warningNo: queryParams.warningNo,
       warningType: queryParams.warningType,
       warningLevel: queryParams.warningLevel,
       startTime: queryParams.dateRange?.[0] || "",
@@ -818,7 +797,7 @@ function handleQuery() {
 function resetQuery() {
   queryParams.pageNum = 1;
   queryParams.pageSize = 10;
-  queryParams.warningName = "";
+  queryParams.warningNo = "";
   queryParams.warningType = "";
   queryParams.warningLevel = "";
   queryParams.dateRange = [];
@@ -967,8 +946,13 @@ async function loadDeviceList() {
 }
 
 function confirmDevice(row) {
+  if (!row.equipmentCode?.trim()) {
+    ElMessage.warning("该设备缺少设备编码,请先完善设备台账");
+    return;
+  }
   formData.deviceCode = row.equipmentCode || "";
   formData.deviceName = row.equipmentName || "";
+  formRef.value?.clearValidate("deviceCode");
   devicePickerVisible.value = false;
 }
 
@@ -1004,13 +988,12 @@ async function submitForm() {
         itemId: formData.itemId || "",
         warningId: formData.warningId,
         warningNo: formData.warningNo,
-        warningName: formData.warningName,
+
         warningType: formData.warningType,
         warningLevel: formData.warningLevel,
         warningSpecial: formData.warningSpecial,
-        location: formData.location,
-        longitude: formData.longitude,
-        latitude: formData.latitude,
+
+
         ownershipUnit: formData.ownershipUnit,
         handler: formData.handler,
         reviewer: formData.reviewer,
@@ -1048,7 +1031,7 @@ async function handleView(row) {
 }
 
 async function handleDelete(row) {
-  await ElMessageBox.confirm(`确认删除预警“${row.warningName}”吗?`, "提示", { type: "warning" });
+  await ElMessageBox.confirm(`确认删除预警“${row.warningNo}”吗?`, "提示", { type: "warning" });
   const res = await deleteYjxxData(row.warningId);
   if (res.code !== 200) {
     ElMessage.error(res.msg || "删除失败");
@@ -1063,7 +1046,7 @@ async function handlePublish(row) {
     ElMessage.warning("发布前请先编辑预警并选择处置人");
     return;
   }
-  await ElMessageBox.confirm(`确认发布预警“${row.warningName}”吗?`, "提示", { type: "warning" });
+  await ElMessageBox.confirm(`确认发布预警“${row.warningNo}”吗?`, "提示", { type: "warning" });
   const res = await releaseYjxxData(row.warningId, { reviewer: row.reviewer || undefined });
   if (res.code !== 200) {
     ElMessage.error(res.msg || "发布失败");

+ 33 - 92
src/views/subSystem/lifeCompany/lAlertInformation/LReportUpload.vue

@@ -5,17 +5,17 @@
       <div class="page-header">
         <div>
           <div class="page-title">预警报告上传</div>
-          <div class="page-subtitle">提供预警报告附件上传功能,结合设备报警曲线、预警位置和周边要素分析,描述预警发生的具体内容</div>
+          <div class="page-subtitle">提供预警报告附件上传功能,结合设备报警曲线、关联设备和周边要素分析,描述预警发生的具体内容</div>
         </div>
       </div>
     </el-card>
 
     <el-card shadow="never" class="page-card">
       <el-form :model="queryParams" :inline="true">
-        <el-form-item label="预警名称">
+        <el-form-item label="预警编号">
           <el-input
-            v-model="queryParams.warningName"
-            placeholder="请输入预警名称"
+            v-model="queryParams.warningNo"
+            placeholder="请输入预警编号"
             clearable
             style="width: 220px"
             @keyup.enter="loadWarningOptions"
@@ -53,11 +53,11 @@
             <el-option
               v-for="item in warningOptions"
               :key="item.warningId"
-              :label="item.warningName"
+              :label="item.warningNo"
               :value="item.warningId"
             >
               <div class="warning-option">
-                <span>{{ item.warningName }}</span>
+                <span>{{ item.warningNo }}</span>
                 <el-tag :type="getLevelTagType(item.warningLevel)">{{ item.warningLevelText }}</el-tag>
               </div>
             </el-option>
@@ -143,10 +143,8 @@
           <el-empty v-if="!warningDetail.basicInfo" description="请先选择预警" />
           <el-descriptions v-else :column="1" border size="small">
             <el-descriptions-item label="预警编号">{{ currentBasicInfo.warningNo || "-" }}</el-descriptions-item>
-            <el-descriptions-item label="预警名称">{{ currentBasicInfo.warningName || "-" }}</el-descriptions-item>
             <el-descriptions-item label="预警类型">{{ currentBasicInfo.warningTypeText || "-" }}</el-descriptions-item>
             <el-descriptions-item label="预警级别">{{ currentBasicInfo.warningLevelText || "-" }}</el-descriptions-item>
-            <el-descriptions-item label="预警位置">{{ currentBasicInfo.location || "-" }}</el-descriptions-item>
             <el-descriptions-item label="发布人">{{ currentBasicInfo.publisher || "-" }}</el-descriptions-item>
             <el-descriptions-item label="发布时间">{{ currentBasicInfo.publishTime || "-" }}</el-descriptions-item>
             <el-descriptions-item label="权属单位">{{ currentBasicInfo.ownershipUnit || "-" }}</el-descriptions-item>
@@ -189,24 +187,14 @@
               />
             </el-tab-pane>
 
-            <el-tab-pane label="预警位置情况" name="location">
-              <div class="location-pane">
-                <div class="gis-card">
-                  <div class="gis-title">GIS定位信息</div>
-                  <div class="gis-point">
-                    <div class="point-badge">预警点</div>
-                    <div class="point-coord">
-                      经度:{{ gisInfo.longitude || "-" }} / 纬度:{{ gisInfo.latitude || "-" }}
-                    </div>
-                  </div>
-                </div>
-                <el-descriptions :column="1" border size="small">
-                  <el-descriptions-item label="位置描述">{{ currentBasicInfo.location || "-" }}</el-descriptions-item>
-                  <el-descriptions-item label="权属单位">{{ currentBasicInfo.ownershipUnit || "-" }}</el-descriptions-item>
-                  <el-descriptions-item label="处置人">{{ currentBasicInfo.handler || "-" }}</el-descriptions-item>
-                  <el-descriptions-item label="状态">{{ currentBasicInfo.statusText || currentBasicInfo.status || "-" }}</el-descriptions-item>
-                </el-descriptions>
-              </div>
+            <el-tab-pane label="关联设备" name="device">
+              <el-descriptions :column="1" border size="small">
+                <el-descriptions-item label="设备名称">{{ currentBasicInfo.deviceName || "-" }}</el-descriptions-item>
+                <el-descriptions-item label="设备编码">{{ currentBasicInfo.deviceCode || "-" }}</el-descriptions-item>
+                <el-descriptions-item label="权属单位">{{ currentBasicInfo.ownershipUnit || "-" }}</el-descriptions-item>
+                <el-descriptions-item label="处置人">{{ currentBasicInfo.handler || "-" }}</el-descriptions-item>
+                <el-descriptions-item label="状态">{{ currentBasicInfo.statusText || currentBasicInfo.status || "-" }}</el-descriptions-item>
+              </el-descriptions>
             </el-tab-pane>
 
             <el-tab-pane label="周边要素分析" name="environment">
@@ -247,7 +235,7 @@
               <h4>预警具体内容描述</h4>
             </div>
             <div class="desc-content">
-              <p>{{ currentBasicInfo.warningContent || "暂无预警内容描述" }}</p>
+              <p class="warning-content">{{ currentBasicInfo.warningContent || "暂无预警内容描述" }}</p>
               <p v-if="reportSummary"><strong>报告补充摘要:</strong>{{ reportSummary }}</p>
             </div>
           </div>
@@ -258,6 +246,8 @@
 </template>
 
 <script setup>
+import { useWarningStatuses } from '@/views/subSystem/lifeCompany/warningWorkflow'
+const { warningStatusOptions, databaseStatusLabels } = useWarningStatuses()
 import { computed, nextTick, onBeforeUnmount, onMounted, ref } from "vue";
 import { ElMessage } from "element-plus";
 import { CircleCloseFilled, Document, InfoFilled, Upload, UploadFilled } from "@element-plus/icons-vue";
@@ -283,14 +273,14 @@ let curveChart = null;
 
 const warningTypeOptions = ref([]);
 const warningLevelOptions = ref([]);
-const warningStatusOptions = ref([]);
+
 const warningOptions = ref([]);
 const selectedWarningId = ref("");
 const warningDetail = ref({});
 const minioBaseUrl = (import.meta.env.VITE_APP_MINIO_BASE_URL || "").trim();
 
 const queryParams = ref({
-  warningName: "",
+  warningNo: "",
   warningType: "",
   warningLevel: "",
   status: ""
@@ -310,32 +300,28 @@ const warningLevelLabelMap = computed(() => {
   }, {});
 });
 
-const warningStatusLabelMap = computed(() => {
-  return warningStatusOptions.value.reduce((acc, item) => {
-    acc[item.dictValue] = item.dictLabel;
-    return acc;
-  }, {});
-});
+const warningStatusLabelMap = databaseStatusLabels;
 
 const currentBasicInfo = computed(() => {
   const basic = warningDetail.value.basicInfo || {};
   return {
+    deviceCode: basic.deviceCode || basic.device_code || "",
+    deviceName: basic.deviceName || basic.device_name || "",
     warningId: basic.warningId || basic.warning_id || "",
     warningNo: basic.warningNo || basic.warning_no || "",
-    warningName: basic.warningName || basic.warning_name || "",
+
     warningType: basic.warningType || basic.warning_type || "",
     warningTypeText: warningTypeLabelMap.value[basic.warningType || basic.warning_type] || basic.warningType || basic.warning_type || "-",
     warningLevel: basic.warningLevel || basic.warning_level || "",
     warningLevelText: warningLevelLabelMap.value[basic.warningLevel || basic.warning_level] || basic.warningLevel || basic.warning_level || "-",
-    location: basic.location || "",
     ownershipUnit: basic.ownershipUnit || basic.ownership_unit || "",
     publisher: basic.publisher || "",
     publishTime: basic.publishTime || basic.publish_time || "",
     handler: basic.handler || "",
     status: basic.status || "",
     statusText: warningStatusLabelMap.value[basic.status] || basic.statusText || basic.status || "",
-    longitude: basic.longitude || "",
-    latitude: basic.latitude || "",
+
+
     warningContent: basic.warningContent || basic.warning_content || "",
     warningSpecial: basic.warningSpecial || basic.warning_special || "",
     remark: basic.remark || ""
@@ -345,7 +331,6 @@ const currentBasicInfo = computed(() => {
 const alarmList = computed(() => warningDetail.value.alarmList || []);
 const attachmentList = computed(() => warningDetail.value.attachmentList || []);
 const disposalHistory = computed(() => warningDetail.value.disposalHistory || []);
-const gisInfo = computed(() => warningDetail.value.gisLocation || {});
 const hasArchive = computed(() => !!warningDetail.value.electronicArchive);
 
 const curveSummary = computed(() => {
@@ -366,7 +351,7 @@ const environmentConclusion = computed(() => {
   if (!warningDetail.value.basicInfo) {
     return "请选择预警后查看周边要素分析结论。";
   }
-  return `本次预警“${currentBasicInfo.value.warningName || "-"}”当前包含 ${alarmList.value.length} 条关联报警、${disposalHistory.value.length} 条处置记录、${attachmentList.value.length} 份附件资料。结合预警位置“${currentBasicInfo.value.location || "-"}”与电子存档情况,建议在上传报告时补充现场核查结论、报警峰值说明和后续处置建议。`;
+  return `本次预警“${currentBasicInfo.value.warningNo || "-"}”当前包含 ${alarmList.value.length} 条关联报警、${disposalHistory.value.length} 条处置记录、${attachmentList.value.length} 份附件资料。结合关联设备“${currentBasicInfo.value.deviceName || currentBasicInfo.value.deviceCode || "-"}”与电子存档情况,建议在上传报告时补充现场核查结论、报警峰值说明和后续处置建议。`;
 });
 
 function getLevelTagType(level) {
@@ -380,7 +365,7 @@ function getLevelTagType(level) {
 }
 
 function getStatusText(status) {
-  return warningStatusLabelMap.value[status] || status || "-";
+  return databaseStatusLabels.value[status] || status || "-"
 }
 
 function getStatusTagType(status) {
@@ -450,7 +435,7 @@ function normalizeWarningRow(item) {
   const warningLevel = item.warningLevel || item.warning_level;
   return {
     warningId,
-    warningName: item.warningName || item.warning_name,
+    warningNo: item.warningNo || item.warning_no || "",
     warningType: item.warningType || item.warning_type,
     warningLevel,
     warningLevelText: warningLevelLabelMap.value[warningLevel] || warningLevel
@@ -458,14 +443,13 @@ function normalizeWarningRow(item) {
 }
 
 async function loadDicts() {
-  const [typeRes, levelRes, statusRes] = await Promise.all([
+  const [typeRes, levelRes] = await Promise.all([
     getAlertTypeDictionaryData({ dictType: "alert_type" }),
-    getAlertTypeDictionaryData({ dictType: "alert_level" }),
-    getAlertTypeDictionaryData({ dictType: "pre_alarm_status" })
+    getAlertTypeDictionaryData({ dictType: "alert_level" })
   ]);
   warningTypeOptions.value = typeRes.rows || [];
   warningLevelOptions.value = levelRes.rows || [];
-  warningStatusOptions.value = statusRes.rows || [];
+
 }
 
 async function loadWarningOptions() {
@@ -474,7 +458,7 @@ async function loadWarningOptions() {
     const res = await getdbyjlistData({
       pageNum: 1,
       pageSize: 200,
-      warningName: queryParams.value.warningName || undefined,
+      warningNo: queryParams.value.warningNo || undefined,
       warningType: queryParams.value.warningType || undefined,
       warningLevel: queryParams.value.warningLevel || undefined,
       status: queryParams.value.status || undefined
@@ -598,7 +582,7 @@ async function submitReport() {
 
 function resetQuery() {
   queryParams.value = {
-    warningName: "",
+    warningNo: "",
     warningType: "",
     warningLevel: "",
     status: ""
@@ -773,48 +757,6 @@ onBeforeUnmount(() => {
   margin-bottom: 16px;
 }
 
-.location-pane {
-  display: grid;
-  grid-template-columns: 1fr 1fr;
-  gap: 16px;
-}
-
-.gis-card {
-  min-height: 180px;
-  padding: 18px;
-  border-radius: 14px;
-  background: linear-gradient(135deg, #eef6ff, #f8fbff);
-  border: 1px solid #dbeafe;
-}
-
-.gis-title {
-  font-size: 15px;
-  font-weight: 600;
-  color: #1d4ed8;
-}
-
-.gis-point {
-  margin-top: 28px;
-  display: flex;
-  flex-direction: column;
-  gap: 14px;
-}
-
-.point-badge {
-  width: 76px;
-  text-align: center;
-  padding: 6px 0;
-  border-radius: 999px;
-  background: #ef4444;
-  color: #fff;
-  font-size: 12px;
-}
-
-.point-coord {
-  font-size: 14px;
-  color: #374151;
-}
-
 .factors-grid {
   display: grid;
   grid-template-columns: repeat(4, minmax(0, 1fr));
@@ -893,7 +835,6 @@ onBeforeUnmount(() => {
 }
 
 @media (max-width: 768px) {
-  .location-pane,
   .factors-grid {
     grid-template-columns: 1fr;
   }

+ 21 - 34
src/views/subSystem/lifeCompany/lAlertInformation/LTobeHandled.vue

@@ -31,18 +31,15 @@
 
     <el-card shadow="never" class="page-card">
       <el-form :model="queryParams" :inline="true">
-        <el-form-item label="预警名称">
+        <el-form-item label="预警编号">
           <el-input
-            v-model="queryParams.warningName"
-            placeholder="请输入预警名称"
+            v-model="queryParams.warningNo"
+            placeholder="请输入预警编号"
             clearable
             style="width: 220px"
             @keyup.enter="handleQuery"
           />
         </el-form-item>
-        <el-form-item label="预警编号">
-          <el-input v-model="queryParams.warningNo" placeholder="请输入预警编号" clearable style="width: 200px" />
-        </el-form-item>
         <el-form-item label="预警专项">
           <el-input v-model="queryParams.warningSpecial" placeholder="请输入预警专项" clearable style="width: 200px" />
         </el-form-item>
@@ -75,9 +72,6 @@
         <el-form-item label="报警编号">
           <el-input v-model="queryParams.alarmCode" placeholder="请输入报警编号" clearable style="width: 180px" />
         </el-form-item>
-        <el-form-item label="报警位置">
-          <el-input v-model="queryParams.location" placeholder="请输入报警位置" clearable style="width: 200px" />
-        </el-form-item>
         <el-form-item label="权属单位">
           <el-input v-model="queryParams.ownershipUnit" placeholder="请输入权属单位" clearable style="width: 180px" />
         </el-form-item>
@@ -112,7 +106,7 @@
             {{ (pagination.pageNum - 1) * pagination.pageSize + scope.$index + 1 }}
           </template>
         </el-table-column>
-        <el-table-column label="预警名称" prop="warningName" min-width="180" show-overflow-tooltip />
+
         <el-table-column v-if="activeTab === 'NOTICE'" label="督办通知" prop="taskName" min-width="250" show-overflow-tooltip />
         <el-table-column v-if="activeTab === 'NOTICE'" label="阅读状态" width="90">
           <template #default="scope">{{ scope.row.readStatus === 'READ' ? '已读' : '未读' }}</template>
@@ -130,7 +124,6 @@
             {{ scope.row.alarmCodeList.length ? scope.row.alarmCodeList.join(",") : "-" }}
           </template>
         </el-table-column>
-        <el-table-column label="报警位置" prop="location" min-width="180" show-overflow-tooltip />
         <el-table-column label="权属单位" prop="ownershipUnit" width="160" show-overflow-tooltip />
         <el-table-column label="预警级别" width="110" align="center">
           <template #default="scope">
@@ -173,7 +166,6 @@
       <template v-if="detailData.basicInfo">
         <WarningItemSummary :warning="detailData.basicInfo" />
         <el-descriptions :column="2" border>
-          <el-descriptions-item label="预警名称">{{ detailBasic.warningName || "-" }}</el-descriptions-item>
           <el-descriptions-item label="预警编号">{{ detailBasic.warningNo || "-" }}</el-descriptions-item>
           <el-descriptions-item label="预警专项">{{ detailBasic.warningSpecial || "-" }}</el-descriptions-item>
           <el-descriptions-item label="预警类型">{{ detailBasic.warningTypeText || "-" }}</el-descriptions-item>
@@ -181,10 +173,8 @@
           <el-descriptions-item label="处置人">{{ detailBasic.handler || "-" }}</el-descriptions-item>
           <el-descriptions-item label="发布人">{{ detailBasic.publisher || "-" }}</el-descriptions-item>
           <el-descriptions-item label="权属单位">{{ detailBasic.ownershipUnit || "-" }}</el-descriptions-item>
-          <el-descriptions-item label="报警位置" :span="2">{{ detailBasic.location || "-" }}</el-descriptions-item>
           <el-descriptions-item label="发布时间">{{ formatDateTime(detailBasic.publishTime) }}</el-descriptions-item>
-          <el-descriptions-item label="经纬度">{{ detailBasic.longitude || "-" }} / {{ detailBasic.latitude || "-" }}</el-descriptions-item>
-          <el-descriptions-item label="预警内容" :span="2">{{ detailBasic.warningContent || "-" }}</el-descriptions-item>
+          <el-descriptions-item label="预警内容" :span="2"><span class="warning-content">{{ detailBasic.warningContent || "-" }}</span></el-descriptions-item>
           <el-descriptions-item label="备注" :span="2">{{ detailBasic.remark || "-" }}</el-descriptions-item>
         </el-descriptions>
 
@@ -222,8 +212,8 @@
     <!-- 预警解除对话框 -->
     <el-dialog v-model="resolveDialog.visible" title="解除预警" width="500px" append-to-body>
       <el-form label-width="100px">
-        <el-form-item label="预警名称">
-          <el-input :model-value="resolveDialog.row?.warningName || '-'" disabled />
+        <el-form-item label="预警编号">
+          <el-input :model-value="resolveDialog.row?.warningNo || '-'" disabled />
         </el-form-item>
         <el-form-item label="处置说明" required>
           <el-input
@@ -247,8 +237,8 @@
     <!-- 退回重办对话框 -->
     <el-dialog v-model="returnDialog.visible" title="退回重办" width="500px" append-to-body>
       <el-form label-width="100px">
-        <el-form-item label="预警名称">
-          <el-input :model-value="returnDialog.row?.warningName || '-'" disabled />
+        <el-form-item label="预警编号">
+          <el-input :model-value="returnDialog.row?.warningNo || '-'" disabled />
         </el-form-item>
         <el-form-item label="退回说明" required>
           <el-input
@@ -273,6 +263,8 @@
 </template>
 
 <script setup>
+import { useWarningStatuses } from '@/views/subSystem/lifeCompany/warningWorkflow'
+const { warningStatusOptions, databaseStatusLabels } = useWarningStatuses()
 import WarningItemSummary from '../components/WarningItemSummary.vue';
 import WarningDisposalReasons from '../components/WarningDisposalReasons.vue';
 import WarningAttachments from "../components/WarningAttachments.vue";
@@ -281,7 +273,6 @@ import { computed, onMounted, reactive, ref } from "vue";
 import { ElMessage, ElMessageBox } from "element-plus";
 import { parseTime } from "@/utils/ruoyi";
 import WarningWorkflowActions from "../WarningWorkflowActions.vue";
-import { warningStatusLabels } from "../warningWorkflow";
 import { getAlertTypeDictionaryData, getTodoListData, getWarningDetailData, readWarningNotification, resolveWarningData, returnWarningData } from "@/api/smxyjldczxt/yjxxfb/yjfb.js";
 
 const loading = ref(false);
@@ -312,7 +303,7 @@ const returnDialog = reactive({
 });
 
 const queryParams = reactive({
-  warningName: "",
+
   warningNo: "",
   warningSpecial: "",
   warningType: "",
@@ -320,7 +311,6 @@ const queryParams = reactive({
   handler: "",
   publisher: "",
   alarmCode: "",
-  location: "",
   ownershipUnit: "",
   dateRange: []
 });
@@ -353,7 +343,7 @@ const noticeCount = computed(() => noticeTotal.value);
 const pagedList = computed(() => currentList.value);
 
 function getStatusText(status) {
-  return warningStatusLabels[status] || status || "-";
+  return databaseStatusLabels.value[status] || status || "-"
 }
 
 function getStatusTagType(status) {
@@ -367,18 +357,17 @@ const detailBasic = computed(() => {
   const warningType = basic.warningType || basic.warning_type || "";
   const warningLevel = basic.warningLevel || basic.warning_level || "";
   return {
-    warningName: basic.warningName || basic.warning_name || "",
+
     warningNo: basic.warningNo || basic.warning_no || "",
     warningSpecial: basic.warningSpecial || basic.warning_special || "",
     warningTypeText: warningTypeLabelMap.value[warningType] || warningType || "-",
-    warningLevelText: warningLevelLabelMap.value[warningLevel] || warningLevel || "-",
+    warningLevelText: warningLevelLabelMap.value[warningLevel] || "-",
     handler: basic.handler || "",
     publisher: basic.publisher || "",
     ownershipUnit: basic.ownershipUnit || basic.ownership_unit || "",
-    location: basic.location || "",
     publishTime: basic.publishTime || basic.publish_time || "",
-    longitude: basic.longitude || "",
-    latitude: basic.latitude || "",
+
+
     warningContent: basic.warningContent || basic.warning_content || "",
     remark: basic.remark || ""
   };
@@ -418,13 +407,13 @@ function enrichTodoRows(records) {
       ...item,
       todoId: item.todo_id || item.todoId,
       warningId: item.warning_id || item.warningId,
-      warningName: item.warning_name || item.warningName || "",
+
       warningNo: item.warning_no || item.warningNo || "",
       warningSpecial: item.warning_special || item.warningSpecial || "",
       warningType,
       warningTypeText: warningTypeLabelMap.value[warningType] || warningType || "-",
       warningLevel,
-      warningLevelText: warningLevelLabelMap.value[warningLevel] || warningLevel || "-",
+      warningLevelText: warningLevelLabelMap.value[warningLevel] || "-",
       ownershipUnit: item.ownership_unit || item.ownershipUnit || "",
       publishTime: item.publish_time || item.publishTime || "",
       reviewer: item.reviewer || item.publisher || "",
@@ -444,7 +433,7 @@ async function loadTodoList(type) {
     pageNum: pagination.pageNum,
     pageSize: pagination.pageSize,
     todoType: type,
-    warningName: queryParams.warningName || undefined,
+
     warningNo: queryParams.warningNo || undefined,
     warningSpecial: queryParams.warningSpecial || undefined,
     warningType: queryParams.warningType || undefined,
@@ -452,7 +441,6 @@ async function loadTodoList(type) {
     handler: queryParams.handler || undefined,
     publisher: queryParams.publisher || undefined,
     alarmCode: queryParams.alarmCode || undefined,
-    location: queryParams.location || undefined,
     ownershipUnit: queryParams.ownershipUnit || undefined,
     startTime: startTime || undefined,
     endTime: endTime || undefined
@@ -510,7 +498,7 @@ function handleQuery() {
 }
 
 function resetQuery() {
-  queryParams.warningName = "";
+
   queryParams.warningNo = "";
   queryParams.warningSpecial = "";
   queryParams.warningType = "";
@@ -518,7 +506,6 @@ function resetQuery() {
   queryParams.handler = "";
   queryParams.publisher = "";
   queryParams.alarmCode = "";
-  queryParams.location = "";
   queryParams.ownershipUnit = "";
   queryParams.dateRange = [];
   pagination.pageNum = 1;

+ 7 - 6
src/views/subSystem/lifeCompany/lOverviewWarning/LTodayNot.vue

@@ -8,10 +8,10 @@
       <div class="metric-card"><span>最高优先级</span><strong class="level-value">{{ highestLevel }}</strong><small>按当前未处置预警级别计算</small></div>
     </div>
     <el-card shadow="never" class="table-card">
-      <template #header><div class="card-title"><div><span>重点关注清单</span><em>{{ total }} 条</em></div><div class="filters"><el-select v-model="selectedType" clearable placeholder="全部预警类型" @change="resetPage"><el-option v-for="item in typeOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select><el-select v-model="selectedLevel" clearable placeholder="全部级别" @change="resetPage"><el-option v-for="item in levelOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select><el-input v-model="keyword" clearable placeholder="搜索名称、专项或单位" @keyup.enter="resetPage" @clear="resetPage"><template #prefix><el-icon><Search /></el-icon></template></el-input><el-button type="primary" @click="resetPage">查询</el-button></div></div></template>
+      <template #header><div class="card-title"><div><span>重点关注清单</span><em>{{ total }} 条</em></div><div class="filters"><el-select v-model="selectedType" clearable placeholder="全部预警类型" @change="resetPage"><el-option v-for="item in typeOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select><el-select v-model="selectedLevel" clearable placeholder="全部级别" @change="resetPage"><el-option v-for="item in levelOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select><el-input v-model="keyword" clearable placeholder="搜索编号、专项或单位" @keyup.enter="resetPage" @clear="resetPage"><template #prefix><el-icon><Search /></el-icon></template></el-input><el-button type="primary" @click="resetPage">查询</el-button></div></div></template>
       <el-table v-loading="tableLoading" :data="rows" stripe highlight-current-row empty-text="当前暂无未处置预警" @row-click="openDetail">
         <el-table-column label="关注" width="74" align="center"><template #default="{ row }"><span class="priority-dot" :class="`level-${warningLevelCode(row)}`" /></template></el-table-column>
-        <el-table-column label="预警事项" min-width="190" show-overflow-tooltip><template #default="{ row }">{{ row.warningName || row.warning_name || '未命名预警' }}</template></el-table-column>
+        <el-table-column label="预警编号" min-width="190" show-overflow-tooltip><template #default="{ row }">{{ row.warningNo || row.warning_no || '预警编号未生成' }}</template></el-table-column>
         <el-table-column label="预警类型" width="120"><template #default="{ row }">{{ warningTypeText(row) }}</template></el-table-column>
         <el-table-column label="预警专项" min-width="150" show-overflow-tooltip><template #default="{ row }">{{ row.warningSpecial || row.warning_special || '未设置' }}</template></el-table-column>
         <el-table-column label="级别" width="100" align="center"><template #default="{ row }"><el-tag :type="warningLevelTag(row)">{{ warningLevelText(row) }}</el-tag></template></el-table-column>
@@ -28,19 +28,20 @@
 </template>
 
 <script setup name="WarningTodayUnprocessed">
+import { loadWarningReferences } from '../lstatistics/statisticsShared'
 import { computed, onMounted, ref } from 'vue'
 import { ElMessage } from 'element-plus'
 import { Refresh, Search } from '@element-plus/icons-vue'
 import { pageWarningTodayUnprocessed } from '@/api/warning/dashboard'
-import { warningTypeLabels } from '../lstatistics/statisticsShared'
+import { warningTypeOptions, warningLevelLabels } from '../lstatistics/statisticsShared'
 import WarningDetailDrawer from './WarningDetailDrawer.vue'
-import { dashboardData, formatDashboardTime, pageRecords, pageTotal, warningLevelCode, warningLevelLabels, warningLevelTag, warningLevelText, warningStatusTag, warningStatusText, warningTypeText } from './dashboardShared'
+import { dashboardData, formatDashboardTime, pageRecords, pageTotal, warningLevelCode, warningLevelTag, warningLevelText, warningStatusTag, warningStatusText, warningTypeText } from './dashboardShared'
 
 const loading=ref(false);const tableLoading=ref(false);const errorMessage=ref('');const keyword=ref('');const selectedType=ref('');const selectedLevel=ref('');const pageNum=ref(1);const pageSize=ref(10);const rows=ref([]);const total=ref(0);const ownershipCount=ref(0);const highestLevelValue=ref(0);const generatedAt=ref('');const detailVisible=ref(false);const selectedRow=ref(null)
-const typeOptions=Object.entries(warningTypeLabels).filter(([value])=>['WATER_PIPE','SEWER_PIPE','GAS_PIPE','MANHOLE'].includes(value)).map(([value,label])=>({value,label}));const levelOptions=[{value:'1',label:'蓝色(IV级)'},{value:'2',label:'黄色(III级)'},{value:'3',label:'橙色(II级)'},{value:'4',label:'红色(I级)'}];const highestLevel=computed(()=>warningLevelLabels[String(highestLevelValue.value)]||'-');
+const typeOptions = warningTypeOptions;const levelOptions = computed(() => Object.entries(warningLevelLabels).map(([value, label]) => ({ value, label })));const highestLevel=computed(()=>warningLevelLabels[String(highestLevelValue.value)]||'-');
 function openDetail(row){selectedRow.value=row;detailVisible.value=true}function resetPage(){pageNum.value=1;loadPage()}function handleSizeChange(){pageNum.value=1;loadPage()}
 async function loadPage(){tableLoading.value=true;errorMessage.value='';try{const response=await pageWarningTodayUnprocessed({pageNum:pageNum.value,pageSize:pageSize.value,warningType:selectedType.value||undefined,warningLevel:selectedLevel.value||undefined,keyword:keyword.value.trim()||undefined});const data=dashboardData(response,{});rows.value=pageRecords(response);total.value=pageTotal(response);ownershipCount.value=Number(data.ownershipCount||0);highestLevelValue.value=Number(data.highestLevel||0);generatedAt.value=data.generatedAt||''}catch(error){rows.value=[];total.value=0;ownershipCount.value=0;highestLevelValue.value=0;errorMessage.value=error?.message||'今日未处置预警加载失败';ElMessage.error(errorMessage.value)}finally{tableLoading.value=false}}
-async function loadData(){loading.value=true;errorMessage.value='';try{await loadPage()}catch(error){errorMessage.value=error?.message||'今日未处置预警加载失败,请稍后重试';ElMessage.error(errorMessage.value)}finally{loading.value=false}}
+async function loadData(){loading.value=true;errorMessage.value='';try{ await loadWarningReferences();await loadPage()}catch(error){errorMessage.value=error?.message||'今日未处置预警加载失败,请稍后重试';ElMessage.error(errorMessage.value)}finally{loading.value=false}}
 onMounted(loadData)
 </script>
 

+ 4 - 3
src/views/subSystem/lifeCompany/lOverviewWarning/Lhistory.vue

@@ -7,9 +7,9 @@
       <el-card shadow="never" class="chart-card"><template #header><div class="card-title"><span>专项预警分布</span><em>{{ specialStats.length }} 个专项</em></div></template><div ref="chartRef" class="chart-box" /><el-empty v-if="!specialStats.length && !loading" description="暂无专项统计数据" /></el-card>
     </div>
     <el-card shadow="never" class="table-card">
-      <template #header><div class="card-title"><div><span>历史预警明细</span><em>{{ total }} 条</em></div><div class="filters"><el-select v-model="selectedSpecial" clearable placeholder="全部预警专项" @change="resetPage"><el-option v-for="item in specialStats" :key="item.specialName" :label="item.specialName" :value="item.specialName" /></el-select><el-input v-model="keyword" clearable placeholder="搜索名称、位置或单位" @keyup.enter="resetPage" @clear="resetPage"><template #prefix><el-icon><Search /></el-icon></template></el-input><el-button type="primary" @click="resetPage">查询</el-button></div></div></template>
+      <template #header><div class="card-title"><div><span>历史预警明细</span><em>{{ total }} 条</em></div><div class="filters"><el-select v-model="selectedSpecial" clearable placeholder="全部预警专项" @change="resetPage"><el-option v-for="item in specialStats" :key="item.specialName" :label="item.specialName" :value="item.specialName" /></el-select><el-input v-model="keyword" clearable placeholder="搜索编号、专项或单位" @keyup.enter="resetPage" @clear="resetPage"><template #prefix><el-icon><Search /></el-icon></template></el-input><el-button type="primary" @click="resetPage">查询</el-button></div></div></template>
       <el-table v-loading="tableLoading" :data="rows" stripe highlight-current-row empty-text="暂无符合条件的历史预警" @row-click="openDetail">
-        <el-table-column label="预警事项" min-width="190" show-overflow-tooltip><template #default="{ row }">{{ row.warningName || row.warning_name || '未命名预警' }}</template></el-table-column>
+        <el-table-column label="预警编号" min-width="190" show-overflow-tooltip><template #default="{ row }">{{ row.warningNo || row.warning_no || '预警编号未生成' }}</template></el-table-column>
         <el-table-column label="预警类型" width="120"><template #default="{ row }">{{ warningTypeText(row) }}</template></el-table-column>
         <el-table-column label="预警专项" min-width="150" show-overflow-tooltip><template #default="{ row }">{{ row.warningSpecial || row.warning_special || '未设置' }}</template></el-table-column>
         <el-table-column label="预警级别" width="105" align="center"><template #default="{ row }"><el-tag :type="warningLevelTag(row)">{{ warningLevelText(row) }}</el-tag></template></el-table-column>
@@ -25,6 +25,7 @@
 </template>
 
 <script setup name="WarningHistoryOverview">
+import { loadWarningReferences } from '../lstatistics/statisticsShared'
 import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
 import { ElMessage } from 'element-plus'
 import { Refresh, Search } from '@element-plus/icons-vue'
@@ -39,7 +40,7 @@ function openDetail(row){selectedRow.value=row;detailVisible.value=true}function
 function handleSizeChange(){pageNum.value=1;loadPage()}
 function renderChart(){if(!chartRef.value||!specialStats.value.length){chart?.clear();return}chart ||= echarts.init(chartRef.value);chart.setOption({tooltip:{trigger:'item',formatter:'{b}<br/>{c} 条 ({d}%)'},legend:{type:'scroll',orient:'vertical',right:4,top:'center',textStyle:{color:'#52637a'}},series:[{type:'pie',radius:['46%','70%'],center:['38%','52%'],avoidLabelOverlap:true,itemStyle:{borderColor:'#fff',borderWidth:3},label:{show:false},emphasis:{label:{show:true,fontSize:15,fontWeight:'bold'}},data:specialStats.value.map(item=>({name:item.specialName,value:item.count}))}],color:['#2563eb','#0f766e','#f59e0b','#dc2626','#64748b','#7c3aed']})}
 async function loadPage(){tableLoading.value=true;errorMessage.value='';try{const response=await pageWarningHistory({pageNum:pageNum.value,pageSize:pageSize.value,warningSpecial:selectedSpecial.value||undefined,keyword:keyword.value.trim()||undefined});rows.value=pageRecords(response);total.value=pageTotal(response)}catch(error){rows.value=[];total.value=0;errorMessage.value=error?.message||'历史预警明细加载失败';ElMessage.error(errorMessage.value)}finally{tableLoading.value=false}}
-async function loadData(){loading.value=true;errorMessage.value='';try{result.value={...result.value,...dashboardData(await getWarningHistoryOverview(),{})};await nextTick();renderChart();await loadPage()}catch(error){errorMessage.value=error?.message||'历史预警概况加载失败,请稍后重试';ElMessage.error(errorMessage.value)}finally{loading.value=false}}
+async function loadData(){loading.value=true;errorMessage.value='';try{ await loadWarningReferences();result.value={...result.value,...dashboardData(await getWarningHistoryOverview(),{})};await nextTick();renderChart();await loadPage()}catch(error){errorMessage.value=error?.message||'历史预警概况加载失败,请稍后重试';ElMessage.error(errorMessage.value)}finally{loading.value=false}}
 onMounted(()=>{loadData();window.addEventListener('resize',resize)});onUnmounted(()=>{window.removeEventListener('resize',resize);chart?.dispose()})
 </script>
 

+ 7 - 7
src/views/subSystem/lifeCompany/lOverviewWarning/Ltoday.vue

@@ -11,12 +11,11 @@
       <button class="metric-card primary" :class="{ active: activeTab === 'all' }" type="button" @click="selectTab('all')"><span class="metric-label">今日预警总量</span><strong>{{ totalCount }}</strong><small>今天发布的全部非草稿预警</small></button>
     </div>
     <el-card shadow="never" class="table-card">
-      <template #header><div class="card-title"><div><span>{{ tabTitle }}</span><em>{{ total }} 条</em></div><div class="filters"><el-select v-model="warningType" clearable placeholder="全部类型" @change="resetPage"><el-option v-for="item in typeOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select><el-select v-model="warningLevel" clearable placeholder="全部级别" @change="resetPage"><el-option v-for="item in levelOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select><el-input v-model="keyword" clearable placeholder="搜索名称、专项或位置" class="search-input" @keyup.enter="resetPage" @clear="resetPage"><template #prefix><el-icon><Search /></el-icon></template></el-input><el-button type="primary" @click="resetPage">查询</el-button></div></div></template>
+      <template #header><div class="card-title"><div><span>{{ tabTitle }}</span><em>{{ total }} 条</em></div><div class="filters"><el-select v-model="warningType" clearable placeholder="全部类型" @change="resetPage"><el-option v-for="item in typeOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select><el-select v-model="warningLevel" clearable placeholder="全部级别" @change="resetPage"><el-option v-for="item in levelOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select><el-input v-model="keyword" clearable placeholder="搜索编号、专项或单位" class="search-input" @keyup.enter="resetPage" @clear="resetPage"><template #prefix><el-icon><Search /></el-icon></template></el-input><el-button type="primary" @click="resetPage">查询</el-button></div></div></template>
       <el-table v-loading="tableLoading" :data="rows" stripe highlight-current-row empty-text="暂无符合条件的预警" @row-click="openDetail">
-        <el-table-column label="预警事项" min-width="190" show-overflow-tooltip><template #default="{ row }">{{ row.warningName || row.warning_name || '未命名预警' }}</template></el-table-column>
+        <el-table-column label="预警编号" min-width="190" show-overflow-tooltip><template #default="{ row }">{{ row.warningNo || row.warning_no || '预警编号未生成' }}</template></el-table-column>
         <el-table-column label="预警类型" width="120"><template #default="{ row }">{{ warningTypeText(row) }}</template></el-table-column>
         <el-table-column label="预警专项" min-width="150" show-overflow-tooltip><template #default="{ row }">{{ row.warningSpecial || row.warning_special || '未设置' }}</template></el-table-column>
-        <el-table-column label="位置" min-width="170" show-overflow-tooltip><template #default="{ row }">{{ row.location || '未设置' }}</template></el-table-column>
         <el-table-column label="发布时间" min-width="165"><template #default="{ row }">{{ formatDashboardTime(row.publishTime || row.publish_time || row.createTime) }}</template></el-table-column>
         <el-table-column label="状态" width="105" align="center"><template #default="{ row }"><el-tag :type="warningStatusTag(row)">{{ warningStatusText(row) }}</el-tag></template></el-table-column>
         <el-table-column label="操作" width="90" fixed="right" align="center"><template #default="{ row }"><el-button link type="primary" @click.stop="openDetail(row)">查看详情</el-button></template></el-table-column>
@@ -28,11 +27,12 @@
 </template>
 
 <script setup name="WarningTodayOverview">
+import { loadWarningReferences } from '../lstatistics/statisticsShared'
 import { computed, onMounted, ref } from 'vue'
 import { ElMessage } from 'element-plus'
 import { Refresh, Search } from '@element-plus/icons-vue'
 import { getWarningTodayOverview, pageWarningTodayOverview } from '@/api/warning/dashboard'
-import { warningTypeLabels } from '../lstatistics/statisticsShared'
+import { warningTypeOptions, warningLevelLabels } from '../lstatistics/statisticsShared'
 import WarningDetailDrawer from './WarningDetailDrawer.vue'
 import { dashboardData, formatDashboardTime, pageRecords, pageTotal, warningStatusTag, warningStatusText, warningTypeText } from './dashboardShared'
 
@@ -41,15 +41,15 @@ const stats = ref({ todayTotal: 0, unresolvedCount: 0, resolvedCount: 0 })
 const unresolvedCount = computed(() => Number(stats.value.unresolvedCount || 0))
 const resolvedCount = computed(() => Number(stats.value.resolvedCount || 0))
 const totalCount = computed(() => Number(stats.value.todayTotal || 0))
-const typeOptions = Object.entries(warningTypeLabels).filter(([value]) => ['WATER_PIPE', 'SEWER_PIPE', 'GAS_PIPE', 'MANHOLE'].includes(value)).map(([value, label]) => ({ value, label }))
-const levelOptions = [{ value: '1', label: '蓝色(IV级)' }, { value: '2', label: '黄色(III级)' }, { value: '3', label: '橙色(II级)' }, { value: '4', label: '红色(I级)' }]
+const typeOptions = warningTypeOptions
+const levelOptions = computed(() => Object.entries(warningLevelLabels).map(([value, label]) => ({ value, label })))
 const tabTitle = computed(() => ({ unresolved: '仍未解除预警', resolved: '今日已解除预警', all: '今日全部预警' }[activeTab.value]))
 function resetPage() { pageNum.value = 1; loadPage() }
 function handleSizeChange() { pageNum.value = 1; loadPage() }
 function selectTab(tab) { if (activeTab.value !== tab) { activeTab.value = tab; resetPage() } else { resetPage() } }
 function openDetail(row) { selectedRow.value = row; detailVisible.value = true }
 async function loadPage() { tableLoading.value = true; errorMessage.value = ''; try { const response = await pageWarningTodayOverview({ category: activeTab.value, pageNum: pageNum.value, pageSize: pageSize.value, warningType: warningType.value || undefined, warningLevel: warningLevel.value || undefined, keyword: keyword.value.trim() || undefined }); rows.value = pageRecords(response); total.value = pageTotal(response) } catch (error) { rows.value = []; total.value = 0; errorMessage.value = error?.message || '今日预警明细加载失败'; ElMessage.error(errorMessage.value) } finally { tableLoading.value = false } }
-async function loadData() { loading.value = true; errorMessage.value = ''; try { stats.value = { ...stats.value, ...dashboardData(await getWarningTodayOverview(), {}) }; await loadPage() } catch (error) { errorMessage.value = error?.message || '今日预警概况加载失败,请稍后重试'; ElMessage.error(errorMessage.value) } finally { loading.value = false } }
+async function loadData() { loading.value = true; errorMessage.value = ''; try { await loadWarningReferences(); stats.value = { ...stats.value, ...dashboardData(await getWarningTodayOverview(), {}) }; await loadPage() } catch (error) { errorMessage.value = error?.message || '今日预警概况加载失败,请稍后重试'; ElMessage.error(errorMessage.value) } finally { loading.value = false } }
 onMounted(loadData)
 </script>
 

+ 1 - 2
src/views/subSystem/lifeCompany/lOverviewWarning/WarningDetailDrawer.vue

@@ -3,7 +3,7 @@
     <template v-if="row">
       <div class="detail-hero">
         <div class="detail-kicker">WARNING EVENT</div>
-        <div class="detail-title">{{ detail.warningName }}</div>
+        <div class="detail-title">{{ detail.warningNo }}</div>
         <div class="detail-meta">
           <el-tag :type="levelTag">{{ detail.warningLevel }}</el-tag>
           <el-tag :type="statusTag" effect="plain">{{ detail.status }}</el-tag>
@@ -14,7 +14,6 @@
       <el-descriptions :column="2" border class="detail-descriptions">
         <el-descriptions-item label="预警类型">{{ detail.warningType }}</el-descriptions-item>
         <el-descriptions-item label="预警专项">{{ detail.warningSpecial }}</el-descriptions-item>
-        <el-descriptions-item label="预警位置" :span="2">{{ detail.location }}</el-descriptions-item>
         <el-descriptions-item label="权属单位">{{ detail.ownershipUnit }}</el-descriptions-item>
         <el-descriptions-item label="发布人">{{ detail.publisher }}</el-descriptions-item>
         <el-descriptions-item label="发布时间">{{ detail.publishTime }}</el-descriptions-item>

+ 14 - 42
src/views/subSystem/lifeCompany/lOverviewWarning/dashboardShared.js

@@ -1,29 +1,6 @@
-import { warningTypeLabel } from '../lstatistics/statisticsShared'
-
-export const warningLevelLabels = {
-  // 预警级别编码遵循国家常用颜色规范:1 蓝、2 黄、3 橙、4 红。
-  '1': '蓝色(IV级)',
-  '2': '黄色(III级)',
-  '3': '橙色(II级)',
-  '4': '红色(I级)',
-  I: '红色(I级)',
-  II: '橙色(II级)',
-  III: '黄色(III级)',
-  IV: '蓝色(IV级)',
-  RED: '红色',
-  ORANGE: '橙色',
-  YELLOW: '黄色',
-  BLUE: '蓝色'
-}
-
-export const warningStatusLabels = {
-  DRAFT: '草稿',
-  PENDING: '待处置',
-  RECEIVED: '已接收',
-  PROCESSING: '处置中',
-  HANDLED: '已处置',
-  CLOSED: '已解除'
-}
+import { warningTypeLabel, warningTypeLabels, warningLevelLabels, statusLabels } from '../lstatistics/statisticsShared'
+export { warningLevelLabels }
+export const warningStatusLabels = statusLabels
 
 export function dashboardData(response, fallback = {}) {
   return response?.data ?? fallback
@@ -52,34 +29,29 @@ export function warningTypeText(row) {
 }
 
 export function isSupportedWarningType(row) {
-  return ['供水管网', '排水管网', '燃气管网', '窨井'].includes(warningTypeText(row))
+  return !!warningTypeLabels[listValue(row, 'warningType', 'warning_type')]
 }
 
 export function warningLevelText(row) {
   const value = listValue(row, 'warningLevel', 'warning_level')
-  return warningLevelLabels[String(value)] || value || '未设置'
+  return listValue(row, 'warningLevelName', 'warning_level_name') || warningLevelLabels[String(value)] || value || '未设置'
 }
 
 export function warningLevelCode(row) {
-  const value = String(listValue(row, 'warningLevel', 'warning_level')).toUpperCase()
-  if (['4', 'I', 'RED'].includes(value)) return '4'
-  if (['3', 'II', 'ORANGE'].includes(value)) return '3'
-  if (['2', 'III', 'YELLOW'].includes(value)) return '2'
-  if (['1', 'IV', 'BLUE'].includes(value)) return '1'
-  return ''
+  return String(listValue(row, 'warningLevel', 'warning_level'))
 }
 
 export function warningStatusText(row) {
   const value = listValue(row, 'status', 'warningStatus', 'warning_status')
   const normalizedValue = String(value || '').toUpperCase()
-  return warningStatusLabels[normalizedValue] || value || '未设置'
+  return listValue(row, 'statusName', 'status_name') || warningStatusLabels[normalizedValue] || value || '未设置'
 }
 
 export function warningLevelTag(row) {
   const value = warningLevelCode(row)
-  if (value === '4') return 'danger'
-  if (value === '3' || value === '2') return 'warning'
-  if (value === '1') return 'primary'
+  if (value === '1') return 'danger'
+  if (value === '2' || value === '3') return 'warning'
+  if (value === '4') return 'primary'
   return 'info'
 }
 
@@ -102,12 +74,12 @@ export function formatDashboardTime(value, fallback = '-') {
 export function detailView(row = {}) {
   return {
     warningId: listValue(row, 'warningId', 'warning_id'),
-    warningNo: listValue(row, 'warningNo', 'warning_no'),
-    warningName: listValue(row, 'warningName', 'warning_name') || '未命名预警',
+    warningNo: listValue(row, 'warningNo', 'warning_no') || '预警编号未生成',
     warningType: warningTypeText(row),
     warningLevel: warningLevelText(row),
     warningSpecial: listValue(row, 'warningSpecial', 'warning_special') || '未设置',
-    location: listValue(row, 'location') || '未设置',
+    deviceCode: listValue(row, 'deviceCode', 'device_code') || '',
+    deviceName: listValue(row, 'deviceName', 'device_name') || '',
     ownershipUnit: listValue(row, 'ownershipUnit', 'ownership_unit') || '未设置',
     publisher: listValue(row, 'publisher') || '未设置',
     publishTime: formatDashboardTime(listValue(row, 'publishTime', 'publish_time'), '未设置'),
@@ -123,7 +95,7 @@ export function filterRows(rows, keyword) {
   if (!value) return rows || []
   return (rows || []).filter(row => {
     const detail = detailView(row)
-    return [detail.warningName, detail.warningSpecial, detail.location, detail.ownershipUnit, detail.warningType]
+    return [detail.warningNo, detail.warningSpecial, detail.deviceCode, detail.deviceName, detail.ownershipUnit, detail.warningType]
       .some(item => String(item).toLowerCase().includes(value))
   })
 }

+ 4 - 3
src/views/subSystem/lifeCompany/lhome/lHome.vue

@@ -137,11 +137,11 @@
               </el-tag>
             </template>
           </el-table-column>
-          <el-table-column label="预警事项" min-width="190" show-overflow-tooltip>
+          <el-table-column label="预警编号" min-width="190" show-overflow-tooltip>
             <template #default="{ row }">
               <div class="warning-name">
                 <i :class="`level-${warningLevelCode(row)}`" />
-                <span>{{ listValue(row, 'warningName', 'warning_name') || '未命名预警' }}</span>
+                <span>{{ listValue(row, 'warningNo', 'warning_no') || '预警编号未生成' }}</span>
               </div>
             </template>
           </el-table-column>
@@ -199,6 +199,7 @@
 </template>
 
 <script setup>
+import { loadWarningReferences } from '../lstatistics/statisticsShared'
 import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
 import { useRouter } from 'vue-router'
 import { ElMessage } from 'element-plus'
@@ -469,7 +470,7 @@ async function loadData() {
     }))
   ]
 
-  try {
+  try { await loadWarningReferences();
     const results = await Promise.allSettled(requests.map(item => item.promise))
     const failedLabels = []
     let successCount = 0

+ 1 - 1
src/views/subSystem/lifeCompany/lstatistics/LcallEff.vue

@@ -9,4 +9,4 @@
 
 <style scoped lang="scss">
 
-</style>
+</style>

+ 1 - 1
src/views/subSystem/lifeCompany/lstatistics/LdisposalAnalysis.vue

@@ -15,4 +15,4 @@
 
 <style scoped lang="scss">
 
-</style>
+</style>

+ 1 - 1
src/views/subSystem/lifeCompany/lstatistics/LwarningStatistics.vue

@@ -10,4 +10,4 @@
 
 <style scoped lang="scss">
 
-</style>
+</style>

+ 4 - 3
src/views/subSystem/lifeCompany/lstatistics/disposalEfficiency/index.vue

@@ -4,10 +4,11 @@
     <el-alert v-if="errorMessage" :title="errorMessage" type="error" show-icon closable @close="errorMessage = ''" />
     <div class="metric-grid"><div v-for="metric in metrics" :key="metric.label" class="metric-card"><span>{{ metric.label }}</span><strong>{{ metric.value }}</strong><small>{{ metric.note }}</small></div></div>
     <div class="chart-grid"><el-card shadow="never"><template #header><div class="card-title"><span>处置时效区间</span><em>小时</em></div></template><div ref="rangeRef" class="chart-box" /></el-card><el-card shadow="never"><template #header><div class="card-title"><span>专项平均处置时效</span><em>高时效优先督导</em></div></template><div ref="specialRef" class="chart-box" /></el-card></div>
-    <el-card shadow="never" class="table-card"><template #header><div class="card-title"><span>已处置预警明细</span><em>{{ total }} 条</em></div></template><el-table v-loading="loading" :data="rows" stripe><el-table-column prop="warningNo" label="预警编号" min-width="150"/><el-table-column prop="warningName" label="预警事项" min-width="180" show-overflow-tooltip/><el-table-column label="预警专项" min-width="140"><template #default="{row}">{{ row.warning_special || row.warningSpecial || '-' }}</template></el-table-column><el-table-column label="发布时间" min-width="160"><template #default="{row}">{{ row.publish_time || row.publishTime || '-' }}</template></el-table-column><el-table-column label="处置时长" width="120"><template #default="{row}"><b>{{ row.dispose_hours ?? row.disposeHours ?? '-' }}</b> 小时</template></el-table-column><el-table-column label="状态" width="100"><template #default="{row}"><el-tag type="success">{{ row.status === 'CLOSED' ? '已解除' : '已处置' }}</el-tag></template></el-table-column></el-table><pagination v-show="total > 0" v-model:page="query.pageNum" v-model:limit="query.pageSize" :total="total" @pagination="loadPage" /></el-card>
+    <el-card shadow="never" class="table-card"><template #header><div class="card-title"><span>已处置预警明细</span><em>{{ total }} 条</em></div></template><el-table v-loading="loading" :data="rows" stripe><el-table-column prop="warningNo" label="预警编号" min-width="150"/><el-table-column label="预警专项" min-width="140"><template #default="{row}">{{ row.warning_special || row.warningSpecial || '-' }}</template></el-table-column><el-table-column label="发布时间" min-width="160"><template #default="{row}">{{ row.publish_time || row.publishTime || '-' }}</template></el-table-column><el-table-column label="处置时长" width="120"><template #default="{row}"><b>{{ row.dispose_hours ?? row.disposeHours ?? '-' }}</b> 小时</template></el-table-column><el-table-column label="状态" width="100"><template #default="{row}"><el-tag type="success">{{ row.status === 'CLOSED' ? '已解除' : '已处置' }}</el-tag></template></el-table-column></el-table><pagination v-show="total > 0" v-model:page="query.pageNum" v-model:limit="query.pageSize" :total="total" @pagination="loadPage" /></el-card>
   </div>
 </template>
 <script setup name="WarningDisposeEfficiency">
+import { loadWarningReferences } from '../statisticsShared'
 import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
 import { ElMessage } from 'element-plus'
 import { Refresh } from '@element-plus/icons-vue'
@@ -18,8 +19,8 @@ const dateRange=ref(defaultRange()); const warningSpecial=ref(''); const sortTyp
 const value = (key, fallback='-') => overview.value[key] ?? overview.value[key.replace(/_([a-z])/g, (_,c)=>c.toUpperCase())] ?? fallback
 const metrics=computed(()=>[{label:'平均处置时长',value:safeNumber(value('avg_hours'),2),note:'小时'},{label:'最长处置时长',value:safeNumber(value('max_hours'),2),note:'小时'},{label:'最短处置时长',value:safeNumber(value('min_hours'),2),note:'小时'},{label:'完成处置数',value:value('total_count',0),note:'已处置/已解除'}])
 function renderCharts(){if(!rangeRef.value||!specialRef.value)return;rangeChart ||= echarts.init(rangeRef.value);specialChart ||= echarts.init(specialRef.value);rangeChart.setOption({tooltip:{trigger:'axis'},grid:{left:45,right:18,top:22,bottom:38},xAxis:{type:'category',data:rangeRows.value.map(r=>r.time_range||r.timeRange)},yAxis:{type:'value',minInterval:1},series:[{type:'bar',barWidth:34,data:rangeRows.value.map(r=>Number(r.warning_count??r.warningCount??0)),itemStyle:{color:'#2563eb',borderRadius:[6,6,0,0]}}]});specialChart.setOption({tooltip:{trigger:'axis'},grid:{left:55,right:18,top:22,bottom:54},xAxis:{type:'category',data:specialRows.value.map(r=>r.warning_special||r.warningSpecial||'未设置'),axisLabel:{rotate:25}},yAxis:{type:'value',name:'小时'},series:[{type:'bar',barWidth:28,data:specialRows.value.map(r=>Number(r.avg_dispose_hours??r.avgDisposeHours??0)),itemStyle:{color:'#0f766e',borderRadius:[6,6,0,0]}}]})}
-async function loadData(){loading.value=true;errorMessage.value='';try{const params={...rangeParams(dateRange.value),warningSpecial:warningSpecial.value||undefined};const [a,b,c]=await Promise.all([getDisposeEfficiencyOverview(params),getDisposeEfficiencyRange(params),getDisposeEfficiencySpecial(params)]);overview.value=responseData(a,{});rangeRows.value=responseData(b,[]);specialRows.value=responseData(c,[]);await loadPage();await nextTick();renderCharts()}catch(error){errorMessage.value=error?.message||'统计数据加载失败';ElMessage.error(errorMessage.value)}finally{loading.value=false}}
-async function loadPage(){const res=await pageDisposeEfficiency({...rangeParams(dateRange.value),warningSpecial:warningSpecial.value||undefined,sortType:sortType.value,...query.value});rows.value=rowsOf(res).map(row=>({...row,warningNo:row.warningNo??row.warning_no,warningName:row.warningName??row.warning_name}));total.value=totalOf(res)}
+async function loadData(){loading.value=true;errorMessage.value='';try{ await loadWarningReferences();const params={...rangeParams(dateRange.value),warningSpecial:warningSpecial.value||undefined};const [a,b,c]=await Promise.all([getDisposeEfficiencyOverview(params),getDisposeEfficiencyRange(params),getDisposeEfficiencySpecial(params)]);overview.value=responseData(a,{});rangeRows.value=responseData(b,[]);specialRows.value=responseData(c,[]);await loadPage();await nextTick();renderCharts()}catch(error){errorMessage.value=error?.message||'统计数据加载失败';ElMessage.error(errorMessage.value)}finally{loading.value=false}}
+async function loadPage(){const res=await pageDisposeEfficiency({...rangeParams(dateRange.value),warningSpecial:warningSpecial.value||undefined,sortType:sortType.value,...query.value});rows.value=rowsOf(res).map(row=>({...row,warningNo:row.warningNo??row.warning_no}));total.value=totalOf(res)}
 function resize(){rangeChart?.resize();specialChart?.resize()};onMounted(()=>{loadData();window.addEventListener('resize',resize)});onUnmounted(()=>{window.removeEventListener('resize',resize);rangeChart?.dispose();specialChart?.dispose()})
 </script>
 <style scoped lang="scss">.statistics-page{padding:22px;background:#f4f7fb;min-height:calc(100vh - 84px);color:#172b4d}.page-head{display:flex;justify-content:space-between;align-items:flex-end;margin-bottom:18px}.eyebrow{font-size:11px;letter-spacing:2px;color:#0f766e}.page-head h1{margin:6px 0 4px;font-size:26px}.page-head p{margin:0;color:#718096}.filter-card{display:flex;gap:12px;align-items:center;margin-bottom:16px}.special-input{width:190px}.sort-select{width:150px}.metric-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-bottom:16px}.metric-card{padding:18px 20px;background:#fff;border:1px solid #e6ebf2;border-radius:8px;display:flex;flex-direction:column;gap:8px}.metric-card span{font-size:13px;color:#718096}.metric-card strong{font-size:26px;color:#172b4d}.metric-card small{color:#9aa7b8}.chart-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px}.card-title{display:flex;justify-content:space-between;font-weight:600}.card-title em{font-style:normal;font-size:12px;color:#94a3b8;font-weight:400}.chart-box{height:290px}.table-card{margin-bottom:20px}@media(max-width:900px){.metric-grid,.chart-grid{grid-template-columns:1fr 1fr}.filter-card{flex-wrap:wrap}}@media(max-width:600px){.metric-grid,.chart-grid{grid-template-columns:1fr}.filter-card>*{width:100%!important}.page-head{align-items:flex-start;gap:12px;flex-direction:column}}</style>

+ 2 - 1
src/views/subSystem/lifeCompany/lstatistics/disposalStatus/index.vue

@@ -8,6 +8,7 @@
   </div>
 </template>
 <script setup name="WarningDisposeStatus">
+import { loadWarningReferences } from '../statisticsShared'
 import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
 import { ElMessage } from 'element-plus'
 import { Refresh } from '@element-plus/icons-vue'
@@ -18,7 +19,7 @@ const dateRange = ref(defaultRange()); const warningSpecial = ref(''); const loa
 const count = rows => rows.reduce((total, row) => total + Number(row.status_count ?? row.statusCount ?? row.disposal_count ?? row.disposalCount ?? 0), 0)
 const metrics = computed(() => [{ label: '统计预警数', value: count(statusRows.value), note: '当前筛选周期' }, { label: '状态类型', value: statusRows.value.length, note: '非草稿状态' }, { label: '处置动作数', value: count(typeRows.value), note: '已记录动作' }, { label: '主要状态', value: statusRows.value[0] ? labelOf(statusLabels, statusRows.value[0].status) : '-', note: '数量最多' }])
 function renderCharts() { if (!statusChartRef.value || !typeChartRef.value) return; statusChart ||= echarts.init(statusChartRef.value); typeChart ||= echarts.init(typeChartRef.value); statusChart.setOption({ color: ['#2563eb', '#0f766e', '#f59e0b', '#ef4444'], tooltip: { trigger: 'item' }, series: [{ type: 'pie', radius: ['45%', '72%'], label: { formatter: '{b}\n{c} 条' }, data: statusRows.value.map(row => ({ name: labelOf(statusLabels, row.status), value: Number(row.status_count ?? row.statusCount ?? 0) })) }] }); typeChart.setOption({ color: ['#2563eb', '#0f766e', '#f59e0b', '#8b5cf6'], tooltip: { trigger: 'axis' }, grid: { left: 44, right: 24, top: 24, bottom: 36 }, xAxis: { type: 'category', data: typeRows.value.map(row => labelOf(disposalTypeLabels, row.disposal_type ?? row.disposalType)), axisLabel: { interval: 0 } }, yAxis: { type: 'value', minInterval: 1 }, series: [{ type: 'bar', barWidth: 32, data: typeRows.value.map(row => Number(row.disposal_count ?? row.disposalCount ?? 0)), itemStyle: { borderRadius: [6, 6, 0, 0] } }] }) }
-async function loadData() { loading.value = true; errorMessage.value = ''; try { const params = { ...rangeParams(dateRange.value), warningSpecial: warningSpecial.value || undefined }; const [statusResponse, typeResponse] = await Promise.all([getDisposeStatusStat(params), getDisposalTypeStat(params)]); statusRows.value = responseData(statusResponse, []); typeRows.value = responseData(typeResponse, []); await nextTick(); renderCharts() } catch (error) { errorMessage.value = error?.message || '统计数据加载失败'; ElMessage.error(errorMessage.value) } finally { loading.value = false } }
+async function loadData() { loading.value = true; errorMessage.value = ''; try { await loadWarningReferences(); const params = { ...rangeParams(dateRange.value), warningSpecial: warningSpecial.value || undefined }; const [statusResponse, typeResponse] = await Promise.all([getDisposeStatusStat(params), getDisposalTypeStat(params)]); statusRows.value = responseData(statusResponse, []); typeRows.value = responseData(typeResponse, []); await nextTick(); renderCharts() } catch (error) { errorMessage.value = error?.message || '统计数据加载失败'; ElMessage.error(errorMessage.value) } finally { loading.value = false } }
 function reset() { dateRange.value = defaultRange(); warningSpecial.value = ''; loadData() }
 function resize() { statusChart?.resize(); typeChart?.resize() }
 onMounted(() => { loadData(); window.addEventListener('resize', resize) }); onUnmounted(() => { window.removeEventListener('resize', resize); statusChart?.dispose(); typeChart?.dispose() })

+ 11 - 14
src/views/subSystem/lifeCompany/lstatistics/industryAnalysis/index.vue

@@ -64,7 +64,7 @@
       <el-table v-loading="loading || tableLoading" :data="rows" stripe empty-text="当前筛选条件暂无数据">
         <el-table-column prop="industryName" label="行业" min-width="110" />
         <el-table-column prop="warningNo" label="预警编号" min-width="155" />
-        <el-table-column prop="warningName" label="预警事项" min-width="180" show-overflow-tooltip />
+
         <el-table-column label="级别" width="80" align="center">
           <template #default="{ row }"><el-tag :type="levelTag(row.warningLevel)">{{ levelLabel(row.warningLevel) }}</el-tag></template>
         </el-table-column>
@@ -83,6 +83,7 @@
 </template>
 
 <script setup name="WarningIndustryAnalysis">
+import { loadWarningReferences } from '../statisticsShared'
 import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
 import { ElMessage } from 'element-plus'
 import { Refresh } from '@element-plus/icons-vue'
@@ -93,7 +94,7 @@ import {
   getIndustryAnalysisSummary,
   pageIndustryAnalysis
 } from '@/api/warning/statistics'
-import { defaultRange, formatDateTime, rangeParams, responseData, rowsOf, totalOf } from '../statisticsShared'
+import { defaultRange, formatDateTime, rangeParams, responseData, rowsOf, totalOf, statusLabels, warningLevelLabels } from '../statisticsShared'
 
 const industryOptions = [
   { value: 'water_supply', label: '供水管网' },
@@ -101,13 +102,9 @@ const industryOptions = [
   { value: 'gas', label: '燃气管网' },
   { value: 'manhole', label: '窨井' }
 ]
-const analysisStatusLabels = {
-  PENDING: '已发布(待接收)',
-  RECEIVED: '已接收',
-  PROCESSING: '处置中',
-  HANDLED: '已处置(待核查)',
-  CLOSED: '已解除'
-}
+const analysisStatusLabels = computed(() => Object.fromEntries(
+  Object.entries(statusLabels).filter(([value]) => value !== 'DRAFT')
+))
 const dateRange = ref(defaultRange())
 const industryCode = ref('')
 const status = ref('')
@@ -140,8 +137,8 @@ const metrics = computed(() => {
   ]
 })
 
-const statusLabel = value => analysisStatusLabels[value === 'RESOLVED' ? 'CLOSED' : value] || value || '未设置'
-const levelLabel = value => ({ 1: '一级', 2: '二级', 3: '三级', 4: '四级' }[String(value)] || value || '-')
+const statusLabel = value => statusLabels[value] || value || '未设置'
+const levelLabel = value => warningLevelLabels[String(value)] || value || '-'
 const levelTag = value => ({ 1: 'danger', 2: 'warning', 3: 'success', 4: 'info' }[String(value)] || 'info')
 
 function params() {
@@ -153,7 +150,7 @@ function renderCharts() {
   if (statusRows.value.length) statusChart ||= echarts.init(statusChartRef.value)
   if (efficiencyRows.value.length) efficiencyChart ||= echarts.init(efficiencyChartRef.value)
   const industries = [...new Set(statusRows.value.map(row => row.industry_name || row.industryName || '未设置'))]
-  const statuses = ['PENDING', 'RECEIVED', 'PROCESSING', 'HANDLED', 'CLOSED']
+  const statuses = Object.keys(analysisStatusLabels.value)
   statusChart?.setOption({
     tooltip: { trigger: 'axis' },
     legend: { type: 'scroll', top: 0, data: statuses.map(statusLabel) },
@@ -196,7 +193,7 @@ async function loadPage() {
       ...row,
       industryName: row.industryName ?? row.industry_name,
       warningNo: row.warningNo ?? row.warning_no,
-      warningName: row.warningName ?? row.warning_name,
+
       warningLevel: row.warningLevel ?? row.warning_level,
       deviceName: row.deviceName ?? row.device_name,
       deviceCode: row.deviceCode ?? row.device_code,
@@ -217,7 +214,7 @@ async function loadData() {
   loading.value = true
   errorMessage.value = ''
   query.value.pageNum = 1
-  try {
+  try { await loadWarningReferences();
     const [summaryResponse, statusResponse, efficiencyResponse] = await Promise.all([
       getIndustryAnalysisSummary(params()),
       getIndustryAnalysisStatus(params()),

+ 4 - 3
src/views/subSystem/lifeCompany/lstatistics/receiveEfficiency/index.vue

@@ -4,10 +4,11 @@
     <el-alert v-if="errorMessage" :title="errorMessage" type="error" show-icon closable @close="errorMessage = ''" />
     <div class="metric-grid"><div v-for="metric in metrics" :key="metric.label" class="metric-card"><span>{{ metric.label }}</span><strong>{{ metric.value }}</strong><small>{{ metric.note }}</small></div></div>
     <div class="chart-grid"><el-card shadow="never"><template #header><div class="card-title"><span>接警时效区间</span><em>从发布时间至首次接收</em></div></template><div ref="rangeRef" class="chart-box" /></el-card><el-card shadow="never"><template #header><div class="card-title"><span>按类型平均接警时效</span><em>小时</em></div></template><div ref="typeRef" class="chart-box" /></el-card></div>
-    <el-card shadow="never"><template #header><div class="card-title"><span>接警效率明细</span><em>{{ total }} 条</em></div></template><el-table v-loading="loading" :data="rows" stripe><el-table-column prop="warningNo" label="预警编号" min-width="150"/><el-table-column prop="warningName" label="预警事项" min-width="180" show-overflow-tooltip/><el-table-column label="类型" min-width="120"><template #default="{row}">{{ typeLabel(row.warning_type||row.warningType) }}</template></el-table-column><el-table-column label="首次接警" min-width="160"><template #default="{row}">{{ row.receive_time||row.receiveTime||'-' }}</template></el-table-column><el-table-column label="接警时长" width="120"><template #default="{row}"><b>{{ row.receive_hours??row.receiveHours??'-' }}</b> 小时</template></el-table-column><el-table-column label="状态" width="100"><template #default="{row}"><el-tag>{{ statusLabels[row.status]||row.status }}</el-tag></template></el-table-column></el-table><pagination v-show="total > 0" v-model:page="query.pageNum" v-model:limit="query.pageSize" :total="total" @pagination="loadPage" /></el-card>
+    <el-card shadow="never"><template #header><div class="card-title"><span>接警效率明细</span><em>{{ total }} 条</em></div></template><el-table v-loading="loading" :data="rows" stripe><el-table-column prop="warningNo" label="预警编号" min-width="150"/><el-table-column label="类型" min-width="120"><template #default="{row}">{{ typeLabel(row.warning_type||row.warningType) }}</template></el-table-column><el-table-column label="首次接警" min-width="160"><template #default="{row}">{{ row.receive_time||row.receiveTime||'-' }}</template></el-table-column><el-table-column label="接警时长" width="120"><template #default="{row}"><b>{{ row.receive_hours??row.receiveHours??'-' }}</b> 小时</template></el-table-column><el-table-column label="状态" width="100"><template #default="{row}"><el-tag>{{ statusLabels[row.status]||row.status }}</el-tag></template></el-table-column></el-table><pagination v-show="total > 0" v-model:page="query.pageNum" v-model:limit="query.pageSize" :total="total" @pagination="loadPage" /></el-card>
   </div>
 </template>
 <script setup name="WarningReceiveEfficiency">
+import { loadWarningReferences } from '../statisticsShared'
 import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
 import { ElMessage } from 'element-plus'
 import { Refresh } from '@element-plus/icons-vue'
@@ -17,8 +18,8 @@ import { defaultRange, labelOf, rangeParams, responseData, rowsOf, safeNumber, s
 const dateRange=ref(defaultRange());const warningType=ref('');const warningSpecial=ref('');const status=ref('');const loading=ref(false);const errorMessage=ref('');const overview=ref({});const rangeRows=ref([]);const typeRows=ref([]);const rows=ref([]);const total=ref(0);const query=ref({pageNum:1,pageSize:10});const rangeRef=ref();const typeRef=ref();let rangeChart;let typeChart
 const typeOptions=warningTypeOptions;const typeLabel=value=>labelOf(warningTypeLabels,value);const read=(key, fallback='-')=>overview.value[key]??overview.value[key.replace(/_([a-z])/g,(_,c)=>c.toUpperCase())]??fallback;const metrics=computed(()=>[{label:'平均接警时长',value:safeNumber(read('avg_hours'),2),note:'小时'},{label:'最长接警时长',value:safeNumber(read('max_hours'),2),note:'小时'},{label:'最短接警时长',value:safeNumber(read('min_hours'),2),note:'小时'},{label:'有效接警数',value:read('total_count',0),note:'已接收预警'}])
 function render(){if(!rangeRef.value||!typeRef.value)return;rangeChart ||= echarts.init(rangeRef.value);typeChart ||= echarts.init(typeRef.value);rangeChart.setOption({tooltip:{trigger:'axis'},grid:{left:46,right:18,top:22,bottom:38},xAxis:{type:'category',data:rangeRows.value.map(r=>r.time_range||r.timeRange)},yAxis:{type:'value',minInterval:1},series:[{type:'bar',barWidth:32,data:rangeRows.value.map(r=>Number(r.warning_count??r.warningCount??0)),itemStyle:{color:'#2563eb',borderRadius:[6,6,0,0]}}]});typeChart.setOption({tooltip:{trigger:'axis'},grid:{left:55,right:18,top:22,bottom:54},xAxis:{type:'category',data:typeRows.value.map(r=>typeLabel(r.warning_type||r.warningType)),axisLabel:{rotate:25}},yAxis:{type:'value',name:'小时'},series:[{type:'bar',barWidth:28,data:typeRows.value.map(r=>Number(r.avg_receive_hours??r.avgReceiveHours??0)),itemStyle:{color:'#dc2626',borderRadius:[6,6,0,0]}}]})}
-async function loadData(){loading.value=true;errorMessage.value='';try{const params={...rangeParams(dateRange.value),warningType:warningType.value||undefined,warningSpecial:warningSpecial.value||undefined,status:status.value||undefined};const [a,b,c]=await Promise.all([getReceiveEfficiencyOverview(params),getReceiveEfficiencyRange(params),getReceiveEfficiencyType(params)]);overview.value=responseData(a,{});rangeRows.value=responseData(b,[]);typeRows.value=responseData(c,[]);await loadPage();await nextTick();render()}catch(error){errorMessage.value=error?.message||'接警效率加载失败';ElMessage.error(errorMessage.value)}finally{loading.value=false}}
-async function loadPage(){const res=await pageReceiveEfficiency({...rangeParams(dateRange.value),warningType:warningType.value||undefined,warningSpecial:warningSpecial.value||undefined,status:status.value||undefined,sortType:'desc',...query.value});rows.value=rowsOf(res).map(row=>({...row,warningNo:row.warningNo??row.warning_no,warningName:row.warningName??row.warning_name}));total.value=totalOf(res)}
+async function loadData(){loading.value=true;errorMessage.value='';try{ await loadWarningReferences();const params={...rangeParams(dateRange.value),warningType:warningType.value||undefined,warningSpecial:warningSpecial.value||undefined,status:status.value||undefined};const [a,b,c]=await Promise.all([getReceiveEfficiencyOverview(params),getReceiveEfficiencyRange(params),getReceiveEfficiencyType(params)]);overview.value=responseData(a,{});rangeRows.value=responseData(b,[]);typeRows.value=responseData(c,[]);await loadPage();await nextTick();render()}catch(error){errorMessage.value=error?.message||'接警效率加载失败';ElMessage.error(errorMessage.value)}finally{loading.value=false}}
+async function loadPage(){const res=await pageReceiveEfficiency({...rangeParams(dateRange.value),warningType:warningType.value||undefined,warningSpecial:warningSpecial.value||undefined,status:status.value||undefined,sortType:'desc',...query.value});rows.value=rowsOf(res).map(row=>({...row,warningNo:row.warningNo??row.warning_no}));total.value=totalOf(res)}
 function resize(){rangeChart?.resize();typeChart?.resize()};onMounted(()=>{loadData();window.addEventListener('resize',resize)});onUnmounted(()=>{window.removeEventListener('resize',resize);rangeChart?.dispose();typeChart?.dispose()})
 </script>
 <style scoped lang="scss">.statistics-page{padding:22px;background:#f4f7fb;min-height:calc(100vh - 84px);color:#172b4d}.page-head{display:flex;justify-content:space-between;align-items:flex-end;margin-bottom:18px}.eyebrow{font-size:11px;letter-spacing:2px;color:#dc2626}.page-head h1{margin:6px 0 4px;font-size:26px}.page-head p{margin:0;color:#718096}.filter-card{display:flex;gap:12px;align-items:center;margin-bottom:16px}.filter-select{width:150px}.special-input{width:180px}.metric-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-bottom:16px}.metric-card{padding:18px 20px;background:#fff;border:1px solid #e6ebf2;border-radius:8px;display:flex;flex-direction:column;gap:8px}.metric-card span{font-size:13px;color:#718096}.metric-card strong{font-size:26px;color:#172b4d}.metric-card small{color:#9aa7b8}.chart-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px}.card-title{display:flex;justify-content:space-between;font-weight:600}.card-title em{font-style:normal;font-size:12px;color:#94a3b8;font-weight:400}.chart-box{height:290px}@media(max-width:1000px){.filter-card{flex-wrap:wrap}.metric-grid,.chart-grid{grid-template-columns:1fr 1fr}}@media(max-width:600px){.metric-grid,.chart-grid{grid-template-columns:1fr}.filter-card>*{width:100%!important}.page-head{align-items:flex-start;gap:12px;flex-direction:column}}</style>

+ 26 - 47
src/views/subSystem/lifeCompany/lstatistics/statisticsShared.js

@@ -1,55 +1,34 @@
-export const warningTypeLabels = {
-  WATER_PIPE: '供水管网',
-  SEWER_PIPE: '排水管网',
-  GAS_PIPE: '燃气管网',
-  MANHOLE: '窨井',
-  '供水': '供水管网',
-  '供水管网': '供水管网',
-  '供水管网预警': '供水管网',
-  '排水': '排水管网',
-  '排水管网': '排水管网',
-  '排水管网预警': '排水管网',
-  '燃气': '燃气管网',
-  '燃气管网': '燃气管网',
-  '燃气管网预警': '燃气管网',
-  '窨井预警': '窨井'
-}
-
-// 业务范围固定为四类城市生命线设施;别名仅用于兼容历史数据,不在筛选器中重复展示。
-export const warningTypeOptions = [
-  { value: 'WATER_PIPE', label: '供水管网' },
-  { value: 'SEWER_PIPE', label: '排水管网' },
-  { value: 'GAS_PIPE', label: '燃气管网' },
-  { value: 'MANHOLE', label: '窨井' }
-]
+import { reactive } from 'vue'
+import request from '@/utils/request'
 
-export const statusLabels = {
-  DRAFT: '草稿',
-  PENDING: '待处置',
-  RECEIVED: '已接收',
-  PROCESSING: '处置中',
-  HANDLED: '已处置',
-  CLOSED: '已解除'
+export const warningTypeLabels = reactive({})
+export const warningTypeOptions = reactive([])
+export const statusLabels = reactive({})
+export const warningLevelLabels = reactive({})
+let referenceRequest
+export function loadWarningReferences() {
+  if (!referenceRequest) referenceRequest = Promise.all([
+    request({ url: '/warning/config/types', method: 'get' }),
+    request({ url: '/warning/config/statuses', method: 'get' }),
+    request({ url: '/system/dict/data/type/alert_level', method: 'get' })
+  ]).then(([types, statuses, levels]) => {
+    const typeList = types.data || []
+    warningTypeOptions.splice(0, warningTypeOptions.length, ...typeList.map(d => ({ value: d.dictValue, label: d.dictLabel })))
+    for (const map of [warningTypeLabels, statusLabels, warningLevelLabels]) Object.keys(map).forEach(k => delete map[k])
+    typeList.forEach(d => { warningTypeLabels[d.dictValue] = d.dictLabel })
+    ;(statuses.data || []).forEach(d => { statusLabels[d.dictValue] = d.dictLabel })
+    ;(levels.data || []).forEach(d => { warningLevelLabels[d.dictValue] = d.dictLabel })
+  }).catch(error => { referenceRequest = undefined; throw error })
+  return referenceRequest
 }
 
 export const disposalTypeLabels = {
-  RELEASE: '发布处置',
-  RESOLVE: '解除预警',
-  RETURN: '退回重办',
-  UPGRADE: '升级预警'
-}
-
-export function labelOf(map, value) {
-  const legacyTypeLabels = { '1': '供水管网', '2': '排水管网', '3': '燃气管网', '4': '窨井' }
-  const normalizedValue = value === undefined || value === null ? '' : String(value).toUpperCase()
-  return map[value] || map[normalizedValue] || (map === warningTypeLabels ? legacyTypeLabels[String(value)] : undefined) || value || '未设置'
-}
-
-export function warningTypeLabel(value) {
-  if (value === undefined || value === null || value === '') return '未设置'
-  const legacyLabels = { '1': '供水管网', '2': '排水管网', '3': '燃气管网', '4': '窨井' }
-  return warningTypeLabels[value] || legacyLabels[String(value)] || (Object.values(warningTypeLabels).includes(value) ? value : '未设置')
+  RELEASE: '发布预警', RECEIVE: '接收预警', START: '开始处置', HANDLE: '提交处置结果',
+  RESOLVE: '解除预警', CLEAR: '核查解除', AUTO_CLEAR: '系统自动解除',
+  RETURN: '退回重办', UPGRADE: '升级预警', SUPERVISION: '预警督办', INSTRUCTION: '领导批示', REPORT: '上传报告'
 }
+export function labelOf(map, value) { return map[value] || value || '未设置' }
+export function warningTypeLabel(value) { return warningTypeLabels[value] || value || '未设置' }
 
 export function responseData(response, fallback = []) {
   return response?.data ?? fallback

+ 3 - 2
src/views/subSystem/lifeCompany/lstatistics/today/index.vue

@@ -1,10 +1,11 @@
 <template>
   <div class="statistics-page"><section class="page-head"><div><span class="eyebrow">LIVE WARNING DESK</span><h1>今日预警统计</h1><p>快速查看今日非草稿预警及处置进展。</p></div><el-button type="primary" :loading="loading" @click="loadData"><el-icon><Refresh /></el-icon>刷新数据</el-button></section>
     <div class="metric-grid"><button v-for="metric in metricCards" :key="metric.key" class="metric-card" :class="{active: activeStatus === metric.status}" @click="selectStatus(metric.status)"><span>{{ metric.label }}</span><strong>{{ metric.value }}</strong><small>{{ metric.note }}</small></button></div>
-    <el-card shadow="never" class="table-card"><template #header><div class="card-title"><span>{{ activeStatus ? statusLabels[activeStatus] : '今日全部预警' }}</span><div><el-button text @click="selectStatus('')">全部</el-button><el-button type="primary" plain @click="loadData">刷新</el-button></div></div></template><el-table v-loading="loading" :data="rows" stripe empty-text="今日暂无预警"><el-table-column prop="warningNo" label="预警编号" min-width="150"/><el-table-column prop="warningName" label="预警事项" min-width="190" show-overflow-tooltip/><el-table-column prop="warningType" label="预警类型" min-width="120"/><el-table-column prop="warningSpecial" label="预警专项" min-width="140"/><el-table-column prop="publishTime" label="发布时间" min-width="165"/><el-table-column label="处置状态" width="110"><template #default="{row}"><el-tag :type="row.status === 'CLOSED' ? 'success' : row.status === 'HANDLED' ? 'primary' : 'warning'">{{ statusLabels[row.status] || row.status }}</el-tag></template></el-table-column></el-table><pagination v-show="total > 0" v-model:page="query.pageNum" v-model:limit="query.pageSize" :total="total" @pagination="loadPage" /></el-card>
+    <el-card shadow="never" class="table-card"><template #header><div class="card-title"><span>{{ activeStatus ? statusLabels[activeStatus] : '今日全部预警' }}</span><div><el-button text @click="selectStatus('')">全部</el-button><el-button type="primary" plain @click="loadData">刷新</el-button></div></div></template><el-table v-loading="loading" :data="rows" stripe empty-text="今日暂无预警"><el-table-column prop="warningNo" label="预警编号" min-width="150"/><el-table-column prop="warningType" label="预警类型" min-width="120"/><el-table-column prop="warningSpecial" label="预警专项" min-width="140"/><el-table-column prop="publishTime" label="发布时间" min-width="165"/><el-table-column label="处置状态" width="110"><template #default="{row}"><el-tag :type="row.status === 'CLOSED' ? 'success' : row.status === 'HANDLED' ? 'primary' : 'warning'">{{ statusLabels[row.status] || row.status }}</el-tag></template></el-table-column></el-table><pagination v-show="total > 0" v-model:page="query.pageNum" v-model:limit="query.pageSize" :total="total" @pagination="loadPage" /></el-card>
   </div>
 </template>
 <script setup name="WarningToday">
+import { loadWarningReferences } from '../statisticsShared'
 import { computed, onMounted, ref } from 'vue'
 import { ElMessage } from 'element-plus'
 import { Refresh } from '@element-plus/icons-vue'
@@ -13,7 +14,7 @@ import { responseData, rowsOf, statusLabels, totalOf, warningTypeLabel } from '.
 const loading=ref(false);const errorMessage=ref('');const stats=ref({});const rows=ref([]);const total=ref(0);const activeStatus=ref('');const query=ref({pageNum:1,pageSize:10})
 const read=(...keys)=>{for(const key of keys){if(stats.value[key] !== undefined)return Number(stats.value[key])}return 0}
 const metricCards=computed(()=>[{key:'total',label:'今日预警',value:read('today_total','todayTotal'),note:'非草稿状态',status:''},{key:'handled',label:'已处置',value:read('handled_today','handledToday'),note:'完成处置',status:'HANDLED'},{key:'closed',label:'已解除',value:read('closed_today','closedToday'),note:'解除预警',status:'CLOSED'}])
-async function loadData(){loading.value=true;errorMessage.value='';try{const res=await getTodayWarningStats();stats.value=responseData(res,{});await loadPage()}catch(error){errorMessage.value=error?.message||'今日预警加载失败';ElMessage.error(errorMessage.value)}finally{loading.value=false}}
+async function loadData(){loading.value=true;errorMessage.value='';try{ await loadWarningReferences();const res=await getTodayWarningStats();stats.value=responseData(res,{});await loadPage()}catch(error){errorMessage.value=error?.message||'今日预警加载失败';ElMessage.error(errorMessage.value)}finally{loading.value=false}}
 async function loadPage(){const res=await pageTodayWarnings({...query.value,status:activeStatus.value||undefined});rows.value=rowsOf(res).map(row=>({...row,warningType:warningTypeLabel(row.warningType??row.warning_type)}));total.value=totalOf(res)}
 function selectStatus(status){activeStatus.value=status;query.value.pageNum=1;loadPage()};onMounted(loadData)
 </script>

+ 2 - 1
src/views/subSystem/lifeCompany/lstatistics/trend/index.vue

@@ -6,6 +6,7 @@
   </div>
 </template>
 <script setup name="WarningTrend">
+import { loadWarningReferences } from '../statisticsShared'
 import { nextTick, onMounted, onUnmounted, ref } from 'vue'
 import { ElMessage } from 'element-plus'
 import { Refresh } from '@element-plus/icons-vue'
@@ -14,7 +15,7 @@ import { getWarningTrendByDay, getWarningTrendByMonth } from '@/api/warning/stat
 import { defaultRange, rangeParams, responseData } from '../statisticsShared'
 const granularity=ref('day');const dateRange=ref(defaultRange(30));const warningSpecial=ref('');const loading=ref(false);const errorMessage=ref('');const rows=ref([]);const chartRef=ref();let chart
 function render(){if(!chartRef.value)return;chart ||= echarts.init(chartRef.value);const dateKey=granularity.value==='day'?'stat_date':'stat_month';const dateCamelKey=granularity.value==='day'?'statDate':'statMonth';const readDate=row=>row[dateKey]??row[dateCamelKey]??'';const dates=[...new Set(rows.value.map(readDate))].filter(Boolean);const specials=[...new Set(rows.value.map(r=>r.warning_special||r.warningSpecial||'未设置'))];chart.setOption({tooltip:{trigger:'axis'},legend:{top:0,data:specials},grid:{left:48,right:22,top:42,bottom:38},xAxis:{type:'category',boundaryGap:false,data:dates},yAxis:{type:'value',minInterval:1,name:'数量'},series:specials.map((special,index)=>({name:special,type:'line',smooth:true,symbol:'circle',symbolSize:7,data:dates.map(date=>{const row=rows.value.find(item=>readDate(item)===date&&(item.warning_special||item.warningSpecial||'未设置')===special);return Number(row?.warning_count??row?.warningCount??0)}),lineStyle:{width:3},itemStyle:{color:['#2563eb','#0f766e','#f59e0b','#ef4444','#8b5cf6'][index%5]}}))})}
-async function loadData(){loading.value=true;errorMessage.value='';try{const params={...rangeParams(dateRange.value),warningSpecial:warningSpecial.value||undefined};const res=granularity.value==='day'?await getWarningTrendByDay(params):await getWarningTrendByMonth(params);rows.value=responseData(res,[]);await nextTick();render()}catch(error){errorMessage.value=error?.message||'趋势数据加载失败';ElMessage.error(errorMessage.value)}finally{loading.value=false}}
+async function loadData(){loading.value=true;errorMessage.value='';try{ await loadWarningReferences();const params={...rangeParams(dateRange.value),warningSpecial:warningSpecial.value||undefined};const res=granularity.value==='day'?await getWarningTrendByDay(params):await getWarningTrendByMonth(params);rows.value=responseData(res,[]);await nextTick();render()}catch(error){errorMessage.value=error?.message||'趋势数据加载失败';ElMessage.error(errorMessage.value)}finally{loading.value=false}}
 function resize(){chart?.resize()};onMounted(()=>{loadData();window.addEventListener('resize',resize)});onUnmounted(()=>{window.removeEventListener('resize',resize);chart?.dispose()})
 </script>
 <style scoped lang="scss">.statistics-page{padding:22px;background:#f4f7fb;min-height:calc(100vh - 84px);color:#172b4d}.page-head{display:flex;justify-content:space-between;align-items:flex-end;margin-bottom:18px}.eyebrow{font-size:11px;letter-spacing:2px;color:#2563eb}.page-head h1{margin:6px 0 4px;font-size:26px}.page-head p{margin:0;color:#718096}.filter-card{display:flex;gap:14px;align-items:center;margin-bottom:16px}.special-input{width:220px}.card-title{display:flex;justify-content:space-between;font-weight:600}.card-title em{font-style:normal;font-size:12px;color:#94a3b8;font-weight:400}.trend-chart{height:470px}@media(max-width:700px){.filter-card{flex-wrap:wrap}.filter-card>*{width:100%!important}.page-head{align-items:flex-start;gap:12px;flex-direction:column}}

+ 43 - 55
src/views/subSystem/lifeCompany/lwarningInfoCont/LAlertQuery.vue

@@ -4,7 +4,7 @@
       <div class="page-header">
         <div>
           <div class="page-title">预警信息管理</div>
-          <div class="page-subtitle">支持预警查询、处置过程跟踪和可视化流程查询,掌握预警历史处置情况、GIS定位和电子存档信息</div>
+          <div class="page-subtitle">支持预警查询、处置过程跟踪和可视化流程查询,掌握预警历史处置情况和电子存档信息</div>
         </div>
         <el-button type="primary" icon="Refresh" @click="reloadAll">刷新</el-button>
       </div>
@@ -30,11 +30,8 @@
 
     <el-card shadow="never" class="page-card">
       <el-form :model="queryParams" :inline="true">
-        <el-form-item label="预警名称">
-          <el-input v-model="queryParams.warningName" placeholder="请输入预警名称" clearable style="width: 220px" @keyup.enter="handleQuery" />
-        </el-form-item>
         <el-form-item label="预警编号">
-          <el-input v-model="queryParams.warningNo" placeholder="请输入预警编号" clearable style="width: 180px" />
+          <el-input v-model="queryParams.warningNo" placeholder="请输入预警编号" clearable style="width: 220px" @keyup.enter="handleQuery" />
         </el-form-item>
         <el-form-item label="预警类型">
           <el-select v-model="queryParams.warningType" clearable placeholder="请选择预警类型" style="width: 180px">
@@ -58,17 +55,9 @@
         </el-form-item>
         <el-form-item label="状态">
           <el-select v-model="queryParams.status" clearable placeholder="请选择状态" style="width: 180px">
-            <el-option label="已接收" value="RECEIVED" />
-            <el-option label="待处理" value="PENDING" />
-            <el-option label="处理中" value="PROCESSING" />
-            <el-option label="已处理" value="HANDLED" />
-            <el-option label="已解除" value="CLOSED" />
-            <el-option label="已退回" value="RETURNED" />
+            <el-option v-for="item in warningStatusOptions" :key="item.value" :label="item.label" :value="item.value" />
           </el-select>
         </el-form-item>
-        <el-form-item label="预警位置">
-          <el-input v-model="queryParams.location" placeholder="请输入预警位置" clearable style="width: 220px" />
-        </el-form-item>
         <el-form-item label="发布人">
           <el-input v-model="queryParams.publisher" placeholder="请输入发布人" clearable style="width: 180px" />
         </el-form-item>
@@ -103,7 +92,7 @@
             {{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}
           </template>
         </el-table-column>
-        <el-table-column label="预警名称" prop="warningName" min-width="180" show-overflow-tooltip />
+
         <el-table-column label="预警编号" prop="warningNo" width="170" />
         <el-table-column label="预警类型" prop="warningTypeText" width="120" />
         <el-table-column label="预警级别" width="110" align="center">
@@ -120,7 +109,6 @@
             </el-tag>
           </template>
         </el-table-column>
-        <el-table-column label="预警位置" prop="location" min-width="180" show-overflow-tooltip />
         <el-table-column label="发布人" prop="publisher" width="120" />
         <el-table-column label="权属单位" prop="ownershipUnit" width="160" show-overflow-tooltip />
         <el-table-column label="发布时间" prop="publishTime" width="180" />
@@ -152,7 +140,7 @@
             <el-tab-pane :label="`已完成 (${completedTotal})`" name="completed" />
           </el-tabs>
           <el-table :data="trackList" height="360" @row-click="handleSelectWarningFromTrack">
-            <el-table-column label="预警名称" prop="warningName" min-width="170" show-overflow-tooltip />
+            <el-table-column label="预警编号" prop="warningNo" min-width="180" show-overflow-tooltip />
             <el-table-column label="预警类型" prop="warningTypeText" width="120" />
             <el-table-column label="预警级别" width="100" align="center">
               <template #default="scope">
@@ -184,7 +172,7 @@
 
           <template v-else>
             <div class="selected-info">
-              <div class="selected-name">{{ processMeta.warningName || selectedWarningRow?.warningName || "-" }}</div>
+              <div class="selected-name">{{ processMeta.warningNo || selectedWarningRow?.warningNo || "-" }}</div>
               <div class="selected-meta">
                 <span>编号:{{ processMeta.warningNo || selectedWarningRow?.warningNo || "-" }}</span>
                 <span>状态:{{ getStatusText(processMeta.status || selectedWarningRow?.status) }}</span>
@@ -222,14 +210,14 @@
               <el-timeline-item
                 v-for="item in processList"
                 :key="item.disposalId"
-                :timestamp="item.createTime || '-'"
+                :timestamp="formatDateTime(item.createTime)"
                 :type="getTimelineType(item.disposalType)"
               >
                 <div class="timeline-title">{{ getProcessTypeText(item.disposalType) }}</div>
                 <div>{{ item.disposalContent || "-" }}</div>
                 <div class="timeline-sub">处置人:{{ item.disposalUser || "-" }}</div>
                 <WarningDisposalReasons :record="item" />
-            <WarningAttachments :attachments="attachmentsForDisposal(item, processAttachments)" />
+                <WarningAttachments :attachments="attachmentsForDisposal(item, processAttachments)" />
               </el-timeline-item>
             </el-timeline>
           </template>
@@ -241,7 +229,6 @@
       <template v-if="detailData.basicInfo">
         <WarningItemSummary :warning="detailData.basicInfo" />
         <el-descriptions :column="2" border>
-          <el-descriptions-item label="预警名称">{{ detailBasic.warningName || "-" }}</el-descriptions-item>
           <el-descriptions-item label="预警编号">{{ detailBasic.warningNo || "-" }}</el-descriptions-item>
           <el-descriptions-item label="预警类型">{{ detailBasic.warningTypeText || "-" }}</el-descriptions-item>
           <el-descriptions-item label="预警级别">{{ detailBasic.warningLevelText || "-" }}</el-descriptions-item>
@@ -249,10 +236,8 @@
           <el-descriptions-item label="发布人">{{ detailBasic.publisher || "-" }}</el-descriptions-item>
           <el-descriptions-item label="处置人">{{ detailBasic.handler || "-" }}</el-descriptions-item>
           <el-descriptions-item label="权属单位">{{ detailBasic.ownershipUnit || "-" }}</el-descriptions-item>
-          <el-descriptions-item label="预警位置" :span="2">{{ detailBasic.location || "-" }}</el-descriptions-item>
           <el-descriptions-item label="发布时间">{{ detailBasic.publishTime || "-" }}</el-descriptions-item>
-          <el-descriptions-item label="GIS定位">{{ detailGis.longitude || "-" }} / {{ detailGis.latitude || "-" }}</el-descriptions-item>
-          <el-descriptions-item label="预警内容" :span="2">{{ detailBasic.warningContent || "-" }}</el-descriptions-item>
+          <el-descriptions-item label="预警内容" :span="2"><span class="warning-content">{{ detailBasic.warningContent || "-" }}</span></el-descriptions-item>
         </el-descriptions>
 
         <el-divider content-position="left">流程处置信息</el-divider>
@@ -260,9 +245,11 @@
           <el-timeline-item
             v-for="(item, index) in detailData.disposalHistory"
             :key="index"
-            :timestamp="item.createTime || item.create_time || item.disposalTime || item.disposal_time || '-'"
+            :timestamp="formatDateTime(item.createTime || item.create_time || item.disposalTime || item.disposal_time)"
           >
-            {{ item.disposalContent || item.disposal_content || item.content || "-" }}
+            <div class="timeline-title">{{ getProcessTypeText(item.disposalType || item.disposal_type) }}</div>
+            <div>{{ item.disposalContent || item.disposal_content || item.content || "-" }}</div>
+            <div class="timeline-sub">处置人:{{ item.disposalUser || item.disposal_user || "-" }}</div>
             <WarningDisposalReasons :record="item" />
             <WarningAttachments :attachments="attachmentsForDisposal(item, detailData.attachmentList)" />
           </el-timeline-item>
@@ -285,7 +272,10 @@
 </template>
 
 <script setup>
+import { useWarningStatuses } from '@/views/subSystem/lifeCompany/warningWorkflow'
+const { warningStatusOptions, databaseStatusLabels } = useWarningStatuses()
 import { computed, onMounted, reactive, ref } from "vue";
+import { parseTime } from "@/utils/ruoyi";
 import WarningItemSummary from '../components/WarningItemSummary.vue';
 import WarningDisposalReasons from '../components/WarningDisposalReasons.vue';
 import WarningAttachments from "../components/WarningAttachments.vue";
@@ -327,12 +317,11 @@ const detailData = ref({});
 const queryParams = reactive({
   pageNum: 1,
   pageSize: 10,
-  warningName: "",
+
   warningNo: "",
   warningType: "",
   warningLevel: "",
   status: "",
-  location: "",
   publisher: "",
   ownershipUnit: "",
   dateRange: []
@@ -355,7 +344,7 @@ const warningLevelLabelMap = computed(() => {
 const trackList = computed(() => (trackTab.value === "processing" ? processingList.value : completedList.value));
 const processNodes = computed(() => processDiagram.value.nodes || []);
 const processMeta = computed(() => ({
-  warningName: processDiagram.value.warningName || "",
+
   warningNo: processDiagram.value.warningNo || "",
   status: processDiagram.value.status || ""
 }));
@@ -365,23 +354,27 @@ const detailBasic = computed(() => {
   const warningType = basic.warningType || basic.warning_type || "";
   const warningLevel = basic.warningLevel || basic.warning_level || "";
   return {
-    warningName: basic.warningName || basic.warning_name || "",
+
     warningNo: basic.warningNo || basic.warning_no || "",
-    warningTypeText: warningTypeLabelMap.value[warningType] || warningType || "-",
-    warningLevelText: warningLevelLabelMap.value[warningLevel] || warningLevel || "-",
+    warningTypeText: basic.warning_type_name || basic.warningTypeName || warningTypeLabelMap.value[warningType] || "-",
+    warningLevelText: warningLevelLabelMap.value[warningLevel] || "-",
     status: basic.status || "",
     publisher: basic.publisher || "",
     handler: basic.handler || "",
     ownershipUnit: basic.ownershipUnit || basic.ownership_unit || "",
-    location: basic.location || "",
-    publishTime: basic.publishTime || basic.publish_time || "",
+    publishTime: formatDateTime(basic.publishTime || basic.publish_time),
     warningContent: basic.warningContent || basic.warning_content || ""
   };
 });
 
-const detailGis = computed(() => detailData.value.gisLocation || {});
 const detailArchive = computed(() => detailData.value.electronicArchive || {});
 
+function formatDateTime(value) {
+  if (!value) return "-";
+  const date = new Date(value);
+  return Number.isNaN(date.getTime()) ? value : parseTime(date);
+}
+
 function getLevelTagType(level) {
   return {
     "1": "danger",
@@ -392,15 +385,7 @@ function getLevelTagType(level) {
 }
 
 function getStatusText(status) {
-  return {
-    DRAFT: "草稿",
-    RECEIVED: "已接收",
-    PENDING: "待处理",
-    PROCESSING: "处理中",
-    HANDLED: "已处理",
-    CLOSED: "已解除",
-    RETURNED: "已退回"
-  }[status] || status || "-";
+  return databaseStatusLabels.value[status] || status || "-"
 }
 
 function getStatusTagType(status) {
@@ -410,8 +395,7 @@ function getStatusTagType(status) {
     PENDING: "warning",
     PROCESSING: "warning",
     HANDLED: "success",
-    CLOSED: "",
-    RETURNED: "danger"
+    CLOSED: "info"
   }[status] || "";
 }
 
@@ -420,6 +404,11 @@ function getProcessTypeText(type) {
     RELEASE: "发布预警",
     UPGRADE: "升级预警",
     RESOLVE: "解除预警",
+    AUTO_CLEAR: "系统自动解除",
+    CLEAR: "核查解除",
+    RECEIVE: "接收预警",
+    START: "开始处置",
+    HANDLE: "提交处置结果",
     RETURN: "退回重办",
     SUPERVISION: "预警督办",
     INSTRUCTION: "领导批示"
@@ -431,6 +420,8 @@ function getTimelineType(type) {
     RELEASE: "primary",
     UPGRADE: "warning",
     RESOLVE: "success",
+    AUTO_CLEAR: "success",
+    CLEAR: "success",
     RETURN: "danger",
     SUPERVISION: "primary",
     INSTRUCTION: "info"
@@ -442,17 +433,16 @@ function normalizeWarningRow(item) {
   const warningLevel = item.warningLevel || item.warning_level || "";
   return {
     warningId: item.warningId || item.warning_id,
-    warningName: item.warningName || item.warning_name || "",
+
     warningNo: item.warningNo || item.warning_no || "",
     warningType,
-    warningTypeText: warningTypeLabelMap.value[warningType] || warningType || "-",
+    warningTypeText: item.warning_type_name || item.warningTypeName || warningTypeLabelMap.value[warningType] || "-",
     warningLevel,
-    warningLevelText: warningLevelLabelMap.value[warningLevel] || warningLevel || "-",
+    warningLevelText: warningLevelLabelMap.value[warningLevel] || "-",
     status: item.status || "",
-    location: item.location || "",
     publisher: item.publisher || "",
     ownershipUnit: item.ownershipUnit || item.ownership_unit || "",
-    publishTime: item.publishTime || item.publish_time || "",
+    publishTime: formatDateTime(item.publishTime || item.publish_time),
     handler: item.handler || ""
   };
 }
@@ -472,12 +462,11 @@ async function loadWarnings() {
     const res = await getdbyjlistData({
       pageNum: queryParams.pageNum,
       pageSize: queryParams.pageSize,
-      warningName: queryParams.warningName || undefined,
+
       warningNo: queryParams.warningNo || undefined,
       warningType: queryParams.warningType || undefined,
       warningLevel: queryParams.warningLevel || undefined,
       status: queryParams.status || undefined,
-      location: queryParams.location || undefined,
       publisher: queryParams.publisher || undefined,
       ownershipUnit: queryParams.ownershipUnit || undefined,
       startTime: queryParams.dateRange?.[0] || undefined,
@@ -553,12 +542,11 @@ function handleQuery() {
 function resetQuery() {
   queryParams.pageNum = 1;
   queryParams.pageSize = 10;
-  queryParams.warningName = "";
+
   queryParams.warningNo = "";
   queryParams.warningType = "";
   queryParams.warningLevel = "";
   queryParams.status = "";
-  queryParams.location = "";
   queryParams.publisher = "";
   queryParams.ownershipUnit = "";
   queryParams.dateRange = [];

+ 23 - 35
src/views/subSystem/lifeCompany/lwarningInfoCont/LwarningDisp.vue

@@ -11,11 +11,8 @@
 
     <el-card shadow="never" class="page-card">
       <el-form :model="queryParams" :inline="true">
-        <el-form-item label="预警名称">
-          <el-input v-model="queryParams.warningName" placeholder="请输入预警名称" clearable style="width: 220px" @keyup.enter="handleQuery" />
-        </el-form-item>
         <el-form-item label="预警编号">
-          <el-input v-model="queryParams.warningNo" placeholder="请输入预警编号" clearable style="width: 180px" />
+          <el-input v-model="queryParams.warningNo" placeholder="请输入预警编号" clearable style="width: 220px" @keyup.enter="handleQuery" />
         </el-form-item>
         <el-form-item label="预警类型">
           <el-select v-model="queryParams.warningType" clearable placeholder="请选择预警类型" style="width: 180px">
@@ -39,11 +36,7 @@
         </el-form-item>
         <el-form-item label="状态">
           <el-select v-model="queryParams.status" clearable placeholder="请选择状态" style="width: 180px">
-            <el-option label="已接收" value="RECEIVED" />
-            <el-option label="已发布(待接收)" value="PENDING" />
-            <el-option label="处理中" value="PROCESSING" />
-            <el-option label="已处置(待核查)" value="HANDLED" />
-            <el-option label="已解除" value="CLOSED" />
+            <el-option v-for="item in warningStatusOptions" :key="item.value" :label="item.label" :value="item.value" />
           </el-select>
         </el-form-item>
         <el-form-item label="处置人">
@@ -77,7 +70,7 @@
             {{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}
           </template>
         </el-table-column>
-        <el-table-column label="预警名称" prop="warningName" min-width="180" show-overflow-tooltip />
+
         <el-table-column label="预警编号" prop="warningNo" width="170" />
         <el-table-column label="预警类型" prop="warningTypeText" width="120" />
         <el-table-column label="预警级别" width="110" align="center">
@@ -91,7 +84,6 @@
         <el-table-column label="设备名称" prop="deviceName" min-width="140" show-overflow-tooltip />
         <el-table-column label="设备编码" prop="deviceCode" width="160" show-overflow-tooltip />
         <el-table-column label="发布人" prop="publisher" width="120" />
-        <el-table-column label="报警位置" prop="location" min-width="180" show-overflow-tooltip />
         <el-table-column label="权属单位" prop="ownershipUnit" width="160" show-overflow-tooltip />
         <el-table-column label="状态" width="120" align="center">
           <template #default="scope">
@@ -128,7 +120,6 @@
       <template v-if="detailData.basicInfo">
         <WarningItemSummary :warning="detailData.basicInfo" />
         <el-descriptions :column="2" border>
-          <el-descriptions-item label="预警名称">{{ detailBasic.warningName || "-" }}</el-descriptions-item>
           <el-descriptions-item label="预警编号">{{ detailBasic.warningNo || "-" }}</el-descriptions-item>
           <el-descriptions-item label="预警专项">{{ detailBasic.warningSpecial || "-" }}</el-descriptions-item>
           <el-descriptions-item label="预警类型">{{ detailBasic.warningTypeText || "-" }}</el-descriptions-item>
@@ -139,10 +130,9 @@
           <el-descriptions-item label="设备编码">{{ detailBasic.deviceCode || "-" }}</el-descriptions-item>
           <el-descriptions-item label="发布人">{{ detailBasic.publisher || "-" }}</el-descriptions-item>
           <el-descriptions-item label="核查人">{{ detailBasic.reviewer || detailBasic.publisher || "-" }}</el-descriptions-item>
-          <el-descriptions-item label="报警位置" :span="2">{{ detailBasic.location || "-" }}</el-descriptions-item>
           <el-descriptions-item label="权属单位">{{ detailBasic.ownershipUnit || "-" }}</el-descriptions-item>
           <el-descriptions-item label="发布时间">{{ formatDateTime(detailBasic.publishTime) }}</el-descriptions-item>
-          <el-descriptions-item label="预警内容" :span="2">{{ detailBasic.warningContent || "-" }}</el-descriptions-item>
+          <el-descriptions-item label="预警内容" :span="2"><span class="warning-content">{{ detailBasic.warningContent || "-" }}</span></el-descriptions-item>
         </el-descriptions>
 
         <el-divider content-position="left">处置记录</el-divider>
@@ -170,8 +160,8 @@
 
     <el-dialog v-model="resolveVisible" title="预警解除" width="520px" append-to-body>
       <el-form label-width="100px">
-        <el-form-item label="预警名称">
-          <el-input :model-value="currentRow?.warningName || '-'" disabled />
+        <el-form-item label="预警编号">
+          <el-input :model-value="currentRow?.warningNo || '-'" disabled />
         </el-form-item>
         <el-form-item label="核查说明">
           <el-input v-model="resolveForm.disposalContent" type="textarea" :rows="4" placeholder="请输入预警解除说明" />
@@ -185,8 +175,8 @@
 
     <el-dialog v-model="upgradeVisible" title="预警升级" width="560px" append-to-body>
       <el-form label-width="100px">
-        <el-form-item label="预警名称">
-          <el-input :model-value="currentRow?.warningName || '-'" disabled />
+        <el-form-item label="预警编号">
+          <el-input :model-value="currentRow?.warningNo || '-'" disabled />
         </el-form-item>
         <el-form-item label="新预警级别">
           <el-select v-model="upgradeForm.newLevel" placeholder="请选择新预警级别" style="width: 100%">
@@ -261,8 +251,8 @@
 
     <el-dialog v-model="returnVisible" title="预警退回" width="520px" append-to-body>
       <el-form label-width="100px">
-        <el-form-item label="预警名称">
-          <el-input :model-value="currentRow?.warningName || '-'" disabled />
+        <el-form-item label="预警编号">
+          <el-input :model-value="currentRow?.warningNo || '-'" disabled />
         </el-form-item>
         <el-form-item label="退回说明">
           <el-input v-model="returnForm.disposalContent" type="textarea" :rows="4" placeholder="请输入退回重办说明" />
@@ -277,13 +267,14 @@
 </template>
 
 <script setup>
+import { useWarningStatuses } from '@/views/subSystem/lifeCompany/warningWorkflow'
+const { warningStatusOptions, databaseStatusLabels } = useWarningStatuses()
 import { computed, onMounted, reactive, ref } from "vue";
 import { ElMessage } from "element-plus";
 import { Upload } from "@element-plus/icons-vue";
 import { parseTime } from "@/utils/ruoyi";
 import useUserStore from "@/store/modules/user";
 import { enabledAll } from "@/api/system/user";
-import { warningStatusLabels } from "../warningWorkflow";
 import WarningItemSummary from '../components/WarningItemSummary.vue';
 import WarningDisposalReasons from '../components/WarningDisposalReasons.vue';
 import WarningAttachments from "../components/WarningAttachments.vue";
@@ -323,7 +314,7 @@ const returnVisible = ref(false);
 const queryParams = reactive({
   pageNum: 1,
   pageSize: 10,
-  warningName: "",
+
   warningNo: "",
   warningType: "",
   warningLevel: "",
@@ -391,18 +382,17 @@ const detailBasic = computed(() => {
   const warningType = basic.warningType || basic.warning_type || "";
   const warningLevel = basic.warningLevel || basic.warning_level || "";
   return {
-    warningName: basic.warningName || basic.warning_name || "",
+
     warningNo: basic.warningNo || basic.warning_no || "",
     warningSpecial: basic.warningSpecial || basic.warning_special || "",
-    warningTypeText: warningTypeLabelMap.value[warningType] || warningType || "-",
-    warningLevelText: warningLevelLabelMap.value[warningLevel] || warningLevel || "-",
+    warningTypeText: basic.warning_type_name || basic.warningTypeName || warningTypeLabelMap.value[warningType] || "-",
+    warningLevelText: warningLevelLabelMap.value[warningLevel] || "-",
     status: basic.status || "",
     handler: basic.handler || "",
     deviceCode: basic.deviceCode || basic.device_code || "",
     deviceName: basic.deviceName || basic.device_name || "",
     publisher: basic.publisher || "",
     reviewer: basic.reviewer || "",
-    location: basic.location || "",
     ownershipUnit: basic.ownershipUnit || basic.ownership_unit || "",
     publishTime: basic.publishTime || basic.publish_time || "",
     warningContent: basic.warningContent || basic.warning_content || ""
@@ -419,7 +409,7 @@ function getLevelTagType(level) {
 }
 
 function getStatusText(status) {
-  return warningStatusLabels[status] || status || "-";
+  return databaseStatusLabels.value[status] || status || "-"
 }
 
 function getStatusTagType(status) {
@@ -429,8 +419,7 @@ function getStatusTagType(status) {
     PENDING: "warning",
     PROCESSING: "warning",
     HANDLED: "success",
-    CLOSED: "info",
-    RETURNED: "danger"
+    CLOSED: "info"
   }[status] || "info";
 }
 
@@ -439,18 +428,17 @@ function normalizeWarningRow(item) {
   const warningLevel = item.warningLevel || item.warning_level || "";
   return {
     warningId: item.warningId || item.warning_id,
-    warningName: item.warningName || item.warning_name || "",
+
     warningNo: item.warningNo || item.warning_no || "",
     warningType,
-    warningTypeText: warningTypeLabelMap.value[warningType] || warningType || "-",
+    warningTypeText: item.warning_type_name || item.warningTypeName || warningTypeLabelMap.value[warningType] || "-",
     warningLevel,
-    warningLevelText: warningLevelLabelMap.value[warningLevel] || warningLevel || "-",
+    warningLevelText: warningLevelLabelMap.value[warningLevel] || "-",
     handler: item.handler || "",
     deviceCode: item.deviceCode || item.device_code || "",
     deviceName: item.deviceName || item.device_name || "",
     publisher: item.publisher || "",
     reviewer: item.reviewer || "",
-    location: item.location || "",
     ownershipUnit: item.ownershipUnit || item.ownership_unit || "",
     publishTime: item.publishTime || item.publish_time || "",
     status: item.status || ""
@@ -500,7 +488,7 @@ async function loadList() {
     const res = await getdbyjlistData({
       pageNum: queryParams.pageNum,
       pageSize: queryParams.pageSize,
-      warningName: queryParams.warningName || undefined,
+
       warningNo: queryParams.warningNo || undefined,
       warningType: queryParams.warningType || undefined,
       warningLevel: queryParams.warningLevel || undefined,
@@ -525,7 +513,7 @@ function handleQuery() {
 function resetQuery() {
   queryParams.pageNum = 1;
   queryParams.pageSize = 10;
-  queryParams.warningName = "";
+
   queryParams.warningNo = "";
   queryParams.warningType = "";
   queryParams.warningLevel = "";

+ 30 - 4
src/views/subSystem/lifeCompany/warningWorkflow.js

@@ -1,9 +1,35 @@
 // 处置完成仍需核查;退回进入处置中,只有 CLOSED 是终态。
-export const warningStatusLabels = {
-  DRAFT: '草稿', PENDING: '已发布(待接收)', RECEIVED: '已接收',
-  PROCESSING: '处置中', HANDLED: '已处置(待核查)', CLOSED: '已解除'
+import { computed, onMounted, ref } from 'vue'
+import request from '@/utils/request'
+const statusRows = ref([])
+const typeRows = ref([])
+const levelRows = ref([])
+let loadingStatuses
+export function useWarningReferences() {
+  onMounted(async () => {
+    if (!loadingStatuses) loadingStatuses = Promise.all([
+      request({ url: '/warning/config/statuses', method: 'get' }),
+      request({ url: '/warning/config/types', method: 'get' }),
+      request({ url: '/system/dict/data/type/alert_level', method: 'get' })
+    ]).then(([statuses, types, levels]) => {
+        statusRows.value = statuses.data || []
+        typeRows.value = types.data || []
+        levelRows.value = levels.data || []
+      })
+      .catch(() => {}) // 请求封装统一提示错误,下次进入页面可重试。
+      .finally(() => { loadingStatuses = undefined })
+    await loadingStatuses
+  })
+  return {
+    warningStatusOptions: computed(() => statusRows.value.map(d => ({ value: d.dictValue, label: d.dictLabel }))),
+    databaseStatusLabels: computed(() => Object.fromEntries(statusRows.value.map(d => [d.dictValue, d.dictLabel]))),
+    typeOptions: computed(() => typeRows.value.map(d => ({ value: d.dictValue, label: d.dictLabel }))),
+    levelOptions: computed(() => levelRows.value.map(d => ({ value: d.dictValue, label: d.dictLabel }))),
+    typeLabels: computed(() => Object.fromEntries(typeRows.value.map(d => [d.dictValue, d.dictLabel]))),
+    levelLabels: computed(() => Object.fromEntries(levelRows.value.map(d => [d.dictValue, d.dictLabel])))
+  }
 }
-
+export function useWarningStatuses() { return useWarningReferences() }
 export function workflowActions(row, username) {
   if (row?.todo_type === 'DONE' || row?.todoType === 'DONE') return []
   if (Array.isArray(row?.availableActions)) return row.availableActions

+ 2 - 1
src/views/subSystem/warningList/codeGenerate/index.vue

@@ -14,6 +14,7 @@
   </div>
 </template>
 <script setup name="WarningCodeGenerate">
+import { listWarningTypes } from '@/api/warning/list'
 import { ref, reactive, onMounted } from 'vue'
 import { useRouter } from 'vue-router'
 import { getDicts } from '@/api/system/dict/data'
@@ -32,7 +33,7 @@ async function generate() {
   finally { if (current === version) loading.value = false }
 }
 onMounted(async () => {
-  const [t, l] = await Promise.all([getDicts('alert_type'), getDicts('alert_level')])
+  const [t, l] = await Promise.all([listWarningTypes(), getDicts('alert_level')])
   types.value = normalizeWarningTypeDict(t.data); levels.value = normalizeWarningLevelDict(l.data)
 })
 </script>

+ 2 - 1
src/views/subSystem/warningList/itemDetail/index.vue

@@ -90,6 +90,7 @@
 </template>
 
 <script setup name="WarningItemDetail">
+import { listWarningTypes } from '@/api/warning/list'
 import { computed, onMounted, reactive, ref, watch } from 'vue'
 import { useRoute } from 'vue-router'
 import { ElMessage } from 'element-plus'
@@ -120,7 +121,7 @@ function typeLabel(value) {
 }
 async function loadTypes() {
   try {
-    const res = await getDicts('alert_type')
+    const res = await listWarningTypes()
     warningTypes.value = normalizeWarningTypeDict(res.data)
   } catch {
     warningTypes.value = fallbackWarningTypes

+ 2 - 1
src/views/subSystem/warningList/itemManage/index.vue

@@ -276,6 +276,7 @@
 </template>
 
 <script setup name="WarningItemManage">
+import { listWarningTypes } from '@/api/warning/list'
 import { onMounted, reactive, ref, watch } from 'vue'
 import { useRouter, useRoute } from 'vue-router'
 import { ElMessage, ElMessageBox } from 'element-plus'
@@ -349,7 +350,7 @@ function typeLabel(value) {
 
 async function loadTypes() {
   try {
-    const [res, levels] = await Promise.all([getDicts('alert_type'), getDicts('alert_level')])
+    const [res, levels] = await Promise.all([listWarningTypes(), getDicts('alert_level')])
     warningTypes.value = normalizeWarningTypeDict(res.data)
     warningLevels.value = normalizeWarningLevelDict(levels.data)
   } catch {

+ 2 - 1
src/views/subSystem/warningList/itemQuery/index.vue

@@ -164,6 +164,7 @@
 </template>
 
 <script setup name="WarningItemQuery">
+import { listWarningTypes } from '@/api/warning/list'
 import { computed, onMounted, reactive, ref } from 'vue'
 import { useRouter } from 'vue-router'
 import { CircleCheck, CircleClose, Collection, Refresh, RefreshRight, Search, View, Warning } from '@element-plus/icons-vue'
@@ -215,7 +216,7 @@ function typeLabel(value) {
 
 async function loadTypes() {
   try {
-    const [res, levels] = await Promise.all([getDicts('alert_type'), getDicts('alert_level')])
+    const [res, levels] = await Promise.all([listWarningTypes(), getDicts('alert_level')])
     warningTypes.value = normalizeWarningTypeDict(res.data)
     warningLevels.value = normalizeWarningLevelDict(levels.data)
   } catch {

+ 2 - 1
src/views/subSystem/warningList/reasonManage/index.vue

@@ -174,6 +174,7 @@
 </template>
 
 <script setup name="WarningReasonManage">
+import { listWarningTypes } from '@/api/warning/list'
 import { onMounted, reactive, ref, watch } from 'vue'
 import { useRoute } from 'vue-router'
 import { ElMessage, ElMessageBox } from 'element-plus'
@@ -234,7 +235,7 @@ function resetForm(data = emptyForm()) {
 }
 async function loadTypes() {
   try {
-    const [res, levels] = await Promise.all([getDicts('alert_type'), getDicts('alert_level')])
+    const [res, levels] = await Promise.all([listWarningTypes(), getDicts('alert_level')])
     warningTypes.value = normalizeWarningTypeDict(res.data)
     warningLevels.value = normalizeWarningLevelDict(levels.data)
   } catch {

+ 1 - 1
src/views/subSystem/warningList/shared.js

@@ -1,4 +1,4 @@
-// 与预警发布共用 alert_type / alert_level 字典。字典加载失败时不允许提交猜测的编码。
+// 与预警发布共用 warning_type 表和 alert_level 字典。字典加载失败时不允许提交猜测的编码。
 export const fallbackWarningTypes = []
 
 export const warningRegions = [