From 950e1332f89e3d18a8f4b415bd4fe274dce1e954 Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期五, 28 八月 2026 16:16:28 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_pro2.0' into dev_pro2.0

---
 src/views/hrm/salary/calculation/index.vue |  107 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 102 insertions(+), 5 deletions(-)

diff --git a/src/views/hrm/salary/calculation/index.vue b/src/views/hrm/salary/calculation/index.vue
index 59551ab..33a1f36 100644
--- a/src/views/hrm/salary/calculation/index.vue
+++ b/src/views/hrm/salary/calculation/index.vue
@@ -7,15 +7,20 @@
 import { Page } from '#/packages/effects/common-ui/src';
 import { downloadFileFromBlobPart } from '#/packages/utils/src';
 
-import { message, Modal, Form, FormItem, DatePicker, TreeSelect, Table, InputNumber, Alert } from 'ant-design-vue';
+import { message, Modal, Form, FormItem, DatePicker, TreeSelect, Table, InputNumber, Alert, Tag } from 'ant-design-vue';
+
+import { DICT_TYPE } from '#/packages/constants/src';
+import { getDictLabel } from '#/packages/effects/hooks/src';
 
 import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
 import {
   calculateSalary,
   confirmSalary,
+  deleteSalaryCalculation,
   exportSalaryCalculation,
   getSalaryCalculationPage,
   previewSalaryCalculation,
+  revokeSalaryCalculation,
   saveSalaryCalculation,
 } from '#/api/hrm/salary/calculation';
 import { getDeptList } from '#/api/system/dept';
@@ -102,7 +107,8 @@
   const deduction = (record.socialSecurityDeduction || 0) +
     (record.housingFundDeduction || 0) +
     (record.taxDeduction || 0) +
-    (record.otherDeduction || 0);
+    (record.otherDeduction || 0) +
+    (record.leaveDeduction || 0);
   return income - deduction;
 }
 
@@ -149,7 +155,7 @@
   handleRefresh();
 }
 
-/** 鎵归噺纭 */
+/** 鎵归噺纭閫変腑鐨勮褰� */
 async function handleBatchConfirm() {
   const records = gridApi.grid.getCheckboxRecords() as HrmSalaryCalculationApi.SalaryCalculation[];
   if (records.length === 0) {
@@ -160,6 +166,58 @@
   await confirmSalary(ids);
   message.success('纭鎴愬姛');
   handleRefresh();
+}
+
+/** 鎵归噺淇濆瓨閫変腑鐨勬牳绠楄褰曪紙浠呭緟纭鐘舵�侊級 */
+async function handleBatchSave() {
+  const records = gridApi.grid.getCheckboxRecords() as HrmSalaryCalculationApi.SalaryCalculation[];
+  if (records.length === 0) {
+    message.warning('璇烽�夋嫨瑕佷繚瀛樼殑璁板綍');
+    return;
+  }
+  const pending = records.filter((r) => r.status === 0);
+  if (pending.length === 0) {
+    message.warning('閫変腑鐨勮褰曞潎闈炲緟纭鐘舵�侊紝鏃犻渶淇濆瓨');
+    return;
+  }
+  const first = pending[0];
+  if (!first?.period) {
+    message.warning('缂哄皯鏍哥畻鍛ㄦ湡');
+    return;
+  }
+  await saveSalaryCalculation({ period: first.period, list: pending });
+  message.success('鎵归噺淇濆瓨鎴愬姛');
+  handleRefresh();
+}
+
+/** 鎾ら攢纭锛堝凡纭 鈫� 寰呯‘璁わ紝鍙噸鏂版牳绠楋級 */
+async function handleRevoke(row: HrmSalaryCalculationApi.SalaryCalculation) {
+  Modal.confirm({
+    title: '鎾ら攢纭',
+    content: `纭畾鎾ら攢銆�${row.no}銆戠殑纭鍚楋紵鎾ら攢鍚庡彲閲嶆柊鏍哥畻銆俙,
+    okText: '纭畾',
+    cancelText: '鍙栨秷',
+    onOk: async () => {
+      await revokeSalaryCalculation([row.id!]);
+      message.success('鎾ら攢鎴愬姛');
+      handleRefresh();
+    },
+  });
+}
+
+/** 鍒犻櫎寰呯‘璁ょ殑鏍哥畻璁板綍 */
+async function handleDelete(row: HrmSalaryCalculationApi.SalaryCalculation) {
+  Modal.confirm({
+    title: '纭鍒犻櫎',
+    content: `纭畾鍒犻櫎銆�${row.no}銆戠殑鏍哥畻璁板綍鍚楋紵鍒犻櫎鍚庨渶閲嶆柊鏍哥畻銆俙,
+    okText: '纭畾',
+    cancelText: '鍙栨秷',
+    onOk: async () => {
+      await deleteSalaryCalculation(row.id!);
+      message.success('鍒犻櫎鎴愬姛');
+      handleRefresh();
+    },
+  });
 }
 
 /** 瀵煎嚭钖叕鏍哥畻 */
@@ -178,7 +236,6 @@
     keepSource: true,
     checkboxConfig: {
       highlight: true,
-      reserve: true,
     },
     proxyConfig: {
       ajax: {
@@ -189,6 +246,10 @@
             ...formValues,
           }),
       },
+    },
+    pagingConfig: {
+      pageSize: 20,
+      pageSizes: [20, 50, 100],
     },
     rowConfig: {
       keyField: 'id',
@@ -257,7 +318,7 @@
         v-if="previewData.length > 0"
         :columns="usePreviewColumns()"
         :data-source="previewData"
-        :pagination="false"
+        :pagination="{ pageSize: 20, showSizeChanger: true, showTotal: (t) => `鍏� ${t} 浜篳 }"
         :scroll="{ x: 1800, y: 400 }"
         size="small"
         row-key="userId"
@@ -365,6 +426,16 @@
               @change="(val: number) => updateFieldValue(record, 'otherDeduction', val)"
             />
           </template>
+          <template v-else-if="column.dataIndex === 'leaveDeduction'">
+            <InputNumber
+              v-model:value="record.leaveDeduction"
+              :min="0"
+              :precision="2"
+              size="small"
+              style="width: 90px"
+              @change="(val: number) => updateFieldValue(record, 'leaveDeduction', val)"
+            />
+          </template>
           <template v-else-if="column.dataIndex === 'actualSalary'">
             <span class="font-bold text-green-600">{{ record.actualSalary?.toFixed(2) }}</span>
           </template>
@@ -416,6 +487,12 @@
               onClick: handleBatchConfirm,
             },
             {
+              label: '鎵归噺淇濆瓨',
+              type: 'primary',
+              auth: ['hrm:salary-calculation:save'],
+              onClick: handleBatchSave,
+            },
+            {
               label: $t('ui.actionTitle.export'),
               type: 'primary',
               icon: ACTION_ICON.DOWNLOAD,
@@ -424,6 +501,11 @@
             },
           ]"
         />
+      </template>
+      <template #status="{ row }">
+        <Tag :color="row.status === 0 ? 'warning' : row.status === 10 ? 'success' : 'processing'">
+          {{ getDictLabel(DICT_TYPE.HRM_SALARY_STATUS, row.status) }}
+        </Tag>
       </template>
       <template #actions="{ row }">
         <TableAction
@@ -435,6 +517,21 @@
               ifShow: row.status === 0,
               onClick: handleConfirm.bind(null, row),
             },
+            {
+              label: '鍒犻櫎',
+              type: 'link',
+              danger: true,
+              auth: ['hrm:salary-calculation:delete'],
+              ifShow: row.status === 0,
+              onClick: handleDelete.bind(null, row),
+            },
+            {
+              label: '鎾ら攢纭',
+              type: 'link',
+              auth: ['hrm:salary-calculation:confirm'],
+              ifShow: row.status === 10,
+              onClick: handleRevoke.bind(null, row),
+            },
           ]"
         />
       </template>

--
Gitblit v1.9.3