From 01e75ef5ee9e4da3df1e13b056932403d36a81d5 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 12 三月 2026 11:02:30 +0800
Subject: [PATCH] 进销存升级 1.新增员工入职不要附件上传 2.员工台账中部分信息用中文展示

---
 src/views/personnelManagement/monthlyStatistics/components/formDia.vue |  295 +++++++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 228 insertions(+), 67 deletions(-)

diff --git a/src/views/personnelManagement/monthlyStatistics/components/formDia.vue b/src/views/personnelManagement/monthlyStatistics/components/formDia.vue
index eb6dea2..36c2ec3 100644
--- a/src/views/personnelManagement/monthlyStatistics/components/formDia.vue
+++ b/src/views/personnelManagement/monthlyStatistics/components/formDia.vue
@@ -1,12 +1,15 @@
 <template>
-  <el-dialog
+  <FormDialog
     v-model="dialogVisible"
     :title="operationType === 'add' ? '鏂板缓宸ヨ祫琛�' : '缂栬緫宸ヨ祫琛�'"
     width="90%"
-    :close-on-click-modal="false"
-    destroy-on-close
     @close="closeDia"
   >
+    <template #footer>
+      <el-button type="info" @click="saveDraft">淇濆瓨鑽夌</el-button>
+      <el-button type="primary" @click="submitForm">纭鎻愪氦</el-button>
+      <el-button @click="closeDia">鍙栨秷</el-button>
+    </template>
     <div class="form-dia-body">
       <!-- 鍩虹璧勬枡 -->
       <el-card class="form-card" shadow="never">
@@ -28,11 +31,13 @@
               </el-form-item>
             </el-col>
             <el-col :span="6">
-              <el-form-item label="閫夋嫨閮ㄩ棬" prop="deptId">
+              <el-form-item label="閫夋嫨閮ㄩ棬" prop="deptIds">
                 <el-select
-                  v-model="form.deptId"
+                  v-model="form.deptIds"
                   placeholder="璇烽�夋嫨"
                   clearable
+                  multiple
+                  collapse-tags-tooltip
                   style="width: 100%"
                 >
                   <el-option
@@ -86,6 +91,24 @@
                 </el-select>
               </el-form-item>
             </el-col>
+            <el-col :span="6">
+              <el-form-item label="瀹℃牳浜�" prop="auditUserId">
+                <el-select
+                  v-model="form.auditUserId"
+                  placeholder="璇烽�夋嫨瀹℃牳浜�"
+                  clearable
+                  filterable
+                  style="width: 100%"
+                >
+                  <el-option
+                    v-for="item in userList"
+                    :key="item.userId"
+                    :label="item.nickName"
+                    :value="item.userId"
+                  />
+                </el-select>
+              </el-form-item>
+            </el-col>
           </el-row>
         </el-form>
       </el-card>
@@ -93,10 +116,7 @@
       <!-- 鎿嶄綔鎸夐挳 -->
       <div class="toolbar">
         <el-button type="primary" @click="handleGenerate">鐢熸垚宸ヨ祫琛�</el-button>
-        <el-button @click="handleExport">瀵煎嚭</el-button>
-        <el-button @click="handleImport">瀵煎叆</el-button>
         <el-button @click="handleClear">娓呯┖</el-button>
-        <el-button @click="openAddPerson">鏂板浜哄憳</el-button>
         <el-button @click="handleBatchDelete">鍒犻櫎</el-button>
         <el-button @click="handleTaxForm">涓◣琛�</el-button>
       </div>
@@ -179,6 +199,70 @@
               />
             </template>
           </el-table-column>
+          <el-table-column label="鍏朵粬鏀嚭" minWidth="110">
+            <template #default="{ row }">
+              <el-input
+                v-model.number="row.otherDeduct"
+                type="number"
+                placeholder="0"
+                size="small"
+                @input="row.otherDeduct = parseNum(row.otherDeduct)"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="宸ヨ祫涓◣" minWidth="110">
+            <template #default="{ row }">
+              <el-input
+                v-model.number="row.salaryTax"
+                type="number"
+                placeholder="0"
+                size="small"
+                @input="row.salaryTax = parseNum(row.salaryTax)"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="搴斿彂宸ヨ祫" minWidth="110">
+            <template #default="{ row }">
+              <el-input
+                v-model.number="row.grossSalary"
+                type="number"
+                placeholder="0"
+                size="small"
+                @input="row.grossSalary = parseNum(row.grossSalary)"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="搴旀墸宸ヨ祫" minWidth="110">
+            <template #default="{ row }">
+              <el-input
+                v-model.number="row.deductSalary"
+                type="number"
+                placeholder="0"
+                size="small"
+                @input="row.deductSalary = parseNum(row.deductSalary)"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="瀹炲彂宸ヨ祫" minWidth="110">
+            <template #default="{ row }">
+              <el-input
+                v-model.number="row.netSalary"
+                type="number"
+                placeholder="0"
+                size="small"
+                @input="row.netSalary = parseNum(row.netSalary)"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="澶囨敞" minWidth="120">
+            <template #default="{ row }">
+              <el-input
+                v-model="row.remark"
+                placeholder="璇疯緭鍏�"
+                size="small"
+              />
+            </template>
+          </el-table-column>
           <el-table-column label="鎿嶄綔" width="80" align="center" fixed="right">
             <template #default="{ row }">
               <el-button type="primary" link @click="removeEmployee(row)">鍒犻櫎</el-button>
@@ -186,15 +270,14 @@
           </el-table-column>
         </el-table>
         <div v-if="!employeeList.length" class="table-empty">鏆傛棤鏁版嵁</div>
+        <div v-else class="salary-total">
+          <span class="total-label">宸ヨ祫鎬婚锛�</span>
+          <span class="total-value">楼 {{ totalSalary.toFixed(2) }}</span>
+        </div>
       </div>
     </div>
 
-    <template #footer>
-      <div class="dialog-footer">
-        <el-button @click="closeDia">鍙栨秷</el-button>
-        <el-button type="primary" @click="submitForm">纭畾</el-button>
-      </div>
-    </template>
+
 
     <!-- 鏂板浜哄憳寮圭獥 -->
     <el-dialog
@@ -249,12 +332,13 @@
         />
       </el-table>
     </el-dialog>
-  </el-dialog>
+  </FormDialog>
 </template>
 
 <script setup>
 import { ref, reactive, toRefs, computed, getCurrentInstance, nextTick } from "vue";
 import { ArrowUp } from "@element-plus/icons-vue";
+import FormDialog from "@/components/Dialog/FormDialog.vue";
 import { listDept } from "@/api/system/dept.js";
 import { staffOnJobList } from "@/api/personnelManagement/monthlyStatistics.js";
 import { bankList } from "@/api/personnelManagement/bank.js";
@@ -263,6 +347,8 @@
   staffSalaryMainUpdate,
   staffSalaryMainCalculateSalary,
 } from "@/api/personnelManagement/staffSalaryMain.js";
+import { userListNoPageByTenantId } from "@/api/system/user.js";
+
 
 const emit = defineEmits(["update:modelValue", "close"]);
 const props = defineProps({
@@ -288,6 +374,7 @@
 const employeeList = ref([]);
 const selectedEmployees = ref([]);
 const bankOptions = ref([]);
+const userList = ref([]);
 const taxTableData = ref([
   { level: 1, range: "涓嶈秴杩�36000鍏�", rate: 3, quickDeduction: 0 },
   { level: 2, range: "瓒呰繃36000-144000鍏�", rate: 10, quickDeduction: 2520 },
@@ -309,18 +396,32 @@
   form: {
     id: undefined,
     salaryTitle: "",
-    deptId: undefined,
+    deptIds: [],
     salaryMonth: "",
     remark: "",
     payBank: "",
+    auditUserId: undefined,
   },
   rules: {
     salaryTitle: [{ required: true, message: "璇疯緭鍏ュ伐璧勪富棰�", trigger: "blur" }],
-    deptId: [{ required: true, message: "璇烽�夋嫨閮ㄩ棬", trigger: "change" }],
+    deptIds: [{ required: true, message: "璇烽�夋嫨閮ㄩ棬", trigger: "change" }],
     salaryMonth: [{ required: true, message: "璇烽�夋嫨宸ヨ祫鏈堜唤", trigger: "change" }],
+    auditUserId: [{ required: true, message: "璇烽�夋嫨瀹℃牳浜�", trigger: "change" }],
   },
 });
 const { form, rules } = toRefs(data);
+
+// 璁$畻宸ヨ祫鎬婚锛堟墍鏈夊憳宸ュ疄鍙戝伐璧勪箣鍜岋級
+const totalSalary = computed(() => {
+  return employeeList.value.reduce((sum, e) => sum + parseNum(e.netSalary), 0);
+});
+
+// 鏍规嵁瀹℃牳浜篒D鑾峰彇瀹℃牳浜哄悕绉�
+const auditUserName = computed(() => {
+  if (!form.value.auditUserId) return "";
+  const user = userList.value.find(u => u.userId === form.value.auditUserId);
+  return user ? user.nickName : "";
+});
 
 const loadBankOptions = () => {
   return bankList().then((res) => {
@@ -328,6 +429,12 @@
     bankOptions.value = list
       .map((b) => (b?.bankName == null ? "" : String(b.bankName).trim()))
       .filter((v) => v !== "");
+  });
+};
+
+const loadUserList = () => {
+  return userListNoPageByTenantId().then((res) => {
+    userList.value = res.data || [];
   });
 };
 
@@ -390,24 +497,52 @@
   nextTick(() => {
     loadDeptOptions();
     loadBankOptions();
+    loadUserList();
     employeeList.value = [];
     Object.assign(form.value, {
       id: undefined,
       salaryTitle: "",
-      deptId: undefined,
+      deptIds: [],
       salaryMonth: "",
       remark: "",
       payBank: "",
+      auditUserId: undefined,
     });
     // 缂栬緫锛氬垪琛ㄩ〉宸茶繑鍥炰富琛ㄥ瓧娈碉紱杩欓噷鍙仛鍥炴樉锛堟槑缁嗙敱鈥滅敓鎴愬伐璧勮〃/璁$畻宸ヨ祫鈥濆緱鍒帮級
     if (type === "edit" && row?.id) {
       form.value.id = row.id;
       form.value.salaryTitle = row.salaryTitle ?? "";
       // deptIds 鍚庣鏄瓧绗︿覆锛堝涓敤閫楀彿鍒嗛殧锛夛紱褰撳墠琛ㄥ崟浠嶆槸鍗曢�� deptId
-      form.value.deptId = row.deptIds ? Number(String(row.deptIds).split(",")[0]) : undefined;
+      form.value.deptIds = row.deptIds
+        ? String(row.deptIds).split(",").map((id) => Number(id.trim())).filter(Boolean)
+        : [];
       form.value.salaryMonth = row.salaryMonth ?? "";
       form.value.remark = row.remark ?? "";
       form.value.payBank = row.payBank ?? "";
+      form.value.auditUserId = row.auditUserId ?? undefined;
+      
+      // 濡傛灉鏈夊憳宸ユ槑缁嗘暟鎹紝鐩存帴鍙嶆樉
+      if (row.staffSalaryDetailList && row.staffSalaryDetailList.length > 0) {
+        employeeList.value = row.staffSalaryDetailList.map((e) => ({
+          staffOnJobId: e.staffOnJobId ?? e.staffId ?? e.id,
+          id: e.staffOnJobId ?? e.staffId ?? e.id,
+          staffName: e.staffName ?? "",
+          postName: e.postName ?? "",
+          deptName: e.deptName ?? "",
+          basicSalary: parseNum(e.basicSalary),
+          pieceSalary: parseNum(e.pieceSalary),
+          hourlySalary: parseNum(e.hourlySalary),
+          otherIncome: parseNum(e.otherIncome),
+          socialPersonal: parseNum(e.socialPersonal),
+          fundPersonal: parseNum(e.fundPersonal),
+          otherDeduct: parseNum(e.otherDeduct),
+          salaryTax: parseNum(e.salaryTax),
+          grossSalary: parseNum(e.grossSalary),
+          deductSalary: parseNum(e.deductSalary),
+          netSalary: parseNum(e.netSalary),
+          remark: e.remark ?? "",
+        }));
+      }
     }
   });
 };
@@ -480,7 +615,7 @@
 };
 
 const handleGenerate = () => {
-  if (!form.value.deptId) {
+  if (!form.value.deptIds?.length) {
     proxy.$modal.msgWarning("璇峰厛閫夋嫨閮ㄩ棬");
     return;
   }
@@ -488,14 +623,11 @@
     proxy.$modal.msgWarning("璇峰厛閫夋嫨宸ヨ祫鏈堜唤");
     return;
   }
-  if (!employeeList.value?.length) {
-    proxy.$modal.msgWarning("璇峰厛鏂板浜哄憳");
-    return;
-  }
-  const ids = employeeList.value
-    .map((e) => e.staffOnJobId ?? e.staffId ?? e.id)
-    .filter(Boolean);
-  staffSalaryMainCalculateSalary(ids).then((res) => {
+  const payload = {
+    ids: form.value.deptIds,
+    date: form.value.salaryMonth,
+  };
+  staffSalaryMainCalculateSalary(payload).then((res) => {
     const list = Array.isArray(res?.data) ? res.data : [];
     if (!list.length) {
       proxy.$modal.msgWarning("鏈绠楀埌宸ヨ祫鏁版嵁");
@@ -524,14 +656,6 @@
   });
 };
 
-const handleExport = () => {
-  proxy.$modal.msgInfo("瀵煎嚭鍔熻兘闇�瀵规帴鍚庣");
-};
-
-const handleImport = () => {
-  proxy.$modal.msgInfo("瀵煎叆鍔熻兘闇�瀵规帴鍚庣");
-};
-
 const handleClear = () => {
   proxy.$modal.confirm("纭畾娓呯┖褰撳墠鍛樺伐鍒楄〃鍚楋紵").then(() => {
     employeeList.value = [];
@@ -545,38 +669,58 @@
 const submitForm = () => {
   formRef.value?.validate((valid) => {
     if (!valid) return;
-    const payload = {
-      ...form.value,
-      deptIds: form.value.deptId ? String(form.value.deptId) : "",
-      detailList: employeeList.value.map((e) => ({
-        staffOnJobId: e.staffOnJobId ?? e.staffId ?? e.id,
-        staffName: e.staffName,
-        basicSalary: parseNum(e.basicSalary),
-        pieceSalary: parseNum(e.pieceSalary),
-        hourlySalary: parseNum(e.hourlySalary),
-        otherIncome: parseNum(e.otherIncome),
-        socialPersonal: parseNum(e.socialPersonal),
-        fundPersonal: parseNum(e.fundPersonal),
-        otherDeduct: parseNum(e.otherDeduct),
-        salaryTax: parseNum(e.salaryTax),
-        grossSalary: parseNum(e.grossSalary),
-        deductSalary: parseNum(e.deductSalary),
-        netSalary: parseNum(e.netSalary),
-        remark: e.remark ?? "",
-      })),
-    };
-    if (props.operationType === "add") {
-      staffSalaryMainAdd({ ...payload, status: 1 }).then(() => {
-        proxy.$modal.msgSuccess("鏂板鎴愬姛");
-        closeDia();
-      });
-    } else {
-      staffSalaryMainUpdate(payload).then(() => {
-        proxy.$modal.msgSuccess("淇敼鎴愬姛");
-        closeDia();
-      });
-    }
+    saveData(3); // 纭鎻愪氦锛岀姸鎬佷负3锛堝緟瀹℃牳锛�
   });
+};
+
+const saveDraft = () => {
+  formRef.value?.validate((valid) => {
+    if (!valid) return;
+    saveData(1); // 淇濆瓨鑽夌锛岀姸鎬佷负1锛堣崏绋匡級
+  });
+};
+
+const saveData = (status) => {
+  const payload = {
+    id: form.value.id,
+    salaryTitle: form.value.salaryTitle,
+    deptIds: form.value.deptIds?.length ? form.value.deptIds.join(",") : "",
+    salaryMonth: form.value.salaryMonth,
+    remark: form.value.remark,
+    payBank: form.value.payBank,
+    auditUserId: form.value.auditUserId,
+    auditUserName: auditUserName.value,
+    totalSalary: totalSalary.value,
+    staffSalaryDetailList: employeeList.value.map((e) => ({
+      staffOnJobId: e.staffOnJobId ?? e.staffId ?? e.id,
+      staffName: e.staffName,
+      postName: e.postName ?? "",
+      deptName: e.deptName ?? "",
+      basicSalary: parseNum(e.basicSalary),
+      pieceSalary: parseNum(e.pieceSalary),
+      hourlySalary: parseNum(e.hourlySalary),
+      otherIncome: parseNum(e.otherIncome),
+      socialPersonal: parseNum(e.socialPersonal),
+      fundPersonal: parseNum(e.fundPersonal),
+      otherDeduct: parseNum(e.otherDeduct),
+      salaryTax: parseNum(e.salaryTax),
+      grossSalary: parseNum(e.grossSalary),
+      deductSalary: parseNum(e.deductSalary),
+      netSalary: parseNum(e.netSalary),
+      remark: e.remark ?? "",
+    })),
+  };
+  if (props.operationType === "add") {
+    staffSalaryMainAdd({ ...payload, status }).then(() => {
+      proxy.$modal.msgSuccess(status === 1 ? "鑽夌淇濆瓨鎴愬姛" : "鎻愪氦鎴愬姛");
+      closeDia();
+    });
+  } else {
+    staffSalaryMainUpdate({ ...payload, status }).then(() => {
+      proxy.$modal.msgSuccess(status === 1 ? "鑽夌淇濆瓨鎴愬姛" : "鎻愪氦鎴愬姛");
+      closeDia();
+    });
+  }
 };
 
 const closeDia = () => {
@@ -640,4 +784,21 @@
 .dialog-footer {
   text-align: right;
 }
+.salary-total {
+  margin-top: 16px;
+  padding: 12px 16px;
+  background-color: #f5f7fa;
+  border-radius: 4px;
+  text-align: right;
+  font-size: 16px;
+}
+.salary-total .total-label {
+  color: #606266;
+  margin-right: 8px;
+}
+.salary-total .total-value {
+  color: #f56c6c;
+  font-weight: bold;
+  font-size: 18px;
+}
 </style>

--
Gitblit v1.9.3