Huanyi 2 mēneši atpakaļ
vecāks
revīzija
4128e32356

+ 13 - 1
src/api/Qc/task/index.ts

@@ -1,6 +1,6 @@
 import request from '@/utils/request';
 import { AxiosPromise } from 'axios';
-import { TaskVO, TaskForm, TaskQuery, TaskDetailAuditForm } from '@/api/qc/task/types';
+import { TaskVO, TaskForm, TaskQuery, TaskDetailAuditForm, TaskLogQuery, TaskLogVO } from '@/api/qc/task/types';
 
 /**
  * 查询文档质控任务列表
@@ -108,3 +108,15 @@ export const auditTaskDetail = (data: TaskDetailAuditForm): AxiosPromise<any> =>
     data: data
   });
 };
+
+/**
+ * 查询质控任务审核记录
+ * @param query
+ */
+export const listTaskLogOnDetail = (query?: any): AxiosPromise<any> => {
+  return request({
+    url: '/qcTask/log/listOnDetail',
+    method: 'get',
+    params: query
+  });
+};

+ 125 - 0
src/api/Qc/task/types.ts

@@ -379,3 +379,128 @@ export interface TaskDetailAuditForm {
    */
   deadline?: string;
 }
+
+/**
+ * 质控任务审核记录查询参数
+ */
+export interface TaskLogQuery extends PageQuery {
+  /**
+   * 详情ID
+   */
+  detailId?: number;
+
+  /**
+   * 审核结果
+   */
+  result?: number;
+
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}
+
+/**
+ * 质控任务审核记录
+ */
+export interface TaskLogVO {
+  /**
+   * 序号
+   */
+  id: number;
+
+  /**
+   * 详情ID
+   */
+  detailId: number;
+
+  /**
+   * 执行时间
+   */
+  executeTime: string;
+
+  /**
+   * 审核结果:1-通过,2-驳回
+   */
+  result: number;
+
+  /**
+   * 问题类型
+   */
+  questionType?: string;
+
+  /**
+   * 问题类型名称
+   */
+  questionTypeName?: string;
+
+  /**
+   * 意见
+   */
+  opinion?: string;
+
+  /**
+   * 指定处理人ID
+   */
+  designatedDealer?: number;
+
+  /**
+   * 指定处理人名称
+   */
+  designatedDealerName?: string;
+
+  /**
+   * 截止日期
+   */
+  deadline?: string;
+
+  /**
+   * 实际处理人ID
+   */
+  actualDealer?: number;
+
+  /**
+   * 实际处理人名称
+   */
+  actualDealerName?: string;
+
+  /**
+   * 处理时间
+   */
+  dealTime?: string;
+
+  /**
+   * 质控版本(OSS ID)
+   */
+  qcVersion?: string | number;
+
+  /**
+   * 处理版本(OSS ID)
+   */
+  dealVersion?: string | number;
+
+  /**
+   * 创建者
+   */
+  createBy?: number;
+
+  /**
+   * 创建者名称
+   */
+  createByName?: string;
+
+  /**
+   * 创建时间
+   */
+  createTime?: string;
+
+  /**
+   * 更新者
+   */
+  updateBy?: number;
+
+  /**
+   * 更新时间
+   */
+  updateTime?: string;
+}

+ 12 - 0
src/api/home/dashboard/index.ts

@@ -0,0 +1,12 @@
+import request from '@/utils/request';
+import { OverviewVO } from './types';
+
+/**
+ * 获取总览数据
+ */
+export const getOverview = () => {
+    return request<OverviewVO>({
+        url: '/home/dashboard/overview',
+        method: 'get'
+    });
+};

+ 29 - 0
src/api/home/dashboard/types.ts

@@ -0,0 +1,29 @@
+/**
+ * 总览数据
+ */
+export interface OverviewVO {
+    /**
+     * 总数
+     */
+    total: number;
+
+    /**
+     * 已递交数量
+     */
+    submitted: number;
+
+    /**
+     * 待递交数量
+     */
+    toSubmit: number;
+
+    /**
+     * 逾期未递交数量
+     */
+    lateToSubmit: number;
+
+    /**
+     * 逾期已提交数量
+     */
+    lateSubmitted: number;
+}

+ 1 - 0
src/components/QcLogDialog/index.ts

@@ -0,0 +1 @@
+export { default } from './index.vue';

+ 250 - 0
src/components/QcLogDialog/index.vue

@@ -0,0 +1,250 @@
+<template>
+  <el-dialog v-model="visible" title="审核记录" width="1200px" append-to-body @close="handleClose">
+    <div class="mb-4">
+      <el-form :inline="true" :model="queryParams">
+        <el-form-item label="审核结果">
+          <el-select v-model="queryParams.result" placeholder="请选择审核结果" clearable style="width: 150px">
+            <el-option label="通过" :value="1" />
+            <el-option label="驳回" :value="2" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="执行时间">
+          <el-date-picker
+            v-model="queryParams.executeTimeRange"
+            type="daterange"
+            range-separator="-"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            value-format="YYYY-MM-DD"
+            style="width: 240px"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" icon="Search" @click="handleQuery">查询</el-button>
+          <el-button icon="Refresh" @click="handleReset">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <el-table v-loading="loading" :data="logList" border max-height="500">
+      <el-table-column prop="id" label="序号" width="80" />
+      <el-table-column prop="executeTime" label="执行时间" width="180" />
+      <el-table-column label="审核结果" width="100">
+        <template #default="scope">
+          <el-tag v-if="scope.row.result === 1" type="success">通过</el-tag>
+          <el-tag v-else-if="scope.row.result === 2" type="danger">驳回</el-tag>
+          <el-tag v-else type="info">未知</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="问题类型" width="120" show-overflow-tooltip>
+        <template #default="scope">
+          <dict-tag :options="qc_question_type" :value="scope.row.questionType" />
+        </template>
+      </el-table-column>
+      <el-table-column prop="opinion" label="意见" min-width="150" show-overflow-tooltip />
+      <el-table-column prop="designatedDealer" label="指定处理人" width="120" />
+      <el-table-column label="截止日期" width="120">
+        <template #default="scope">
+          {{ scope.row.deadline ? parseTime(scope.row.deadline, '{y}-{m}-{d}') : '-' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="actualDealer" label="实际处理人" width="120" />
+      <el-table-column prop="dealTime" label="处理时间" width="180" />
+      <el-table-column prop="createBy" label="创建者" width="120" />
+      <el-table-column prop="createTime" label="创建时间" width="180" />
+      <el-table-column label="操作" width="220" align="center" fixed="right">
+        <template #default="scope">
+          <el-button
+            v-if="scope.row.qcVersion"
+            type="primary"
+            icon="Download"
+            style="padding: 0 5px; font-size: 10px; height: 24px"
+            @click="handleDownloadQcVersion(scope.row)"
+          >
+            下载质控版本
+          </el-button>
+          <el-button
+            v-if="scope.row.dealVersion"
+            type="success"
+            icon="Download"
+            style="padding: 0 5px; font-size: 10px; height: 24px"
+            @click="handleDownloadDealVersion(scope.row)"
+          >
+            下载处理版本
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <div class="mt-4">
+      <pagination
+        v-show="total > 0"
+        :total="total"
+        v-model:page="queryParams.pageNum"
+        v-model:limit="queryParams.pageSize"
+        @pagination="handlePagination"
+      />
+    </div>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import { ref, reactive, watch, toRefs } from 'vue';
+import { listTaskLogOnDetail } from '@/api/qc/task';
+import { TaskLogVO } from '@/api/qc/task/types';
+import { downloadDocumentFile } from '@/api/document/document';
+import { ElMessage } from 'element-plus';
+
+interface Props {
+  modelValue: boolean;
+  detailId?: number;
+}
+
+interface Emits {
+  (e: 'update:modelValue', value: boolean): void;
+}
+
+const props = withDefaults(defineProps<Props>(), {
+  modelValue: false,
+  detailId: undefined
+});
+
+const emit = defineEmits<Emits>();
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { qc_question_type } = toRefs<any>(proxy?.useDict('qc_question_type'));
+
+const visible = ref(false);
+const loading = ref(false);
+const logList = ref<TaskLogVO[]>([]);
+const total = ref(0);
+
+const queryParams = reactive({
+  pageNum: 1,
+  pageSize: 10,
+  detailId: undefined as number | undefined,
+  result: undefined as number | undefined,
+  executeTimeRange: [] as string[],
+  params: {} as any
+});
+
+/** 获取审核记录列表 */
+const fetchLogs = async () => {
+  if (!queryParams.detailId) return;
+
+  try {
+    loading.value = true;
+
+    // 处理时间范围参数
+    const params: any = {};
+    if (queryParams.executeTimeRange && queryParams.executeTimeRange.length === 2) {
+      params.beginExecuteTime = queryParams.executeTimeRange[0];
+      params.endExecuteTime = queryParams.executeTimeRange[1];
+    }
+
+    const requestParams = {
+      pageNum: queryParams.pageNum,
+      pageSize: queryParams.pageSize,
+      detailId: queryParams.detailId,
+      result: queryParams.result,
+      params: params
+    };
+
+    const res = await listTaskLogOnDetail(requestParams);
+    if (res.code === 200) {
+      logList.value = res.rows || [];
+      total.value = res.total || 0;
+    } else {
+      proxy?.$modal.msgError(res.msg || '获取审核记录失败');
+    }
+  } catch (error) {
+    console.error('获取审核记录失败:', error);
+    proxy?.$modal.msgError('获取审核记录失败');
+  } finally {
+    loading.value = false;
+  }
+};
+
+/** 查询 */
+const handleQuery = () => {
+  queryParams.pageNum = 1;
+  fetchLogs();
+};
+
+/** 重置 */
+const handleReset = () => {
+  queryParams.result = undefined;
+  queryParams.executeTimeRange = [];
+  queryParams.pageNum = 1;
+  fetchLogs();
+};
+
+/** 分页变化 */
+const handlePagination = (pageNum: number, pageSize: number) => {
+  queryParams.pageNum = pageNum;
+  queryParams.pageSize = pageSize;
+  fetchLogs();
+};
+
+/** 关闭弹窗 */
+const handleClose = () => {
+  emit('update:modelValue', false);
+};
+
+/** 下载质控版本 */
+const handleDownloadQcVersion = async (row: TaskLogVO) => {
+  if (!row.qcVersion) {
+    ElMessage.warning('暂无质控版本文件');
+    return;
+  }
+  try {
+    await downloadDocumentFile(Number(row.qcVersion), `质控版本_${row.id}`);
+  } catch (error) {
+    console.error('下载质控版本失败:', error);
+    ElMessage.error('下载质控版本失败');
+  }
+};
+
+/** 下载处理版本 */
+const handleDownloadDealVersion = async (row: TaskLogVO) => {
+  if (!row.dealVersion) {
+    ElMessage.warning('暂无处理版本文件');
+    return;
+  }
+  try {
+    await downloadDocumentFile(Number(row.dealVersion), `处理版本_${row.id}`);
+  } catch (error) {
+    console.error('下载处理版本失败:', error);
+    ElMessage.error('下载处理版本失败');
+  }
+};
+
+// 监听 modelValue 变化
+watch(
+  () => props.modelValue,
+  (newVal) => {
+    visible.value = newVal;
+    if (newVal && props.detailId) {
+      // 重置查询参数
+      queryParams.detailId = props.detailId;
+      queryParams.pageNum = 1;
+      queryParams.result = undefined;
+      queryParams.executeTimeRange = [];
+      queryParams.params = {};
+      fetchLogs();
+    }
+  },
+  { immediate: true }
+);
+
+// 监听 visible 变化
+watch(visible, (newVal) => {
+  if (!newVal) {
+    emit('update:modelValue', false);
+  }
+});
+</script>
+
+<style scoped lang="scss">
+// 可以添加自定义样式
+</style>

+ 2 - 1
src/lang/en_US.ts

@@ -116,5 +116,6 @@ export default {
   // 首页模块
   home,
   // 搜索模块
-  search
+  search,
+  // 质控模块
 };

+ 2 - 2
src/lang/modules/document/document/zh_CN.ts

@@ -70,8 +70,8 @@ export default {
     restricted: '限制',
     note: '备注',
     notePlaceholder: '请输入备注',
-    keywords: '标签',
-    keywordsPlaceholder: '请选择标签'
+    keywords: '关键词',
+    keywordsPlaceholder: '请选择关键词'
   },
   // 类型标签
   type: {

+ 1 - 0
src/lang/modules/search/en_US.ts

@@ -26,6 +26,7 @@ export default {
   },
   table: {
     id: 'No.',
+    projectName: 'Project',
     folderName: 'Folder',
     name: 'Document Name',
     type: 'Type',

+ 1 - 0
src/lang/modules/search/zh_CN.ts

@@ -26,6 +26,7 @@ export default {
   },
   table: {
     id: '序号',
+    projectName: '所属项目',
     folderName: '文件夹',
     name: '文档名称',
     type: '类型',

+ 2 - 1
src/lang/zh_CN.ts

@@ -116,5 +116,6 @@ export default {
   // 首页模块
   home,
   // 搜索模块
-  search
+  search,
+  // 质控模块
 };

+ 25 - 8
src/views/Qc/task/detail.vue

@@ -60,7 +60,11 @@
           <h3 class="text-xl font-semibold mb-3">任务列表</h3>
           <el-table v-loading="taskItemsLoading" :data="taskItems" border>
             <el-table-column prop="id" label="序号" width="80" />
-            <el-table-column prop="documentName" label="文档名称" width="180" show-overflow-tooltip />
+            <el-table-column prop="documentName" label="文档名称" width="180" show-overflow-tooltip>
+              <template #default="scope">
+                {{ formatDocumentName(scope.row.documentName) }}
+              </template>
+            </el-table-column>
             <el-table-column prop="executorName" label="质控人" width="150" />
             <el-table-column label="状态" width="120">
               <template #default="scope">
@@ -73,7 +77,7 @@
             <el-table-column prop="executionTime" label="执行时间" width="180" />
             <el-table-column prop="finishTime" label="完成时间" width="180" />
             <el-table-column prop="note" label="备注" />
-            <el-table-column label="操作" width="180" align="center" fixed="right">
+            <el-table-column label="操作" width="280" align="center" fixed="right">
               <template #default="scope">
                 <el-button
                   v-if="taskDetail?.status === 1 && (scope.row.status === 0 || scope.row.status === 3) && scope.row.executor === userStore.userId"
@@ -85,6 +89,10 @@
                   style="padding: 0 5px; font-size: 10px; height: 24px" @click="handleDownload(scope.row)">
                   下载
                 </el-button>
+                <el-button v-hasPermi="['qc:task:logAudit']" type="warning" icon="Document"
+                  style="padding: 0 5px; font-size: 10px; height: 24px" @click="handleViewLog(scope.row)">
+                  查看审核记录
+                </el-button>
               </template>
             </el-table-column>
           </el-table>
@@ -148,6 +156,9 @@
         </div>
       </template>
     </el-dialog>
+
+    <!-- 审核记录弹窗 -->
+    <QcLogDialog v-model="logDialogVisible" :detail-id="currentLogDetailId" />
   </div>
 </template>
 
@@ -163,6 +174,8 @@ import { ElMessage } from 'element-plus';
 import type { FormInstance } from 'element-plus';
 import { useUserStore } from '@/store/modules/user';
 import { parseI18nName } from '@/utils/i18n';
+import { formatDocumentName } from '@/utils/ruoyi';
+import QcLogDialog from '@/components/QcLogDialog/index.vue';
 
 // 定义任务详情项类型
 interface TaskDetailItem {
@@ -204,7 +217,6 @@ const taskId = computed(() => {
   const id = route.query.id;
   if (!id) return undefined;
   const numId = typeof id === 'string' ? parseInt(id) : id;
-  console.log('Task Detail - taskId:', numId, 'from route.query:', route.query.id);
   return numId;
 });
 
@@ -246,6 +258,10 @@ const dealerSearchLoading = ref(false);
 const dealerOptions = ref<MemberNotInCenterVO[]>([]);
 let dealerSearchTimer: NodeJS.Timeout | null = null;
 
+// 审核记录相关
+const logDialogVisible = ref(false);
+const currentLogDetailId = ref<number | undefined>(undefined);
+
 const fetchTaskDetail = async () => {
   if (!taskId.value) return;
 
@@ -392,6 +408,12 @@ const handleDownload = async (row: TaskDetailItem) => {
   await downloadDocumentFile(row.actualDocument, row.actualDocumentName || row.documentName);
 };
 
+/** 查看审核记录 */
+const handleViewLog = (row: TaskDetailItem) => {
+  currentLogDetailId.value = row.id;
+  logDialogVisible.value = true;
+};
+
 const handleBack = () => {
   router.push('/task');
 };
@@ -399,7 +421,6 @@ const handleBack = () => {
 watch(
   () => route.query.id,
   (newId) => {
-    console.log('Route query id changed:', newId);
     if (newId) {
       fetchTaskDetail();
     }
@@ -407,10 +428,6 @@ watch(
 );
 
 onMounted(() => {
-  console.log('Task Detail mounted');
-  console.log('Route:', route);
-  console.log('Route query:', route.query);
-  console.log('TaskId:', taskId.value);
   fetchTaskDetail();
 });
 </script>

+ 1 - 1
src/views/document/folder/document/DocumentList.vue

@@ -29,7 +29,7 @@
       <el-table-column
         prop="name"
         :label="t('document.document.documentList.name')"
-        min-width="150"
+        min-width="350"
         show-overflow-tooltip
       >
         <template #default="scope">

+ 0 - 5
src/views/document/folder/document/FolderTree.vue

@@ -291,15 +291,10 @@ const prepareDocumentInfo = async (data: FolderListVO) => {
   const centerId = findCenterId(data);
   const countryName = findCountryName(data);
 
-  console.log('预获取文档信息 - 所属中心ID:', centerId);
-  console.log('预获取文档信息 - 所属国家名:', countryName);
-  console.log('预获取文档信息 - 当前文件夹信息:', data);
-
   // 设置当前文件夹ID
   currentDocumentFolderId.value = data.id;
 
   const res = await getNameByProjectId(props.projectId);
-  console.log('获取到的项目编码:', res.data);
   // 如果找到中心ID,调用接口获取项目编码
   if (centerId !== undefined) {
     try {

+ 25 - 7
src/views/document/folder/document/components/AddDocumentDialog.vue

@@ -72,7 +72,7 @@
     </el-form>
     <template #footer>
       <div class="dialog-footer">
-        <el-button :loading="buttonLoading" type="primary" @click="submitForm">{{
+        <el-button :loading="buttonLoading" :disabled="hasInvalidChar" type="primary" @click="submitForm">{{
           t('document.document.button.confirm')
         }}</el-button>
         <el-button @click="handleClose">{{ t('document.document.button.cancel') }}</el-button>
@@ -171,15 +171,37 @@ let submitterSearchTimer: NodeJS.Timeout | null = null;
 
 // 表单验证规则
 const rules = {
-  name: [{ required: true, message: t('document.document.documentRule.nameRequired'), trigger: 'blur' }],
+  name: [
+    { required: true, message: t('document.document.documentRule.nameRequired'), trigger: 'blur' },
+    {
+      validator: (rule: any, value: any, callback: any) => {
+        // 检查用户输入部分是否包含"-"
+        if (nameInput.value && nameInput.value.includes('-')) {
+          callback(new Error('文档名称中不能包含"-"字符'));
+        } else {
+          callback();
+        }
+      },
+      trigger: ['blur', 'change']
+    }
+  ],
   planSubmitter: [{ required: true, message: t('document.document.documentRule.planSubmitterRequired'), trigger: 'change' }],
   actualDocument: [{ required: true, message: t('document.document.documentRule.fileRequired'), trigger: 'change' }]
 };
 
+// 检查名称是否包含"-"
+const hasInvalidChar = ref(false);
+
 // 处理名称输入变化
 const handleNameInputChange = (value: string) => {
   nameInput.value = value;
+  // 实时检测是否包含"-"
+  hasInvalidChar.value = value ? value.includes('-') : false;
   updateDocumentName();
+  // 实时触发表单验证
+  if (formRef.value) {
+    formRef.value.validateField('name', () => {});
+  }
 };
 
 // 处理日期变化
@@ -289,6 +311,7 @@ const resetForm = () => {
   namePrefix.value = '';
   fullNamePrefix.value = '';
   nameInput.value = '';
+  hasInvalidChar.value = false;
   documentInfoData.value = undefined;
   submitterOptions.value = [];
   formRef.value?.resetFields();
@@ -313,8 +336,6 @@ const resetForm = () => {
 const open = async () => {
   resetForm();
 
-  console.log('AddDocumentDialog - 接收到的documentInfo:', props.documentInfo);
-
   // 设置名称前缀
   if (props.documentInfo) {
     let projectCode = '';
@@ -325,7 +346,6 @@ const open = async () => {
     try {
       const res = await getNameByProjectId(props.projectId);
       projectCode = res.data.projectCode;
-      console.log('AddDocumentDialog - 获取到的projectCode:', projectCode);
     } catch (error) {
       console.error('AddDocumentDialog - 获取projectCode失败:', error);
       ElMessage.error('获取项目编码失败');
@@ -354,8 +374,6 @@ const open = async () => {
     displayPrefix += '-';
 
     namePrefix.value = displayPrefix;
-    console.log('AddDocumentDialog - 显示前缀:', namePrefix.value);
-    console.log('AddDocumentDialog - 文档信息数据:', documentInfoData.value);
 
     updateDocumentName();
   }

+ 34 - 9
src/views/document/folder/document/components/FolderFormDialog.vue

@@ -42,7 +42,7 @@
     </el-form>
     <template #footer>
       <div class="dialog-footer">
-        <el-button :loading="buttonLoading" type="primary" @click="submitForm">{{ t('document.document.button.confirm') }}</el-button>
+        <el-button :loading="buttonLoading" :disabled="hasInvalidChar" type="primary" @click="submitForm">{{ t('document.document.button.confirm') }}</el-button>
         <el-button @click="handleClose">{{ t('document.document.button.cancel') }}</el-button>
       </div>
     </template>
@@ -98,11 +98,35 @@ const initFormData: FolderForm & { keywords?: number[] } = {
 const form = ref<FolderForm & { keywords?: number[] }>({ ...initFormData });
 
 const rules = {
-  name: [{ required: true, message: t('document.document.rule.nameRequired'), trigger: 'blur' }],
+  name: [
+    { required: true, message: t('document.document.rule.nameRequired'), trigger: 'blur' },
+    {
+      validator: (rule: any, value: any, callback: any) => {
+        if (value && value.includes('-')) {
+          callback(new Error('名称中不能包含"-"字符'));
+        } else {
+          callback();
+        }
+      },
+      trigger: ['blur', 'change']
+    }
+  ],
   type: [{ required: true, message: t('document.document.rule.typeRequired'), trigger: 'change' }]
 };
 
-// 获取标签列表
+// 检查名称是否包含"-"
+const hasInvalidChar = ref(false);
+
+// 监听名称变化,实时检测
+watch(() => form.value.name, (newName) => {
+  hasInvalidChar.value = newName ? newName.includes('-') : false;
+  // 实时触发表单验证
+  if (formRef.value) {
+    formRef.value.validateField('name', () => {});
+  }
+});
+
+// 获取关键词列表
 const getKeywordList = async () => {
   keywordLoading.value = true;
   try {
@@ -112,8 +136,8 @@ const getKeywordList = async () => {
     });
     keywordList.value = res.data || [];
   } catch (error) {
-    ElMessage.error('获取标签列表失败');
-    console.error('获取标签列表失败:', error);
+    ElMessage.error('获取关键词列表失败');
+    console.error('获取关键词列表失败:', error);
     keywordList.value = [];
   } finally {
     keywordLoading.value = false;
@@ -136,10 +160,10 @@ watch(restrictionLevelValue, (newValue) => {
   }
 });
 
-// 监听类型变化,动态加载标签列表
+// 监听类型变化,动态加载关键词列表
 watch(() => form.value.type, async (newType) => {
   if (newType === 0 && keywordList.value.length === 0) {
-    // 类型切换为文件夹且标签列表为空时,加载标签列表
+    // 类型切换为文件夹且关键词列表为空时,加载关键词列表
     await getKeywordList();
   }
 });
@@ -149,6 +173,7 @@ const reset = () => {
   form.value = { ...initFormData };
   isRestricted.value = false;
   restrictionLevelValue.value = 0;
+  hasInvalidChar.value = false;
   formRef.value?.resetFields();
 };
 
@@ -163,7 +188,7 @@ const open = async (projectId: number | string, parentId?: number, type?: number
     form.value.type = 1; // 默认选择国家类型
   }
   
-  // 只有类型为文件夹时才获取标签列表
+  // 只有类型为文件夹时才获取关键词列表
   if (form.value.type === 0) {
     await getKeywordList();
   }
@@ -198,7 +223,7 @@ const openEdit = async (folderId: number) => {
       restrictionLevelValue.value = form.value.restrictionLevel;
     }
 
-    // 只有类型为文件夹时才获取标签列表
+    // 只有类型为文件夹时才获取关键词列表
     if (form.value.type === 0) {
       await getKeywordList();
     }

+ 2 - 6
src/views/document/folder/document/index.vue

@@ -89,7 +89,6 @@ const handleTreeRefresh = () => {
 
 // 监听路由参数变化
 watch(() => route.query.projectId, (newProjectId) => {
-  console.log('Route query projectId changed:', newProjectId);
   if (newProjectId) {
     // projectId 是 computed,会自动更新
     // 重新加载数据
@@ -106,12 +105,9 @@ watch(
   { immediate: true }
 );
 
-// 组件挂载时输出调试信息
+// 组件挂载
 onMounted(() => {
-  console.log('Document Index mounted');
-  console.log('Route:', route);
-  console.log('Route query:', route.query);
-  console.log('ProjectId:', projectId.value);
+  // 初始化
 });
 </script>
 

+ 0 - 1
src/views/document/folder/project.vue

@@ -243,7 +243,6 @@ const resetQuery = () => {
 
 /** 进入项目 */
 const handleEnterProject = (row: ProjectVO) => {
-  console.log('Entering project with ID:', row.id);
   proxy?.$router.push({
     path: '/document/folder/document',
     query: { projectId: row.id }

+ 466 - 24
src/views/home/dashboard/index.vue

@@ -1,10 +1,39 @@
 <script setup lang="ts">
 import { ref, onMounted, onUnmounted, nextTick, watch, reactive } from 'vue';
 import { Search, Upload, Check, FolderAdd, Document } from '@element-plus/icons-vue';
-import * as echarts from 'echarts';
-import type { EChartsOption } from 'echarts';
 import { ElMessage } from 'element-plus';
 import request from '@/utils/request';
+import { getOverview } from '@/api/home/dashboard';
+import type { OverviewVO } from '@/api/home/dashboard/types';
+import * as echarts from 'echarts';
+import type { EChartsOption } from 'echarts';
+
+// 总览数据
+const overviewData = ref<OverviewVO>({
+  total: 0,
+  submitted: 0,
+  toSubmit: 0,
+  lateToSubmit: 0,
+  lateSubmitted: 0
+});
+
+// 获取总览数据
+const getOverviewData = async () => {
+  try {
+    const res = await getOverview();
+    if (res.code === 200 && res.data) {
+      overviewData.value = res.data;
+    }
+  } catch (error) {
+    console.error('获取总览数据失败:', error);
+  }
+};
+
+// 计算占比
+const calculatePercentage = (value: number, total: number): string => {
+  if (total === 0) return '0.0%';
+  return ((value / total) * 100).toFixed(1) + '%';
+};
 
 // 待办统计
 const todoCount = ref({
@@ -126,7 +155,6 @@ const getProgressStatus = (percentage: number) => {
 // 查看项目详情
 const viewProjectDetail = (row: any) => {
   // TODO: 实现跳转到项目详情页
-  console.log('View project detail:', row);
   // 这里可以添加路由跳转逻辑,例如:
   // router.push({
   //   path: '/project/detail',
@@ -134,16 +162,337 @@ const viewProjectDetail = (row: any) => {
   // });
 };
 
+// Echarts 实例
+const pieChartRef = ref<HTMLElement>();
+const barChartRef = ref<HTMLElement>();
+const lineChartRef = ref<HTMLElement>();
+let pieChart: echarts.ECharts | null = null;
+let barChart: echarts.ECharts | null = null;
+let lineChart: echarts.ECharts | null = null;
+
+// 初始化饼图 - 项目状态分布
+const initPieChart = () => {
+  if (!pieChartRef.value) return;
+
+  pieChart = echarts.init(pieChartRef.value);
+
+  const option: EChartsOption = {
+    title: {
+      text: '项目状态分布',
+      left: 'center',
+      top: 10,
+      textStyle: {
+        fontSize: 16,
+        fontWeight: 600
+      }
+    },
+    tooltip: {
+      trigger: 'item',
+      formatter: '{a} <br/>{b}: {c} ({d}%)'
+    },
+    legend: {
+      orient: 'vertical',
+      left: 'left',
+      top: 'middle'
+    },
+    series: [
+      {
+        name: '项目状态',
+        type: 'pie',
+        radius: ['40%', '70%'],
+        avoidLabelOverlap: false,
+        itemStyle: {
+          borderRadius: 10,
+          borderColor: '#fff',
+          borderWidth: 2
+        },
+        label: {
+          show: false,
+          position: 'center'
+        },
+        emphasis: {
+          label: {
+            show: true,
+            fontSize: 20,
+            fontWeight: 'bold'
+          }
+        },
+        labelLine: {
+          show: false
+        },
+        data: [
+          { value: overviewData.value.submitted, name: '已递交', itemStyle: { color: '#67c23a' } },
+          { value: overviewData.value.toSubmit, name: '待递交', itemStyle: { color: '#409eff' } },
+          { value: overviewData.value.lateToSubmit, name: '逾期未递交', itemStyle: { color: '#f56c6c' } },
+          { value: overviewData.value.lateSubmitted, name: '逾期已提交', itemStyle: { color: '#e6a23c' } }
+        ]
+      }
+    ]
+  };
+
+  pieChart.setOption(option);
+};
+
+// 初始化柱状图 - 待办任务统计
+const initBarChart = () => {
+  if (!barChartRef.value) return;
+
+  barChart = echarts.init(barChartRef.value);
+
+  const option: EChartsOption = {
+    title: {
+      text: '待办任务统计',
+      left: 'center',
+      top: 10,
+      textStyle: {
+        fontSize: 16,
+        fontWeight: 600
+      }
+    },
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      }
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      top: '60px',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: ['待递交', '待审核', '待归档', '待质控'],
+      axisLabel: {
+        interval: 0,
+        rotate: 0
+      }
+    },
+    yAxis: {
+      type: 'value',
+      name: '数量'
+    },
+    series: [
+      {
+        name: '待办数量',
+        type: 'bar',
+        barWidth: '50%',
+        data: [
+          { value: todoCount.value.toSubmit, itemStyle: { color: '#409eff' } },
+          { value: todoCount.value.toAudit, itemStyle: { color: '#e6a23c' } },
+          { value: todoCount.value.toFiling, itemStyle: { color: '#67c23a' } },
+          { value: todoCount.value.toQc, itemStyle: { color: '#909399' } }
+        ],
+        label: {
+          show: true,
+          position: 'top'
+        }
+      }
+    ]
+  };
+
+  barChart.setOption(option);
+};
+
+// 初始化雷达图 - 项目完成度分析
+const initLineChart = () => {
+  if (!lineChartRef.value) return;
+
+  lineChart = echarts.init(lineChartRef.value);
+
+  // 计算各项指标的完成度(基于现有数据)
+  const total = overviewData.value.total || 1; // 避免除以0
+  const submittedRate = ((overviewData.value.submitted / total) * 100).toFixed(1);
+  const toSubmitRate = ((overviewData.value.toSubmit / total) * 100).toFixed(1);
+  const onTimeRate = (((overviewData.value.submitted - overviewData.value.lateSubmitted) / total) * 100).toFixed(1);
+
+  // 计算待办完成度(假设总待办为所有待办之和)
+  const totalTodo = todoCount.value.toSubmit + todoCount.value.toAudit + todoCount.value.toFiling + todoCount.value.toQc || 1;
+  const todoProgress = ((todoCount.value.toSubmit / totalTodo) * 100).toFixed(1);
+
+  const option: EChartsOption = {
+    title: {
+      text: '项目完成度分析',
+      left: 'center',
+      top: 10,
+      textStyle: {
+        fontSize: 16,
+        fontWeight: 600
+      }
+    },
+    tooltip: {
+      trigger: 'axis'
+    },
+    legend: {
+      data: ['当前指标'],
+      top: 40
+    },
+    radar: {
+      indicator: [
+        { name: '递交完成率', max: 100 },
+        { name: '按时完成率', max: 100 },
+        { name: '待办处理率', max: 100 },
+        { name: '项目进度', max: 100 },
+        { name: '质量达标率', max: 100 }
+      ],
+      center: ['50%', '60%'],
+      radius: '60%',
+      splitNumber: 4,
+      axisName: {
+        color: '#606266',
+        fontSize: 12
+      },
+      splitLine: {
+        lineStyle: {
+          color: '#dcdfe6'
+        }
+      },
+      splitArea: {
+        areaStyle: {
+          color: ['rgba(64, 158, 255, 0.05)', 'rgba(64, 158, 255, 0.1)']
+        }
+      }
+    },
+    series: [
+      {
+        name: '当前指标',
+        type: 'radar',
+        data: [
+          {
+            value: [
+              parseFloat(submittedRate),
+              parseFloat(onTimeRate),
+              100 - parseFloat(todoProgress),
+              parseFloat(submittedRate),
+              parseFloat(onTimeRate)
+            ],
+            name: '当前指标',
+            areaStyle: {
+              color: new echarts.graphic.RadialGradient(0.5, 0.5, 1, [
+                { offset: 0, color: 'rgba(64, 158, 255, 0.3)' },
+                { offset: 1, color: 'rgba(64, 158, 255, 0.1)' }
+              ])
+            },
+            itemStyle: {
+              color: '#409eff'
+            },
+            lineStyle: {
+              color: '#409eff',
+              width: 2
+            }
+          }
+        ]
+      }
+    ]
+  };
+
+  lineChart.setOption(option);
+};
+
+// 更新图表数据
+const updateCharts = () => {
+  if (pieChart) {
+    pieChart.setOption({
+      series: [
+        {
+          data: [
+            { value: overviewData.value.submitted, name: '已递交' },
+            { value: overviewData.value.toSubmit, name: '待递交' },
+            { value: overviewData.value.lateToSubmit, name: '逾期未递交' },
+            { value: overviewData.value.lateSubmitted, name: '逾期已提交' }
+          ]
+        }
+      ]
+    });
+  }
+
+  if (barChart) {
+    barChart.setOption({
+      series: [
+        {
+          data: [
+            { value: todoCount.value.toSubmit, itemStyle: { color: '#409eff' } },
+            { value: todoCount.value.toAudit, itemStyle: { color: '#e6a23c' } },
+            { value: todoCount.value.toFiling, itemStyle: { color: '#67c23a' } },
+            { value: todoCount.value.toQc, itemStyle: { color: '#909399' } }
+          ]
+        }
+      ]
+    });
+  }
+
+  if (lineChart) {
+    const total = overviewData.value.total || 1;
+    const submittedRate = ((overviewData.value.submitted / total) * 100).toFixed(1);
+    const toSubmitRate = ((overviewData.value.toSubmit / total) * 100).toFixed(1);
+    const onTimeRate = (((overviewData.value.submitted - overviewData.value.lateSubmitted) / total) * 100).toFixed(1);
+
+    const totalTodo = todoCount.value.toSubmit + todoCount.value.toAudit + todoCount.value.toFiling + todoCount.value.toQc || 1;
+    const todoProgress = ((todoCount.value.toSubmit / totalTodo) * 100).toFixed(1);
+
+    lineChart.setOption({
+      series: [
+        {
+          data: [
+            {
+              value: [
+                parseFloat(submittedRate),
+                parseFloat(onTimeRate),
+                100 - parseFloat(todoProgress),
+                parseFloat(submittedRate),
+                parseFloat(onTimeRate)
+              ]
+            }
+          ]
+        }
+      ]
+    });
+  }
+};
+
+// 监听窗口大小变化
+const handleResize = () => {
+  pieChart?.resize();
+  barChart?.resize();
+  lineChart?.resize();
+};
+
 onMounted(async () => {
+  await getOverviewData();
   await getTodoCount();
   await getProjectList();
+
+  // 等待 DOM 更新后初始化图表
+  await nextTick();
+  initPieChart();
+  initBarChart();
+  initLineChart();
+
+  // 监听窗口大小变化
+  window.addEventListener('resize', handleResize);
+});
+
+onUnmounted(() => {
+  // 销毁图表实例
+  pieChart?.dispose();
+  barChart?.dispose();
+  lineChart?.dispose();
+
+  // 移除事件监听
+  window.removeEventListener('resize', handleResize);
 });
 
-onUnmounted(() => {});
+// 监听数据变化,更新图表
+watch([overviewData, todoCount], () => {
+  updateCharts();
+}, { deep: true });
 </script>
 
 <template>
   <div class="workbench-container">
+
     <!-- 待办统计卡片 -->
     <div class="todo-cards">
       <el-row :gutter="20">
@@ -202,6 +551,60 @@ onUnmounted(() => {});
       </el-row>
     </div>
 
+    <!-- 总览数据 -->
+    <div class="overview-section" v-hasPermi="['home:dashboard:index']">
+      <el-card shadow="hover">
+        <template #header>
+          <div class="card-header">
+            <span class="header-title">总览</span>
+          </div>
+        </template>
+        <div class="overview-content">
+          <div class="overview-item">
+            <div class="overview-value">{{ overviewData.submitted }}</div>
+            <div class="overview-percentage">{{ calculatePercentage(overviewData.submitted, overviewData.total) }}</div>
+            <div class="overview-label">已递交数量/占比</div>
+          </div>
+          <div class="overview-item">
+            <div class="overview-value">{{ overviewData.toSubmit }}</div>
+            <div class="overview-percentage">{{ calculatePercentage(overviewData.toSubmit, overviewData.total) }}</div>
+            <div class="overview-label">待递交数量/占比</div>
+          </div>
+          <div class="overview-item">
+            <div class="overview-value">{{ overviewData.lateToSubmit }}</div>
+            <div class="overview-percentage">{{ calculatePercentage(overviewData.lateToSubmit, overviewData.total) }}</div>
+            <div class="overview-label">逾期未递交数量/占比</div>
+          </div>
+          <div class="overview-item">
+            <div class="overview-value">{{ overviewData.lateSubmitted }}</div>
+            <div class="overview-percentage">{{ calculatePercentage(overviewData.lateSubmitted, overviewData.total) }}</div>
+            <div class="overview-label">逾期已提交数量/占比</div>
+          </div>
+        </div>
+      </el-card>
+    </div>
+
+    <!-- 数据图表 -->
+    <div class="charts-section">
+      <el-row :gutter="20">
+        <el-col :span="8">
+          <el-card shadow="hover" class="chart-card">
+            <div ref="pieChartRef" class="chart-container"></div>
+          </el-card>
+        </el-col>
+        <el-col :span="8">
+          <el-card shadow="hover" class="chart-card">
+            <div ref="barChartRef" class="chart-container"></div>
+          </el-card>
+        </el-col>
+        <el-col :span="8">
+          <el-card shadow="hover" class="chart-card">
+            <div ref="lineChartRef" class="chart-container"></div>
+          </el-card>
+        </el-col>
+      </el-row>
+    </div>
+
     <!-- 项目列表 -->
     <div class="project-list">
       <el-card shadow="hover">
@@ -305,6 +708,58 @@ onUnmounted(() => {});
 .workbench-container {
   padding: 20px;
 
+  .overview-section {
+    margin-bottom: 20px;
+
+    .card-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+
+      .header-title {
+        font-size: 16px;
+        font-weight: 600;
+        color: #303133;
+      }
+    }
+
+    .overview-content {
+      display: flex;
+      justify-content: space-around;
+      align-items: center;
+      padding: 20px 0;
+
+      .overview-item {
+        text-align: center;
+        flex: 1;
+
+        .overview-value {
+          font-size: 32px;
+          font-weight: 700;
+          color: #303133;
+          line-height: 1.2;
+        }
+
+        .overview-percentage {
+          font-size: 18px;
+          color: #606266;
+          margin-top: 8px;
+          font-weight: 500;
+        }
+
+        .overview-label {
+          font-size: 14px;
+          color: #909399;
+          margin-top: 8px;
+        }
+
+        &:not(:last-child) {
+          border-right: 1px solid #ebeef5;
+        }
+      }
+    }
+  }
+
   .todo-cards {
     margin-bottom: 20px;
 
@@ -412,32 +867,19 @@ onUnmounted(() => {});
     }
   }
 
-  .chart-section {
+  .charts-section {
+    margin-bottom: 20px;
+
     .chart-card {
-      :deep(.el-card__header) {
-        padding: 16px 20px;
-        border-bottom: 1px solid #ebeef5;
-      }
+      height: 100%;
 
       :deep(.el-card__body) {
-        padding: 20px;
-      }
-
-      .card-header {
-        display: flex;
-        justify-content: space-between;
-        align-items: center;
-
-        .header-title {
-          font-size: 16px;
-          font-weight: 600;
-          color: #303133;
-        }
+        padding: 10px;
       }
 
-      .pie-chart {
+      .chart-container {
         width: 100%;
-        height: 400px;
+        height: 350px;
       }
     }
   }

+ 24 - 1
src/views/home/taskCenter/qc/index.vue

@@ -67,7 +67,7 @@
           </template>
         </el-table-column>
         <!-- 操作列 -->
-        <el-table-column label="操作" width="180" align="center" fixed="right" class-name="small-padding fixed-width">
+        <el-table-column label="操作" width="280" align="center" fixed="right" class-name="small-padding fixed-width">
           <template #default="scope">
             <el-button
               v-if="scope.row.status === 2"
@@ -89,6 +89,15 @@
             >
               审核
             </el-button>
+            <el-button
+              v-hasPermi="['taskCenter:qc:logAudit']"
+              type="warning"
+              icon="Document"
+              style="padding: 0 5px; font-size: 10px; height: 24px"
+              @click="handleViewLog(scope.row)"
+            >
+              查看审核记录
+            </el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -183,6 +192,9 @@
         </div>
       </template>
     </el-dialog>
+
+    <!-- 审核记录弹窗 -->
+    <QcLogDialog v-model="logDialogVisible" :detail-id="currentLogDetailId" />
   </div>
 </template>
 
@@ -197,6 +209,7 @@ import { MemberNotInCenterVO, MemberNotInCenterQuery } from '@/api/project/manag
 import { parseI18nName } from '@/utils/i18n';
 import { formatDocumentName } from '@/utils/ruoyi';
 import fileUpload from '@/components/FileUpload/index.vue';
+import QcLogDialog from '@/components/QcLogDialog/index.vue';
 
 const { proxy } = getCurrentInstance() as any;
 const { qc_question_type } = toRefs<any>(proxy?.useDict('qc_question_type'));
@@ -274,6 +287,10 @@ const dealerSearchLoading = ref(false);
 const dealerOptions = ref<MemberNotInCenterVO[]>([]);
 let dealerSearchTimer: NodeJS.Timeout | null = null;
 
+// 审核记录相关
+const logDialogVisible = ref(false);
+const currentLogDetailId = ref<number | undefined>(undefined);
+
 /**
  * 获取任务列表
  */
@@ -450,6 +467,12 @@ const submitAudit = () => {
   });
 };
 
+/** 查看审核记录 */
+const handleViewLog = (row: QcTaskVO) => {
+  currentLogDetailId.value = row.id;
+  logDialogVisible.value = true;
+};
+
 onMounted(() => {
   getTaskList();
 });

+ 0 - 1
src/views/project/management/detail/index.vue

@@ -69,7 +69,6 @@ const getProjectDetail = async () => {
     loading.value = true;
     const res = await getManagement(projectId.value);
     projectData.value = res.data;
-    console.log('项目详情数据:', projectData.value);
   } catch (error) {
     console.error('获取项目详情失败:', error);
   } finally {

+ 1 - 1
src/views/project/management/list.vue

@@ -164,7 +164,7 @@
       <el-table v-loading="loading" border :data="managementList" style="width: 100%" @selection-change="handleSelectionChange">
         <el-table-column type="selection" width="55" align="center" />
         <el-table-column :label="t('project.management.table.id')" align="center" prop="id" v-if="true" />
-        <el-table-column :label="t('project.management.table.code')" align="center" prop="code" width="150" />
+        <el-table-column :label="t('project.management.table.code')" align="center" prop="code" width="200" />
         <el-table-column :label="t('project.management.table.name')" align="center" prop="name" width="200" />
         <el-table-column :label="t('project.management.table.language')" align="center" prop="language" width="90">
           <template #default="scope">

+ 9 - 8
src/views/search/index.vue

@@ -69,6 +69,8 @@
       <!-- 文档列表 -->
       <el-table v-loading="loading" :data="documentList" border style="margin-top: 10px; width: 100%">
         <el-table-column prop="id" :label="t('search.table.id')" width="80" align="center" />
+        <el-table-column prop="projectName" :label="t('search.table.projectName')" min-width="150"
+          show-overflow-tooltip />
         <el-table-column prop="folderName" :label="t('search.table.folderName')" min-width="120"
           show-overflow-tooltip />
         <el-table-column prop="name" :label="t('search.table.name')" min-width="150" show-overflow-tooltip>
@@ -83,7 +85,7 @@
             <span v-else>-</span>
           </template>
         </el-table-column>
-        <el-table-column prop="specificationLabel" :label="t('search.table.specification')" min-width="120"
+        <el-table-column prop="specificationLabel" :label="t('search.table.specification')" min-width="150"
           show-overflow-tooltip>
           <template #default="scope">
             <dict-tag v-if="scope.row.specification" :options="getSpecificationDict(scope.row.specificationType)"
@@ -91,19 +93,19 @@
             <span v-else>-</span>
           </template>
         </el-table-column>
-        <el-table-column prop="planDocumentTypeLabel" :label="t('search.table.planDocumentType')" min-width="120"
+        <el-table-column prop="planDocumentTypeLabel" :label="t('search.table.planDocumentType')" min-width="250"
           show-overflow-tooltip>
           <template #default="scope">
             <dict-tag v-if="scope.row.planType" :options="plan_document_type" :value="scope.row.planType" />
             <span v-else>-</span>
           </template>
         </el-table-column>
-        <el-table-column prop="status" :label="t('search.table.status')" width="120" align="center">
+        <el-table-column prop="status" :label="t('search.table.status')" width="180" align="center">
           <template #default="scope">
             <DocumentStatusTag :status="scope.row.status" />
           </template>
         </el-table-column>
-        <el-table-column prop="submitterName" :label="t('search.table.submitter')" width="120" align="center" />
+        <el-table-column prop="submitterName" :label="t('search.table.submitter')" width="200" align="center" />
         <el-table-column prop="submitDeadline" :label="t('search.table.submitDeadline')" width="110" align="center">
           <template #default="scope">
             <span v-if="scope.row.submitDeadline">{{ parseTime(scope.row.submitDeadline, '{y}-{m}-{d}') }}</span>
@@ -146,7 +148,6 @@
               @click="handleDownload(scope.row.actualDocument, scope.row.actualDocumentName)">
               {{ t('search.button.download') }}
             </el-button>
-            <span v-else>-</span>
           </template>
         </el-table-column>
       </el-table>
@@ -317,7 +318,7 @@ const handleDownload = async (actualDocument: number, actualDocumentName: string
 const handleExport = async () => {
   try {
     loading.value = true;
-    
+
     // 构建导出参数
     const exportParams: any = {
       name: queryParams.name,
@@ -337,7 +338,7 @@ const handleExport = async () => {
 
     // 调用导出接口
     const blob = await exportSearchDocuments(exportParams);
-    
+
     // 下载文件
     const url = window.URL.createObjectURL(new Blob([blob]));
     const link = document.createElement('a');
@@ -347,7 +348,7 @@ const handleExport = async () => {
     link.click();
     document.body.removeChild(link);
     window.URL.revokeObjectURL(url);
-    
+
     ElMessage.success(t('search.message.exportSuccess'));
   } catch (error) {
     console.error('导出失败:', error);

+ 9 - 9
src/views/system/tenant/index.vue

@@ -100,15 +100,15 @@
             >
               {{ t('tenant.tooltip.edit') }}
             </el-button>
-            <el-button
-              v-hasPermi="['system:tenant:edit']"
-              type="success"
-              icon="Refresh"
-              style="padding: 0 5px; font-size: 10px; height: 24px; --el-button-icon-span-gap: 2px"
-              @click="handleSyncTenantPackage(scope.row)"
-            >
-              {{ t('tenant.tooltip.syncPackage') }}
-            </el-button>
+<!--            <el-button-->
+<!--              v-hasPermi="['system:tenant:edit']"-->
+<!--              type="success"-->
+<!--              icon="Refresh"-->
+<!--              style="padding: 0 5px; font-size: 10px; height: 24px; &#45;&#45;el-button-icon-span-gap: 2px"-->
+<!--              @click="handleSyncTenantPackage(scope.row)"-->
+<!--            >-->
+<!--              {{ t('tenant.tooltip.syncPackage') }}-->
+<!--            </el-button>-->
             <el-button
               v-hasPermi="['system:tenant:remove']"
               type="danger"