Browse Source

[Mod 0000]数据质量页面导出增加弹框选择时间范围

wangkeyi 3 months ago
parent
commit
b923a96247

+ 1 - 0
src/views/dashboard/basicInfo/dataQuality/components/DataQualityModal.vue

@@ -8,6 +8,7 @@
     :min-height="600"
     :max-height="1000"
     scrollable
+    centered
     destroyOnClose
     :bodyStyle="{ padding: '20px' }"
   >

+ 25 - 26
src/views/dashboard/basicInfo/dataQuality/dataQuality.data.ts

@@ -135,32 +135,6 @@ export function getSearchFormSchema(dynamicStatusOptions: Ref<{ label: string; v
       groupName: '常规查询',
       show: false,
     },
-    {
-      field: 'startTime',
-      label: '起始日期',
-      component: 'DatePicker',
-      componentProps: {
-        //日期格式化,页面上显示的值
-        format: 'YYYY-MM-DD hh:mm:ss',
-        //返回值格式化(绑定值的格式)
-        valueFormat: 'YYYY-MM-DD hh:mm:ss',
-      },
-      defaultValue: dayjs().add(-30, 'day').format('YYYY-MM-DD hh:mm:ss'),
-      colProps: { span: 6 },
-    },
-    {
-      field: 'endTime',
-      label: '结束日期',
-      component: 'DatePicker',
-      componentProps: {
-        //日期格式化,页面上显示的值
-        format: 'YYYY-MM-DD hh:mm:ss',
-        //返回值格式化(绑定值的格式)
-        valueFormat: 'YYYY-MM-DD hh:mm:ss',
-      },
-      defaultValue: dayjs().format('YYYY-MM-DD hh:mm:ss'),
-      colProps: { span: 6 },
-    },
   ];
   return searchFormSchema;
 }
@@ -239,3 +213,28 @@ export const formSchema: FormSchema[] = [
   //   ],
   // },
 ];
+
+export const exportFormSchema: FormSchema[] = [
+  {
+    field: 'startTime',
+    label: '开始时间',
+    component: 'DatePicker',
+    componentProps: {
+      showTime: true,
+      format: 'YYYY-MM-DD HH:mm:ss',
+    },
+    required: true,
+    rules: [{ required: true, message: '请选择开始时间', trigger: 'blur' }],
+  },
+  {
+    field: 'endTime',
+    label: '结束时间',
+    component: 'DatePicker',
+    componentProps: {
+      showTime: true,
+      format: 'YYYY-MM-DD HH:mm:ss',
+    },
+    required: true,
+    rules: [{ required: true, message: '请选择结束时间', trigger: 'blur' }],
+  },
+];

+ 161 - 47
src/views/dashboard/basicInfo/dataQuality/index.vue

@@ -6,11 +6,8 @@
       <BasicTable style="padding: 0" @register="registerUnresolvedTable">
         <template #resetBefore>
           <a-button type="primary" class="ml-8px" preIcon="mdi:page-next-outline" @click="handleOpenModal({}, 'add')"> 新增问题 </a-button>
-          <a-button type="default" class="ml-8px" preIcon="mdi:download" @click="onExportXlsA"> 导出 </a-button>
+          <a-button type="default" class="ml-8px" preIcon="mdi:download" @click="handleOpenExportModal('unresolved')"> 导出 </a-button>
         </template>
-        <!-- <template #submitBefore>
-          <a-button type="primary" preIcon="mdi:page-next-outline" @click="handleOpenModal({}, 'add')"> 新增问题 </a-button>
-        </template> -->
         <template #queJson="{ record }">
           <div style="display: flex; align-items: center; gap: 8px; width: 100%; justify-content: space-between">
             <span style="white-space: pre-line; word-wrap: break-word; line-height: 1.6; display: block; text-align: left; padding: 2px 4px">
@@ -61,14 +58,13 @@
     <TabPane key="resolved" tab="已解决">
       <BasicTable style="padding: 0" @register="registerResolvedTable">
         <template #resetBefore>
-          <a-button type="default" class="ml-8px" preIcon="mdi:download" @click="onExportXlsB"> 导出 </a-button>
+          <a-button type="default" class="ml-8px" preIcon="mdi:download" @click="handleOpenExportModal('resolved')"> 导出 </a-button>
         </template>
         <template #queJson="{ record }">
           <div style="display: flex; align-items: center; gap: 8px; width: 100%">
             <span style="flex: 1; text-align: center">
               {{ record?.queJson ? formatQueJson(record.queJson) : '' }}
             </span>
-            <!-- 按钮:无需额外样式,自然靠最右侧 -->
             <button @click="record && handleOpenModal(record, 'view')" class="action-btn" title="查看问题详情">
               <SvgIcon name="view" />
             </button>
@@ -85,22 +81,63 @@
 
   <!-- 处理弹框 -->
   <DataQualityModal @register="registerModal" @success="handleModalSuccess" />
+
+  <!-- 导出时间选择Modal-->
+  <Modal
+    v-model:open="exportModalVisible"
+    title="选择导出时间范围"
+    :width="600"
+    @ok="handleExportConfirm"
+    @cancel="handleExportCancel"
+    okText="确认导出"
+    cancelText="取消"
+    centered
+    :confirm-loading="exportConfirmLoading"
+    destroyOnClose
+    :bodyStyle="{ padding: '20px' }"
+  >
+    <a-form
+      ref="exportFormRef"
+      :model="exportFormData"
+      :rules="exportFormRules"
+      layout="horizontal"
+      :label-col="{ span: 6 }"
+      :wrapper-col="{ span: 18 }"
+    >
+      <a-form-item
+        v-for="schema in exportFormSchema"
+        :key="schema.field"
+        :name="schema.field"
+        :label="schema.label"
+        :rules="schema.rules"
+      >
+        <component
+          :is="getExportFormComponent(schema.component)"
+          v-model:value="exportFormData[schema.field]"
+          v-bind="schema.componentProps"
+          :placeholder="`请选择${schema.label}`"
+          style="width: 100%"
+        />
+      </a-form-item>
+    </a-form>
+  </Modal>
 </template>
 
 <script setup lang="ts">
-  import { ref, nextTick, computed, onMounted } from 'vue';
+  import { ref, nextTick, computed, onMounted, reactive } from 'vue';
   import { useRouter } from 'vue-router';
-  import { BasicTable } from '/@/components/Table';
+  import { BasicTable, } from '/@/components/Table';
   import { useModal } from '/@/components/Modal';
-  import { Tabs, TabPane, Popconfirm, message } from 'ant-design-vue';
+  import { Tabs, TabPane, Popconfirm, message, Modal, DatePicker } from 'ant-design-vue';
+  import type { FormInstance } from 'ant-design-vue/es/form';
   import DataQualityModal from './components/DataQualityModal.vue';
   import { SvgIcon } from '/@/components/Icon';
-  import { getColumns, getSearchFormSchema, type ProductionStatusMap } from './dataQuality.data';
+  import { getColumns, getSearchFormSchema, type ProductionStatusMap, exportFormSchema } from './dataQuality.data';
   import { getDataQuaQueList, addDataQuaQue, deleteDataQuaQue, editDataQuaQue } from '../basicInfo.api';
   import { findNode } from '/@/utils/helper/treeHelper';
   import { useMineDepartmentStore } from '/@/store/modules/mine';
   import { getDictItemsByCode } from '/@/utils/dict';
-  import dayjs from 'dayjs';
+  import dayjs, { Dayjs } from 'dayjs';
   import { useListPage } from '/@/hooks/system/useListPage';
 
   // 路由实例
@@ -110,6 +147,43 @@
   // 响应式数据
   const activeKey = ref('unresolved'); // 激活的Tab键
   const pageMode = ref('add');
+  
+  // 导出Modal相关状态
+  const exportModalVisible = ref(false);
+  const exportFormRef = ref<FormInstance>();
+  const exportConfirmLoading = ref(false);
+  const exportType = ref<'resolved' | 'unresolved'>('unresolved'); // 记录当前导出类型
+  const exportConfig = ref({
+    url: '/province/dataQuaQue/exportDataQuaQueList',
+    name: '数据质量',
+    params: {
+      isOk: 0,
+      startTime: '',
+      endTime: '',
+    },
+  });
+
+  // 导出表单数据和规则(参考DataQualityModal写法)
+  const exportFormData = reactive({
+    startTime: null as Dayjs | null,
+    endTime: null as Dayjs | null,
+  });
+
+  // 提取导出表单规则(从exportFormSchema)
+  const exportFormRules = reactive({
+    startTime: exportFormSchema.find(item => item.field === 'startTime')?.rules || [],
+    endTime: exportFormSchema.find(item => item.field === 'endTime')?.rules || [],
+  });
+
+  // 导出表单组件映射
+  const exportFormComponentMap = {
+    DatePicker,
+  };
+
+  // 获取导出表单组件
+  const getExportFormComponent = (componentName: string) => {
+    return exportFormComponentMap[componentName as keyof typeof exportFormComponentMap];
+  };
 
   // ========== 定义动态状态映射/下拉选项 ==========
   // 1. 动态生产状态映射(key: 状态value,value: 包含label/color的配置)
@@ -183,7 +257,6 @@
       indexColumnProps: {
         title: '序号',
       },
-      // canResize: false,
       actionColumn: {
         width: 200,
         title: '操作',
@@ -192,19 +265,13 @@
       },
       immediate: false, // 先不立即加载,等状态数据获取后再加载
     },
-    exportConfig: {
-      url: '/province/dataQuaQue/exportDataQuaQueList',
-      name: '数据质量',
-      params: {
-        isOk: 0,
-      },
-    },
+    exportConfig: exportConfig.value,
   });
 
   const [registerUnresolvedTable, { reload: reloadUnresolved }] = tableContextA;
 
   // 已解决表格注册
-  const { tableContext: tableContextB, onExportXls: onExportXlsB } = useListPage({
+  const { tableContext: tableContextB, onExportXls: onExportXlsB  } = useListPage({
     tableProps: {
       api: async (params: any) => {
         return await getDataQuaQueList({ ...params, isOk: true });
@@ -219,7 +286,6 @@
       useSearchForm: true,
       pagination: true,
       striped: true,
-      // bordered: true,
       showIndexColumn: false,
       indexColumnProps: {
         title: '序号',
@@ -232,13 +298,7 @@
       },
       immediate: false, // 先不立即加载
     },
-    exportConfig: {
-      url: '/province/dataQuaQue/exportDataQuaQueList',
-      name: '数据质量',
-      params: {
-        isOk: 1,
-      },
-    },
+    exportConfig: exportConfig.value,
   });
 
   const [registerResolvedTable, { reload: reloadResolved }] = tableContextB;
@@ -246,6 +306,77 @@
   // 弹框注册
   const [registerModal, { openModal }] = useModal();
 
+  /**
+   * 打开导出时间选择Modal
+   * @param type 导出类型:resolved 或 unresolved
+   */
+  function handleOpenExportModal(type: 'resolved' | 'unresolved') {
+    exportType.value = type;
+    exportModalVisible.value = true;
+    // 打开Modal时重置表单
+    nextTick(() => {
+      exportFormRef.value?.resetFields();
+      exportFormData.startTime = null;
+      exportFormData.endTime = null;
+    });
+  }
+
+  /**
+   * 导出Modal确认处理
+   */
+  async function handleExportConfirm() {
+    try {
+      exportConfirmLoading.value = true;
+      // 表单校验(参考DataQualityModal的校验方式)
+      if (!exportFormRef.value) return;
+      const validateResult = await exportFormRef.value.validate();
+      if (!validateResult) return;
+
+      // 格式化时间
+      const startTime = exportFormData.startTime?.format('YYYY-MM-DD HH:mm:ss') || '';
+      const endTime = exportFormData.endTime?.format('YYYY-MM-DD HH:mm:ss') || '';
+
+      // 校验时间逻辑(结束时间不能早于开始时间)
+      if (exportFormData.startTime && exportFormData.endTime && dayjs(endTime).isBefore(dayjs(startTime))) {
+        message.error('结束时间不能早于开始时间');
+        return;
+      }
+
+      // 根据类型选择对应的exportConfig和导出方法
+      exportConfig.value.params = {
+        isOk: exportType.value === 'resolved' ? 1 : 0,
+        startTime,
+        endTime,
+      };
+
+      if (exportType.value === 'unresolved') {
+        await onExportXlsA();
+      } else {
+        await onExportXlsB();
+      }
+
+      // 关闭Modal
+      exportModalVisible.value = false;
+      message.success('导出请求已发送,请注意查收文件');
+    } catch (error: any) {
+      console.error('导出失败:', error);
+      message.error(error.message || '导出失败,请检查表单填写是否正确');
+    } finally {
+      exportConfirmLoading.value = false;
+    }
+  }
+
+  /**
+   * 导出Modal取消处理
+   */
+  function handleExportCancel() {
+    exportModalVisible.value = false;
+    // 取消时重置表单
+    exportFormRef.value?.resetFields();
+    exportFormData.startTime = null;
+    exportFormData.endTime = null;
+  }
+
   // 解析queJson并拼接orderNum+queCon的辅助函数
   function formatQueJson(queJsonStr: string) {
     // 空值处理
@@ -309,17 +440,6 @@
     await safeReloadActiveTable();
   }
 
-  /**
-   * 根据标签获取表格数据(已解决/未解决)
-   * @param result 弹框数据
-   */
-  // function getQuaQueListByTab() {
-  //   return async (params: any) => {
-  //     const isOk = activeKey.value === 'resolved' ? true : false;
-  //     return await getDataQuaQueList({ ...params, isOk: isOk });
-  //   };
-  // }
-
   /**
    * 打开弹框函数
    * @param result 弹框数据
@@ -413,8 +533,10 @@
     try {
       await editDataQuaQue(copyRecord);
       await safeReloadActiveTable();
+      message.success('标记为已解决成功');
     } catch (error) {
       console.error('操作失败:', error);
+      message.error('操作失败,请稍后重试');
     }
   }
 
@@ -426,14 +548,6 @@
 </script>
 
 <style scoped lang="less">
-  // .data-quality-page {
-  //   padding: 0 12px;
-  //   margin: 16px;
-  //   border: 1px solid @border-color-base;
-  //   .ant-form {
-  //     background-color: #fff;
-  //   }
-  // }
   .form-part {
     padding: 12px 10px 6px 10px;
     margin-bottom: 8px;