From b461c6527e3a85e9af59e7680e792bcb5ffb6b7e Mon Sep 17 00:00:00 2001
From: ZN <zhang_12370@163.com>
Date: 星期二, 10 三月 2026 15:53:37 +0800
Subject: [PATCH] Merge branch 'dev_New' of http://114.132.189.42:9002/r/product-inventory-management into dev_New
---
src/views/personnelManagement/monthlyStatistics/components/formDia.vue | 427 +++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 333 insertions(+), 94 deletions(-)
diff --git a/src/views/personnelManagement/monthlyStatistics/components/formDia.vue b/src/views/personnelManagement/monthlyStatistics/components/formDia.vue
index 0882ba4..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">
@@ -17,9 +20,9 @@
<el-form ref="formRef" :model="form" :rules="rules" label-position="top">
<el-row :gutter="24">
<el-col :span="6">
- <el-form-item label="宸ヨ祫涓婚" prop="title">
+ <el-form-item label="宸ヨ祫涓婚" prop="salaryTitle">
<el-input
- v-model="form.title"
+ v-model="form.salaryTitle"
placeholder="璇疯緭鍏�"
clearable
maxlength="20"
@@ -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
@@ -45,9 +50,9 @@
</el-form-item>
</el-col>
<el-col :span="6">
- <el-form-item label="閫夋嫨宸ヨ祫鏈堜唤" prop="payMonth">
+ <el-form-item label="閫夋嫨宸ヨ祫鏈堜唤" prop="salaryMonth">
<el-date-picker
- v-model="form.payMonth"
+ v-model="form.salaryMonth"
type="month"
value-format="YYYY-MM"
format="YYYY-MM"
@@ -67,16 +72,51 @@
</el-form-item>
</el-col>
</el-row>
+ <el-row :gutter="24">
+ <el-col :span="6">
+ <el-form-item label="鏀粯閾惰" prop="payBank">
+ <el-select
+ v-model="form.payBank"
+ placeholder="璇烽�夋嫨"
+ clearable
+ filterable
+ style="width: 100%"
+ >
+ <el-option
+ v-for="b in bankOptions"
+ :key="b"
+ :label="b"
+ :value="b"
+ />
+ </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>
<!-- 鎿嶄綔鎸夐挳 -->
<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>
@@ -92,7 +132,6 @@
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="鍛樺伐濮撳悕" prop="staffName" minWidth="100" />
- <el-table-column label="瑙掕壊" prop="roleName" minWidth="100" />
<el-table-column label="閮ㄩ棬" prop="deptName" minWidth="100" />
<el-table-column label="鍩烘湰宸ヨ祫" minWidth="110">
<template #default="{ row }">
@@ -108,11 +147,11 @@
<el-table-column label="璁′欢宸ヨ祫" minWidth="110">
<template #default="{ row }">
<el-input
- v-model.number="row.pieceworkSalary"
+ v-model.number="row.pieceSalary"
type="number"
placeholder="0"
size="small"
- @input="row.pieceworkSalary = parseNum(row.pieceworkSalary)"
+ @input="row.pieceSalary = parseNum(row.pieceSalary)"
/>
</template>
</el-table-column>
@@ -141,22 +180,86 @@
<el-table-column label="绀句繚涓汉" minWidth="110">
<template #default="{ row }">
<el-input
- v-model.number="row.socialSecurityIndividuals"
+ v-model.number="row.socialPersonal"
type="number"
placeholder="0"
size="small"
- @input="row.socialSecurityIndividuals = parseNum(row.socialSecurityIndividuals)"
+ @input="row.socialPersonal = parseNum(row.socialPersonal)"
/>
</template>
</el-table-column>
<el-table-column label="鍏Н閲戜釜浜�" minWidth="120">
<template #default="{ row }">
<el-input
- v-model.number="row.providentFundIndividuals"
+ v-model.number="row.fundPersonal"
type="number"
placeholder="0"
size="small"
- @input="row.providentFundIndividuals = parseNum(row.providentFundIndividuals)"
+ @input="row.fundPersonal = parseNum(row.fundPersonal)"
+ />
+ </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>
@@ -167,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
@@ -230,19 +332,23 @@
/>
</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";
import {
- monthlyStatisticsAdd,
- monthlyStatisticsUpdate,
- monthlyStatisticsGet,
-} from "@/api/personnelManagement/monthlyStatistics.js";
+ staffSalaryMainAdd,
+ staffSalaryMainUpdate,
+ staffSalaryMainCalculateSalary,
+} from "@/api/personnelManagement/staffSalaryMain.js";
+import { userListNoPageByTenantId } from "@/api/system/user.js";
+
const emit = defineEmits(["update:modelValue", "close"]);
const props = defineProps({
@@ -267,6 +373,8 @@
const deptStaffTree = ref([]);
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 },
@@ -287,18 +395,48 @@
const data = reactive({
form: {
id: undefined,
- title: "",
- deptId: undefined,
- payMonth: "",
+ salaryTitle: "",
+ deptIds: [],
+ salaryMonth: "",
remark: "",
+ payBank: "",
+ auditUserId: undefined,
},
rules: {
- title: [{ required: true, message: "璇疯緭鍏ュ伐璧勪富棰�", trigger: "blur" }],
- deptId: [{ required: true, message: "璇烽�夋嫨閮ㄩ棬", trigger: "change" }],
- payMonth: [{ required: true, message: "璇烽�夋嫨宸ヨ祫鏈堜唤", trigger: "change" }],
+ salaryTitle: [{ required: true, message: "璇疯緭鍏ュ伐璧勪富棰�", trigger: "blur" }],
+ 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) => {
+ const list = Array.isArray(res?.data) ? res.data : [];
+ 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 || [];
+ });
+};
// 鎵佸钩鍖栭儴闂ㄦ爲渚涗笅鎷変娇鐢�
function flattenDept(tree, list = []) {
@@ -358,32 +496,53 @@
const openDialog = (type, row) => {
nextTick(() => {
loadDeptOptions();
+ loadBankOptions();
+ loadUserList();
employeeList.value = [];
Object.assign(form.value, {
id: undefined,
- title: "",
- deptId: undefined,
- payMonth: "",
+ salaryTitle: "",
+ deptIds: [],
+ salaryMonth: "",
remark: "",
+ payBank: "",
+ auditUserId: undefined,
});
+ // 缂栬緫锛氬垪琛ㄩ〉宸茶繑鍥炰富琛ㄥ瓧娈碉紱杩欓噷鍙仛鍥炴樉锛堟槑缁嗙敱鈥滅敓鎴愬伐璧勮〃/璁$畻宸ヨ祫鈥濆緱鍒帮級
if (type === "edit" && row?.id) {
- monthlyStatisticsGet(row.id).then((res) => {
- const d = res.data || {};
- form.value.id = d.id;
- form.value.title = d.title ?? d.payDateStr ?? "";
- form.value.deptId = d.deptId;
- form.value.payMonth = d.payMonth ?? d.payDate ?? d.payDateStr ?? "";
- form.value.remark = d.remark ?? "";
- employeeList.value = (d.detailList || d.employeeList || []).map((e) => ({
- ...e,
+ form.value.id = row.id;
+ form.value.salaryTitle = row.salaryTitle ?? "";
+ // deptIds 鍚庣鏄瓧绗︿覆锛堝涓敤閫楀彿鍒嗛殧锛夛紱褰撳墠琛ㄥ崟浠嶆槸鍗曢�� deptId
+ 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),
- pieceworkSalary: parseNum(e.pieceworkSalary),
+ pieceSalary: parseNum(e.pieceSalary),
hourlySalary: parseNum(e.hourlySalary),
otherIncome: parseNum(e.otherIncome),
- socialSecurityIndividuals: parseNum(e.socialSecurityIndividuals),
- providentFundIndividuals: parseNum(e.providentFundIndividuals),
+ 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 ?? "",
}));
- });
+ }
}
});
};
@@ -412,17 +571,23 @@
if (existIds.has(id)) return;
existIds.add(id);
employeeList.value.push({
- staffId: id,
- id: id,
+ staffOnJobId: id,
+ id,
staffName: node.label,
- roleName: node.roleName ?? node.role ?? "",
+ postName: node.postName ?? node.post ?? "",
deptName: node.deptName ?? "",
basicSalary: 0,
- pieceworkSalary: 0,
+ pieceSalary: 0,
hourlySalary: 0,
otherIncome: 0,
- socialSecurityIndividuals: 0,
- providentFundIndividuals: 0,
+ socialPersonal: 0,
+ fundPersonal: 0,
+ otherDeduct: 0,
+ salaryTax: 0,
+ grossSalary: 0,
+ deductSalary: 0,
+ netSalary: 0,
+ remark: "",
});
});
addPersonVisible.value = false;
@@ -430,7 +595,7 @@
const removeEmployee = (row) => {
employeeList.value = employeeList.value.filter(
- (e) => (e.staffId || e.id) !== (row.staffId || row.id)
+ (e) => (e.staffOnJobId || e.id) !== (row.staffOnJobId || row.id)
);
};
@@ -443,22 +608,52 @@
proxy.$modal.msgWarning("璇峰厛鍕鹃�夎鍒犻櫎鐨勫憳宸�");
return;
}
- const ids = new Set(selectedEmployees.value.map((e) => e.staffId || e.id));
+ const ids = new Set(selectedEmployees.value.map((e) => e.staffOnJobId || e.id));
employeeList.value = employeeList.value.filter(
- (e) => !ids.has(e.staffId || e.id)
+ (e) => !ids.has(e.staffOnJobId || e.id)
);
};
const handleGenerate = () => {
- proxy.$modal.msgInfo("鐢熸垚宸ヨ祫琛ㄥ姛鑳介渶瀵规帴鍚庣");
-};
-
-const handleExport = () => {
- proxy.$modal.msgInfo("瀵煎嚭鍔熻兘闇�瀵规帴鍚庣");
-};
-
-const handleImport = () => {
- proxy.$modal.msgInfo("瀵煎叆鍔熻兘闇�瀵规帴鍚庣");
+ if (!form.value.deptIds?.length) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨閮ㄩ棬");
+ return;
+ }
+ if (!form.value.salaryMonth) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨宸ヨ祫鏈堜唤");
+ return;
+ }
+ 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("鏈绠楀埌宸ヨ祫鏁版嵁");
+ return;
+ }
+ employeeList.value = list.map((e) => ({
+ ...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 ?? "",
+ }));
+ proxy.$modal.msgSuccess("鐢熸垚鎴愬姛");
+ });
};
const handleClear = () => {
@@ -474,31 +669,58 @@
const submitForm = () => {
formRef.value?.validate((valid) => {
if (!valid) return;
- const payload = {
- ...form.value,
- detailList: employeeList.value.map((e) => ({
- staffId: e.staffId ?? e.id,
- staffName: e.staffName,
- basicSalary: parseNum(e.basicSalary),
- pieceworkSalary: parseNum(e.pieceworkSalary),
- hourlySalary: parseNum(e.hourlySalary),
- otherIncome: parseNum(e.otherIncome),
- socialSecurityIndividuals: parseNum(e.socialSecurityIndividuals),
- providentFundIndividuals: parseNum(e.providentFundIndividuals),
- })),
- };
- if (props.operationType === "add") {
- monthlyStatisticsAdd(payload).then(() => {
- proxy.$modal.msgSuccess("鏂板鎴愬姛");
- closeDia();
- });
- } else {
- monthlyStatisticsUpdate(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 = () => {
@@ -562,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