From 332cfbec0e7dddadc5c5f676d183d06210abc981 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期三, 27 五月 2026 16:46:19 +0800
Subject: [PATCH] 人员台账增加民族筛选、补贴配置页面、人员薪资修改工资表、增加厂家管理页面、库存管理增加来源字段和废品库
---
src/views/inventoryManagement/manufacturer/index.vue | 50
src/views/inventoryManagement/stockManagement/New.vue | 53
src/views/inventoryManagement/manufacturer/components/HomeTab.vue | 588 ++++++++
src/views/personnelManagement/employeeRecord/index.vue | 689 +++++----
src/views/inventoryManagement/manufacturer/filesDia.vue | 198 ++
src/views/personnelManagement/employeeRecord/components/BasicInfoSection.vue | 237 +-
src/views/personnelManagement/monthlyStatistics/components/formDia.vue | 1430 ++++++++++---------
src/views/personnelManagement/subsidyConfig/index.vue | 437 ++++++
src/views/inventoryManagement/manufacturer/components/BlacklistTab.vue | 583 ++++++++
src/api/personnelManagement/subsidyConfig.js | 19
10 files changed, 3,163 insertions(+), 1,121 deletions(-)
diff --git a/src/api/personnelManagement/subsidyConfig.js b/src/api/personnelManagement/subsidyConfig.js
new file mode 100644
index 0000000..f4f9f43
--- /dev/null
+++ b/src/api/personnelManagement/subsidyConfig.js
@@ -0,0 +1,19 @@
+import request from "@/utils/request";
+
+// 鏌ヨ琛ヨ创閰嶇疆鍒楄〃
+export function listSubsidyConfiguration(query) {
+ return request({
+ url: "/subsidyConfiguration/list",
+ method: "get",
+ params: query,
+ });
+}
+
+// 淇濆瓨琛ヨ创閰嶇疆
+export function saveSubsidyConfiguration(data) {
+ return request({
+ url: "/subsidyConfiguration/save",
+ method: "post",
+ data: data,
+ });
+}
diff --git a/src/views/inventoryManagement/manufacturer/components/BlacklistTab.vue b/src/views/inventoryManagement/manufacturer/components/BlacklistTab.vue
new file mode 100644
index 0000000..3c2e01d
--- /dev/null
+++ b/src/views/inventoryManagement/manufacturer/components/BlacklistTab.vue
@@ -0,0 +1,583 @@
+<template>
+ <div class="app-container">
+ <div class="search_form">
+ <div>
+ <span class="search_title">鍘傚妗f锛�</span>
+ <el-input v-model="searchForm.supplierName"
+ style="width: 240px"
+ placeholder="杈撳叆鍘傚鍚嶇О鎼滅储"
+ @change="handleQuery"
+ clearable
+ :prefix-icon="Search" />
+ <el-button type="primary"
+ @click="handleQuery"
+ style="margin-left: 10px">鎼滅储</el-button>
+ </div>
+ <div>
+ <el-button @click="handleOut">瀵煎嚭</el-button>
+ <el-button type="danger"
+ plain
+ @click="handleDelete">鍒犻櫎</el-button>
+ </div>
+ </div>
+ <div class="table_list">
+ <PIMTable rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"></PIMTable>
+ </div>
+ <el-dialog v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板鍘傚淇℃伅' : '缂栬緫鍘傚淇℃伅'"
+ width="70%"
+ @close="closeDia">
+ <el-form :model="form"
+ label-width="140px"
+ label-position="top"
+ :rules="rules"
+ ref="formRef">
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍘傚鍚嶇О锛�"
+ prop="supplierName">
+ <el-input v-model="form.supplierName"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="绾崇◣浜鸿瘑鍒彿锛�"
+ prop="taxpayerIdentificationNum">
+ <el-input v-model="form.taxpayerIdentificationNum"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍏徃鍦板潃锛�"
+ prop="companyAddress">
+ <el-input v-model="form.companyAddress"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍏徃鐢佃瘽锛�"
+ prop="companyPhone">
+ <el-input v-model="form.companyPhone"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="寮�鎴疯锛�"
+ prop="bankAccountName">
+ <el-input v-model="form.bankAccountName"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璐﹀彿锛�"
+ prop="bankAccountNum">
+ <el-input v-model="form.bankAccountNum"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鑱旂郴浜猴細"
+ prop="contactUserName">
+ <el-input v-model="form.contactUserName"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鑱旂郴鐢佃瘽锛�"
+ prop="contactUserPhone">
+ <el-input v-model="form.contactUserPhone"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="缁存姢浜猴細"
+ prop="maintainUserId">
+ <el-select v-model="form.maintainUserId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ disabled>
+ <el-option v-for="item in userList"
+ :key="item.nickName"
+ :label="item.nickName"
+ :value="item.userId" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="缁存姢鏃堕棿锛�"
+ prop="maintainTime">
+ <el-date-picker style="width: 100%"
+ v-model="form.maintainTime"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍘傚绫诲瀷锛�"
+ prop="supplierType">
+ <el-select v-model="form.supplierType"
+ placeholder="璇烽�夋嫨"
+ clearable>
+ <el-option label="鐢�"
+ value="鐢�" />
+ <el-option label="涔�"
+ value="涔�" />
+ <el-option label="涓�"
+ value="涓�" />
+ <el-option label="涓�"
+ value="涓�" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鏄惁鐧藉悕鍗曪細"
+ prop="isWhite">
+ <el-select v-model="form.isWhite"
+ placeholder="璇烽�夋嫨"
+ clearable>
+ <el-option label="鏄�"
+ :value="0" />
+ <el-option label="鍚�"
+ :value="1" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary"
+ @click="submitForm">纭</el-button>
+ <el-button @click="closeDia">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ <!-- 鍘傚瀵煎叆瀵硅瘽妗� -->
+ <el-dialog :title="upload.title"
+ v-model="upload.open"
+ width="400px"
+ append-to-body>
+ <el-upload ref="uploadRef"
+ :limit="1"
+ accept=".xlsx, .xls"
+ :headers="upload.headers"
+ :action="upload.url + '?updateSupport=' + upload.updateSupport"
+ :disabled="upload.isUploading"
+ :on-progress="handleFileUploadProgress"
+ :on-success="handleFileSuccess"
+ :on-error="handleFileError"
+ :auto-upload="false"
+ drag>
+ <el-icon class="el-icon--upload"><upload-filled /></el-icon>
+ <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
+ <template #tip>
+ <div class="el-upload__tip text-center">
+ <span>浠呭厑璁稿鍏ls銆亁lsx鏍煎紡鏂囦欢銆�</span>
+ <el-link type="primary"
+ :underline="false"
+ style="font-size: 12px; vertical-align: baseline"
+ @click="importTemplate">涓嬭浇妯℃澘</el-link>
+ </div>
+ </template>
+ </el-upload>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary"
+ @click="submitFileForm">纭� 瀹�</el-button>
+ <el-button @click="upload.open = false">鍙� 娑�</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ <FileList v-if="fileListDialogVisible"
+ v-model:visible="fileListDialogVisible"
+ record-type="supplier_manage"
+ :record-id="recordId" />
+ </div>
+</template>
+
+<script setup>
+ import { onMounted, ref } from "vue";
+ import { Search } from "@element-plus/icons-vue";
+ import { delSupplier } from "@/api/basicData/supplierManageFile.js";
+ import { ElMessageBox } from "element-plus";
+ import { userListNoPage } from "@/api/system/user.js";
+ import {
+ addSupplier,
+ getSupplier,
+ listSupplier,
+ updateSupplier,
+ } from "@/api/basicData/supplierManageFile.js";
+ import useUserStore from "@/store/modules/user";
+ import { getToken } from "@/utils/auth.js";
+ const FileList = defineAsyncComponent(() =>
+ import("@/components/Dialog/FileList.vue")
+ );
+ const { proxy } = getCurrentInstance();
+ const userStore = useUserStore();
+
+ const tableColumn = ref([
+ {
+ label: "鍘傚鍚嶇О",
+ prop: "supplierName",
+ width: 250,
+ },
+ {
+ label: "鍘傚绫诲瀷",
+ prop: "supplierType",
+ width: 120,
+ },
+ {
+ label: "绾崇◣浜鸿瘑鍒彿",
+ prop: "taxpayerIdentificationNum",
+ width: 230,
+ },
+ {
+ label: "鍏徃鍦板潃",
+ prop: "companyAddress",
+ width: 220,
+ },
+ {
+ label: "鑱旂郴鏂瑰紡",
+ prop: "companyPhone",
+ width: 150,
+ },
+ {
+ label: "寮�鎴疯",
+ prop: "bankAccountName",
+ width: 220,
+ },
+ {
+ label: "璐﹀彿",
+ prop: "bankAccountNum",
+ width: 220,
+ },
+ {
+ label: "鑱旂郴浜�",
+ prop: "contactUserName",
+ },
+ {
+ label: "鑱旂郴鐢佃瘽",
+ prop: "contactUserPhone",
+ width: 150,
+ },
+ {
+ label: "缁存姢浜�",
+ prop: "maintainUserName",
+ },
+
+ {
+ label: "缁存姢鏃堕棿",
+ prop: "maintainTime",
+ width: 100,
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 150,
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: row => {
+ openForm("edit", row);
+ },
+ },
+ {
+ //璧勮川闄勪欢
+ name: "璧勮川鏂囦欢",
+ type: "text",
+ clickFun: row => {
+ openFileDialog(row);
+ },
+ },
+ ],
+ },
+ ]);
+ const tableData = ref([]);
+ const selectedRows = ref([]);
+ const userList = ref([]);
+ const tableLoading = ref(false);
+ const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+ });
+ const fileListDialogVisible = ref(false);
+ const recordId = ref();
+ // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+ const operationType = ref("");
+ const dialogFormVisible = ref(false);
+ const data = reactive({
+ searchForm: {
+ supplierName: "",
+ },
+ form: {
+ supplierName: "",
+ taxpayerIdentificationNum: "",
+ companyAddress: "",
+ companyPhone: "",
+ bankAccountName: "",
+ bankAccountNum: "",
+ contactUserName: "",
+ contactUserPhone: "",
+ maintainUserId: "",
+ maintainTime: "",
+ supplierType: "",
+ isWhite: "",
+ },
+ rules: {
+ supplierName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ taxpayerIdentificationNum: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ companyAddress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ companyPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ bankAccountName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ bankAccountNum: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ contactUserName: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
+ contactUserPhone: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
+ maintainUserId: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+ maintainTime: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+ supplierType: [
+ { required: true, message: "璇烽�夋嫨鍘傚绫诲瀷", trigger: "change" },
+ ],
+ },
+ });
+ const { searchForm, form, rules } = toRefs(data);
+
+ // 鏌ヨ鍒楄〃
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ const handleQuery = () => {
+ page.current = 1;
+ getList();
+ };
+ const pagination = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+ };
+ /** 鎻愪氦涓婁紶鏂囦欢 */
+ function submitFileForm() {
+ upload.isUploading = true;
+ proxy.$refs["uploadRef"].submit();
+ }
+ const getList = () => {
+ tableLoading.value = true;
+ listSupplier({ ...searchForm.value, ...page, isWhite: 1 }).then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ });
+ };
+ const upload = reactive({
+ // 鏄惁鏄剧ず寮瑰嚭灞傦紙鍘傚瀵煎叆锛�
+ open: false,
+ // 寮瑰嚭灞傛爣棰橈紙鍘傚瀵煎叆锛�
+ title: "",
+ // 鏄惁绂佺敤涓婁紶
+ isUploading: false,
+ // 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹�
+ updateSupport: 1,
+ // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+ headers: { Authorization: "Bearer " + getToken() },
+ // 涓婁紶鐨勫湴鍧�
+ url: import.meta.env.VITE_APP_BASE_API + "/system/supplier/import",
+ });
+ /** 瀵煎叆鎸夐挳鎿嶄綔 */
+ function handleImport() {
+ upload.title = "鍘傚瀵煎叆";
+ upload.open = true;
+ }
+ /** 涓嬭浇妯℃澘 */
+ function importTemplate() {
+ proxy.download("/system/supplier/downloadTemplate", {}, "鍘傚瀵煎叆妯℃澘.xlsx");
+ }
+
+ /**鏂囦欢涓婁紶涓鐞� */
+ const handleFileUploadProgress = (event, file, fileList) => {
+ upload.isUploading = true;
+ };
+
+ /** 鏂囦欢涓婁紶鎴愬姛澶勭悊 */
+ const handleFileSuccess = (response, file, fileList) => {
+ upload.isUploading = false;
+ if (response.code === 200) {
+ proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
+ upload.open = false;
+ proxy.$refs["uploadRef"].clearFiles();
+ getList();
+ } else if (response.code === 500) {
+ proxy.$modal.msgError(response.msg);
+ } else {
+ proxy.$modal.msgWarning(response.msg);
+ }
+ };
+
+ /** 鏂囦欢涓婁紶澶辫触澶勭悊 */
+ const handleFileError = (error, file, fileList) => {
+ upload.isUploading = false;
+ proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
+ };
+ // 琛ㄦ牸閫夋嫨鏁版嵁
+ const handleSelectionChange = selection => {
+ selectedRows.value = selection;
+ };
+ // 鎵撳紑寮规
+ const openForm = (type, row) => {
+ operationType.value = type;
+ form.value = {};
+ form.value.maintainUserId = userStore.id;
+ form.value.maintainTime = getCurrentDate();
+ userListNoPage().then(res => {
+ userList.value = res.data;
+ });
+ if (type === "edit") {
+ getSupplier(row.id).then(res => {
+ form.value = { ...res.data };
+ });
+ }
+ dialogFormVisible.value = true;
+ };
+ // 鎻愪氦琛ㄥ崟
+ const submitForm = () => {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ if (operationType.value === "edit") {
+ submitEdit();
+ } else {
+ submitAdd();
+ }
+ }
+ });
+ };
+ // 鎻愪氦鏂板
+ const submitAdd = () => {
+ addSupplier(form.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+ };
+ // 鎻愪氦淇敼
+ const submitEdit = () => {
+ updateSupplier(form.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+ };
+ // 鍏抽棴寮规
+ const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+ };
+ // 瀵煎嚭
+ const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download(
+ "/system/supplier/export",
+ { isWhite: 1 },
+ "鍘傚妗f.xlsx"
+ );
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ };
+ // 鍒犻櫎
+ const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ // 妫�鏌ユ槸鍚︽湁浠栦汉缁存姢鐨勬暟鎹�
+ const unauthorizedData = selectedRows.value.filter(
+ item => item.maintainUserName !== userStore.nickName
+ );
+ if (unauthorizedData.length > 0) {
+ proxy.$modal.msgWarning("涓嶅彲鍒犻櫎浠栦汉缁存姢鐨勬暟鎹�");
+ return;
+ }
+ ids = selectedRows.value.map(item => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ tableLoading.value = true;
+ delSupplier(ids)
+ .then(res => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ };
+
+ // 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
+ function getCurrentDate() {
+ const today = new Date();
+ const year = today.getFullYear();
+ const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
+ const day = String(today.getDate()).padStart(2, "0");
+ return `${year}-${month}-${day}`;
+ }
+ // 鎵撳紑闄勪欢寮规
+ const openFileDialog = async row => {
+ recordId.value = row.id;
+ fileListDialogVisible.value = true;
+ };
+
+ onMounted(() => {
+ getList();
+ });
+
+ defineExpose({
+ getList,
+ });
+</script>
+
+
diff --git a/src/views/inventoryManagement/manufacturer/components/HomeTab.vue b/src/views/inventoryManagement/manufacturer/components/HomeTab.vue
new file mode 100644
index 0000000..08985ae
--- /dev/null
+++ b/src/views/inventoryManagement/manufacturer/components/HomeTab.vue
@@ -0,0 +1,588 @@
+<template>
+ <div>
+ <div class="search_form">
+ <div style="margin-bottom: 10px;">
+ <span class="search_title">鍘傚妗f锛�</span>
+ <el-input v-model="searchForm.supplierName"
+ style="width: 240px"
+ placeholder="杈撳叆鍘傚鍚嶇О鎼滅储"
+ @change="handleQuery"
+ clearable
+ :prefix-icon="Search" />
+ <el-button type="primary"
+ @click="handleQuery"
+ style="margin-left: 10px">鎼滅储</el-button>
+ </div>
+ <div style="margin-bottom: 10px;">
+ <el-button type="primary"
+ @click="openForm('add')">鏂板鍘傚</el-button>
+ <el-button @click="handleOut">瀵煎嚭</el-button>
+ <el-button type="info"
+ plain
+ icon="Upload"
+ @click="handleImport">瀵煎叆</el-button>
+ <el-button type="danger"
+ plain
+ @click="handleDelete">鍒犻櫎</el-button>
+ </div>
+ </div>
+ <div class="table_list">
+ <PIMTable rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"></PIMTable>
+ </div>
+ <el-dialog v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板鍘傚淇℃伅' : '缂栬緫鍘傚淇℃伅'"
+ width="70%"
+ @close="closeDia">
+ <el-form :model="form"
+ label-width="140px"
+ label-position="top"
+ :rules="rules"
+ ref="formRef">
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍘傚鍚嶇О锛�"
+ prop="supplierName">
+ <el-input v-model="form.supplierName"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="绾崇◣浜鸿瘑鍒彿锛�"
+ prop="taxpayerIdentificationNum">
+ <el-input v-model="form.taxpayerIdentificationNum"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍏徃鍦板潃锛�"
+ prop="companyAddress">
+ <el-input v-model="form.companyAddress"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍏徃鐢佃瘽锛�"
+ prop="companyPhone">
+ <el-input v-model="form.companyPhone"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="寮�鎴疯锛�"
+ prop="bankAccountName">
+ <el-input v-model="form.bankAccountName"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璐﹀彿锛�"
+ prop="bankAccountNum">
+ <el-input v-model="form.bankAccountNum"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鑱旂郴浜猴細"
+ prop="contactUserName">
+ <el-input v-model="form.contactUserName"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鑱旂郴鐢佃瘽锛�"
+ prop="contactUserPhone">
+ <el-input v-model="form.contactUserPhone"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="缁存姢浜猴細"
+ prop="maintainUserId">
+ <el-select v-model="form.maintainUserId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ disabled>
+ <el-option v-for="item in userList"
+ :key="item.nickName"
+ :label="item.nickName"
+ :value="item.userId" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="缁存姢鏃堕棿锛�"
+ prop="maintainTime">
+ <el-date-picker style="width: 100%"
+ v-model="form.maintainTime"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍘傚绫诲瀷锛�"
+ prop="supplierType">
+ <el-select v-model="form.supplierType"
+ placeholder="璇烽�夋嫨"
+ clearable>
+ <el-option label="鐢�"
+ value="鐢�" />
+ <el-option label="涔�"
+ value="涔�" />
+ <el-option label="涓�"
+ value="涓�" />
+ <el-option label="涓�"
+ value="涓�" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鏄惁鐧藉悕鍗曪細"
+ prop="isWhite">
+ <el-select v-model="form.isWhite"
+ placeholder="璇烽�夋嫨"
+ clearable>
+ <el-option label="鏄�"
+ :value="0" />
+ <el-option label="鍚�"
+ :value="1" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary"
+ @click="submitForm">纭</el-button>
+ <el-button @click="closeDia">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ <!-- 鍘傚瀵煎叆瀵硅瘽妗� -->
+ <el-dialog :title="upload.title"
+ v-model="upload.open"
+ width="400px"
+ append-to-body>
+ <el-upload ref="uploadRef"
+ :limit="1"
+ accept=".xlsx, .xls"
+ :headers="upload.headers"
+ :action="upload.url + '?updateSupport=' + upload.updateSupport"
+ :disabled="upload.isUploading"
+ :on-progress="handleFileUploadProgress"
+ :on-success="handleFileSuccess"
+ :on-error="handleFileError"
+ :auto-upload="false"
+ drag>
+ <el-icon class="el-icon--upload"><upload-filled /></el-icon>
+ <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
+ <template #tip>
+ <div class="el-upload__tip text-center">
+ <span>浠呭厑璁稿鍏ls銆亁lsx鏍煎紡鏂囦欢銆�</span>
+ <el-link type="primary"
+ :underline="false"
+ style="font-size: 12px; vertical-align: baseline"
+ @click="importTemplate">涓嬭浇妯℃澘</el-link>
+ </div>
+ </template>
+ </el-upload>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary"
+ @click="submitFileForm">纭� 瀹�</el-button>
+ <el-button @click="upload.open = false">鍙� 娑�</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ <FileList v-if="fileListDialogVisible"
+ v-model:visible="fileListDialogVisible"
+ record-type="supplier_manage"
+ :record-id="recordId" />
+ </div>
+</template>
+
+<script setup>
+ import { onMounted, ref } from "vue";
+ import { Search } from "@element-plus/icons-vue";
+ import { delSupplier } from "@/api/basicData/supplierManageFile.js";
+ import { ElMessageBox } from "element-plus";
+ import { userListNoPage } from "@/api/system/user.js";
+ import {
+ addSupplier,
+ getSupplier,
+ listSupplier,
+ updateSupplier,
+ } from "@/api/basicData/supplierManageFile.js";
+ import useUserStore from "@/store/modules/user";
+ import { getToken } from "@/utils/auth.js";
+ const FileList = defineAsyncComponent(() =>
+ import("@/components/Dialog/FileList.vue")
+ );
+ const { proxy } = getCurrentInstance();
+ const userStore = useUserStore();
+
+ const tableColumn = ref([
+ {
+ label: "鍘傚鍚嶇О",
+ prop: "supplierName",
+ width: 250,
+ },
+ {
+ label: "鍘傚绫诲瀷",
+ prop: "supplierType",
+ width: 120,
+ },
+ {
+ label: "绾崇◣浜鸿瘑鍒彿",
+ prop: "taxpayerIdentificationNum",
+ width: 230,
+ },
+ {
+ label: "鍏徃鍦板潃",
+ prop: "companyAddress",
+ width: 220,
+ },
+ {
+ label: "鑱旂郴鏂瑰紡",
+ prop: "companyPhone",
+ width: 150,
+ },
+ {
+ label: "寮�鎴疯",
+ prop: "bankAccountName",
+ width: 220,
+ },
+ {
+ label: "璐﹀彿",
+ prop: "bankAccountNum",
+ width: 220,
+ },
+ {
+ label: "鑱旂郴浜�",
+ prop: "contactUserName",
+ },
+ {
+ label: "鑱旂郴鐢佃瘽",
+ prop: "contactUserPhone",
+ width: 150,
+ },
+ {
+ label: "缁存姢浜�",
+ prop: "maintainUserName",
+ },
+
+ {
+ label: "缁存姢鏃堕棿",
+ prop: "maintainTime",
+ width: 100,
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 150,
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: row => {
+ openForm("edit", row);
+ },
+ },
+ {
+ //璧勮川闄勪欢
+ name: "璧勮川鏂囦欢",
+ type: "text",
+ clickFun: row => {
+ openFileDialog(row);
+ },
+ },
+ ],
+ },
+ ]);
+ const tableData = ref([]);
+ const selectedRows = ref([]);
+ const userList = ref([]);
+ const tableLoading = ref(false);
+ const fileListDialogVisible = ref(false);
+ const recordId = ref();
+ const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+ });
+ // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+ const operationType = ref("");
+ const dialogFormVisible = ref(false);
+ const data = reactive({
+ searchForm: {
+ supplierName: "",
+ },
+ form: {
+ supplierName: "",
+ taxpayerIdentificationNum: "",
+ companyAddress: "",
+ companyPhone: "",
+ bankAccountName: "",
+ bankAccountNum: "",
+ contactUserName: "",
+ contactUserPhone: "",
+ maintainUserId: "",
+ maintainTime: "",
+ supplierType: "",
+ isWhite: "",
+ },
+ rules: {
+ supplierName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ taxpayerIdentificationNum: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ companyAddress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ companyPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ bankAccountName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ bankAccountNum: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ contactUserName: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
+ contactUserPhone: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
+ maintainUserId: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+ maintainTime: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+ supplierType: [
+ { required: true, message: "璇烽�夋嫨鍘傚绫诲瀷", trigger: "change" },
+ ],
+ },
+ });
+ const { searchForm, form, rules } = toRefs(data);
+
+ // 鏌ヨ鍒楄〃
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ const handleQuery = () => {
+ page.current = 1;
+ getList();
+ };
+ const pagination = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+ };
+ /** 鎻愪氦涓婁紶鏂囦欢 */
+ function submitFileForm() {
+ upload.isUploading = true;
+ proxy.$refs["uploadRef"].submit();
+ }
+ const getList = () => {
+ tableLoading.value = true;
+ listSupplier({ ...searchForm.value, ...page, isWhite: 0 }).then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ });
+ };
+ const upload = reactive({
+ // 鏄惁鏄剧ず寮瑰嚭灞傦紙鍘傚瀵煎叆锛�
+ open: false,
+ // 寮瑰嚭灞傛爣棰橈紙鍘傚瀵煎叆锛�
+ title: "",
+ // 鏄惁绂佺敤涓婁紶
+ isUploading: false,
+ // 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹�
+ updateSupport: 1,
+ // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+ headers: { Authorization: "Bearer " + getToken() },
+ // 涓婁紶鐨勫湴鍧�
+ url: import.meta.env.VITE_APP_BASE_API + "/system/supplier/import",
+ });
+ /** 瀵煎叆鎸夐挳鎿嶄綔 */
+ function handleImport() {
+ upload.title = "鍘傚瀵煎叆";
+ upload.open = true;
+ }
+ /** 涓嬭浇妯℃澘 */
+ function importTemplate() {
+ proxy.download("/system/supplier/downloadTemplate", {}, "鍘傚瀵煎叆妯℃澘.xlsx");
+ }
+
+ /**鏂囦欢涓婁紶涓鐞� */
+ const handleFileUploadProgress = (event, file, fileList) => {
+ upload.isUploading = true;
+ };
+
+ /** 鏂囦欢涓婁紶鎴愬姛澶勭悊 */
+ const handleFileSuccess = (response, file, fileList) => {
+ upload.isUploading = false;
+ if (response.code === 200) {
+ proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
+ upload.open = false;
+ proxy.$refs["uploadRef"].clearFiles();
+ getList();
+ } else if (response.code === 500) {
+ proxy.$modal.msgError(response.msg);
+ } else {
+ proxy.$modal.msgWarning(response.msg);
+ }
+ };
+
+ /** 鏂囦欢涓婁紶澶辫触澶勭悊 */
+ const handleFileError = (error, file, fileList) => {
+ upload.isUploading = false;
+ proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
+ };
+ // 琛ㄦ牸閫夋嫨鏁版嵁
+ const handleSelectionChange = selection => {
+ selectedRows.value = selection;
+ };
+ // 鎵撳紑寮规
+ const openForm = (type, row) => {
+ operationType.value = type;
+ form.value = {};
+ form.value.maintainUserId = userStore.id;
+ form.value.maintainTime = getCurrentDate();
+ userListNoPage().then(res => {
+ userList.value = res.data;
+ });
+ if (type === "edit") {
+ getSupplier(row.id).then(res => {
+ form.value = { ...res.data };
+ });
+ }
+ dialogFormVisible.value = true;
+ };
+ // 鎻愪氦琛ㄥ崟
+ const submitForm = () => {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ if (operationType.value === "edit") {
+ submitEdit();
+ } else {
+ submitAdd();
+ }
+ }
+ });
+ };
+ // 鎻愪氦鏂板
+ const submitAdd = () => {
+ addSupplier(form.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+ };
+ // 鎻愪氦淇敼
+ const submitEdit = () => {
+ updateSupplier(form.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+ };
+ // 鍏抽棴寮规
+ const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+ };
+ // 瀵煎嚭
+ const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download(
+ "/system/supplier/export",
+ { isWhite: 0 },
+ "鍘傚妗f.xlsx"
+ );
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ };
+ // 鍒犻櫎
+ const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ // 妫�鏌ユ槸鍚︽湁浠栦汉缁存姢鐨勬暟鎹�
+ const unauthorizedData = selectedRows.value.filter(
+ item => item.maintainUserName !== userStore.nickName
+ );
+ if (unauthorizedData.length > 0) {
+ proxy.$modal.msgWarning("涓嶅彲鍒犻櫎浠栦汉缁存姢鐨勬暟鎹�");
+ return;
+ }
+ ids = selectedRows.value.map(item => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ tableLoading.value = true;
+ delSupplier(ids)
+ .then(res => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ };
+
+ // 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
+ function getCurrentDate() {
+ const today = new Date();
+ const year = today.getFullYear();
+ const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
+ const day = String(today.getDate()).padStart(2, "0");
+ return `${year}-${month}-${day}`;
+ }
+ // 鎵撳紑闄勪欢寮规
+ const openFileDialog = async row => {
+ recordId.value = row.id;
+ fileListDialogVisible.value = true;
+ };
+
+ onMounted(() => {
+ getList();
+ });
+
+ defineExpose({
+ getList,
+ });
+</script>
+
diff --git a/src/views/inventoryManagement/manufacturer/filesDia.vue b/src/views/inventoryManagement/manufacturer/filesDia.vue
new file mode 100644
index 0000000..5b1a72e
--- /dev/null
+++ b/src/views/inventoryManagement/manufacturer/filesDia.vue
@@ -0,0 +1,198 @@
+<template>
+ <div>
+ <el-dialog v-model="dialogFormVisible"
+ title="涓婁紶闄勪欢"
+ width="50%"
+ @close="closeDia">
+ <div style="margin-bottom: 10px;text-align: right">
+ <el-upload v-model:file-list="fileList"
+ class="upload-demo"
+ :action="uploadUrl"
+ :on-success="handleUploadSuccess"
+ :on-error="handleUploadError"
+ name="file"
+ :show-file-list="false"
+ :headers="headers"
+ style="display: inline;margin-right: 10px">
+ <el-button type="primary">涓婁紶闄勪欢</el-button>
+ </el-upload>
+ <el-button type="danger"
+ plain
+ @click="handleDelete">鍒犻櫎</el-button>
+ </div>
+ <PIMTable rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :tableLoading="tableLoading"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ height="500"
+ @pagination-change="paginationSearch"
+ :total="total"
+ :page="page.current"
+ :limit="page.size">
+ </PIMTable>
+ <pagination style="margin: 10px 0"
+ v-show="total > 0"
+ @pagination="paginationSearch"
+ :total="total"
+ :page="page.current"
+ :limit="page.size" />
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button @click="closeDia">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ <filePreview ref="filePreviewRef" />
+ </div>
+</template>
+
+<script setup>
+ import { ref } from "vue";
+ import { ElMessageBox } from "element-plus";
+ import { getToken } from "@/utils/auth.js";
+ import filePreview from "@/components/filePreview/index.vue";
+ import {
+ fileAdd,
+ fileDel,
+ fileListPage,
+ } from "@/api/basicData/supplierManageFile.js";
+ import Pagination from "@/components/PIMTable/Pagination.vue";
+ const { proxy } = getCurrentInstance();
+ const emit = defineEmits(["close"]);
+
+ const dialogFormVisible = ref(false);
+ const currentId = ref("");
+ const selectedRows = ref([]);
+ const filePreviewRef = ref();
+ const tableColumn = ref([
+ {
+ label: "鏂囦欢鍚嶇О",
+ prop: "name",
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ operation: [
+ {
+ name: "涓嬭浇",
+ type: "text",
+ clickFun: row => {
+ downLoadFile(row);
+ },
+ },
+ {
+ name: "棰勮",
+ type: "text",
+ clickFun: row => {
+ lookFile(row);
+ },
+ },
+ ],
+ },
+ ]);
+ const page = reactive({
+ current: 1,
+ size: 100,
+ });
+ const total = ref(0);
+ const tableData = ref([]);
+ const fileList = ref([]);
+ const tableLoading = ref(false);
+ const headers = ref({
+ Authorization: "Bearer " + getToken(),
+ });
+ const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/file/upload"); // 涓婁紶鐨勫浘鐗囨湇鍔″櫒鍦板潃
+
+ // 鎵撳紑寮规
+ const openDialog = row => {
+ dialogFormVisible.value = true;
+ currentId.value = row.id;
+ getList();
+ };
+ const paginationSearch = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+ };
+ const getList = () => {
+ fileListPage({ supplierId: currentId.value, ...page }).then(res => {
+ tableData.value = res.data.records;
+ total.value = res.data.total;
+ });
+ };
+ // 琛ㄦ牸閫夋嫨鏁版嵁
+ const handleSelectionChange = selection => {
+ selectedRows.value = selection;
+ };
+
+ // 鍏抽棴寮规
+ const closeDia = () => {
+ dialogFormVisible.value = false;
+ emit("close");
+ };
+ // 涓婁紶鎴愬姛澶勭悊
+ function handleUploadSuccess(res, file) {
+ // 濡傛灉涓婁紶鎴愬姛
+ if (res.code == 200) {
+ const fileRow = {};
+ fileRow.name = res.data.originalName;
+ fileRow.url = res.data.tempPath;
+ uploadFile(fileRow);
+ } else {
+ proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
+ }
+ }
+ function uploadFile(file) {
+ file.supplierId = currentId.value;
+ fileAdd(file).then(res => {
+ proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
+ getList();
+ });
+ }
+ // 涓婁紶澶辫触澶勭悊
+ function handleUploadError() {
+ proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
+ }
+ // 涓嬭浇闄勪欢
+ const downLoadFile = row => {
+ proxy.$download.byUrl(row.url, row.originalFilename);
+ };
+ // 鍒犻櫎
+ const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ ids = selectedRows.value.map(item => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ fileDel(ids).then(res => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ };
+ // 棰勮闄勪欢
+ const lookFile = row => {
+ filePreviewRef.value.open(row.url);
+ };
+
+ defineExpose({
+ openDialog,
+ });
+</script>
+
+<style scoped>
+</style>
\ No newline at end of file
diff --git a/src/views/inventoryManagement/manufacturer/index.vue b/src/views/inventoryManagement/manufacturer/index.vue
new file mode 100644
index 0000000..cca52ff
--- /dev/null
+++ b/src/views/inventoryManagement/manufacturer/index.vue
@@ -0,0 +1,50 @@
+<!-- 鍦ㄤ綘鐨勪富椤甸潰涓� -->
+<template>
+ <div class="app-container">
+ <el-tabs v-model="activeTab"
+ @tab-change="handleTabChange">
+ <el-tab-pane label="姝e父鍘傚"
+ name="home">
+ <HomeTab ref="homeTab" />
+ </el-tab-pane>
+ <el-tab-pane label="榛戝悕鍗�"
+ name="blacklist">
+ <BlacklistTab ref="blacklistTab" />
+ </el-tab-pane>
+ </el-tabs>
+ </div>
+</template>
+
+<script>
+ import HomeTab from "./components/HomeTab.vue";
+ import BlacklistTab from "./components/BlacklistTab.vue";
+
+ export default {
+ name: "MainPage",
+ components: {
+ HomeTab,
+ BlacklistTab,
+ },
+ data() {
+ return {
+ activeTab: "home",
+ };
+ },
+ methods: {
+ handleTabChange(tabName) {
+ this.activeTab = tabName;
+ this.$nextTick(() => {
+ if (tabName === "home") {
+ this.$refs.homeTab &&
+ this.$refs.homeTab.getList &&
+ this.$refs.homeTab.getList();
+ } else if (tabName === "blacklist") {
+ this.$refs.blacklistTab &&
+ this.$refs.blacklistTab.getList &&
+ this.$refs.blacklistTab.getList();
+ }
+ });
+ },
+ },
+ };
+</script>
diff --git a/src/views/inventoryManagement/stockManagement/New.vue b/src/views/inventoryManagement/stockManagement/New.vue
index 2addb95..0b50731 100644
--- a/src/views/inventoryManagement/stockManagement/New.vue
+++ b/src/views/inventoryManagement/stockManagement/New.vue
@@ -32,6 +32,11 @@
<el-input v-model="formState.unit"
disabled />
</el-form-item>
+ <el-form-item label="鍘傚"
+ prop="manufacturer">
+ <el-input v-model="formState.manufacturer"
+ placeholder="璇疯緭鍏ュ巶瀹�" />
+ </el-form-item>
<el-form-item label="搴撳瓨绫诲瀷"
prop="type"
:rules="[
@@ -42,11 +47,32 @@
}
]">
<el-select v-model="formState.type"
- placeholder="璇烽�夋嫨搴撳瓨绫诲瀷">
- <el-option label="鍚堟牸搴撳瓨"
+ placeholder="璇烽�夋嫨搴撳瓨绫诲瀷"
+ @change="handleTypeChange">
+ <el-option label="鍚堟牸搴�"
value="qualified" />
- <el-option label="涓嶅悎鏍煎簱瀛�"
+ <el-option label="搴熷搧搴�"
+ value="waste" />
+ <el-option label="涓嶅悎鏍煎簱"
value="unqualified" />
+ </el-select>
+ </el-form-item>
+ <el-form-item v-if="formState.type && formState.type !== 'unqualified'"
+ label="鏉ユ簮"
+ prop="source"
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨鏉ユ簮',
+ trigger: 'change',
+ }
+ ]">
+ <el-select v-model="formState.source"
+ placeholder="璇烽�夋嫨鏉ユ簮">
+ <el-option v-for="item in sourceOptions"
+ :key="item"
+ :label="item"
+ :value="item" />
</el-select>
</el-form-item>
<el-form-item label="搴撳瓨鏁伴噺"
@@ -120,11 +146,30 @@
productModelName: "",
unit: "",
type: undefined,
+ manufacturer: "",
+ source: "",
qualitity: 0,
batchNo: null,
warnNum: 0,
remark: "",
});
+
+ const sourceOptions = computed(() => {
+ if (formState.value.type === "qualified") {
+ return ["閲囪喘鍏ュ簱", "鐢熶骇鍏ュ簱", "澶栧崗鍏ュ簱", "淇鍏ュ簱"];
+ } else if (formState.value.type === "waste") {
+ return ["鐢熶骇浜х敓", "杩愯緭浜х敓", "瑁佸壀浜х敓"];
+ }
+ return [];
+ });
+
+ const handleTypeChange = val => {
+ if (val === "unqualified") {
+ formState.value.source = "鑷畾涔�";
+ } else {
+ formState.value.source = "";
+ }
+ };
const isShow = computed({
get() {
@@ -158,6 +203,8 @@
productModelName: "",
unit: "",
type: undefined,
+ manufacturer: "",
+ source: "",
qualitity: 0,
batchNo: null,
warnNum: 0,
diff --git a/src/views/personnelManagement/employeeRecord/components/BasicInfoSection.vue b/src/views/personnelManagement/employeeRecord/components/BasicInfoSection.vue
index 0aa4f06..4a038ea 100644
--- a/src/views/personnelManagement/employeeRecord/components/BasicInfoSection.vue
+++ b/src/views/personnelManagement/employeeRecord/components/BasicInfoSection.vue
@@ -1,154 +1,149 @@
<template>
- <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>
</template>
-
<el-row :gutter="24">
<el-col :span="5">
- <el-form-item label="鍛樺伐缂栧彿" prop="staffNo">
- <el-input
- v-model="form.staffNo"
- placeholder="璇疯緭鍏�"
- clearable
- maxlength="20"
- show-word-limit
- :disabled="operationType !== 'add'"
- />
+ <el-form-item label="鍛樺伐缂栧彿"
+ prop="staffNo">
+ <el-input v-model="form.staffNo"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="20"
+ show-word-limit
+ :disabled="operationType !== 'add'" />
</el-form-item>
</el-col>
<el-col :span="5">
- <el-form-item label="濮撳悕" prop="staffName">
- <el-input
- v-model="form.staffName"
- placeholder="璇疯緭鍏�"
- clearable
- maxlength="50"
- show-word-limit
- />
+ <el-form-item label="濮撳悕"
+ prop="staffName">
+ <el-input v-model="form.staffName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="50"
+ show-word-limit />
</el-form-item>
</el-col>
<el-col :span="5">
- <el-form-item label="鍒悕" prop="alias">
- <el-input
- v-model="form.alias"
- placeholder="璇疯緭鍏�"
- clearable
- maxlength="50"
- show-word-limit
- />
+ <el-form-item label="鍒悕"
+ prop="alias">
+ <el-input v-model="form.alias"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="50"
+ show-word-limit />
</el-form-item>
</el-col>
<el-col :span="5">
- <el-form-item label="鎵嬫満" prop="phone">
- <el-input
- v-model="form.phone"
- placeholder="璇疯緭鍏�"
- clearable
- maxlength="11"
- show-word-limit
- />
+ <el-form-item label="鎵嬫満"
+ prop="phone">
+ <el-input v-model="form.phone"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="11"
+ show-word-limit />
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="鎬у埆" prop="sex">
- <el-select
- v-model="form.sex"
- placeholder="璇烽�夋嫨"
- clearable
- style="width: 100%"
- >
- <el-option label="鐢�" value="鐢�" />
- <el-option label="濂�" value="濂�" />
+ <el-form-item label="鎬у埆"
+ prop="sex">
+ <el-select v-model="form.sex"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%">
+ <el-option label="鐢�"
+ value="鐢�" />
+ <el-option label="濂�"
+ value="濂�" />
</el-select>
</el-form-item>
</el-col>
</el-row>
-
<el-row :gutter="24">
<el-col :span="5">
- <el-form-item label="鍑虹敓鏃ユ湡" prop="birthDate">
- <el-date-picker
- v-model="form.birthDate"
- type="date"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- placeholder="璇烽�夋嫨"
- style="width: 100%"
- clearable
- />
+ <el-form-item label="鍑虹敓鏃ユ湡"
+ prop="birthDate">
+ <el-date-picker v-model="form.birthDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨"
+ style="width: 100%"
+ clearable />
</el-form-item>
</el-col>
<el-col :span="5">
- <el-form-item label="骞撮緞" prop="age">
- <el-input-number
- v-model="form.age"
- :min="0"
- :max="150"
- :precision="0"
- :step="1"
- style="width: 100%"
- />
+ <el-form-item label="骞撮緞"
+ prop="age">
+ <el-input-number v-model="form.age"
+ :min="0"
+ :max="150"
+ :precision="0"
+ :step="1"
+ style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="5">
- <el-form-item label="绫嶈疮" prop="nativePlace">
- <el-input
- v-model="form.nativePlace"
- placeholder="璇疯緭鍏�"
- clearable
- maxlength="50"
- show-word-limit
- />
+ <el-form-item label="绫嶈疮"
+ prop="nativePlace">
+ <el-input v-model="form.nativePlace"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="50"
+ show-word-limit />
</el-form-item>
</el-col>
<el-col :span="5">
- <el-form-item label="姘戞棌" prop="nation">
- <el-input
- v-model="form.nation"
- placeholder="璇疯緭鍏�"
- clearable
- maxlength="20"
- show-word-limit
- />
+ <el-form-item label="姘戞棌"
+ prop="nation">
+ <el-select v-model="form.nation"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%">
+ <el-option v-for="dict in nation_type"
+ :key="dict.label"
+ :label="dict.label"
+ :value="dict.label" />
+ </el-select>
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="濠氬Щ鐘跺喌" prop="maritalStatus">
- <el-select
- v-model="form.maritalStatus"
- placeholder="璇烽�夋嫨"
- clearable
- style="width: 100%"
- >
- <el-option label="鏈" value="鏈" />
- <el-option label="宸插" value="宸插" />
- <el-option label="绂诲紓" value="绂诲紓" />
- <el-option label="涓у伓" value="涓у伓" />
+ <el-form-item label="濠氬Щ鐘跺喌"
+ prop="maritalStatus">
+ <el-select v-model="form.maritalStatus"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%">
+ <el-option label="鏈"
+ value="鏈" />
+ <el-option label="宸插"
+ value="宸插" />
+ <el-option label="绂诲紓"
+ value="绂诲紓" />
+ <el-option label="涓у伓"
+ value="涓у伓" />
</el-select>
</el-form-item>
</el-col>
</el-row>
-
<el-row :gutter="24">
<el-col :span="10">
- <el-form-item label="瑙掕壊" prop="roleId">
- <el-select
- v-model="form.roleId"
- placeholder="璇烽�夋嫨"
- clearable
- style="width: 100%"
- >
- <el-option
- v-for="item in roleOptions"
- :key="item.roleId"
- :label="item.roleName"
- :value="item.roleId"
- :disabled="item.status == 1"
- />
+ <el-form-item label="瑙掕壊"
+ prop="roleId">
+ <el-select v-model="form.roleId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%">
+ <el-option v-for="item in roleOptions"
+ :key="item.roleId"
+ :label="item.roleName"
+ :value="item.roleId"
+ :disabled="item.status == 1" />
</el-select>
</el-form-item>
</el-col>
@@ -157,25 +152,27 @@
</template>
<script setup>
-import { toRefs } from "vue";
+ import { toRefs, getCurrentInstance } from "vue";
-const props = defineProps({
- form: { type: Object, required: true },
- operationType: { type: String, default: "add" },
- roleOptions: { type: Array, default: () => [] },
-});
+ const props = defineProps({
+ form: { type: Object, required: true },
+ operationType: { type: String, default: "add" },
+ roleOptions: { type: Array, default: () => [] },
+ });
-const { form, operationType, roleOptions } = toRefs(props);
+ const { proxy } = getCurrentInstance();
+ const { nation_type } = proxy.useDict("nation_type");
+ const { form, operationType, roleOptions } = toRefs(props);
</script>
<style scoped>
-.form-card {
- margin-bottom: 16px;
-}
+ .form-card {
+ margin-bottom: 16px;
+ }
-.card-title-line {
- color: #f56c6c;
- margin-right: 4px;
-}
+ .card-title-line {
+ color: #f56c6c;
+ margin-right: 4px;
+ }
</style>
diff --git a/src/views/personnelManagement/employeeRecord/index.vue b/src/views/personnelManagement/employeeRecord/index.vue
index a0699b0..82af109 100644
--- a/src/views/personnelManagement/employeeRecord/index.vue
+++ b/src/views/personnelManagement/employeeRecord/index.vue
@@ -3,90 +3,101 @@
<div class="search_form mb20">
<div>
<span class="search_title">濮撳悕锛�</span>
- <el-input
- v-model="searchForm.staffName"
- style="width: 240px"
- placeholder="璇疯緭鍏ュ鍚嶆悳绱�"
- @change="handleQuery"
- clearable
- :prefix-icon="Search"
- />
+ <el-input v-model="searchForm.staffName"
+ style="width: 240px"
+ placeholder="璇疯緭鍏ュ鍚嶆悳绱�"
+ @change="handleQuery"
+ clearable
+ :prefix-icon="Search" />
<span class="search_title search_title2">閮ㄩ棬锛�</span>
- <el-tree-select
- v-model="searchForm.sysDeptId"
- :data="deptOptions"
- check-strictly
- :render-after-expand="false"
- style="width: 240px"
- placeholder="璇烽�夋嫨"
- />
- <span class="search_title search_title2">鍏ヨ亴鏃ユ湡锛�</span>
- <el-date-picker
- v-model="searchForm.contractStartTime"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- placeholder="璇烽�夋嫨"
- />
+ <el-tree-select v-model="searchForm.sysDeptId"
+ :data="deptOptions"
+ check-strictly
+ :render-after-expand="false"
+ style="width: 240px"
+ placeholder="璇烽�夋嫨" />
+ <span class="search_title search_title2">鍏ヨ亴鏃ユ湡锛�</span>
+ <el-date-picker v-model="searchForm.contractStartTime"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨" />
+ <span class="search_title search_title2">姘戞棌锛�</span>
+ <el-select v-model="searchForm.nation"
+ placeholder="璇烽�夋嫨姘戞棌"
+ clearable
+ style="width: 240px"
+ @change="handleQuery">
+ <el-option v-for="dict in nation_type"
+ :key="dict.label"
+ :label="dict.label"
+ :value="dict.label" />
+ </el-select>
<!-- <span style="margin-left: 10px" class="search_title">鍚堝悓缁撴潫鏃ユ湡锛�</span> -->
<!-- <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
placeholder="璇烽�夋嫨" clearable @change="changeDaterange" /> -->
- <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
- >鎼滅储</el-button
- >
+ <el-button type="primary"
+ @click="handleQuery"
+ style="margin-left: 10px">鎼滅储</el-button>
</div>
<div>
- <el-button type="primary" @click="openFormNewOrEditFormDia('add')">鏂板鍏ヨ亴</el-button>
- <el-button type="info" @click="handleImport">瀵煎叆</el-button>
+ <el-button type="primary"
+ @click="openFormNewOrEditFormDia('add')">鏂板鍏ヨ亴</el-button>
+ <el-button type="info"
+ @click="handleImport">瀵煎叆</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
<!-- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button> -->
</div>
</div>
<div class="table_list">
- <PIMTable
- rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :page="page"
- :isSelection="true"
- @selection-change="handleSelectionChange"
- :tableLoading="tableLoading"
- @pagination="pagination"
- :total="page.total"
- >
+ <PIMTable rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"
+ :total="page.total">
<template #positiveDate="{ row }">
<span :class="getPositiveDateClass(row.positiveDate)">{{ row.positiveDate }}</span>
</template>
</PIMTable>
</div>
- <show-form-dia ref="formDia" @close="handleQuery"></show-form-dia>
- <new-or-edit-form-dia ref="formDiaNewOrEditFormDia" @close="handleQuery"></new-or-edit-form-dia>
-
+ <show-form-dia ref="formDia"
+ @close="handleQuery"></show-form-dia>
+ <new-or-edit-form-dia ref="formDiaNewOrEditFormDia"
+ @close="handleQuery"></new-or-edit-form-dia>
<!-- 瀵煎叆瀵硅瘽妗� -->
- <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
- <el-upload
- ref="uploadRef"
- :limit="1"
- accept=".xlsx, .xls"
- :headers="upload.headers"
- :action="upload.url"
- :disabled="upload.isUploading"
- :on-progress="handleFileUploadProgress"
- :on-success="handleFileSuccess"
- :auto-upload="false"
- drag
- >
+ <el-dialog :title="upload.title"
+ v-model="upload.open"
+ width="400px"
+ append-to-body>
+ <el-upload ref="uploadRef"
+ :limit="1"
+ accept=".xlsx, .xls"
+ :headers="upload.headers"
+ :action="upload.url"
+ :disabled="upload.isUploading"
+ :on-progress="handleFileUploadProgress"
+ :on-success="handleFileSuccess"
+ :auto-upload="false"
+ drag>
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
<template #tip>
<div class="el-upload__tip text-center">
<span>浠呭厑璁稿鍏ls銆亁lsx鏍煎紡鏂囦欢銆�</span>
- <el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline; margin-left: 5px;" @click="importTemplate">涓嬭浇妯℃澘</el-link>
+ <el-link type="primary"
+ :underline="false"
+ style="font-size: 12px; vertical-align: baseline; margin-left: 5px;"
+ @click="importTemplate">涓嬭浇妯℃澘</el-link>
</div>
</template>
</el-upload>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary" @click="submitFileForm">纭� 瀹�</el-button>
+ <el-button type="primary"
+ @click="submitFileForm">纭� 瀹�</el-button>
<el-button @click="upload.open = false">鍙� 娑�</el-button>
</div>
</template>
@@ -95,176 +106,192 @@
</template>
<script setup>
-import { Search, UploadFilled } from "@element-plus/icons-vue";
-import {onMounted, ref} from "vue";
-import {ElMessageBox} from "element-plus";
-import { deptTreeSelect } from "@/api/system/user.js";
-import {batchDeleteStaffOnJobs, staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js";
-import { getToken } from "@/utils/auth";
-import dayjs from "dayjs";
+ import { Search, UploadFilled } from "@element-plus/icons-vue";
+ import { onMounted, ref } from "vue";
+ import { ElMessageBox } from "element-plus";
+ import { deptTreeSelect } from "@/api/system/user.js";
+ import {
+ batchDeleteStaffOnJobs,
+ staffOnJobListPage,
+ } from "@/api/personnelManagement/staffOnJob.js";
+ import { getToken } from "@/utils/auth";
+ import dayjs from "dayjs";
-const NewOrEditFormDia = defineAsyncComponent(() => import("@/views/personnelManagement/employeeRecord/components/NewOrEditFormDia.vue"));
-const ShowFormDia = defineAsyncComponent(() => import( "@/views/personnelManagement/employeeRecord/components/Show.vue"));
+ const NewOrEditFormDia = defineAsyncComponent(() =>
+ import(
+ "@/views/personnelManagement/employeeRecord/components/NewOrEditFormDia.vue"
+ )
+ );
+ const ShowFormDia = defineAsyncComponent(() =>
+ import("@/views/personnelManagement/employeeRecord/components/Show.vue")
+ );
-const data = reactive({
- searchForm: {
- staffName: "",
- entryDate: undefined, // 褰曞叆鏃ユ湡
- entryDateStart: undefined,
- entryDateEnd: undefined,
- },
- deptOptions: [],
-});
-const { searchForm, deptOptions } = toRefs(data);
-const tableColumn = ref([
- {
- label: "鐘舵��",
- prop: "staffState",
- dataType: "tag",
- formatData: (params) => {
- if (params == 0) {
- return "绂昏亴";
- } else if (params == 1) {
- return "鍦ㄨ亴";
- } else {
- return null;
- }
+ const data = reactive({
+ searchForm: {
+ staffName: "",
+ sysDeptId: undefined,
+ contractStartTime: undefined,
+ nation: undefined,
+ entryDate: undefined, // 褰曞叆鏃ユ湡
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
},
- formatType: (params) => {
- if (params == 0) {
- return "danger";
- } else if (params == 1) {
- return "primary";
- } else {
- return null;
- }
- },
- },
- {
- label: "鍛樺伐缂栧彿",
- prop: "staffNo",
- },
- {
- label: "濮撳悕",
- prop: "staffName",
- },
- {
- label: "鍒悕",
- prop: "alias",
- },
- {
- label: "鎵嬫満",
- prop: "phone",
- width: 150,
- },
- {
- label: "鎬у埆",
- prop: "sex",
- },
- {
- label: "鍑虹敓鏃ユ湡",
- prop: "birthDate",
- width: 120,
- },
- {
- label: "鍏ヨ亴鏃ユ湡",
- prop: "contractStartTime",
- width: 120,
- },
- {
- label: "杞鏃ユ湡",
- prop: "positiveDate",
- width: 120,
- dataType: "slot",
- slot: "positiveDate",
- },
- {
- label: "骞撮緞",
- prop: "age",
- },
- {
- label: "绫嶈疮",
- prop: "nativePlace",
- },
- {
- label: "姘戞棌",
- prop: "nation",
- width: 100,
- },
- {
- label: "濠氬Щ鐘跺喌",
- prop: "maritalStatus",
- width: 100,
- },
- {
- dataType: "action",
- label: "鎿嶄綔",
- align: "center",
- fixed: 'right',
- width: 180,
- operation: [
- {
- name: "缂栬緫",
- type: "text",
- clickFun: (row) => {
- openFormNewOrEditFormDia("edit", row);
- },
+ deptOptions: [],
+ });
+ const { searchForm, deptOptions } = toRefs(data);
+ const tableColumn = ref([
+ {
+ label: "鐘舵��",
+ prop: "staffState",
+ dataType: "tag",
+ formatData: params => {
+ if (params == 0) {
+ return "绂昏亴";
+ } else if (params == 1) {
+ return "鍦ㄨ亴";
+ } else {
+ return null;
+ }
},
- ],
- },
-]);
-const tableData = ref([]);
-const selectedRows = ref([]);
-const tableLoading = ref(false);
-const page = reactive({
- current: 1,
- size: 100,
- total: 0
-});
-const formDia = ref()
-const formDiaNewOrEditFormDia = ref()
-const { proxy } = getCurrentInstance()
+ formatType: params => {
+ if (params == 0) {
+ return "danger";
+ } else if (params == 1) {
+ return "primary";
+ } else {
+ return null;
+ }
+ },
+ },
+ {
+ label: "鍛樺伐缂栧彿",
+ prop: "staffNo",
+ },
+ {
+ label: "濮撳悕",
+ prop: "staffName",
+ },
+ {
+ label: "鍒悕",
+ prop: "alias",
+ },
+ {
+ label: "鎵嬫満",
+ prop: "phone",
+ width: 150,
+ },
+ {
+ label: "鎬у埆",
+ prop: "sex",
+ },
+ {
+ label: "鍑虹敓鏃ユ湡",
+ prop: "birthDate",
+ width: 120,
+ },
+ {
+ label: "鍏ヨ亴鏃ユ湡",
+ prop: "contractStartTime",
+ width: 120,
+ },
+ {
+ label: "杞鏃ユ湡",
+ prop: "positiveDate",
+ width: 120,
+ dataType: "slot",
+ slot: "positiveDate",
+ },
+ {
+ label: "骞撮緞",
+ prop: "age",
+ },
+ {
+ label: "绫嶈疮",
+ prop: "nativePlace",
+ },
+ {
+ label: "姘戞棌",
+ prop: "nation",
+ width: 100,
+ formatData: params => {
+ return proxy.selectDictLabel(nation_type.value, params);
+ },
+ },
+ {
+ label: "濠氬Щ鐘跺喌",
+ prop: "maritalStatus",
+ width: 100,
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 180,
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: row => {
+ openFormNewOrEditFormDia("edit", row);
+ },
+ },
+ ],
+ },
+ ]);
+ const tableData = ref([]);
+ const selectedRows = ref([]);
+ const tableLoading = ref(false);
+ const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+ });
+ const formDia = ref();
+ const formDiaNewOrEditFormDia = ref();
+ const { proxy } = getCurrentInstance();
+ const { nation_type } = proxy.useDict("nation_type");
-// 瀵煎叆鐩稿叧
-const uploadRef = ref(null)
-const upload = reactive({
- // 鏄惁鏄剧ず寮瑰嚭灞�
- open: false,
- // 寮瑰嚭灞傛爣棰�
- title: "",
- // 鏄惁绂佺敤涓婁紶
- isUploading: false,
- // 璁剧疆涓婁紶鐨勮姹傚ご閮�
- headers: { Authorization: "Bearer " + getToken() },
- // 涓婁紶鐨勫湴鍧�
- url: import.meta.env.VITE_APP_BASE_API + "/staff/staffOnJob/import"
-})
+ // 瀵煎叆鐩稿叧
+ const uploadRef = ref(null);
+ const upload = reactive({
+ // 鏄惁鏄剧ず寮瑰嚭灞�
+ open: false,
+ // 寮瑰嚭灞傛爣棰�
+ title: "",
+ // 鏄惁绂佺敤涓婁紶
+ isUploading: false,
+ // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+ headers: { Authorization: "Bearer " + getToken() },
+ // 涓婁紶鐨勫湴鍧�
+ url: import.meta.env.VITE_APP_BASE_API + "/staff/staffOnJob/import",
+ });
-// 鍒ゆ柇杞鏃ユ湡鏄惁鍦�7澶╁唴
-const getPositiveDateClass = (positiveDate) => {
- if (!positiveDate) return '';
- const today = new Date();
- today.setHours(0, 0, 0, 0);
- const positive = new Date(positiveDate);
- positive.setHours(0, 0, 0, 0);
- const diffTime = positive - today;
- const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
- // 7澶╁唴杞锛堝寘鎷粖澶╋級鏄剧ず璀﹀憡鑹�
- if (diffDays >= 0 && diffDays <= 7) {
- return 'positive-date-warning';
- }
- return '';
-};
+ // 鍒ゆ柇杞鏃ユ湡鏄惁鍦�7澶╁唴
+ const getPositiveDateClass = positiveDate => {
+ if (!positiveDate) return "";
+ const today = new Date();
+ today.setHours(0, 0, 0, 0);
+ const positive = new Date(positiveDate);
+ positive.setHours(0, 0, 0, 0);
+ const diffTime = positive - today;
+ const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
+ // 7澶╁唴杞锛堝寘鎷粖澶╋級鏄剧ず璀﹀憡鑹�
+ if (diffDays >= 0 && diffDays <= 7) {
+ return "positive-date-warning";
+ }
+ return "";
+ };
-const fetchDeptOptions = () => {
+ const fetchDeptOptions = () => {
deptTreeSelect().then(response => {
- console.log(response.data)
+ console.log(response.data);
deptOptions.value = filterDisabledDept(
JSON.parse(JSON.stringify(response.data))
);
});
};
-const filterDisabledDept = deptList => {
+ const filterDisabledDept = deptList => {
return deptList.filter(dept => {
if (dept.disabled) {
return false;
@@ -275,72 +302,74 @@
return true;
});
};
-const changeDaterange = (value) => {
- searchForm.value.entryDateStart = undefined;
- searchForm.value.entryDateEnd = undefined;
- if (value) {
- searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
- searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
- }
- getList();
-};
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- page.current = 1;
- getList();
-};
-const pagination = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
-const getList = () => {
- fetchDeptOptions();
- tableLoading.value = true;
- const params = { ...searchForm.value, ...page };
- params.entryDate = undefined
- staffOnJobListPage({...params}).then(res => {
- tableLoading.value = false;
- tableData.value = res.data.records
- page.total = res.data.total;
- }).catch(err => {
- tableLoading.value = false;
- })
-};
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = (selection) => {
- selectedRows.value = selection;
-};
+ const changeDaterange = value => {
+ searchForm.value.entryDateStart = undefined;
+ searchForm.value.entryDateEnd = undefined;
+ if (value) {
+ searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+ searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+ }
+ getList();
+ };
+ // 鏌ヨ鍒楄〃
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ const handleQuery = () => {
+ page.current = 1;
+ getList();
+ };
+ const pagination = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+ };
+ const getList = () => {
+ fetchDeptOptions();
+ tableLoading.value = true;
+ const params = { ...searchForm.value, ...page };
+ params.entryDate = undefined;
+ staffOnJobListPage({ ...params })
+ .then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ })
+ .catch(err => {
+ tableLoading.value = false;
+ });
+ };
+ // 琛ㄦ牸閫夋嫨鏁版嵁
+ const handleSelectionChange = selection => {
+ selectedRows.value = selection;
+ };
-// 鎵撳紑寮规
-const openForm = (type, row) => {
- nextTick(() => {
- formDia.value?.openDialog(type, row)
- })
-};
-const openFormNewOrEditFormDia = (type, row) => {
- nextTick(() => {
- formDiaNewOrEditFormDia.value?.openDialog(type, row)
- })
-};
+ // 鎵撳紑寮规
+ const openForm = (type, row) => {
+ nextTick(() => {
+ formDia.value?.openDialog(type, row);
+ });
+ };
+ const openFormNewOrEditFormDia = (type, row) => {
+ nextTick(() => {
+ formDiaNewOrEditFormDia.value?.openDialog(type, row);
+ });
+ };
-// 鍒犻櫎
-const handleDelete = () => {
- let ids = [];
- if (selectedRows.value.length > 0) {
- ids = selectedRows.value.map((item) => item.id);
- } else {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+ // 鍒犻櫎
+ const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ ids = selectedRows.value.map(item => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
- batchDeleteStaffOnJobs(ids).then((res) => {
+ batchDeleteStaffOnJobs(ids).then(res => {
proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
getList();
});
@@ -348,69 +377,77 @@
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
-};
+ };
-// 瀵煎嚭
-const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+ // 瀵煎嚭
+ const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
- proxy.download("/staff/staffOnJob/export", {staffState: 1}, "鍛樺伐鍙拌处.xlsx");
+ proxy.download(
+ "/staff/staffOnJob/export",
+ { staffState: 1 },
+ "鍛樺伐鍙拌处.xlsx"
+ );
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
-};
+ };
-// 瀵煎叆鎸夐挳鎿嶄綔
-const handleImport = () => {
- upload.title = "鍛樺伐瀵煎叆"
- upload.open = true
-}
+ // 瀵煎叆鎸夐挳鎿嶄綔
+ const handleImport = () => {
+ upload.title = "鍛樺伐瀵煎叆";
+ upload.open = true;
+ };
-// 涓嬭浇妯℃澘鎿嶄綔
-const importTemplate = () => {
- proxy.download("/staff/staffOnJob/downloadTemplate", {}, `鍛樺伐瀵煎叆妯℃澘_${new Date().getTime()}.xlsx`)
-}
+ // 涓嬭浇妯℃澘鎿嶄綔
+ const importTemplate = () => {
+ proxy.download(
+ "/staff/staffOnJob/downloadTemplate",
+ {},
+ `鍛樺伐瀵煎叆妯℃澘_${new Date().getTime()}.xlsx`
+ );
+ };
-// 鏂囦欢涓婁紶涓鐞�
-const handleFileUploadProgress = (event, file, fileList) => {
- upload.isUploading = true
-}
+ // 鏂囦欢涓婁紶涓鐞�
+ const handleFileUploadProgress = (event, file, fileList) => {
+ upload.isUploading = true;
+ };
-// 鏂囦欢涓婁紶鎴愬姛澶勭悊
-const handleFileSuccess = (response, file, fileList) => {
- upload.open = false
- upload.isUploading = false
- proxy.$refs["uploadRef"].handleRemove(file)
- if (response.code !== 200) {
- proxy.$modal.msgError(response.msg)
- } else {
- proxy.$modal.msgSuccess(response.msg)
- }
- getList()
-}
+ // 鏂囦欢涓婁紶鎴愬姛澶勭悊
+ const handleFileSuccess = (response, file, fileList) => {
+ upload.open = false;
+ upload.isUploading = false;
+ proxy.$refs["uploadRef"].handleRemove(file);
+ if (response.code !== 200) {
+ proxy.$modal.msgError(response.msg);
+ } else {
+ proxy.$modal.msgSuccess(response.msg);
+ }
+ getList();
+ };
-// 鎻愪氦涓婁紶鏂囦欢
-const submitFileForm = () => {
- proxy.$refs["uploadRef"].submit()
-}
+ // 鎻愪氦涓婁紶鏂囦欢
+ const submitFileForm = () => {
+ proxy.$refs["uploadRef"].submit();
+ };
-onMounted(() => {
- getList();
-});
+ onMounted(() => {
+ getList();
+ });
</script>
<style scoped>
-.search_title2 {
- margin-left: 10px;
-}
+ .search_title2 {
+ margin-left: 10px;
+ }
-.positive-date-warning {
- color: #f56c6c;
- font-weight: bold;
-}
+ .positive-date-warning {
+ color: #f56c6c;
+ font-weight: bold;
+ }
</style>
diff --git a/src/views/personnelManagement/monthlyStatistics/components/formDia.vue b/src/views/personnelManagement/monthlyStatistics/components/formDia.vue
index 36c2ec3..35ae756 100644
--- a/src/views/personnelManagement/monthlyStatistics/components/formDia.vue
+++ b/src/views/personnelManagement/monthlyStatistics/components/formDia.vue
@@ -1,505 +1,456 @@
<template>
- <FormDialog
- v-model="dialogVisible"
- :title="operationType === 'add' ? '鏂板缓宸ヨ祫琛�' : '缂栬緫宸ヨ祫琛�'"
- width="90%"
- @close="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 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-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="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" />
</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 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-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 type="primary"
+ @click="handleGenerate">鐢熸垚宸ヨ祫琛�</el-button>
<el-button @click="handleClear">娓呯┖</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="deptName"
+ minWidth="120" />
+ <el-table-column label="鍛樺伐濮撳悕"
+ prop="staffName"
+ minWidth="100" />
+ <el-table-column label="姘戞棌"
+ prop="nation"
+ width="80"
+ align="center" />
+ <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="row.basicSalary = parseNum(row.basicSalary)" />
</template>
</el-table-column>
- <el-table-column label="璁′欢宸ヨ祫" minWidth="110">
+ <el-table-column label="鐧界彮澶╂暟"
+ minWidth="100">
<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.dayDays"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="handleDaysChange(row)" />
</template>
</el-table-column>
- <el-table-column label="璁℃椂宸ヨ祫" minWidth="110">
+ <el-table-column label="澶滅彮澶╂暟"
+ minWidth="100">
<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.nightDays"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="handleDaysChange(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.otherIncome"
- type="number"
- placeholder="0"
- size="small"
- @input="row.otherIncome = parseNum(row.otherIncome)"
- />
+ <el-input v-model.number="row.mealAmount"
+ type="number"
+ placeholder="0"
+ size="small"
+ disabled />
</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.nightAmount"
+ type="number"
+ placeholder="0"
+ size="small"
+ disabled />
</template>
</el-table-column>
- <el-table-column label="鍏Н閲戜釜浜�" minWidth="120">
+ <el-table-column label="鍏朵粬鏀跺叆"
+ minWidth="110">
<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.otherIncome"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="row.otherIncome = parseNum(row.otherIncome)" />
</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.otherDeduct"
- type="number"
- placeholder="0"
- size="small"
- @input="row.otherDeduct = parseNum(row.otherDeduct)"
- />
+ <el-input v-model.number="row.socialPersonal"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="row.socialPersonal = parseNum(row.socialPersonal)" />
</template>
</el-table-column>
- <el-table-column label="宸ヨ祫涓◣" minWidth="110">
+ <el-table-column label="鍏Н閲戜釜浜�"
+ minWidth="120">
<template #default="{ row }">
- <el-input
- v-model.number="row.salaryTax"
- type="number"
- placeholder="0"
- size="small"
- @input="row.salaryTax = parseNum(row.salaryTax)"
- />
+ <el-input v-model.number="row.fundPersonal"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="row.fundPersonal = parseNum(row.fundPersonal)" />
</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.grossSalary"
- type="number"
- placeholder="0"
- size="small"
- @input="row.grossSalary = parseNum(row.grossSalary)"
- />
+ <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">
+ <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)"
- />
+ <el-input v-model.number="row.socialSecurityRetroactive"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="row.socialSecurityRetroactive = parseNum(row.socialSecurityRetroactive)" />
</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.netSalary"
- type="number"
- placeholder="0"
- size="small"
- @input="row.netSalary = parseNum(row.netSalary)"
- />
+ <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="120">
+ <el-table-column label="搴斿彂宸ヨ祫"
+ minWidth="110">
<template #default="{ row }">
- <el-input
- v-model="row.remark"
- placeholder="璇疯緭鍏�"
- size="small"
- />
+ <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="鎿嶄綔" 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.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>
</template>
</el-table-column>
</el-table>
- <div v-if="!employeeList.length" class="table-empty">鏆傛棤鏁版嵁</div>
- <div v-else class="salary-total">
+ <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 { bankList } from "@/api/personnelManagement/bank.js";
-import {
- staffSalaryMainAdd,
- staffSalaryMainUpdate,
- staffSalaryMainCalculateSalary,
-} from "@/api/personnelManagement/staffSalaryMain.js";
-import { userListNoPageByTenantId } from "@/api/system/user.js";
+ 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 {
+ staffSalaryMainAdd,
+ staffSalaryMainUpdate,
+ staffSalaryMainCalculateSalary,
+ } from "@/api/personnelManagement/staffSalaryMain.js";
+ import { userListNoPageByTenantId } from "@/api/system/user.js";
+ import { listSubsidyConfiguration } from "@/api/personnelManagement/subsidyConfig.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 { proxy } = getCurrentInstance();
-
-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 userList = 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 },
-]);
-
-function parseNum(v) {
- if (v === "" || v == null) return 0;
- const n = Number(v);
- return isNaN(n) ? 0 : n;
-}
-
-// 鍩虹璧勬枡琛ㄥ崟
-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 !== "");
+ const emit = defineEmits(["update:modelValue", "close"]);
+ const props = defineProps({
+ modelValue: { type: Boolean, default: false },
+ operationType: { type: String, default: "add" },
+ row: { type: Object, default: () => ({}) },
});
-};
-const loadUserList = () => {
- return userListNoPageByTenantId().then((res) => {
- userList.value = res.data || [];
+ const { proxy } = getCurrentInstance();
+
+ const dialogVisible = computed({
+ get: () => props.modelValue,
+ set: val => emit("update:modelValue", val),
});
-};
-// 鎵佸钩鍖栭儴闂ㄦ爲渚涗笅鎷変娇鐢�
-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 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 userList = ref([]);
+ const subsidyStandard = ref({
+ mealAmount: 0,
+ nightAmount: 0,
});
- return list;
-}
-const loadDeptOptions = () => {
- listDept().then((res) => {
- const tree = res.data ?? [];
- deptOptions.value = flattenDept(tree);
- });
-};
-
-// 鏋勫缓 閮ㄩ棬-浜哄憳 鏍戯紙鐢ㄤ簬鏂板浜哄憳寮圭獥锛�
-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,
- });
+ const loadSubsidyStandard = () => {
+ listSubsidyConfiguration().then(res => {
+ if (res.data && res.data.length > 0) {
+ subsidyStandard.value = {
+ mealAmount: res.data[0].mealAmount || 0,
+ nightAmount: res.data[0].nightAmount || 0,
+ };
}
});
- deptStaffTree.value = Array.from(deptMap.values()).filter(
- (n) => n.children && n.children.length > 0
- );
- });
-};
+ };
-const openDialog = (type, row) => {
- nextTick(() => {
- loadDeptOptions();
- loadBankOptions();
- loadUserList();
- employeeList.value = [];
- Object.assign(form.value, {
+ const handleDaysChange = row => {
+ row.dayDays = parseNum(row.dayDays);
+ row.nightDays = parseNum(row.nightDays);
+
+ // 澶滅彮琛ヨ创璁$畻锛氬鐝ぉ鏁� * 鏍囧噯
+ row.nightAmount = row.nightDays * subsidyStandard.value.nightAmount;
+
+ // 椁愯ˉ璁$畻锛氫粎闄愬洖鏃忥紝(鐧界彮 + 澶滅彮) * 鏍囧噯
+ // 娉ㄦ剰锛歯ation 鍙兘鏄瓧鍏稿�硷紝杩欓噷鍋囪 "鍥炴棌" 鏄洿鎺ュ瓨鍌ㄧ殑瀛楃涓叉垨闇�瑕佹牴鎹瓧鍏稿垽鏂�
+ // 涔嬪墠鐨� BasicInfoSection.vue 涓皯鏃忔槸涓嬫媺妗嗭紝閫氬父瀛樺偍鐨勬槸瀛楀吀鐨� value 鎴� label
+ // 杩欓噷鍏堢畝鍗曞垽鏂寘鍚� "鍥�" 瀛楋紝鎴栬�呮偍鍙互鏍规嵁鍏蜂綋瀛楀吀鍊艰皟鏁�
+ if (row.nation && (row.nation === "鍥炴棌" || row.nation.includes("鍥�"))) {
+ row.mealAmount =
+ (row.dayDays + row.nightDays) * subsidyStandard.value.mealAmount;
+ } else {
+ row.mealAmount = 0;
+ }
+ };
+ 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;
+ }
+
+ // 鍩虹璧勬枡琛ㄥ崟
+ const data = reactive({
+ form: {
id: undefined,
salaryTitle: "",
deptIds: [],
@@ -507,298 +458,433 @@
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 ?? "";
- 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 ?? "",
- }));
- }
- }
- });
-};
-
-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 loadDeptOptions = () => {
+ listDept().then(res => {
+ const tree = res.data ?? [];
+ deptOptions.value = flattenDept(tree);
+ });
+ };
+
+ // 鏋勫缓 閮ㄩ棬-浜哄憳 鏍戯紙鐢ㄤ簬鏂板浜哄憳寮圭獥锛�
+ 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(() => {
+ loadDeptOptions();
+ loadBankOptions();
+ loadUserList();
+ loadSubsidyStandard();
+ 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 => ({
+ staffOnJobId: e.staffOnJobId ?? e.staffId ?? e.id,
+ id: e.staffOnJobId ?? e.staffId ?? e.id,
+ staffName: e.staffName ?? "",
+ postName: e.postName ?? "",
+ deptName: e.deptName ?? "",
+ nation: e.nation ?? "",
+ basicSalary: parseNum(e.basicSalary),
+ dayDays: parseNum(e.dayDays ?? e.dayShiftDays),
+ nightDays: parseNum(e.nightDays ?? e.nightShiftDays),
+ mealAmount: parseNum(e.mealAmount ?? e.mealSubsidy),
+ nightAmount: parseNum(e.nightAmount ?? e.nightSubsidy),
+ otherIncome: parseNum(e.otherIncome),
+ socialPersonal: parseNum(e.socialPersonal),
+ fundPersonal: parseNum(e.fundPersonal),
+ otherDeduct: parseNum(e.otherDeduct),
+ socialSecurityRetroactive: parseNum(e.socialSecurityRetroactive),
+ salaryTax: parseNum(e.salaryTax),
+ grossSalary: parseNum(e.grossSalary),
+ deductSalary: parseNum(e.deductSalary),
+ netSalary: parseNum(e.netSalary),
+ remark: e.remark ?? "",
+ }));
+ }
+ }
+ });
+ };
+
+ const openAddPerson = () => {
+ loadDeptStaffTree();
+ addPersonVisible.value = true;
+ nextTick(() => {
+ personTreeRef.value?.setCheckedKeys([]);
+ });
+ };
+
+ const addPersonClose = () => {};
+
+ const confirmAddPerson = () => {
+ const tree = personTreeRef.value;
+ if (!tree) {
+ addPersonVisible.value = false;
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 = () => {
- proxy.$modal.confirm("纭畾娓呯┖褰撳墠鍛樺伐鍒楄〃鍚楋紵").then(() => {
- 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,
- 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 ?? "",
- })),
+ 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 ?? "",
+ nation: node.nation ?? "",
+ basicSalary: parseNum(node.basicSalary),
+ dayDays: 0,
+ nightDays: 0,
+ mealAmount: 0,
+ nightAmount: 0,
+ otherIncome: 0,
+ socialPersonal: 0,
+ fundPersonal: 0,
+ otherDeduct: 0,
+ socialSecurityRetroactive: 0,
+ salaryTax: 0,
+ grossSalary: 0,
+ deductSalary: 0,
+ netSalary: 0,
+ remark: "",
+ });
+ });
+ addPersonVisible.value = false;
};
- 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 = () => {
- dialogVisible.value = false;
- emit("close");
-};
+ const removeEmployee = row => {
+ employeeList.value = employeeList.value.filter(
+ e => (e.staffOnJobId || e.id) !== (row.staffOnJobId || row.id)
+ );
+ };
-defineExpose({ openDialog });
+ 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("鏈绠楀埌宸ヨ祫鏁版嵁");
+ return;
+ }
+ employeeList.value = list.map(e => ({
+ ...e,
+ staffOnJobId: e.staffOnJobId ?? e.staffId ?? e.id,
+ staffName: e.staffName,
+ postName: e.postName,
+ deptName: e.deptName,
+ nation: e.nation ?? "",
+ basicSalary: parseNum(e.basicSalary),
+ dayDays: parseNum(e.dayDays ?? e.dayShiftDays),
+ nightDays: parseNum(e.nightDays ?? e.nightShiftDays),
+ mealAmount: parseNum(e.mealAmount ?? e.mealSubsidy),
+ nightAmount: parseNum(e.nightAmount ?? e.nightSubsidy),
+ otherIncome: parseNum(e.otherIncome),
+ socialPersonal: parseNum(e.socialPersonal),
+ fundPersonal: parseNum(e.fundPersonal),
+ otherDeduct: parseNum(e.otherDeduct),
+ socialSecurityRetroactive: parseNum(e.socialSecurityRetroactive),
+ salaryTax: parseNum(e.salaryTax),
+ grossSalary: parseNum(e.grossSalary),
+ deductSalary: parseNum(e.deductSalary),
+ netSalary: parseNum(e.netSalary),
+ remark: e.remark ?? "",
+ }));
+ proxy.$modal.msgSuccess("鐢熸垚鎴愬姛");
+ });
+ };
+
+ const handleClear = () => {
+ proxy.$modal
+ .confirm("纭畾娓呯┖褰撳墠鍛樺伐鍒楄〃鍚楋紵")
+ .then(() => {
+ 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,
+ 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 ?? "",
+ nation: e.nation ?? "",
+ basicSalary: parseNum(e.basicSalary),
+ dayDays: parseNum(e.dayDays),
+ nightDays: parseNum(e.nightDays),
+ mealAmount: parseNum(e.mealAmount),
+ nightAmount: parseNum(e.nightAmount),
+ otherIncome: parseNum(e.otherIncome),
+ socialPersonal: parseNum(e.socialPersonal),
+ fundPersonal: parseNum(e.fundPersonal),
+ otherDeduct: parseNum(e.otherDeduct),
+ socialSecurityRetroactive: parseNum(e.socialSecurityRetroactive),
+ 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 = () => {
+ dialogVisible.value = false;
+ emit("close");
+ };
+
+ 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;
-}
-.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;
-}
+ .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>
diff --git a/src/views/personnelManagement/subsidyConfig/index.vue b/src/views/personnelManagement/subsidyConfig/index.vue
new file mode 100644
index 0000000..17aae49
--- /dev/null
+++ b/src/views/personnelManagement/subsidyConfig/index.vue
@@ -0,0 +1,437 @@
+<template>
+ <div class="app-container subsidy-config-container">
+ <el-row :gutter="20">
+ <!-- 宸︿晶閰嶇疆琛ㄥ崟 -->
+ <el-col :span="16">
+ <el-card class="config-card"
+ shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <div class="header-title">
+ <el-icon class="header-icon">
+ <Setting />
+ </el-icon>
+ <span>琛ヨ创鏍囧噯閰嶇疆</span>
+ </div>
+ <div class="header-ops">
+ <el-button type="primary"
+ :loading="loading"
+ @click="submitForm">
+ <el-icon>
+ <Check />
+ </el-icon> 淇濆瓨閰嶇疆
+ </el-button>
+ </div>
+ </div>
+ </template>
+ <el-form ref="formRef"
+ :model="form"
+ :rules="rules"
+ label-position="top"
+ class="subsidy-form">
+ <div class="config-section">
+ <div class="section-title">
+ <el-icon>
+ <Food />
+ </el-icon> 椁愯ˉ璁剧疆
+ </div>
+ <el-row :gutter="40">
+ <el-col :span="12">
+ <el-form-item label="琛ヨ创鏍囧噯閲戦"
+ style="margin-right:20px"
+ prop="mealAmount">
+ <el-input-number v-model="form.mealAmount"
+ :precision="2"
+ :step="1"
+ :min="0"
+ controls-position="right"
+ class="full-width-input" />
+ <span class="input-unit">鍏�/澶�</span>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <div class="quick-info">
+ <div class="info-item">
+ <span class="label">閫傜敤瀵硅薄锛�</span>
+ <el-tag size="small"
+ type="warning">鍥炴棌鍛樺伐</el-tag>
+ </div>
+ <div class="info-item">
+ <span class="label">璁$畻鑼冨洿锛�</span>
+ <span>鐧界彮 + 澶滅彮</span>
+ </div>
+ </div>
+ </el-col>
+ </el-row>
+ </div>
+ <el-divider />
+ <div class="config-section">
+ <div class="section-title">
+ <el-icon>
+ <Moon />
+ </el-icon> 澶滅彮琛ュ姪璁剧疆
+ </div>
+ <el-row :gutter="40">
+ <el-col :span="12">
+ <el-form-item label="琛ュ姪鏍囧噯閲戦"
+ style="margin-right:20px"
+ prop="nightAmount">
+ <el-input-number v-model="form.nightAmount"
+ :precision="2"
+ :step="1"
+ :min="0"
+ controls-position="right"
+ class="full-width-input" />
+ <span class="input-unit">鍏�/澶�</span>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <div class="quick-info">
+ <div class="info-item">
+ <span class="label">閫傜敤瀵硅薄锛�</span>
+ <el-tag size="small">鍏ㄥ憳锛堟帓鐝负澶滅彮锛�</el-tag>
+ </div>
+ <div class="info-item">
+ <span class="label">璁$畻鑼冨洿锛�</span>
+ <span>浠呴檺澶滅彮</span>
+ </div>
+ </div>
+ </el-col>
+ </el-row>
+ </div>
+ </el-form>
+ </el-card>
+ <!-- 璁$畻绀轰緥鍗$墖 -->
+ <el-card class="example-card"
+ shadow="never">
+ <template #header>
+ <div class="card-header-small">
+ <el-icon>
+ <InfoFilled />
+ </el-icon>
+ <span>钖祫璁$畻閫昏緫璇存槑</span>
+ </div>
+ </template>
+ <div class="example-content">
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <div class="example-box meal">
+ <h5>椁愯ˉ璁$畻绀轰緥</h5>
+ <p>鑻ユ爣鍑嗕负 <strong>{{ form.mealAmount }}鍏�/澶�</strong></p>
+ <p>鏌愬洖鏃忓憳宸ワ細鐧界彮10澶╋紝澶滅彮10澶�</p>
+ <div class="formula">
+ 璁$畻锛�(10 + 10) * {{ form.mealAmount }} = <span>{{ (20 * form.mealAmount).toFixed(2) }}鍏�</span>
+ </div>
+ </div>
+ </el-col>
+ <el-col :span="12">
+ <div class="example-box night">
+ <h5>澶滅彮琛ュ姪璁$畻绀轰緥</h5>
+ <p>鑻ユ爣鍑嗕负 <strong>{{ form.nightAmount }}鍏�/澶�</strong></p>
+ <p>鏌愬憳宸ワ細褰撴湀澶滅彮10澶�</p>
+ <div class="formula">
+ 璁$畻锛�10 * {{ form.nightAmount }} = <span>{{ (10 * form.nightAmount).toFixed(2) }}鍏�</span>
+ </div>
+ </div>
+ </el-col>
+ </el-row>
+ </div>
+ </el-card>
+ </el-col>
+ <!-- 鍙充晶瑙勫垯璇存槑 -->
+ <el-col :span="8">
+ <el-card class="rule-card"
+ shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <span>涓氬姟瑙勫垯璇︽儏</span>
+ </div>
+ </template>
+ <el-scrollbar height="500px">
+ <div class="rule-item">
+ <div class="rule-header">
+ <span class="dot warning"></span>
+ <h6>鍏充簬椁愯ˉ鐨勬爣鍑嗕笌鍙戞斁</h6>
+ </div>
+ <p>1. 绯荤粺灏嗚嚜鍔ㄨ瘑鍒憳宸ユ。妗堜腑鐨勩�愭皯鏃忋�戝瓧娈碉紝浠呭鏍囨敞涓衡�滃洖鏃忊�濈殑鍛樺伐璁$畻姝ら」琛ヨ创銆�</p>
+ <p>2. 鍙戞斁渚濇嵁浠ヨ�冨嫟绯荤粺涓殑瀹為檯鍑哄嫟澶╂暟涓哄噯锛屽寘鍚墍鏈夋甯哥彮娆★紙鐧界彮銆佸鐝級銆�</p>
+ <p>3. 璇峰亣銆佹椃宸ョ瓑闈炲嚭鍕ゅぉ鏁颁笉璁″叆璁$畻鑼冨洿銆�</p>
+ </div>
+ <el-divider />
+ <div class="rule-item">
+ <div class="rule-header">
+ <span class="dot primary"></span>
+ <h6>鍏充簬澶滅彮琛ュ姪鐨勬爣鍑嗕笌鍙戞斁</h6>
+ </div>
+ <p>1. 鍙鍛樺伐鐨勬帓鐝彮娆¤瀹氫箟涓衡�滃鐝�濓紝涓旀湁瀹為檯鍑哄嫟璁板綍锛屽嵆鍙韩鍙楁琛ュ姪銆�</p>
+ <p>2. 琛ュ姪鎸夊ぉ璁$畻锛屼笉鍖哄垎宀椾綅鑱岀骇锛岀粺涓�鎵ц姝ゆ爣鍑嗛厤缃��</p>
+ <p>3. 姝よˉ鍔╀笌椁愯ˉ鍙悓鏃朵韩鍙楋紙鑻ョ鍚堥琛ユ潯浠讹級銆�</p>
+ </div>
+ <el-alert title="閰嶇疆鐢熸晥璇存槑"
+ type="info"
+ :closable="false"
+ show-icon
+ style="margin-top: 20px">
+ 淇敼鍚庣殑鏍囧噯灏嗗湪涓嬩竴娆℃墽琛屸�滃伐璧勭粨绠椻�濅换鍔℃椂姝e紡鐢熸晥锛屼笉浼氬奖鍝嶅凡缁撶畻鐨勫巻鍙茶柂璧勬暟鎹��
+ </el-alert>
+ </el-scrollbar>
+ </el-card>
+ </el-col>
+ </el-row>
+ </div>
+</template>
+
+<script setup name="SubsidyConfig">
+ import { ref, onMounted } from "vue";
+ import {
+ Setting,
+ Check,
+ RefreshRight,
+ Food,
+ Moon,
+ InfoFilled,
+ } from "@element-plus/icons-vue";
+ import {
+ listSubsidyConfiguration,
+ saveSubsidyConfiguration,
+ } from "@/api/personnelManagement/subsidyConfig.js";
+ import { ElMessage, ElMessageBox } from "element-plus";
+
+ const formRef = ref(null);
+ const loading = ref(false);
+
+ const form = ref({
+ id: undefined,
+ mealAmount: 0,
+ nightAmount: 0,
+ tenantId: undefined,
+ createTime: undefined,
+ });
+
+ const rules = {
+ mealAmount: [{ required: true, message: "璇疯緭鍏ラ琛ユ爣鍑�", trigger: "blur" }],
+ nightAmount: [
+ { required: true, message: "璇疯緭鍏ュ鐝ˉ鍔╂爣鍑�", trigger: "blur" },
+ ],
+ };
+
+ /** 鏌ヨ閰嶇疆 */
+ const getConfig = async () => {
+ try {
+ const res = await listSubsidyConfiguration();
+ if (res.data && res.data.length > 0) {
+ const config = res.data[0];
+ form.value = {
+ id: config.id,
+ mealAmount: config.mealAmount || 0,
+ nightAmount: config.nightAmount || 0,
+ tenantId: config.tenantId,
+ createTime: config.createTime,
+ };
+ }
+ } catch (error) {
+ console.error("鑾峰彇閰嶇疆澶辫触", error);
+ }
+ };
+
+ /** 鎻愪氦琛ㄥ崟 */
+ const submitForm = async () => {
+ if (!formRef.value) return;
+
+ await formRef.value.validate(async valid => {
+ if (valid) {
+ loading.value = true;
+ try {
+ await saveSubsidyConfiguration(form.value);
+ ElMessage.success("鏍囧噯閰嶇疆宸叉洿鏂�");
+ getConfig(); // 閲嶆柊鍔犺浇浠ヨ幏鍙栧彲鑳界殑鏇存柊锛堝id锛�
+ } catch (error) {
+ console.error("淇濆瓨澶辫触", error);
+ } finally {
+ loading.value = false;
+ }
+ }
+ });
+ };
+
+ onMounted(() => {
+ getConfig();
+ });
+</script>
+
+<style scoped lang="scss">
+ .subsidy-config-container {
+ padding: 20px;
+ background-color: #f5f7fa;
+ min-height: calc(100vh - 84px);
+
+ .config-card {
+ margin-bottom: 20px;
+ border-radius: 8px;
+
+ .card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ .header-title {
+ display: flex;
+ align-items: center;
+ font-size: 18px;
+ font-weight: 600;
+ color: #303133;
+
+ .header-icon {
+ margin-right: 8px;
+ color: #409eff;
+ }
+ }
+ }
+ }
+
+ .subsidy-form {
+ padding: 10px 20px;
+
+ .config-section {
+ .section-title {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ font-size: 16px;
+ font-weight: 500;
+ margin-bottom: 20px;
+ color: #606266;
+
+ .el-icon {
+ color: #409eff;
+ }
+ }
+ }
+
+ .full-width-input {
+ width: 100% !important;
+ }
+
+ .input-unit {
+ position: absolute;
+ right: -45px;
+ top: 0;
+ color: #909399;
+ font-size: 14px;
+ }
+
+ .quick-info {
+ background: #fdf6ec;
+ border-radius: 4px;
+ padding: 15px;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ gap: 10px;
+
+ .info-item {
+ font-size: 14px;
+ color: #666;
+ .label {
+ font-weight: 500;
+ }
+ }
+ }
+ }
+
+ .example-card {
+ background: #fff;
+ border: 1px dashed #dcdfe6;
+
+ .card-header-small {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ font-size: 14px;
+ color: #909399;
+ }
+
+ .example-box {
+ padding: 15px;
+ border-radius: 6px;
+
+ h5 {
+ margin: 0 0 10px 0;
+ font-size: 14px;
+ color: #303133;
+ }
+
+ p {
+ margin: 5px 0;
+ font-size: 13px;
+ color: #606266;
+ }
+
+ .formula {
+ margin-top: 10px;
+ padding-top: 10px;
+ border-top: 1px solid rgba(0, 0, 0, 0.05);
+ font-size: 13px;
+ font-weight: bold;
+
+ span {
+ color: #f56c6c;
+ font-size: 16px;
+ }
+ }
+
+ &.meal {
+ background-color: #f0f9eb;
+ }
+ &.night {
+ background-color: #ecf5ff;
+ }
+ }
+ }
+
+ .rule-card {
+ height: 100%;
+
+ .rule-item {
+ padding: 5px 0;
+
+ .rule-header {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ margin-bottom: 10px;
+
+ .dot {
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ &.warning {
+ background: #e6a23c;
+ }
+ &.primary {
+ background: #409eff;
+ }
+ }
+
+ h6 {
+ margin: 0;
+ font-size: 15px;
+ color: #303133;
+ }
+ }
+
+ p {
+ font-size: 13px;
+ line-height: 1.8;
+ color: #606266;
+ margin: 5px 0 5px 16px;
+ }
+ }
+ }
+ }
+
+ :deep(.el-divider--horizontal) {
+ margin: 24px 0;
+ }
+</style>
--
Gitblit v1.9.3