|
|
@@ -1,7 +1,7 @@
|
|
|
<!-- eslint-disable vue/multi-word-component-names -->
|
|
|
<template>
|
|
|
<!-- Tab标签页 -->
|
|
|
- <Tabs v-model:activeKey="activeKey" class="common-page-tabs" type="line">
|
|
|
+ <Tabs v-model:activeKey="activeKey" class="common-page-tabs" type="line" @change="handleTabChange">
|
|
|
<TabPane key="unresolved" tab="未解决">
|
|
|
<div class="add-button">
|
|
|
<a-button type="default" preIcon="mdi:download" @click="handleExportExcel" style="margin-right: 8px"> 导出 </a-button>
|
|
|
@@ -86,18 +86,23 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
- import { ref, nextTick, computed } from 'vue';
|
|
|
+ import { ref, nextTick, computed, onMounted } from 'vue';
|
|
|
import { useRouter } from 'vue-router';
|
|
|
- import { BasicTable, useTable } from '/@/components/Table';
|
|
|
+ import { BasicTable, useTable, BasicColumn, FormSchema } from '/@/components/Table';
|
|
|
import { useModal } from '/@/components/Modal';
|
|
|
import { Tabs, TabPane, Popconfirm, message } from 'ant-design-vue';
|
|
|
import DataQualityModal from './components/DataQualityModal.vue';
|
|
|
import { SvgIcon } from '/@/components/Icon';
|
|
|
- import { columns, searchFormSchema, productionStatusMap } from './dataQuality.data';
|
|
|
+ import {
|
|
|
+ getColumns,
|
|
|
+ getSearchFormSchema,
|
|
|
+ type ProductionStatusMap,
|
|
|
+ } from './dataQuality.data';
|
|
|
import { getDataQuaQueList, addDataQuaQue, deleteDataQuaQue, editDataQuaQue } from '../basicInfo.api';
|
|
|
- import { findNode, findPath, listToTree } from '/@/utils/helper/treeHelper';
|
|
|
+ import { findNode } from '/@/utils/helper/treeHelper';
|
|
|
import { useMineStore } from '/@/store/modules/mine';
|
|
|
- import dayjs from 'dayjs';
|
|
|
+ import { getDictItemsByCode } from '/@/utils/dict';
|
|
|
+ import dayjs from 'dayjs';
|
|
|
import * as XLSX from 'xlsx';
|
|
|
// 路由实例
|
|
|
const router = useRouter();
|
|
|
@@ -106,13 +111,67 @@
|
|
|
// 响应式数据
|
|
|
const activeKey = ref('unresolved'); // 激活的Tab键
|
|
|
const pageMode = ref('add');
|
|
|
+
|
|
|
+ // ========== 定义动态状态映射/下拉选项 ==========
|
|
|
+ // 1. 动态生产状态映射(key: 状态value,value: 包含label/color的配置)
|
|
|
+ const dynamicProductionStatusMap = ref<ProductionStatusMap>({});
|
|
|
+ // 2. 动态下拉选项(供搜索表单使用)
|
|
|
+ const dynamicProductionStatusOptions = ref<{ label: string; value: string | number }[]>([]);
|
|
|
+
|
|
|
+ // 3. 颜色分配规则(可根据业务灵活调整)
|
|
|
+ const getStatusColor = (statusText: string) => {
|
|
|
+ if (statusText.includes('正常生产')) return 'green'; // 正常生产 → 绿色
|
|
|
+ if (statusText.includes('拟建矿井')) return 'blue'; // 拟建矿井 → 蓝色
|
|
|
+ else return 'red'; // 停产/停建/关闭/整改/责令 → 红色
|
|
|
+ };
|
|
|
+
|
|
|
+ // 4. 从接口获取生产状态列表并生成动态映射/下拉选项
|
|
|
+ const fetchProductionStatus = async () => {
|
|
|
+ try {
|
|
|
+ // 调用接口获取状态列表
|
|
|
+ const statusList = await getDictItemsByCode('mineProStatus');
|
|
|
+ if (!Array.isArray(statusList)) return;
|
|
|
+
|
|
|
+ // 生成动态映射和下拉选项
|
|
|
+ const statusMap: ProductionStatusMap = {};
|
|
|
+ const statusOptions: { label: string; value: string | number }[] = [];
|
|
|
+
|
|
|
+ statusList.forEach((item) => {
|
|
|
+ const value = item.value; // 接口返回的value(数字/字符串)
|
|
|
+ const label = item.text || item.label; // 接口返回的文本
|
|
|
+ const color = getStatusColor(label); // 按规则分配颜色
|
|
|
+
|
|
|
+ // 填充映射表
|
|
|
+ statusMap[value] = { label, value, color };
|
|
|
+ // 填充下拉选项
|
|
|
+ statusOptions.push({ label, value });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 赋值到响应式变量
|
|
|
+ dynamicProductionStatusMap.value = statusMap;
|
|
|
+ dynamicProductionStatusOptions.value = statusOptions;
|
|
|
+
|
|
|
+ // 刷新表格(确保表格使用最新的映射)
|
|
|
+ await safeReloadActiveTable();
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取生产状态列表失败:', error);
|
|
|
+ message.error('生产状态数据加载失败');
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 生成动态列和搜索表单配置
|
|
|
+ const columns = computed(() => getColumns(dynamicProductionStatusMap));
|
|
|
+ const searchFormSchema = computed(() => getSearchFormSchema(dynamicProductionStatusOptions));
|
|
|
+
|
|
|
// 未解决表格注册
|
|
|
const [registerUnresolvedTable, { reload: reloadUnresolved }] = useTable({
|
|
|
- api: getQuaQueListByTab(),
|
|
|
- columns,
|
|
|
+ api: async (params: any) => {
|
|
|
+ return await getDataQuaQueList({ ...params, isOk: false });
|
|
|
+ },
|
|
|
+ columns: columns, // 绑定动态列
|
|
|
formConfig: {
|
|
|
labelWidth: 120,
|
|
|
- schemas: searchFormSchema,
|
|
|
+ schemas: searchFormSchema.value,
|
|
|
showAdvancedButton: false,
|
|
|
schemaGroupNames: ['常规查询'],
|
|
|
},
|
|
|
@@ -129,16 +188,18 @@
|
|
|
dataIndex: 'action',
|
|
|
slots: { customRender: 'action' },
|
|
|
},
|
|
|
- immediate: true,
|
|
|
+ immediate: false, // 先不立即加载,等状态数据获取后再加载
|
|
|
});
|
|
|
|
|
|
// 已解决表格注册
|
|
|
const [registerResolvedTable, { reload: reloadResolved }] = useTable({
|
|
|
- api: getQuaQueListByTab(),
|
|
|
- columns,
|
|
|
+ api: async (params: any) => {
|
|
|
+ return await getDataQuaQueList({ ...params, isOk: true });
|
|
|
+ },
|
|
|
+ columns: columns,
|
|
|
formConfig: {
|
|
|
labelWidth: 120,
|
|
|
- schemas: searchFormSchema,
|
|
|
+ schemas: searchFormSchema.value,
|
|
|
showAdvancedButton: false,
|
|
|
schemaGroupNames: ['常规查询'],
|
|
|
},
|
|
|
@@ -156,7 +217,7 @@
|
|
|
dataIndex: 'action',
|
|
|
slots: { customRender: 'action' },
|
|
|
},
|
|
|
- immediate: true,
|
|
|
+ immediate: false, // 先不立即加载
|
|
|
});
|
|
|
|
|
|
// 弹框注册
|
|
|
@@ -176,7 +237,47 @@
|
|
|
console.error('解析质量问题JSON失败:', error);
|
|
|
return '问题数据解析失败';
|
|
|
}
|
|
|
+ };
|
|
|
+
|
|
|
+ // 安全重载当前激活的表格
|
|
|
+ async function safeReloadActiveTable() {
|
|
|
+ await nextTick();
|
|
|
+ if (activeKey.value === 'unresolved') {
|
|
|
+ try {
|
|
|
+ await reloadUnresolved();
|
|
|
+ } catch (e) {
|
|
|
+ console.warn('未解决表格重载失败:', e);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ try {
|
|
|
+ await reloadResolved();
|
|
|
+ } catch (e) {
|
|
|
+ console.warn('已解决表格重载失败:', e);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+ // 按需重载双表格(仅在「标记已解决」等跨Tab操作时用)
|
|
|
+ async function reloadBothTableSafely() {
|
|
|
+ await nextTick();
|
|
|
+ // 未解决表格:await + try/catch 捕获异步错误
|
|
|
+ try {
|
|
|
+ await reloadUnresolved();
|
|
|
+ } catch (e) {
|
|
|
+ console.warn('未解决表格暂未就绪,跳过重载:', e);
|
|
|
+ }
|
|
|
+ // 已解决表格:同理,一个报错不影响另一个
|
|
|
+ try {
|
|
|
+ await reloadResolved();
|
|
|
+ } catch (e) {
|
|
|
+ console.warn('已解决表格暂未就绪,跳过重载:', e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // tabs切换事件
|
|
|
+ async function handleTabChange(key: string) {
|
|
|
+ activeKey.value = key;
|
|
|
+ await safeReloadActiveTable();
|
|
|
+ };
|
|
|
|
|
|
/**
|
|
|
* 根据标签获取表格数据(已解决/未解决)
|
|
|
@@ -195,10 +296,7 @@
|
|
|
*/
|
|
|
function handleOpenModal(record: any, mode: 'view' | 'edit' | 'add' = 'view') {
|
|
|
pageMode.value = mode;
|
|
|
- openModal(true, {
|
|
|
- record,
|
|
|
- mode,
|
|
|
- });
|
|
|
+ openModal(true, { record, mode });
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -208,43 +306,39 @@
|
|
|
async function handleModalSuccess(result: any) {
|
|
|
try {
|
|
|
if (pageMode.value === 'add') {
|
|
|
- console.log(result);
|
|
|
await addDataQuaQue(result);
|
|
|
} else if (pageMode.value === 'edit') {
|
|
|
await editDataQuaQue(result);
|
|
|
}
|
|
|
- // 刷新表格
|
|
|
- await nextTick();
|
|
|
- reloadUnresolved();
|
|
|
- reloadResolved();
|
|
|
+ await safeReloadActiveTable();
|
|
|
} catch (error) {
|
|
|
console.log('操作失败:', error);
|
|
|
}
|
|
|
}
|
|
|
/**
|
|
|
- * 通用页面跳转方法
|
|
|
- * @param record 当前行数据
|
|
|
- * @param path 目标路径(树形结构所在页面的路由地址)
|
|
|
- */
|
|
|
+ * 通用页面跳转方法
|
|
|
+ * @param record 当前行数据
|
|
|
+ * @param path 目标路径(树形结构所在页面的路由地址)
|
|
|
+ */
|
|
|
async function handleGoToPage(record: any) {
|
|
|
try {
|
|
|
const mineCode = record.mineCode;
|
|
|
- const targetNode = findNode(mineStore.getMineTree, (item) => item.id === mineCode, { id: 'id', pid: 'parentId', children: 'childDepart' });
|
|
|
+ const targetNode = findNode(
|
|
|
+ mineStore.getMineTree,
|
|
|
+ (item) => item.id === mineCode,
|
|
|
+ { id: 'id', pid: 'parentId', children: 'childDepart' }
|
|
|
+ );
|
|
|
|
|
|
let minePath = '';
|
|
|
if (targetNode) {
|
|
|
- minePath = targetNode.parentId; // 取parentId作为minePath
|
|
|
- console.log('minePath(当前节点的parentId):', minePath);
|
|
|
+ minePath = targetNode.parentId;
|
|
|
} else {
|
|
|
message.warning(`未找到矿码【${mineCode}】对应的矿井节点`);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 跳转页面(可携带拼接后的矿名/路径等参数)
|
|
|
- router.push({
|
|
|
- path: `/sealed/${minePath}`,
|
|
|
- query: {},
|
|
|
- });
|
|
|
+ router.push({ path: `/sealed/${minePath}`, query: {} });
|
|
|
} catch (error) {
|
|
|
console.error('矿节点定位失败:', error);
|
|
|
message.error('矿节点定位失败,请稍后重试');
|
|
|
@@ -262,7 +356,7 @@
|
|
|
* 生成已解决气泡提示文案:XX矿井XX问题是否解决了吗?
|
|
|
*/
|
|
|
const getResolveDesc = computed(() => (record: any) => {
|
|
|
- const mineName = record.mineName || '该'; // 矿井名称兜底
|
|
|
+ const mineName = record.mineName || '该';
|
|
|
return `是否确认${mineName}矿井问题已解决?`;
|
|
|
});
|
|
|
|
|
|
@@ -274,7 +368,7 @@
|
|
|
try {
|
|
|
await deleteDataQuaQue({ id: record.id });
|
|
|
await nextTick();
|
|
|
- reloadUnresolved();
|
|
|
+ await safeReloadActiveTable();
|
|
|
} catch (error) {
|
|
|
console.error('删除失败:', error);
|
|
|
}
|
|
|
@@ -288,15 +382,12 @@
|
|
|
const copyRecord = {
|
|
|
...record,
|
|
|
isOk: true,
|
|
|
- updateTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
|
|
+ updateTime: dayjs().format('YYYY-MM-DD HH:mm:ss')
|
|
|
};
|
|
|
- copyRecord.isOk = true;
|
|
|
try {
|
|
|
await editDataQuaQue(copyRecord);
|
|
|
- await nextTick();
|
|
|
- reloadUnresolved();
|
|
|
- reloadResolved();
|
|
|
- } catch (error) {
|
|
|
+ await safeReloadActiveTable();
|
|
|
+ }catch (error) {
|
|
|
console.error('操作失败:', error);
|
|
|
}
|
|
|
}
|
|
|
@@ -307,7 +398,7 @@
|
|
|
async function getAllUnresolvedData() {
|
|
|
try {
|
|
|
const res = await getDataQuaQueList({ pageNum: 1, pageSize: 9999, isOk: false });
|
|
|
- return res.records || []; // 请根据实际接口返回结构调整(比如res.list / res.data等)
|
|
|
+ return res.records || [];
|
|
|
} catch (error) {
|
|
|
console.error('获取未解决数据失败:', error);
|
|
|
return [];
|
|
|
@@ -320,7 +411,7 @@
|
|
|
async function getAllResolvedData() {
|
|
|
try {
|
|
|
const res = await getDataQuaQueList({ pageNum: 1, pageSize: 9999, isOk: true });
|
|
|
- return res.records || []; // 请根据实际接口返回结构调整
|
|
|
+ return res.records || [];
|
|
|
} catch (error) {
|
|
|
console.error('获取已解决数据失败:', error);
|
|
|
return [];
|
|
|
@@ -334,7 +425,7 @@
|
|
|
return dataList.map((item) => ({
|
|
|
煤矿名称: item.mineName || '',
|
|
|
煤矿简称: item.mineNameAbbr || '',
|
|
|
- 生产状态: productionStatusMap[item.mineProStatus]?.label || '未知状态',
|
|
|
+ 生产状态: dynamicProductionStatusMap.value[item.mineProStatus]?.label || '-',
|
|
|
在线状态: item.mineLinkStatus === 1 ? '在线' : item.mineLinkStatus === 0 ? '离线' : '/',
|
|
|
质量问题详情: formatQueJson(item.queJson),
|
|
|
当前状态: item.isOk ? '已解决' : '未解决',
|
|
|
@@ -346,12 +437,10 @@
|
|
|
* 导出Excel核心方法
|
|
|
*/
|
|
|
async function handleExportExcel() {
|
|
|
- // 声明关闭函数
|
|
|
let hideLoading: () => void = () => {};
|
|
|
try {
|
|
|
- // 初始化loading并获取关闭函数
|
|
|
hideLoading = message.loading('正在导出数据,请稍候...');
|
|
|
-
|
|
|
+
|
|
|
const unresolvedList = await getAllUnresolvedData();
|
|
|
const resolvedList = await getAllResolvedData();
|
|
|
|
|
|
@@ -368,18 +457,20 @@
|
|
|
const fileName = `数据质量问题_${dayjs().format('YYYYMMDDHHmmss')}.xlsx`;
|
|
|
XLSX.writeFile(workbook, fileName);
|
|
|
|
|
|
- // 关闭加载提示
|
|
|
hideLoading();
|
|
|
message.success('导出成功!');
|
|
|
} catch (error) {
|
|
|
- // 容错:若loading已初始化,再调用关闭
|
|
|
- if (hideLoading) {
|
|
|
- hideLoading();
|
|
|
- }
|
|
|
+ if (hideLoading) hideLoading();
|
|
|
console.error('Excel导出失败:', error);
|
|
|
message.error('导出失败,请稍后重试');
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // ========== 初始化:先获取状态数据,再加载表格 ==========
|
|
|
+ onMounted(async () => {
|
|
|
+ await fetchProductionStatus(); // 先获取动态状态数据
|
|
|
+ await safeReloadActiveTable();
|
|
|
+ });
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="less">
|