فهرست منبع

fix: 修改bug

shiyanyu 21 ساعت پیش
والد
کامیت
4e313927fd

+ 1 - 1
src/views/EntDeclaration/auditTaskManagement/components/SurveyFormDialog.vue

@@ -14,7 +14,7 @@
       ref="surveyForm"
       :model="form"
       :rules="rules"
-      label-width="120px"
+      label-width="160px"
     >
       <el-row :gutter="20">
         <!-- 动态生成表单字段 -->

+ 7 - 5
src/views/costAudit/baseInfo/catalogManage/index.vue

@@ -972,6 +972,7 @@
   import { allcurrentCostSurveyList } from '@/api/financeSheetManage'
   import { getCostFormDetail } from '@/api/costFormManage'
   import { dictMixin } from '@/mixins/useDict'
+  import { head } from 'lodash'
 
   export default {
     name: 'CatalogManage',
@@ -1227,13 +1228,13 @@
           {
             prop: 'surveyTemplateName',
             label: '成本调查表',
-            align: 'center',
+            headerAlign: 'center',
+            align: 'left',
             // slotName: 'surveyTemplateName',
           },
           {
             prop: 'createTime',
             label: '年度',
-            width: 100,
             align: 'center',
             formatter: (row) => {
               const ct = row && row.createTime
@@ -1246,7 +1247,6 @@
           {
             prop: 'status',
             label: '状态',
-            width: 100,
             align: 'center',
             formatter: (row) => {
               return (
@@ -1284,7 +1284,8 @@
           {
             prop: 'projectName',
             label: '政策文件',
-            align: 'center',
+            headerAlign: 'center',
+            align: 'left',
           },
           {
             prop: 'documentNumber',
@@ -1319,7 +1320,8 @@
           {
             prop: 'informationName',
             label: '资料名称',
-            align: 'center',
+            headerAlign: 'center',
+            align: 'left',
           },
           {
             prop: 'formatRequired',

+ 286 - 58
src/views/costAudit/baseInfo/catalogManage/surveyDialog.vue

@@ -45,7 +45,8 @@
                   .fixedTablesTitle"
                 :key="index"
                 :label="item.rkey"
-                align="center"
+                header-align="center"
+                align="left"
               >
                 <!-- <template slot-scope="scope">
                   {{
@@ -67,19 +68,14 @@
               style="width: 100%"
               :row-class-name="getFixedPreviewRowClass"
             >
-              <!-- <el-table-column label="序号" width="80" align="center">
-                <template slot-scope="scope">
-                  {{ scope.row._displaySeq || '-' }}
-                </template>
-              </el-table-column> -->
-
-              <!-- 动态生成 fixedFields 中的列 -->
+              <!-- 动态生成 fixedFields 中的列(过滤掉 isAuditPeriod=true 的字段,避免与“监审期间+fieldName”重复) -->
               <el-table-column
-                v-for="field in contentEditForm.fixedTable.fixedTablesTitle"
+                v-for="field in fixedColumnsForDisplay"
                 :key="field.rkey"
                 :label="field.rkey"
                 min-width="150"
-                align="center"
+                header-align="center"
+                align="left"
                 :prop="field.rkey"
               >
                 <template slot-scope="scope">
@@ -109,30 +105,28 @@
                 </template>
               </el-table-column>
 
-              <!-- <el-table-column label="备注" min-width="160" align="left">
-                <template slot-scope="scope">
-                  <el-input
-                    v-if="!scope.row._isCategory"
-                    :value="scope.row._displayRemark || ''"
-                    placeholder="请输入备注"
-                    disabled
-                  />
-                </template>
-              </el-table-column> -->
-              <!-- <el-table-column label="指标编号" width="120" align="center">
+              <!-- 监审期间动态列:按 年份 + fieldName 展开(与 FixedTableDialog 一致) -->
+              <el-table-column
+                v-for="col in auditPeriodColumns"
+                :key="col.key"
+                :label="col.label"
+                :prop="col.prop"
+                width="150"
+                header-align="center"
+                align="left"
+              >
                 <template slot-scope="scope">
-                  <span v-if="!scope.row._isCategory">
-                    {{ scope.row.cellCode || '-' }}
+                  <span>
+                    {{
+                      scope.row[col.prop] !== undefined &&
+                      scope.row[col.prop] !== null &&
+                      String(scope.row[col.prop]) !== ''
+                        ? scope.row[col.prop]
+                        : '-'
+                    }}
                   </span>
                 </template>
               </el-table-column>
-              <el-table-column label="计算公式" min-width="150" align="left">
-                <template slot-scope="scope">
-                  <span v-if="!scope.row._isCategory">
-                    {{ scope.row.calculationFormula || '-' }}
-                  </span>
-                </template>
-              </el-table-column> -->
             </el-table>
           </div>
         </div>
@@ -163,7 +157,8 @@
                   .dynamicTableHeaders"
                 :key="index"
                 :label="item.rkey"
-                align="center"
+                header-align="center"
+                align="left"
               >
                 <template slot-scope="scope">
                   {{
@@ -183,7 +178,8 @@
 
 <script>
   import CostAuditDialog from '@/components/costAudit/CostAuditDialog'
-  import { listByCurrentTemplateId } from '@/api/catalogManage.js'
+  import { listByCurrentTemplateId as fetchTemplateItems } from '@/api/catalogManage.js'
+  import { getListBySurveyTemplateIdAndVersion as fetchHeaderMeta } from '@/api/costSurveyTemplateHeaders'
   export default {
     name: 'SurveyDialog',
     components: {
@@ -378,6 +374,90 @@
         }
         return collectedYears
       },
+      // 监审期间字段(isAuditPeriod=true):来自固定表表头元数据 tableHeaders
+      auditPeriodFields() {
+        const headers =
+          (this.contentEditForm.fixedTable &&
+            this.contentEditForm.fixedTable.tableHeaders) ||
+          []
+        const toBool = (v) => {
+          if (v === true) return true
+          if (v === false) return false
+          const s = String(v == null ? '' : v)
+            .trim()
+            .toLowerCase()
+          return ['true', '1', 'y', 'yes', '是'].includes(s)
+        }
+        return (Array.isArray(headers) ? headers : [])
+          .filter((h) => h && toBool(h.isAuditPeriod))
+          .map((h, idx) => ({
+            ...h,
+            __key: String(h.fieldName || h.fieldCname || h.rkey || idx),
+          }))
+      },
+      // 期间字段在行对象上的 prop:ap_${year}__${fieldName}
+      auditPeriodColumns() {
+        const years = Array.isArray(this.auditPeriodYears)
+          ? this.auditPeriodYears
+          : []
+        const fields = Array.isArray(this.auditPeriodFields)
+          ? this.auditPeriodFields
+          : []
+        const cols = []
+        years.forEach((year) => {
+          fields.forEach((m) => {
+            const fieldName = String(
+              m.fieldName || m.fieldCname || m.rkey || m.name || ''
+            ).trim()
+            if (!fieldName) return
+            const prop = this.getAuditPeriodProp(year, fieldName)
+            cols.push({
+              key: `${year}__${m.__key}`,
+              label: `${year}${fieldName}`,
+              prop,
+              year,
+              fieldName,
+            })
+          })
+        })
+        return cols
+      },
+      // 固定表展示列:fixedTablesTitle 中剔除 isAuditPeriod=true 的字段(这些字段应仅通过“监审期间+fieldName”展示)
+      fixedColumnsForDisplay() {
+        const titles =
+          (this.contentEditForm.fixedTable &&
+            this.contentEditForm.fixedTable.fixedTablesTitle) ||
+          []
+        const metas = Array.isArray(this.auditPeriodFields)
+          ? this.auditPeriodFields
+          : []
+        if (!Array.isArray(titles) || titles.length === 0) return []
+        if (!Array.isArray(metas) || metas.length === 0) return titles
+
+        const periodNames = new Set(
+          metas
+            .map((m) =>
+              String(
+                m.fieldName || m.fieldCname || m.rkey || m.name || ''
+              ).trim()
+            )
+            .filter(Boolean)
+        )
+
+        // 只在固定表(templateType=2)时过滤,避免影响单记录/动态表
+        if (String(this.contentEditForm.templateType) !== '2') return titles
+
+        return titles.filter((t) => {
+          const name = String(
+            (t && (t.rkey || t.label || t.fieldName || t.name)) || ''
+          ).trim()
+          if (!name) return true
+          // 如果该列在 auditPeriodFields 中出现,则认为是期间字段,从固定表头移除
+          return !periodNames.has(name)
+        })
+      },
+
+      // 固定表列名候选:用于从列名中兜底解析监审年份(auditPeriodYears 里会用到)
       fixedTableColumnCandidates() {
         const labels = new Set()
         const addLabel = (value) => {
@@ -413,6 +493,7 @@
         }
         return Array.from(labels)
       },
+
       fixedTableDisplayData() {
         const rows =
           (this.contentEditForm.fixedTable &&
@@ -475,6 +556,8 @@
           return level
         }
 
+        const apCols = this.auditPeriodColumns
+
         return rows.map((row, index) => {
           const rowId = normalizeId(row.rowid || row.itemId || index)
           const fixedValues = row.fixedValues || {}
@@ -498,6 +581,32 @@
             }
           })
 
+          // ===== 监审期间 + fieldName:补充到行上(prop 形如 ap_2023__收入) =====
+          ;(Array.isArray(apCols) ? apCols : []).forEach((col) => {
+            if (!col || !col.prop) return
+            const y = String(col.year)
+            const fn = String(col.fieldName || '').trim()
+            if (!y || !fn) return
+
+            // 兼容两种存储键:"2023收入" / "收入_2023"
+            const k1 = `${y}${fn}`
+            const k2 = `${fn}_${y}`
+            const v =
+              fixedValues[k1] !== undefined
+                ? fixedValues[k1]
+                : fixedValues[k2] !== undefined
+                ? fixedValues[k2]
+                : row[k1] !== undefined
+                ? row[k1]
+                : row[k2] !== undefined
+                ? row[k2]
+                : ''
+            return {
+              prop: col.prop,
+              v,
+            }
+          })
+
           // 设置默认显示名称(使用第一个非序号字段)
           let displayName = ''
           const nonSeqField = fixedFields.find((f) => f.rkey !== '序号')
@@ -520,7 +629,7 @@
           const indentLevel = Math.min(level, 5)
           const isCategory = hasChildren || isChild
 
-          return {
+          const out = {
             ...row,
             _displaySeq: displaySeq,
             _displayName: displayName,
@@ -532,6 +641,29 @@
             _indentLevel: indentLevel,
             _rowId: rowId,
           }
+
+          // 把期间列值挂到 out 上
+          ;(Array.isArray(apCols) ? apCols : []).forEach((col) => {
+            if (!col || !col.prop) return
+            const y = String(col.year)
+            const fn = String(col.fieldName || '').trim()
+            if (!y || !fn) return
+            const k1 = `${y}${fn}`
+            const k2 = `${fn}_${y}`
+            const v =
+              fixedValues[k1] !== undefined
+                ? fixedValues[k1]
+                : fixedValues[k2] !== undefined
+                ? fixedValues[k2]
+                : row[k1] !== undefined
+                ? row[k1]
+                : row[k2] !== undefined
+                ? row[k2]
+                : ''
+            out[col.prop] = v !== undefined && v !== null ? v : ''
+          })
+
+          return out
         })
       },
     },
@@ -557,6 +689,41 @@
       },
     },
     methods: {
+      // 期间字段在行对象上的 prop:ap_${year}__${fieldName}
+      getAuditPeriodProp(year, fieldName) {
+        const y = String(year)
+        const f = String(fieldName || '').trim()
+        return `ap_${y}__${f}`
+      },
+      // 尽可能从各种入参/回显结构中解析 surveyTemplateId
+      resolveSurveyTemplateId() {
+        const c = this.contentEditForm || {}
+        const d = c.data || {}
+        const fd = this.formData || {}
+        const fdd = fd.data || {}
+
+        return (
+          d.surveyTemplateId ||
+          d.surveyId ||
+          d.templateId ||
+          c.surveyTemplateId ||
+          c.surveyId ||
+          c.templateId ||
+          fdd.surveyTemplateId ||
+          fdd.surveyId ||
+          fd.surveyTemplateId ||
+          fd.surveyId ||
+          ''
+        )
+      },
+      // 解析版本ID(后端若需要版本维度时使用)
+      resolveVersionId() {
+        const c = this.contentEditForm || {}
+        const d = c.data || {}
+        const fd = this.formData || {}
+        const fdd = fd.data || {}
+        return c.versionId || d.versionId || fd.versionId || fdd.versionId || ''
+      },
       // 初始化表单
       initForm() {
         if (Object.keys(this.formData).length > 0) {
@@ -565,32 +732,81 @@
         }
       },
       getData() {
-        listByCurrentTemplateId({
-          surveyTemplateId:
-            this.contentEditForm.data.surveyId ||
-            this.contentEditForm.data.surveyTemplateId,
-        }).then((res) => {
-          // 根据模板类型解析并显示数据
-          // if (this.contentEditForm.templateType === '1') {
-          //   if (res.value.fixedFields) {
-          //     console.log(this.contentEditForm)
-          //     this.contentEditForm.fixedTable.fixedTablesTitle =
-          //       this.stringToObjects(res.value.fixedFields || '')
-          //     this.contentEditForm.fixedTable.fixedTables = []
-          //     console.log(this.contentEditForm.fixedTable.fixedTablesTitle)
-          //   }
-          // }
-          if (
-            this.contentEditForm.templateType === '1' ||
-            this.contentEditForm.templateType === '2'
-          ) {
-            // 解析并显示固定表项目数据
-            this.parseAndDisplayFixedTableData(res)
-          } else if (this.contentEditForm.templateType === '3') {
-            // 解析并显示动态表项目数据
-            this.parseAndDisplayDynamicTableData(res)
+        const surveyTemplateId = this.resolveSurveyTemplateId()
+        const versionId = this.resolveVersionId()
+
+        // 固定表:必须同时拉取
+        // 1) getListBySurveyTemplateIdAndVersion:拿表头元数据(含 isAuditPeriod)
+        // 2) listByCurrentTemplateId:拿 itemlist/fixedFields 预览数据
+        if (String(this.contentEditForm.templateType) === '2') {
+          if (surveyTemplateId) {
+            fetchHeaderMeta({
+              surveyTemplateId,
+              // 有些环境需要 versionId,不传也不影响其它环境;这里尽量带上
+              ...(versionId ? { versionId } : {}),
+              type: 1,
+            })
+              .then((res) => {
+                if (res && res.code === 200 && Array.isArray(res.value)) {
+                  this.$set(
+                    this.contentEditForm.fixedTable,
+                    'tableHeaders',
+                    res.value
+                  )
+                  this.$set(
+                    this.contentEditForm.dynamicTable,
+                    'tableHeaders',
+                    res.value
+                  )
+                }
+              })
+              .catch(() => {})
           }
-        })
+
+          if (surveyTemplateId) {
+            fetchTemplateItems({ surveyTemplateId }).then((res) => {
+              this.parseAndDisplayFixedTableData(res)
+            })
+          }
+          return
+        }
+
+        // 非固定表:保持原逻辑
+        if (surveyTemplateId) {
+          // 先取字段元数据(含 isAuditPeriod),用于后续展示/兼容
+          fetchHeaderMeta({
+            surveyTemplateId,
+            ...(versionId ? { versionId } : {}),
+            type: 1,
+          })
+            .then((res) => {
+              if (res && res.code === 200 && Array.isArray(res.value)) {
+                this.$set(
+                  this.contentEditForm.fixedTable,
+                  'tableHeaders',
+                  res.value
+                )
+                this.$set(
+                  this.contentEditForm.dynamicTable,
+                  'tableHeaders',
+                  res.value
+                )
+              }
+            })
+            .catch(() => {})
+
+          // 再取数据明细
+          fetchTemplateItems({ surveyTemplateId }).then((res) => {
+            if (
+              this.contentEditForm.templateType === '1' ||
+              this.contentEditForm.templateType === '2'
+            ) {
+              this.parseAndDisplayFixedTableData(res)
+            } else if (this.contentEditForm.templateType === '3') {
+              this.parseAndDisplayDynamicTableData(res)
+            }
+          })
+        }
       },
       /**
        * 解析并回显固定表、单记录项目数据
@@ -879,6 +1095,7 @@
 
 <style scoped lang="scss">
   @import '@/styles/costAudit.scss';
+
   .survey-dialog-container {
     .content-edit-container {
       .table-header-info {
@@ -888,45 +1105,56 @@
         padding: 10px;
         background-color: #f5f7fa;
         border-radius: 4px;
+
         .table-name {
           font-weight: bold;
           color: #303133;
         }
+
         .table-style {
           .el-radio-group {
             margin-left: 10px;
           }
         }
       }
+
       .table-edit-container {
         margin-top: 20px;
+
         .format-input {
           display: flex;
           align-items: center;
+
           .format-prefix {
             margin-right: 5px;
             color: #606266;
           }
         }
+
         .bind-dict-column {
           display: flex;
           flex-direction: column;
+
           .dict-select {
             margin-left: 0 !important;
           }
         }
       }
+
       ::v-deep .category-row {
         background-color: #f5f7fa !important;
+
         td {
           background-color: #f5f7fa !important;
           font-weight: 600;
         }
+
         .category-name {
           color: #409eff;
           font-weight: 600;
         }
       }
+
       .table-item-text {
         display: inline-block;
         width: 100%;

+ 174 - 13
src/views/home/index.vue

@@ -65,7 +65,12 @@
               class="news-item-new"
             >
               <span class="news-dot"></span>
-              <span class="news-title-text">{{ item.noticeTitle }}</span>
+              <span
+                class="news-title-text clickable"
+                @click="handleNewsDetail(item)"
+              >
+                {{ item.noticeTitle }}
+              </span>
               <span class="news-author">{{ item.remark || '管理员' }}</span>
               <span class="news-time">{{ item.createTime }}</span>
             </li>
@@ -115,7 +120,7 @@
             <template slot="empty">
               <Empty></Empty>
             </template>
-            <el-table-column
+            <!-- <el-table-column
               type="index"
               label="序号"
               width="80"
@@ -126,17 +131,25 @@
                 <span v-if="curOrg == '企业单位'">
                   {{ scope.$index + 1 }}
                 </span>
-                <!-- 只显示父节点的序号 -->
                 <div v-else>
-                  <!-- <span v-if="scope.row.children">
-                    {{ getParentNodeIndex(scope.row) }}
-                  </span>
-                  <span v-else></span> -->
                   <span>
                     {{ getParentNodeIndex(scope.row) }}
                   </span>
                 </div>
               </template>
+            </el-table-column> -->
+            <el-table-column
+              prop="warningStatus"
+              label="预警"
+              header-align="center"
+              align="center"
+              width="80"
+            >
+              <template slot-scope="scope">
+                <span
+                  :class="['warning-point', computeWarning(scope.row)]"
+                ></span>
+              </template>
             </el-table-column>
             <el-table-column
               prop="projectName"
@@ -160,6 +173,8 @@
               width="120"
               show-overflow-tooltip
             />
+            <!-- 预警状态(与督办事项页面一致:圆点) -->
+
             <el-table-column
               v-if="curOrg != '企业单位'"
               prop="source"
@@ -562,14 +577,81 @@
     />
     <taskDetail ref="taskDetail" />
     <!-- 填报任务侧边弹窗 -->
-    <task-fill-in
+    <TaskFillIn
       ref="taskFillIn"
-      :visible.sync="taskFillInVisible"
-      :task-info="currentTaskInfo"
-      :view-mode="taskViewMode"
-      @close="handleTaskFillInClose"
       @refresh="handleTaskFillInRefresh"
+      @close="handleTaskFillInClose"
     />
+    <!-- 最新消息详情弹窗(复用通知公告页详情样式与字段) -->
+    <el-dialog
+      title="详情"
+      :visible.sync="noticeDetailVisible"
+      width="60%"
+      :close-on-click-modal="false"
+    >
+      <el-form
+        ref="noticeDetailForm"
+        :model="noticeDetailForm"
+        label-width="140px"
+        disabled
+      >
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="标题:">
+              {{ noticeDetailForm.noticeTitle }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="类型:">
+              {{ noticeDetailForm.noticeType == 1 ? '通知' : '公告' }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="消息来源:">
+              {{ noticeDetailForm.noticeSource }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="状态:">
+              {{ noticeDetailForm.status == '0' ? '未读' : '已读' }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="发送时间:">
+              {{ noticeDetailForm.createTime }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="项目名称:">
+              {{ noticeDetailForm.projectName }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="被监审单位名称:">
+              {{ noticeDetailForm.enterpriseName }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="24">
+            <el-form-item label="内容:">
+              {{ noticeDetailForm.noticeContent }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="备注:">
+              {{ noticeDetailForm.remark }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+    </el-dialog>
   </div>
 </template>
 
@@ -580,7 +662,12 @@
   import { memoManageMixin } from '@/views/costAudit/projectInfo/auditProjectManage/memoManage/memoManageMixin'
   import { doProcessBtn } from '@/api/dataPreliminaryReview'
   import { getReviewTaskList } from '@/api/audit/auditIndex'
-  import { getChartList, getMsgList } from '@/api/home'
+  import {
+    getChartList,
+    getMsgList,
+    readNotice,
+    getNoticeDetail,
+  } from '@/api/home'
   import detailsDialog from '@/views/costAudit/auditInfo/auditManage/details.vue'
   import mainDetailsDialog from '@/views/costAudit/auditInfo/auditManage/mainDetails.vue'
   import taskInfo from '@/components/task/taskInfo.vue'
@@ -641,6 +728,9 @@
         taskFillInVisible: false,
         currentTaskInfo: {},
         taskViewMode: false,
+        // 最新消息详情弹窗
+        noticeDetailVisible: false,
+        noticeDetailForm: {},
       }
     },
     watch: {
@@ -694,6 +784,26 @@
           console.error('加载最新消息失败:', error)
         }
       },
+      // 最新消息:点击标题查看详情(复用通知公告页详情弹窗)
+      handleNewsDetail(row) {
+        const noticeId = row && (row.noticeId || row.id)
+        if (!noticeId) return
+
+        // 标记已读并刷新列表
+        readNotice({ id: noticeId })
+          .then(() => {
+            this.loadNewsList()
+          })
+          .catch(() => {})
+
+        // 获取详情并打开弹窗
+        getNoticeDetail({ id: noticeId }).then((res) => {
+          if (res && res.value) {
+            this.noticeDetailForm = { ...res.value }
+            this.noticeDetailVisible = true
+          }
+        })
+      },
       // 待办事项搜索
       handleTodoSearch() {
         this.pagination.page = 1
@@ -767,6 +877,9 @@
                 projectName: record.projectName,
                 auditObject: record.auditedUnitName,
                 auditPeriod: record.auditPeriod,
+                warningStatus: record.warningStatus,
+                nodeDeadline: record.nodeDeadline,
+                processDeadline: record.processDeadline,
                 source: this.getSourceTypeText(record.sourceType),
                 form: this.getAuditTypeText(record.auditType),
                 status: this.getStatusText(record.status),
@@ -782,6 +895,9 @@
                       projectName: child.projectName,
                       auditObject: child.auditedUnitName,
                       auditPeriod: record.auditPeriod,
+                      warningStatus: child.warningStatus,
+                      nodeDeadline: child.nodeDeadline,
+                      processDeadline: child.processDeadline,
                       source: '',
                       form: '',
                       currentNode: child.currentNode,
@@ -865,6 +981,26 @@
         const day = date.getDay() // 0-6,0表示周日,6表示周六
         return day === 0 || day === 6 // 周日或周六为周末
       },
+      // 预警颜色计算(与督办事项页面一致)
+      computeWarning(row) {
+        if (!row) return ''
+        const ws = (row.warningStatus || '').toString().toLowerCase()
+        if (ws === 'green') return 'green'
+        if (ws === 'yellow') return 'yellow'
+        if (ws === 'res' || ws === 'red') return 'red'
+
+        const parse = (v) => (v ? new Date(v) : null)
+        const now = new Date()
+        const nodeDdl = parse(row.nodeDeadline)
+        const procDdl = parse(row.processDeadline)
+        if (nodeDdl && now <= nodeDdl) return 'green'
+        if (nodeDdl && procDdl) {
+          if (now > nodeDdl && now <= procDdl) return 'yellow'
+          if (now > procDdl) return 'red'
+        }
+        if (!nodeDdl && procDdl) return now <= procDdl ? 'green' : 'red'
+        return ''
+      },
       initChart() {
         // 保存图表实例到组件实例中
         this.chart = echarts.init(this.$refs.chartRef)
@@ -1302,6 +1438,13 @@
     white-space: nowrap;
     margin-right: 20px;
   }
+  .news-title-text.clickable {
+    cursor: pointer;
+  }
+  .news-title-text.clickable:hover {
+    color: #409eff;
+    text-decoration: underline;
+  }
   .news-author {
     color: #999999;
     margin-right: 20px;
@@ -1386,6 +1529,24 @@
   .no-zebra ::v-deep .el-table__body tr:hover > td {
     background-color: #f5f7fa !important;
   }
+
+  /* 预警点样式(与督办事项页面一致) */
+  .warning-point {
+    display: inline-block;
+    width: 12px;
+    height: 12px;
+    border-radius: 50%;
+  }
+  .warning-point.red {
+    background-color: #ff4949;
+  }
+  .warning-point.yellow {
+    background-color: #e6a23c;
+  }
+  .warning-point.green {
+    background-color: #67c23a;
+  }
+
   .w40 {
     width: 40%;
   }