From d1791f762791428af91467b8855de83d54f015f9 Mon Sep 17 00:00:00 2001
From: zhuguifei <312353457@qq.com>
Date: 星期五, 17 四月 2026 15:23:21 +0800
Subject: [PATCH] feat: 1.新增物料、物料类型、材料检验统计等表维护功能  2.完善判定依据-判断依据明细  3.新增判断依据、物料管理等字典翻译类  4.成品物料批次-原始数据维护页面

---
 ruoyi-plus-soybean/src/views/qm/batch/index.vue |  874 +++++++++++++++++++++++++++++++++-------------------------
 1 files changed, 498 insertions(+), 376 deletions(-)

diff --git a/ruoyi-plus-soybean/src/views/qm/batch/index.vue b/ruoyi-plus-soybean/src/views/qm/batch/index.vue
old mode 100644
new mode 100755
index 06ebbff..e25ab9c
--- a/ruoyi-plus-soybean/src/views/qm/batch/index.vue
+++ b/ruoyi-plus-soybean/src/views/qm/batch/index.vue
@@ -1,12 +1,14 @@
 <script setup lang="tsx">
-import { ref } from 'vue';
-import { NDivider } from 'naive-ui';
-import { fetchBatchDeleteBatch, fetchGetBatchList } from '@/service/api/qm/batch';
-import { useAppStore } from '@/store/modules/app';
-import { useAuth } from '@/hooks/business/auth';
-import { useDownload } from '@/hooks/business/download';
-import { defaultTransform, useNaivePaginatedTable, useTableOperate } from '@/hooks/common/table';
-import { $t } from '@/locales';
+import {nextTick, ref} from 'vue';
+import {useRouter} from 'vue-router';
+import {NDivider, NDropdown} from 'naive-ui';
+import {fetchBatchDeleteBatch, fetchGetBatchList} from '@/service/api/qm/batch';
+import {useAppStore} from '@/store/modules/app';
+import {useAuth} from '@/hooks/business/auth';
+import {useDownload} from '@/hooks/business/download';
+import {useSvgIcon} from '@/hooks/common/icon';
+import {defaultTransform, useNaivePaginatedTable, useTableOperate} from '@/hooks/common/table';
+import {$t} from '@/locales';
 import ButtonIcon from '@/components/custom/button-icon.vue';
 import BatchOperateDrawer from './modules/batch-operate-drawer.vue';
 import BatchSearch from './modules/batch-search.vue';
@@ -15,20 +17,146 @@
   name: 'BatchList'
 });
 
-
 const appStore = useAppStore();
-const { download } = useDownload();
-const { hasAuth } = useAuth();
+const router = useRouter();
+const {download} = useDownload();
+const {hasAuth} = useAuth();
+const {SvgIconVNode} = useSvgIcon();
+
+// 鍙抽敭鑿滃崟鐩稿叧
+const showDropdown = ref(false);
+const x = ref(0);
+const y = ref(0);
+const currentRow = ref<Api.Qm.Batch | null>(null);
+
+const dropdownOptions = [
+  {
+    label: '鍘熷鏁版嵁缁存姢',
+    key: 'raw-data-maintenance',
+    icon: SvgIconVNode({icon: 'mdi:database-edit-outline', fontSize: 18})
+  },
+  {
+    label: '缁煎悎娴嬭瘯鍙版暟鎹淮鎶�',
+    key: 'test-bench-maintenance',
+    icon: SvgIconVNode({icon: 'mdi:monitor-dashboard', fontSize: 18})
+  },
+  {
+    label: '鏂板缓澶嶆鎵规',
+    key: 'new-recheck-batch',
+    icon: SvgIconVNode({icon: 'mdi:plus-circle-outline', fontSize: 18})
+  },
+  {
+    type: 'divider',
+    key: 'd1'
+  },
+  {
+    label: '鍗峰寘鍗峰埗妫�楠岀粨鏋滄姤鍛�',
+    key: 'report-rolling',
+    icon: SvgIconVNode({icon: 'mdi:file-document-outline', fontSize: 18})
+  },
+  {
+    label: '鍖呰鏍囪瘑妫�楠屽師濮嬭褰�',
+    key: 'record-packaging',
+    icon: SvgIconVNode({icon: 'mdi:barcode-scan', fontSize: 18})
+  },
+  {
+    label: '鐔勭伀銆佸惈姘寸巼銆佸惈鏈巼鍘熷璁板綍',
+    key: 'record-quality',
+    icon: SvgIconVNode({icon: 'mdi:water-percent', fontSize: 18})
+  },
+  {
+    label: '绔儴钀戒笣鍘熷璁板綍',
+    key: 'record-silk',
+    icon: SvgIconVNode({icon: 'mdi:format-list-bulleted-type', fontSize: 18})
+  },
+  {
+    label: '缁煎悎娴嬭瘯鍙板師濮嬭褰�',
+    key: 'record-bench',
+    icon: SvgIconVNode({icon: 'mdi:chart-line', fontSize: 18})
+  },
+  {
+    label: '澶栬妫�楠屽師濮嬭褰�',
+    key: 'record-appearance',
+    icon: SvgIconVNode({icon: 'mdi:eye-outline', fontSize: 18})
+  },
+  {
+    type: 'divider',
+    key: 'd2'
+  },
+  {
+    label: $t('common.edit'),
+    key: 'edit',
+    icon: SvgIconVNode({icon: 'material-symbols:drive-file-rename-outline-outline', fontSize: 18}),
+    show: hasAuth('qm:batch:edit')
+  },
+  {
+    label: $t('common.delete'),
+    key: 'delete',
+    icon: SvgIconVNode({icon: 'material-symbols:delete-outline', fontSize: 18}),
+    show: hasAuth('qm:batch:remove')
+  }
+];
+
+function handleSelect(key: string) {
+  showDropdown.value = false;
+  if (!currentRow.value) return;
+
+  if (key === 'edit') {
+    edit(currentRow.value.id);
+  } else if (key === 'delete') {
+    window.$dialog?.error({
+      title: $t('common.confirmDelete'),
+      content: $t('common.confirmDelete'),
+      positiveText: $t('common.confirm'),
+      negativeText: $t('common.cancel'),
+      onPositiveClick: () => {
+        handleDelete(currentRow.value!.id);
+      }
+    });
+  } else if (key === 'raw-data-maintenance') {
+    // 璺宠浆鍒� matcheck 椤甸潰
+    if (!currentRow.value.judgeCode) {
+      window.$message?.warning('璇ユ壒娆℃病鏈夊垽瀹氫緷鎹�');
+      return;
+    }
+    router.push({
+      path: '/qm/matcheck',
+      query: {
+        judgeCode: currentRow.value.judgeCode,
+        batchCode: currentRow.value.batchCode,
+        matCode: currentRow.value.matCode
+      }
+    });
+  } else {
+    // 澶勭悊鍏朵粬涓氬姟鎿嶄綔
+    window.$message?.info(`鐐瑰嚮浜�: ${key}`);
+  }
+}
+
+function handleRowProps(row: Api.Qm.Batch) {
+  return {
+    onContextmenu: (e: MouseEvent) => {
+      e.preventDefault();
+      showDropdown.value = false;
+      nextTick().then(() => {
+        currentRow.value = row;
+        x.value = e.clientX;
+        y.value = e.clientY;
+        showDropdown.value = true;
+      });
+    }
+  };
+}
 
 // 绫诲瀷/鍙嶉MES/绫诲埆鐨� value->label 鏄犲皠锛堢敤浜庤〃鏍兼樉绀猴級
-const TYP_MAP: Record<string, string> = { A: '鍒朵笣', B: '鎴愬瀷', C: '鍗峰寘', D: '灏佺', E: '绯栭鏂�' };
-const FLAG_MAP: Record<string, string> = { '0': '鏈笂浼爉es', '1': '宸蹭笂浼�', '3': '浠嶮ES涓嬭浇' };
-const CATEGORY_MAP: Record<string, string> = { '0': '鎴愬搧', '1': '杈呮潗' };
+const FLAG_MAP: Record<string, string> = {'0': '鏈笂浼爉es', '1': '宸蹭笂浼�', '3': '浠嶮ES涓嬭浇'};
+const CATEGORY_MAP: Record<string, string> = {'0': '鎴愬搧', '1': '杈呮潗'};
 
 const searchParams = ref<Api.Qm.BatchSearchParams>({
   pageNum: 1,
   pageSize: 10,
   batchCode: null,
+  isflag: '1',
   typ: null,
   eqpCode: null,
   matCode: null,
@@ -36,387 +164,370 @@
   flag: null,
   toMesDate: null,
   fromMesDate: null,
-  deleted: null,
-  category: null,
+  enabled: '1',
+  deleted: 0,
+  category: '0',
   state: null,
-  params: {}
+  params: {
+    beginBatchDate: `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, '0')}-${String(new Date().getDate()).padStart(2, '0')} 00:00:00`,
+    endBatchDate: `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, '0')}-${String(new Date().getDate()).padStart(2, '0')} 23:59:59`
+  }
 });
 
-const { columns, columnChecks, data, getData, getDataByPage, loading, mobilePagination, scrollX } =
+const {columns, columnChecks, data, getData, getDataByPage, loading, mobilePagination, scrollX} =
   useNaivePaginatedTable({
-  api: () => fetchGetBatchList(searchParams.value),
-  transform: response => defaultTransform(response),
-  onPaginationParamsChange: params => {
-    searchParams.value.pageNum = params.page;
-    searchParams.value.pageSize = params.pageSize;
-  },
-  columns: () => [
-    {
-      type: 'selection',
-      align: 'center',
-      width: 48
+    api: () => fetchGetBatchList(searchParams.value),
+    transform: response => defaultTransform(response),
+    onPaginationParamsChange: params => {
+      searchParams.value.pageNum = params.page;
+      searchParams.value.pageSize = params.pageSize;
     },
-    {
-      key: 'index',
-      title: $t('common.index'),
-      align: 'center',
-      width: 64,
-      render: (_, index) => index + 1
-    },
-    {
-      key: 'id',
-      title: '缂栫爜',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'batchCode',
-      title: '鎵规浠g爜',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'batchName',
-      title: '鎵规鍚嶇О',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'typ',
-      title: '绫诲瀷',
-      align: 'center',
-      minWidth: 120,
-      render: row => TYP_MAP[row.typ] ?? row.typ
-    },
-    {
-      key: 'eqpCode',
-      title: '鏈哄彴浠g爜',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'matCode',
-      title: '鐗屽彿',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'judgeCode',
-      title: '鍒ゅ畾渚濇嵁浠g爜',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'batchDate',
-      title: '鎵规鐢熸垚鏃ユ湡',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'isflag',
-      title: '浣跨敤鏍囧織',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'enabled',
-      title: '鍚敤鏍囧織',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'totalNum',
-      title: '鍒拌揣鎬婚噺',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'results',
-      title: '缁煎悎鍒ゅ畾',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'approver',
-      title: '鎵瑰噯浜�',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'auditor',
-      title: '瀹℃牳浜�',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'creater',
-      title: '鍒涘缓浜�',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'tabDate',
-      title: '鍒惰〃鏃ユ湡',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'verName',
-      title: '鐗堟湰鍚嶇О',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'verCode',
-      title: '鐗堟湰缂栧彿',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'archDate',
-      title: '淇濆瓨鏈�',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'flag',
-      title: '鍙嶉MES',
-      align: 'center',
-      minWidth: 120,
-      render: row => FLAG_MAP[String(row.flag)] ?? row.flag
-    },
-    {
-      key: 'toMesDate',
-      title: '涓婁紶MES鏃堕棿',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'fromMesDate',
-      title: '浠嶮ES鏃堕棿涓嬭浇',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'deleted',
-      title: '鍒犻櫎鏍囧織',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'batchDes',
-      title: '鎵规鎻忚堪',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'category',
-      title: '绫诲埆',
-      align: 'center',
-      minWidth: 120,
-      render: row => CATEGORY_MAP[String(row.category)] ?? row.category
-    },
-    {
-      key: 'makeno',
-      title: '鍗峰埗宸ュ彿',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'shifteqpno',
-      title: '鐝鏈哄彿',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'boxno',
-      title: '瑁呯鍙�',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'pid',
-      title: '鐖舵壒娆″彿',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'reviewer',
-      title: '澶嶆牳浜�',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'rvcount',
-      title: '澶嶆娆℃暟',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'state',
-      title: '鎵规鐘舵��',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'reviewTime',
-      title: '澶嶆牳鏃ユ湡',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'auditTime',
-      title: '瀹℃牳鏃ユ湡',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'spec',
-      title: '瑙勬牸',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'approveTime',
-      title: '鎵瑰噯鏃堕棿',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'unit',
-      title: '鍒拌揣鍗曚綅',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'arrivalTime',
-      title: '鍒拌揣鏃ユ湡',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'storagePlace',
-      title: '瀛樻斁鍦扮偣',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'checker',
-      title: '妫�楠屽憳',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'receiveTime',
-      title: '鎺ュ崟鏃ユ湡',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'inspTime',
-      title: '鎶ユ鏃ユ湡',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'storer',
-      title: '浠撳簱淇濈鍛�',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'isverify',
-      title: '鏄惁楠岃瘉',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'ischk',
-      title: '鏄惁妫�楠�',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'bak1',
-      title: '澶囩敤1',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'bak2',
-      title: '澶囩敤2',
-      align: 'center',
-      minWidth: 120
-    },
-    {
-      key: 'operate',
-      title: $t('common.operate'),
-      align: 'center',
-      width: 130,
-      render: row => {
-        const divider = () => {
-          if (!hasAuth('qm:batch:edit') || !hasAuth('qm:batch:remove')) {
-            return null;
-          }
-          return <NDivider vertical />;
-        };
+    columns: () => [
+      {
+        type: 'selection',
+        align: 'center',
+        width: 48
+      },
+      {
+        key: 'index',
+        title: $t('common.index'),
+        align: 'center',
+        width: 64,
+        render: (_, index) => index + 1
+      },
+      {
+        key: 'batchCode',
+        title: '鎵规鍙�',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'matName',
+        title: '鐗屽彿',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'judgeName',
+        title: '鍒ゅ畾渚濇嵁',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'batchDate',
+        title: '鎵规鐢熸垚鏃ユ湡',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'isflag',
+        title: '浣跨敤鏍囧織',
+        align: 'center',
+        minWidth: 120,
+        render: row => (row.isflag == '1' ? '鏄�' : '鍚�')
+      },
+      {
+        key: 'enabled',
+        title: '鍚敤鏍囧織',
+        align: 'center',
+        minWidth: 120,
+        render: row => (row.enabled == '1' ? '鏄�' : '鍚�')
+      },
+      {
+        key: 'totalNum',
+        title: '鍒拌揣鎬婚噺',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'results',
+        title: '缁煎悎鍒ゅ畾',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'approver',
+        title: '鎵瑰噯浜�',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'auditor',
+        title: '瀹℃牳浜�',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'creater',
+        title: '鍒涘缓浜�',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'tabDate',
+        title: '鍒惰〃鏃ユ湡',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'verName',
+        title: '鐗堟湰鍚嶇О',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'verCode',
+        title: '鐗堟湰缂栧彿',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'archDate',
+        title: '淇濆瓨鏈�',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'flag',
+        title: '鍙嶉MES',
+        align: 'center',
+        minWidth: 120,
+        render: row => FLAG_MAP[String(row.flag)] ?? row.flag
+      },
+      {
+        key: 'toMesDate',
+        title: '涓婁紶MES鏃堕棿',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'fromMesDate',
+        title: '浠嶮ES鏃堕棿涓嬭浇',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'deleted',
+        title: '鍒犻櫎鏍囧織',
+        align: 'center',
+        minWidth: 120,
+        render: row => (row.deleted == 1 ? '鏄�' : '鍚�')
+      },
+      {
+        key: 'batchDes',
+        title: '鎵规鎻忚堪',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'category',
+        title: '绫诲埆',
+        align: 'center',
+        minWidth: 120,
+        render: row => CATEGORY_MAP[String(row.category)] ?? row.category
+      },
+      {
+        key: 'makeno',
+        title: '鍗峰埗宸ュ彿',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'shifteqpno',
+        title: '鐝鏈哄彿',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'boxno',
+        title: '瑁呯鍙�',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'pid',
+        title: '鐖舵壒娆″彿',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'reviewer',
+        title: '澶嶆牳浜�',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'rvcount',
+        title: '澶嶆娆℃暟',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'state',
+        title: '鎵规鐘舵��',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'reviewTime',
+        title: '澶嶆牳鏃ユ湡',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'auditTime',
+        title: '瀹℃牳鏃ユ湡',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'spec',
+        title: '瑙勬牸',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'approveTime',
+        title: '鎵瑰噯鏃堕棿',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'unit',
+        title: '鍒拌揣鍗曚綅',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'arrivalTime',
+        title: '鍒拌揣鏃ユ湡',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'storagePlace',
+        title: '瀛樻斁鍦扮偣',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'checker',
+        title: '妫�楠屽憳',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'receiveTime',
+        title: '鎺ュ崟鏃ユ湡',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'inspTime',
+        title: '鎶ユ鏃ユ湡',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'storer',
+        title: '浠撳簱淇濈鍛�',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'isverify',
+        title: '鏄惁楠岃瘉',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'ischk',
+        title: '鏄惁妫�楠�',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'bak1',
+        title: '澶囩敤1',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'bak2',
+        title: '澶囩敤2',
+        align: 'center',
+        minWidth: 120
+      },
+      {
+        key: 'operate',
+        title: $t('common.operate'),
+        fixed: 'right',
+        align: 'center',
+        width: 130,
+        render: row => {
+          const divider = () => {
+            if (!hasAuth('qm:batch:edit') || !hasAuth('qm:batch:remove')) {
+              return null;
+            }
+            return <NDivider vertical/>;
+          };
 
-        const editBtn = () => {
-          if (!hasAuth('qm:batch:edit')) {
-            return null;
-          }
+          const editBtn = () => {
+            if (!hasAuth('qm:batch:edit')) {
+              return null;
+            }
+            return (
+              <ButtonIcon
+                text
+                type="primary"
+                icon="material-symbols:drive-file-rename-outline-outline"
+                tooltipContent={$t('common.edit')}
+                onClick={() => edit(row.id)}
+              />
+            );
+          };
+
+          const deleteBtn = () => {
+            if (!hasAuth('qm:batch:remove')) {
+              return null;
+            }
+            return (
+              <ButtonIcon
+                text
+                type="error"
+                icon="material-symbols:delete-outline"
+                tooltipContent={$t('common.delete')}
+                popconfirmContent={$t('common.confirmDelete')}
+                onPositiveClick={() => handleDelete(row.id)}
+              />
+            );
+          };
+
           return (
-            <ButtonIcon
-              text
-              type="primary"
-              icon="material-symbols:drive-file-rename-outline-outline"
-              tooltipContent={$t('common.edit')}
-              onClick={() => edit(row.id)}
-            />
+            <div class="flex-center gap-8px">
+              {editBtn()}
+              {divider()}
+              {deleteBtn()}
+            </div>
           );
-        };
-
-        const deleteBtn = () => {
-          if (!hasAuth('qm:batch:remove')) {
-            return null;
-          }
-          return (
-            <ButtonIcon
-              text
-              type="error"
-              icon="material-symbols:delete-outline"
-              tooltipContent={$t('common.delete')}
-              popconfirmContent={$t('common.confirmDelete')}
-              onPositiveClick={() => handleDelete(row.id)}
-            />
-          );
-        };
-
-        return (
-          <div class="flex-center gap-8px">
-            {editBtn()}
-            {divider()}
-            {deleteBtn()}
-          </div>
-        );
+        }
       }
-    }
-  ]
-});
+    ]
+  });
 
-const { drawerVisible, operateType, editingData, handleAdd, handleEdit, checkedRowKeys, onBatchDeleted, onDeleted } =
+const {drawerVisible, operateType, editingData, handleAdd, handleEdit, checkedRowKeys, onBatchDeleted, onDeleted} =
   useTableOperate(data, 'id', getData);
 
 async function handleBatchDelete() {
   // request
-  const { error } = await fetchBatchDeleteBatch(checkedRowKeys.value);
+  const {error} = await fetchBatchDeleteBatch(checkedRowKeys.value);
   if (error) return;
   onBatchDeleted();
 }
 
 async function handleDelete(id: CommonType.IdType) {
   // request
-  const { error } = await fetchBatchDeleteBatch([id]);
+  const {error} = await fetchBatchDeleteBatch([id]);
   if (error) return;
   onDeleted();
 }
@@ -432,7 +543,7 @@
 
 <template>
   <div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
-    <BatchSearch v-model:model="searchParams" @search="getDataByPage" />
+    <BatchSearch v-model:model="searchParams" @search="getDataByPage"/>
     <NCard title="妫�楠屾壒娆″垪琛�" :bordered="false" size="small" class="card-wrapper sm:flex-1-hidden">
       <template #header-extra>
         <TableHeaderOperation
@@ -459,8 +570,19 @@
         remote
         :row-key="row => row.id"
         :pagination="mobilePagination"
+        :row-props="handleRowProps"
         class="sm:h-full"
       />
+      <NDropdown
+        placement="bottom-start"
+        trigger="manual"
+        :x="x"
+        :y="y"
+        :options="dropdownOptions"
+        :show="showDropdown"
+        :on-clickoutside="() => (showDropdown = false)"
+        @select="handleSelect"
+      />
       <BatchOperateDrawer
         v-model:visible="drawerVisible"
         :operate-type="operateType"

--
Gitblit v1.9.3