From a29cb267e67d4cc4d29438e5e3a4bbbb403a1f8b Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期二, 07 七月 2026 14:32:18 +0800
Subject: [PATCH] 转正申请,调岗申请,工作交接申请,申请人可以根据配置得选项来源,选择数据
---
src/views/personnelManagement/monthlyStatistics/components/formDia.vue | 1283 +++++++++++++++++++++++++++++++++++----------------------
1 files changed, 785 insertions(+), 498 deletions(-)
diff --git a/src/views/personnelManagement/monthlyStatistics/components/formDia.vue b/src/views/personnelManagement/monthlyStatistics/components/formDia.vue
index e3105d2..46515ed 100644
--- a/src/views/personnelManagement/monthlyStatistics/components/formDia.vue
+++ b/src/views/personnelManagement/monthlyStatistics/components/formDia.vue
@@ -1,548 +1,814 @@
<template>
- <FormDialog
- v-model="dialogVisible"
- :title="operationType === 'add' ? '鏂板缓宸ヨ祫琛�' : '缂栬緫宸ヨ祫琛�'"
- width="90%"
- @close="closeDia"
- @confirm="submitForm"
- @cancel="closeDia"
- >
+ <FormDialog v-model="dialogVisible"
+ :title="operationType === 'add' ? '鏂板缓宸ヨ祫琛�' : '缂栬緫宸ヨ祫琛�'"
+ width="90%"
+ @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">
+ <el-card class="form-card"
+ shadow="never">
<template #header>
<span class="card-title"><span class="card-title-line">|</span> 鍩虹璧勬枡</span>
- <el-icon class="card-collapse"><ArrowUp /></el-icon>
+ <el-icon class="card-collapse">
+ <ArrowUp />
+ </el-icon>
</template>
- <el-form ref="formRef" :model="form" :rules="rules" label-position="top">
+ <el-form ref="formRef"
+ :model="form"
+ :rules="rules"
+ label-position="top">
<el-row :gutter="24">
<el-col :span="6">
- <el-form-item label="宸ヨ祫涓婚" prop="salaryTitle">
- <el-input
- v-model="form.salaryTitle"
- placeholder="璇疯緭鍏�"
- clearable
- maxlength="20"
- show-word-limit
- />
+ <el-form-item label="宸ヨ祫涓婚"
+ prop="salaryTitle">
+ <el-input v-model="form.salaryTitle"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="20"
+ show-word-limit />
</el-form-item>
</el-col>
<el-col :span="6">
- <el-form-item label="閫夋嫨閮ㄩ棬" prop="deptIds">
- <el-select
- v-model="form.deptIds"
- placeholder="璇烽�夋嫨"
- clearable
- multiple
- collapse-tags
- collapse-tags-tooltip
- style="width: 100%"
- >
- <el-option
- v-for="item in deptOptions"
- :key="item.deptId"
- :label="item.deptName"
- :value="item.deptId"
- />
+ <el-form-item label="閫夋嫨宸ヨ祫鏈堜唤"
+ prop="salaryMonth">
+ <el-date-picker v-model="form.salaryMonth"
+ type="month"
+ value-format="YYYY-MM"
+ format="YYYY-MM"
+ placeholder="璇烽�夋嫨宸ヨ祫鏈堜唤"
+ style="width: 100%"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="6">
+ <el-form-item label="閫夋嫨閮ㄩ棬"
+ prop="deptIds">
+ <el-select v-model="form.deptIds"
+ placeholder="璇烽�夋嫨"
+ clearable
+ multiple
+ collapse-tags-tooltip
+ style="width: 100%">
+ <el-option v-for="item in deptOptions"
+ :key="item.deptId"
+ :label="item.deptName"
+ :value="item.deptId"
+ :disabled="isDeptDisabled(item.deptId)" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
- <el-form-item label="閫夋嫨宸ヨ祫鏈堜唤" prop="salaryMonth">
- <el-date-picker
- v-model="form.salaryMonth"
- type="month"
- value-format="YYYY-MM"
- format="YYYY-MM"
- placeholder="璇烽�夋嫨宸ヨ祫鏈堜唤"
- style="width: 100%"
- clearable
- />
- </el-form-item>
- </el-col>
- <el-col :span="6">
- <el-form-item label="澶囨敞" prop="remark">
- <el-input
- v-model="form.remark"
- placeholder="璇疯緭鍏�"
- clearable
- />
+ <el-form-item label="澶囨敞"
+ prop="remark">
+ <el-input v-model="form.remark"
+ placeholder="璇疯緭鍏�"
+ clearable />
</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-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 type="primary"
+ @click="handleGenerate">鐢熸垚宸ヨ祫琛�</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>
-
<!-- 鍛樺伐宸ヨ祫璇︽儏琛ㄦ牸 -->
<div class="employee-table-wrap">
- <el-table
- ref="employeeTableRef"
- :data="employeeList"
- border
- max-height="400"
- @selection-change="onEmployeeSelectionChange"
- >
- <el-table-column type="selection" width="55" align="center" />
- <el-table-column label="鍛樺伐濮撳悕" prop="staffName" minWidth="100" />
- <el-table-column label="閮ㄩ棬" prop="deptName" minWidth="100" />
- <el-table-column label="鍩烘湰宸ヨ祫" minWidth="110">
+ <el-table ref="employeeTableRef"
+ :data="employeeList"
+ border
+ max-height="400"
+ @selection-change="onEmployeeSelectionChange">
+ <el-table-column type="selection"
+ width="55"
+ align="center" />
+ <el-table-column label="鍛樺伐濮撳悕"
+ prop="staffName"
+ minWidth="100" />
+ <el-table-column label="閮ㄩ棬"
+ prop="deptName"
+ minWidth="100" />
+ <el-table-column label="鍩烘湰宸ヨ祫"
+ minWidth="110">
<template #default="{ row }">
- <el-input
- v-model.number="row.basicSalary"
- type="number"
- placeholder="0"
- size="small"
- @input="row.basicSalary = parseNum(row.basicSalary)"
- />
+ <el-input v-model.number="row.basicSalary"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="handleSalaryInput(row)" />
</template>
</el-table-column>
- <el-table-column label="璁′欢宸ヨ祫" minWidth="110">
+ <el-table-column label="璁′欢宸ヨ祫"
+ minWidth="110">
<template #default="{ row }">
- <el-input
- v-model.number="row.pieceSalary"
- type="number"
- placeholder="0"
- size="small"
- @input="row.pieceSalary = parseNum(row.pieceSalary)"
- />
+ <el-input v-model.number="row.pieceSalary"
+ type="number"
+ placeholder="0"
+ size="small"
+ disabled
+ @input="row.pieceSalary = parseNum(row.pieceSalary)" />
</template>
</el-table-column>
- <el-table-column label="璁℃椂宸ヨ祫" minWidth="110">
+ <el-table-column label="璁℃椂宸ヨ祫"
+ minWidth="110">
<template #default="{ row }">
- <el-input
- v-model.number="row.hourlySalary"
- type="number"
- placeholder="0"
- size="small"
- @input="row.hourlySalary = parseNum(row.hourlySalary)"
- />
+ <el-input v-model.number="row.hourlySalary"
+ type="number"
+ placeholder="0"
+ size="small"
+ disabled
+ @input="row.hourlySalary = parseNum(row.hourlySalary)" />
</template>
</el-table-column>
- <el-table-column label="鍏朵粬鏀跺叆" minWidth="110">
+ <el-table-column label="鍏朵粬鏀跺叆"
+ minWidth="110">
<template #default="{ row }">
- <el-input
- v-model.number="row.otherIncome"
- type="number"
- placeholder="0"
- size="small"
- @input="row.otherIncome = parseNum(row.otherIncome)"
- />
+ <el-input v-model.number="row.otherIncome"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="handleSalaryInput(row)" />
</template>
</el-table-column>
- <el-table-column label="绀句繚涓汉" minWidth="110">
+ <el-table-column label="绀句繚涓汉"
+ minWidth="110">
<template #default="{ row }">
- <el-input
- v-model.number="row.socialPersonal"
- type="number"
- placeholder="0"
- size="small"
- @input="row.socialPersonal = parseNum(row.socialPersonal)"
- />
+ <el-input v-model.number="row.socialPersonal"
+ type="number"
+ placeholder="0"
+ size="small"
+ disabled
+ @input="row.socialPersonal = parseNum(row.socialPersonal)" />
</template>
</el-table-column>
- <el-table-column label="鍏Н閲戜釜浜�" minWidth="120">
+ <el-table-column label="鍏Н閲戜釜浜�"
+ minWidth="120">
<template #default="{ row }">
- <el-input
- v-model.number="row.fundPersonal"
- type="number"
- placeholder="0"
- size="small"
- @input="row.fundPersonal = parseNum(row.fundPersonal)"
- />
+ <el-input v-model.number="row.fundPersonal"
+ type="number"
+ placeholder="0"
+ size="small"
+ disabled
+ @input="row.fundPersonal = parseNum(row.fundPersonal)" />
</template>
</el-table-column>
- <el-table-column label="鎿嶄綔" width="80" align="center" fixed="right">
+ <el-table-column label="鍏朵粬鏀嚭"
+ minWidth="110">
<template #default="{ row }">
- <el-button type="primary" link @click="removeEmployee(row)">鍒犻櫎</el-button>
+ <el-input v-model.number="row.otherDeduct"
+ type="number"
+ placeholder="0"
+ size="small"
+ disabled
+ @input="row.otherDeduct = parseNum(row.otherDeduct)" />
+ </template>
+ </el-table-column>
+ <el-table-column label="绀句繚琛ョ即"
+ minWidth="120">
+ <template #default="{ row }">
+ <el-input v-model.number="row.socialSupplementAmount"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="handleSalaryInput(row)" />
+ </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"
+ disabled
+ @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"
+ disabled
+ @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"
+ disabled
+ @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"
+ disabled
+ @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>
</template>
</el-table-column>
</el-table>
- <div v-if="!employeeList.length" class="table-empty">鏆傛棤鏁版嵁</div>
+ <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>
-
-
-
<!-- 鏂板浜哄憳寮圭獥 -->
- <el-dialog
- v-model="addPersonVisible"
- title="鏂板浜哄憳"
- width="400px"
- append-to-body
- @close="addPersonClose"
- >
+ <el-dialog v-model="addPersonVisible"
+ title="鏂板浜哄憳"
+ width="400px"
+ append-to-body
+ @close="addPersonClose">
<div class="add-person-tree">
- <el-tree
- ref="personTreeRef"
- :data="deptStaffTree"
- show-checkbox
- node-key="id"
- :props="{ label: 'label', children: 'children' }"
- default-expand-all
- />
+ <el-tree ref="personTreeRef"
+ :data="deptStaffTree"
+ show-checkbox
+ node-key="id"
+ :props="{ label: 'label', children: 'children' }"
+ default-expand-all />
</div>
<template #footer>
<el-button @click="addPersonVisible = false">鍙栨秷</el-button>
- <el-button type="primary" @click="confirmAddPerson">纭畾</el-button>
+ <el-button type="primary"
+ @click="confirmAddPerson">纭畾</el-button>
</template>
</el-dialog>
-
<!-- 涓◣琛ㄥ脊绐� -->
- <el-dialog
- v-model="taxDialogVisible"
- title="涓◣琛�"
- width="700px"
- append-to-body
- >
+ <el-dialog v-model="taxDialogVisible"
+ title="涓◣琛�"
+ width="700px"
+ append-to-body>
<div class="tax-desc">涓汉鎵�寰楃◣鍏嶅緛棰濓細5000鍏�</div>
- <el-table :data="taxTableData" border style="width: 100%;margin-bottom: 20px;">
- <el-table-column prop="level" label="绾ф暟" width="80" align="center" />
- <el-table-column
- prop="range"
- label="鍏ㄥ勾搴旂撼绋庢墍寰楅/鍏�"
- min-width="220"
- />
- <el-table-column
- prop="rate"
- label="绋庣巼(%)"
- width="100"
- align="center"
- />
- <el-table-column
- prop="quickDeduction"
- label="閫熺畻鎵i櫎鏁�/鍏�"
- width="160"
- align="center"
- />
+ <el-table :data="taxTableData"
+ border
+ style="width: 100%;margin-bottom: 20px;">
+ <el-table-column prop="level"
+ label="绾ф暟"
+ width="80"
+ align="center" />
+ <el-table-column prop="range"
+ label="鍏ㄥ勾搴旂撼绋庢墍寰楅/鍏�"
+ min-width="220" />
+ <el-table-column prop="rate"
+ label="绋庣巼(%)"
+ width="100"
+ align="center" />
+ <el-table-column prop="quickDeduction"
+ label="閫熺畻鎵i櫎鏁�/鍏�"
+ width="160"
+ align="center" />
</el-table>
</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 {
+ ref,
+ reactive,
+ toRefs,
+ computed,
+ getCurrentInstance,
+ nextTick,
+ watch,
+ } 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 {
staffSalaryMainAdd,
staffSalaryMainUpdate,
staffSalaryMainCalculateSalary,
+ staffSalaryMainCalculateByEmployeeId,
+ staffSalaryMainAvailableDepts,
} from "@/api/personnelManagement/staffSalaryMain.js";
+ import { userListNoPageByTenantId } from "@/api/system/user.js";
-const emit = defineEmits(["update:modelValue", "close"]);
-const props = defineProps({
- modelValue: { type: Boolean, default: false },
- operationType: { type: String, default: "add" },
- row: { type: Object, default: () => ({}) },
-});
+ const emit = defineEmits(["update:modelValue", "close"]);
+ const props = defineProps({
+ modelValue: { type: Boolean, default: false },
+ operationType: { type: String, default: "add" },
+ row: { type: Object, default: () => ({}) },
+ });
-const { proxy } = getCurrentInstance();
+ const { proxy } = getCurrentInstance();
-const dialogVisible = computed({
- get: () => props.modelValue,
- set: (val) => emit("update:modelValue", val),
-});
+ const dialogVisible = computed({
+ get: () => props.modelValue,
+ set: val => emit("update:modelValue", val),
+ });
-const formRef = ref(null);
-const employeeTableRef = ref(null);
-const personTreeRef = ref(null);
-const addPersonVisible = ref(false);
-const taxDialogVisible = ref(false);
-const deptOptions = ref([]);
-const deptStaffTree = ref([]);
-const employeeList = ref([]);
-const selectedEmployees = ref([]);
-const bankOptions = ref([]);
-const taxTableData = ref([
- { level: 1, range: "涓嶈秴杩�36000鍏�", rate: 3, quickDeduction: 0 },
- { level: 2, range: "瓒呰繃36000-144000鍏�", rate: 10, quickDeduction: 2520 },
- { level: 3, range: "瓒呰繃144000-300000鍏�", rate: 20, quickDeduction: 16920 },
- { level: 4, range: "瓒呰繃300000-420000鍏�", rate: 25, quickDeduction: 31920 },
- { level: 5, range: "瓒呰繃420000-660000鍏�", rate: 30, quickDeduction: 52920 },
- { level: 6, range: "瓒呰繃660000-960000鍏�", rate: 35, quickDeduction: 85920 },
- { level: 7, range: "瓒呰繃960000鍏�", rate: 45, quickDeduction: 181920 },
-]);
+ const formRef = ref(null);
+ const employeeTableRef = ref(null);
+ const personTreeRef = ref(null);
+ const addPersonVisible = ref(false);
+ const taxDialogVisible = ref(false);
+ const deptOptions = ref([]);
+ const availableDeptIds = ref(new Set());
+ const deptStaffTree = ref([]);
+ const employeeList = ref([]);
+ const selectedEmployees = ref([]);
+ const bankOptions = ref([]);
+ const userList = ref([]);
+ const recalcTimers = new Map();
+ const recalcVersions = new Map();
+ const taxTableData = ref([
+ { level: 1, range: "涓嶈秴杩�36000鍏�", rate: 3, quickDeduction: 0 },
+ { level: 2, range: "瓒呰繃36000-144000鍏�", rate: 10, quickDeduction: 2520 },
+ { level: 3, range: "瓒呰繃144000-300000鍏�", rate: 20, quickDeduction: 16920 },
+ { level: 4, range: "瓒呰繃300000-420000鍏�", rate: 25, quickDeduction: 31920 },
+ { level: 5, range: "瓒呰繃420000-660000鍏�", rate: 30, quickDeduction: 52920 },
+ { level: 6, range: "瓒呰繃660000-960000鍏�", rate: 35, quickDeduction: 85920 },
+ { level: 7, range: "瓒呰繃960000鍏�", rate: 45, quickDeduction: 181920 },
+ ]);
-function parseNum(v) {
- if (v === "" || v == null) return 0;
- const n = Number(v);
- return isNaN(n) ? 0 : n;
-}
+ function parseNum(v) {
+ if (v === "" || v == null) return 0;
+ const n = Number(v);
+ return isNaN(n) ? 0 : n;
+ }
-// 鍩虹璧勬枡琛ㄥ崟
-const data = reactive({
- form: {
+ function parseNullableNum(v) {
+ if (v === "" || v == null) return null;
+ const n = Number(v);
+ return isNaN(n) ? null : n;
+ }
+
+ const createEmployeeRow = () => ({
+ staffOnJobId: undefined,
id: undefined,
- salaryTitle: "",
- deptIds: [],
- salaryMonth: "",
+ staffName: "",
+ postName: "",
+ deptName: "",
+ basicSalary: 0,
+ pieceSalary: 0,
+ hourlySalary: 0,
+ otherIncome: 0,
+ socialPersonal: 0,
+ fundPersonal: 0,
+ otherDeduct: 0,
+ socialSupplementAmount: null,
+ salaryTax: 0,
+ grossSalary: 0,
+ deductSalary: 0,
+ netSalary: 0,
remark: "",
- payBank: "",
- },
- rules: {
- salaryTitle: [{ required: true, message: "璇疯緭鍏ュ伐璧勪富棰�", trigger: "blur" }],
- deptIds: [{ required: true, message: "璇烽�夋嫨閮ㄩ棬", trigger: "change" }],
- salaryMonth: [{ required: true, message: "璇烽�夋嫨宸ヨ祫鏈堜唤", trigger: "change" }],
- },
-});
-const { form, rules } = toRefs(data);
-
-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 !== "");
});
-};
-// 鎵佸钩鍖栭儴闂ㄦ爲渚涗笅鎷変娇鐢�
-function flattenDept(tree, list = []) {
- if (!tree?.length) return list;
- tree.forEach((node) => {
- list.push({ deptId: node.deptId, deptName: node.deptName });
- if (node.children?.length) flattenDept(node.children, list);
+ const normalizeEmployeeRow = (source, fallback = {}) => ({
+ ...createEmployeeRow(),
+ ...fallback,
+ ...source,
+ staffOnJobId: source?.staffOnJobId ?? source?.staffId ?? source?.id ?? fallback.staffOnJobId ?? fallback.id,
+ id: source?.staffOnJobId ?? source?.staffId ?? source?.id ?? fallback.staffOnJobId ?? fallback.id,
+ staffName: source?.staffName ?? fallback.staffName ?? "",
+ postName: source?.postName ?? fallback.postName ?? "",
+ deptName: source?.deptName ?? fallback.deptName ?? "",
+ basicSalary: parseNum(source?.basicSalary ?? fallback.basicSalary),
+ pieceSalary: parseNum(source?.pieceSalary ?? fallback.pieceSalary),
+ hourlySalary: parseNum(source?.hourlySalary ?? fallback.hourlySalary),
+ otherIncome: parseNum(source?.otherIncome ?? fallback.otherIncome),
+ socialPersonal: parseNum(source?.socialPersonal ?? fallback.socialPersonal),
+ fundPersonal: parseNum(source?.fundPersonal ?? fallback.fundPersonal),
+ otherDeduct: parseNum(source?.otherDeduct ?? fallback.otherDeduct),
+ socialSupplementAmount:
+ source?.socialSupplementAmount ?? fallback.socialSupplementAmount ?? null,
+ salaryTax: parseNum(source?.salaryTax ?? fallback.salaryTax),
+ grossSalary: parseNum(source?.grossSalary ?? fallback.grossSalary),
+ deductSalary: parseNum(source?.deductSalary ?? fallback.deductSalary),
+ netSalary: parseNum(source?.netSalary ?? fallback.netSalary),
+ remark: source?.remark ?? fallback.remark ?? "",
});
- return list;
-}
-const loadDeptOptions = () => {
- listDept().then((res) => {
- const tree = res.data ?? [];
- deptOptions.value = flattenDept(tree);
- });
-};
+ const applyBackendRow = (targetRow, sourceRow) => {
+ Object.assign(targetRow, normalizeEmployeeRow(sourceRow, targetRow));
+ };
-// 鏋勫缓 閮ㄩ棬-浜哄憳 鏍戯紙鐢ㄤ簬鏂板浜哄憳寮圭獥锛�
-const loadDeptStaffTree = () => {
- Promise.all([listDept(), staffOnJobList()]).then(([deptRes, staffRes]) => {
- const tree = deptRes.data ?? [];
- const staffList = staffRes.data ?? [];
- const deptMap = new Map();
- function walk(nodes) {
- nodes.forEach((node) => {
- deptMap.set(node.deptId, {
- id: "dept_" + node.deptId,
- deptId: node.deptId,
- label: node.deptName,
- type: "dept",
- children: [],
+ const clearRowRecalcState = row => {
+ const key = String(row?.staffOnJobId ?? row?.id ?? "");
+ if (!key) return;
+ clearTimeout(recalcTimers.get(key));
+ recalcTimers.delete(key);
+ recalcVersions.delete(key);
+ };
+
+ const resetRecalcState = () => {
+ recalcTimers.forEach(timer => clearTimeout(timer));
+ recalcTimers.clear();
+ recalcVersions.clear();
+ };
+
+ const requestEmployeeRecalculate = row => {
+ const key = String(row?.staffOnJobId ?? row?.id ?? "");
+ if (!key || !form.value.salaryMonth) return;
+ const version = (recalcVersions.get(key) || 0) + 1;
+ recalcVersions.set(key, version);
+ clearTimeout(recalcTimers.get(key));
+ const payload = {
+ staffOnJobId: row.staffOnJobId ?? row.id,
+ salaryMonth: form.value.salaryMonth,
+ staffName: row.staffName ?? "",
+ postName: row.postName ?? "",
+ deptName: row.deptName ?? "",
+ basicSalary: parseNum(row.basicSalary),
+ pieceSalary: parseNum(row.pieceSalary),
+ hourlySalary: parseNum(row.hourlySalary),
+ otherIncome: parseNum(row.otherIncome),
+ otherDeduct: parseNum(row.otherDeduct),
+ socialSupplementAmount: parseNullableNum(row.socialSupplementAmount),
+ remark: row.remark ?? "",
+ };
+ recalcTimers.set(
+ key,
+ setTimeout(() => {
+ staffSalaryMainCalculateByEmployeeId(payload).then(res => {
+ if (recalcVersions.get(key) !== version) return;
+ applyBackendRow(row, res?.data || {});
});
- if (node.children?.length) walk(node.children);
- });
- }
- walk(tree);
- staffList.forEach((s) => {
- const deptId = s.deptId ?? s.dept_id;
- const node = deptMap.get(deptId);
- if (node) {
- node.children.push({
- id: s.id ?? s.staffId,
- staffId: s.id ?? s.staffId,
- label: s.staffName ?? s.name,
- type: "staff",
- ...s,
- });
- }
- });
- deptStaffTree.value = Array.from(deptMap.values()).filter(
- (n) => n.children && n.children.length > 0
+ }, 250)
);
- });
-};
+ };
-const openDialog = (type, row) => {
- nextTick(() => {
- loadDeptOptions();
- loadBankOptions();
- employeeList.value = [];
- Object.assign(form.value, {
+ const handleSalaryInput = row => {
+ row.basicSalary = parseNum(row.basicSalary);
+ row.otherIncome = parseNum(row.otherIncome);
+ requestEmployeeRecalculate(row);
+ };
+
+ // 鍩虹璧勬枡琛ㄥ崟
+ const data = reactive({
+ form: {
id: undefined,
salaryTitle: "",
deptIds: [],
salaryMonth: "",
remark: "",
payBank: "",
+ auditUserId: undefined,
+ },
+ rules: {
+ 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 !== "");
});
- // 缂栬緫锛氬垪琛ㄩ〉宸茶繑鍥炰富琛ㄥ瓧娈碉紱杩欓噷鍙仛鍥炴樉锛堟槑缁嗙敱鈥滅敓鎴愬伐璧勮〃/璁$畻宸ヨ祫鈥濆緱鍒帮級
- if (type === "edit" && row?.id) {
- 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 ?? "";
- }
- });
-};
-
-const openAddPerson = () => {
- loadDeptStaffTree();
- addPersonVisible.value = true;
- nextTick(() => {
- personTreeRef.value?.setCheckedKeys([]);
- });
-};
-
-const addPersonClose = () => {};
-
-const confirmAddPerson = () => {
- const tree = personTreeRef.value;
- if (!tree) {
- addPersonVisible.value = false;
- return;
- }
- const checked = tree.getCheckedNodes();
- const staffNodes = checked.filter((n) => n.type === "staff");
- const existIds = new Set(employeeList.value.map((e) => e.staffId || e.id));
- staffNodes.forEach((node) => {
- const id = node.staffId ?? node.id;
- if (existIds.has(id)) return;
- existIds.add(id);
- employeeList.value.push({
- staffOnJobId: id,
- id,
- staffName: node.label,
- postName: node.postName ?? node.post ?? "",
- deptName: node.deptName ?? "",
- basicSalary: 0,
- pieceSalary: 0,
- hourlySalary: 0,
- otherIncome: 0,
- socialPersonal: 0,
- fundPersonal: 0,
- otherDeduct: 0,
- salaryTax: 0,
- grossSalary: 0,
- deductSalary: 0,
- netSalary: 0,
- remark: "",
- });
- });
- addPersonVisible.value = false;
-};
-
-const removeEmployee = (row) => {
- employeeList.value = employeeList.value.filter(
- (e) => (e.staffOnJobId || e.id) !== (row.staffOnJobId || row.id)
- );
-};
-
-const onEmployeeSelectionChange = (selection) => {
- selectedEmployees.value = selection;
-};
-
-const handleBatchDelete = () => {
- if (!selectedEmployees.value?.length) {
- proxy.$modal.msgWarning("璇峰厛鍕鹃�夎鍒犻櫎鐨勫憳宸�");
- return;
- }
- const ids = new Set(selectedEmployees.value.map((e) => e.staffOnJobId || e.id));
- employeeList.value = employeeList.value.filter(
- (e) => !ids.has(e.staffOnJobId || e.id)
- );
-};
-
-const handleGenerate = () => {
- 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("鏈绠楀埌宸ヨ祫鏁版嵁");
+
+ const loadUserList = () => {
+ return userListNoPageByTenantId().then(res => {
+ userList.value = res.data || [];
+ });
+ };
+
+ // 鎵佸钩鍖栭儴闂ㄦ爲渚涗笅鎷変娇鐢�
+ function flattenDept(tree, list = []) {
+ if (!tree?.length) return list;
+ tree.forEach(node => {
+ list.push({ deptId: node.deptId, deptName: node.deptName });
+ if (node.children?.length) flattenDept(node.children, list);
+ });
+ return list;
+ }
+
+ // 鍔犺浇鎵�鏈夐儴闂�
+ const loadAllDeptOptions = () => {
+ listDept().then(res => {
+ const tree = res.data ?? [];
+ deptOptions.value = flattenDept(tree);
+ });
+ };
+
+ // 鍔犺浇鍙敤閮ㄩ棬鍒楄〃锛堢敤浜庡垽鏂儴闂ㄦ槸鍚﹀彲閫夛級
+ const loadAvailableDepts = (salaryMonth) => {
+ if (!salaryMonth) {
+ availableDeptIds.value = new Set();
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("鐢熸垚鎴愬姛");
+ staffSalaryMainAvailableDepts(salaryMonth).then(res => {
+ const availableDepts = Array.isArray(res.data) ? res.data : [];
+ availableDeptIds.value = new Set(availableDepts.map(d => d.deptId));
+ });
+ };
+
+ // 鍒ゆ柇閮ㄩ棬鏄惁绂佺敤
+ const isDeptDisabled = (deptId) => {
+ // 濡傛灉娌℃湁閫夋嫨鏈堜唤锛屾墍鏈夐儴闂ㄩ兘鍙��
+ if (!form.value.salaryMonth) return false;
+ // 濡傛灉宸查�夋嫨鏈堜唤锛屽彧鏈夊湪鍙敤閮ㄩ棬鍒楄〃涓殑閮ㄩ棬鎵嶅彲閫�
+ return !availableDeptIds.value.has(deptId);
+ };
+
+ // 鏋勫缓 閮ㄩ棬-浜哄憳 鏍戯紙鐢ㄤ簬鏂板浜哄憳寮圭獥锛�
+ const loadDeptStaffTree = () => {
+ Promise.all([listDept(), staffOnJobList()]).then(([deptRes, staffRes]) => {
+ const tree = deptRes.data ?? [];
+ const staffList = staffRes.data ?? [];
+ const deptMap = new Map();
+ function walk(nodes) {
+ nodes.forEach(node => {
+ deptMap.set(node.deptId, {
+ id: "dept_" + node.deptId,
+ deptId: node.deptId,
+ label: node.deptName,
+ type: "dept",
+ children: [],
+ });
+ if (node.children?.length) walk(node.children);
+ });
+ }
+ walk(tree);
+ staffList.forEach(s => {
+ const deptId = s.deptId ?? s.dept_id;
+ const node = deptMap.get(deptId);
+ if (node) {
+ node.children.push({
+ id: s.id ?? s.staffId,
+ staffId: s.id ?? s.staffId,
+ label: s.staffName ?? s.name,
+ type: "staff",
+ ...s,
+ });
+ }
+ });
+ deptStaffTree.value = Array.from(deptMap.values()).filter(
+ n => n.children && n.children.length > 0
+ );
+ });
+ };
+
+ const openDialog = (type, row) => {
+ nextTick(() => {
+ resetRecalcState();
+ loadBankOptions();
+ loadUserList();
+ loadAllDeptOptions();
+ employeeList.value = [];
+ Object.assign(form.value, {
+ id: undefined,
+ salaryTitle: "",
+ 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.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 => normalizeEmployeeRow(e));
+ }
+ }
+ // 缂栬緫鐘舵�佷笖鏈夋湀浠芥椂锛屽姞杞藉彲鐢ㄩ儴闂ㄥ垪琛�
+ if (type === "edit" && form.value.salaryMonth) {
+ loadAvailableDepts(form.value.salaryMonth);
+ }
+ });
+ };
+
+ // 鐩戝惉宸ヨ祫鏈堜唤鍙樺寲锛屾竻绌洪儴闂ㄩ�夋嫨骞跺姞杞藉彲鐢ㄩ儴闂ㄥ垪琛�
+ watch(() => form.value.salaryMonth, (newMonth, oldMonth) => {
+ // 鍒囨崲鏈堜唤鏃舵竻绌哄凡閫夋嫨鐨勯儴闂�
+ if (newMonth !== oldMonth) {
+ form.value.deptIds = [];
+ }
+ loadAvailableDepts(newMonth);
});
-};
-const handleExport = () => {
- proxy.$modal.msgInfo("瀵煎嚭鍔熻兘闇�瀵规帴鍚庣");
-};
+ const openAddPerson = () => {
+ loadDeptStaffTree();
+ addPersonVisible.value = true;
+ nextTick(() => {
+ personTreeRef.value?.setCheckedKeys([]);
+ });
+ };
-const handleImport = () => {
- proxy.$modal.msgInfo("瀵煎叆鍔熻兘闇�瀵规帴鍚庣");
-};
+ const addPersonClose = () => {};
-const handleClear = () => {
- proxy.$modal.confirm("纭畾娓呯┖褰撳墠鍛樺伐鍒楄〃鍚楋紵").then(() => {
- employeeList.value = [];
- }).catch(() => {});
-};
+ const confirmAddPerson = () => {
+ const tree = personTreeRef.value;
+ if (!tree) {
+ addPersonVisible.value = false;
+ return;
+ }
+ const checked = tree.getCheckedNodes();
+ const staffNodes = checked.filter(n => n.type === "staff");
+ const existIds = new Set(employeeList.value.map(e => e.staffId || e.id));
+ staffNodes.forEach(node => {
+ const id = node.staffId ?? node.id;
+ if (existIds.has(id)) return;
+ existIds.add(id);
+ const newRow = normalizeEmployeeRow({
+ staffOnJobId: id,
+ id,
+ staffName: node.label,
+ postName: node.postName ?? node.post ?? "",
+ deptName: node.deptName ?? "",
+ remark: "",
+ socialSupplementAmount: null,
+ });
+ employeeList.value.push(newRow);
+ requestEmployeeRecalculate(newRow);
+ });
+ addPersonVisible.value = false;
+ };
-const handleTaxForm = () => {
- taxDialogVisible.value = true;
-};
+ const removeEmployee = row => {
+ clearRowRecalcState(row);
+ employeeList.value = employeeList.value.filter(
+ e => (e.staffOnJobId || e.id) !== (row.staffOnJobId || row.id)
+ );
+ };
-const submitForm = () => {
- formRef.value?.validate((valid) => {
- if (!valid) return;
+ const onEmployeeSelectionChange = selection => {
+ selectedEmployees.value = selection;
+ };
+
+ const handleBatchDelete = () => {
+ if (!selectedEmployees.value?.length) {
+ proxy.$modal.msgWarning("璇峰厛鍕鹃�夎鍒犻櫎鐨勫憳宸�");
+ return;
+ }
+ const ids = new Set(selectedEmployees.value.map(e => e.staffOnJobId || e.id));
+ selectedEmployees.value.forEach(item => clearRowRecalcState(item));
+ employeeList.value = employeeList.value.filter(
+ e => !ids.has(e.staffOnJobId || e.id)
+ );
+ };
+
+ const handleGenerate = () => {
+ 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;
+ }
+ resetRecalcState();
+ employeeList.value = list.map(e => normalizeEmployeeRow(e));
+ proxy.$modal.msgSuccess("鐢熸垚鎴愬姛");
+ });
+ };
+
+ const handleClear = () => {
+ proxy.$modal
+ .confirm("纭畾娓呯┖褰撳墠鍛樺伐鍒楄〃鍚楋紵")
+ .then(() => {
+ resetRecalcState();
+ employeeList.value = [];
+ })
+ .catch(() => {});
+ };
+
+ const handleTaxForm = () => {
+ taxDialogVisible.value = true;
+ };
+
+ const submitForm = () => {
+ formRef.value?.validate(valid => {
+ if (!valid) return;
+ 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,
@@ -550,7 +816,10 @@
salaryMonth: form.value.salaryMonth,
remark: form.value.remark,
payBank: form.value.payBank,
- staffSalaryDetailList: employeeList.value.map((e) => ({
+ 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 ?? "",
@@ -562,6 +831,7 @@
socialPersonal: parseNum(e.socialPersonal),
fundPersonal: parseNum(e.fundPersonal),
otherDeduct: parseNum(e.otherDeduct),
+ socialSupplementAmount: parseNum(e.socialSupplementAmount),
salaryTax: parseNum(e.salaryTax),
grossSalary: parseNum(e.grossSalary),
deductSalary: parseNum(e.deductSalary),
@@ -570,78 +840,95 @@
})),
};
if (props.operationType === "add") {
- staffSalaryMainAdd({ ...payload, status: 1 }).then(() => {
- proxy.$modal.msgSuccess("鏂板鎴愬姛");
+ staffSalaryMainAdd({ ...payload, status }).then(() => {
+ proxy.$modal.msgSuccess(status === 1 ? "鑽夌淇濆瓨鎴愬姛" : "鎻愪氦鎴愬姛");
closeDia();
});
} else {
- staffSalaryMainUpdate(payload).then(() => {
- proxy.$modal.msgSuccess("淇敼鎴愬姛");
+ staffSalaryMainUpdate({ ...payload, status }).then(() => {
+ proxy.$modal.msgSuccess(status === 1 ? "鑽夌淇濆瓨鎴愬姛" : "鎻愪氦鎴愬姛");
closeDia();
});
}
- });
-};
+ };
-const closeDia = () => {
- dialogVisible.value = false;
- emit("close");
-};
+ const closeDia = () => {
+ resetRecalcState();
+ dialogVisible.value = false;
+ emit("close");
+ };
-defineExpose({ openDialog });
+ defineExpose({ openDialog });
</script>
<style scoped>
-.form-dia-body {
- padding: 0;
-}
-.card-title-line {
- color: #f56c6c;
- margin-right: 4px;
-}
-.form-card {
- margin-bottom: 16px;
-}
-.form-card :deep(.el-card__header) {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 12px 16px;
-}
-.card-title {
- font-weight: 500;
-}
-.card-collapse {
- color: #999;
- cursor: pointer;
-}
-.toolbar {
- margin-bottom: 16px;
- display: flex;
- flex-wrap: wrap;
- gap: 10px;
-}
-.employee-table-wrap {
- position: relative;
- min-height: 120px;
-}
-.table-empty {
- text-align: center;
- padding: 24px;
- color: #999;
- font-size: 14px;
-}
-.add-person-tree {
- max-height: 360px;
- overflow-y: auto;
- padding: 8px 0;
-}
-.tax-desc {
- margin-bottom: 12px;
- font-size: 14px;
- color: #606266;
-}
-.dialog-footer {
- text-align: right;
-}
+ .form-dia-body {
+ padding: 0;
+ }
+ .card-title-line {
+ color: #f56c6c;
+ margin-right: 4px;
+ }
+ .form-card {
+ margin-bottom: 16px;
+ }
+ .form-card :deep(.el-card__header) {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 12px 16px;
+ }
+ .card-title {
+ font-weight: 500;
+ }
+ .card-collapse {
+ color: #999;
+ cursor: pointer;
+ }
+ .toolbar {
+ margin-bottom: 16px;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+ }
+ .employee-table-wrap {
+ position: relative;
+ min-height: 120px;
+ }
+ .table-empty {
+ text-align: center;
+ padding: 24px;
+ color: #999;
+ font-size: 14px;
+ }
+ .add-person-tree {
+ max-height: 360px;
+ overflow-y: auto;
+ padding: 8px 0;
+ }
+ .tax-desc {
+ margin-bottom: 12px;
+ font-size: 14px;
+ color: #606266;
+ }
+ .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