From c1765373914b72a69ac24dca33250b7dc5019465 Mon Sep 17 00:00:00 2001 From: maven <2163098428@qq.com> Date: 星期三, 13 八月 2025 16:27:49 +0800 Subject: [PATCH] yys 新增劳保管理 --- src/views/lavorissue/ledger/Form.vue | 128 ++++++++++ src/api/lavorissce/ledger.js | 38 +++ src/utils/util.js | 16 + src/views/lavorissue/ledger/filesDia.vue | 202 ++++++++++++++++ src/views/lavorissue/ledger/index.vue | 216 ++++++++++++++++++ src/views/lavorissue/ledger/Modal.vue | 70 +++++ 6 files changed, 669 insertions(+), 1 deletions(-) diff --git a/src/api/lavorissce/ledger.js b/src/api/lavorissce/ledger.js new file mode 100644 index 0000000..5b7c94a --- /dev/null +++ b/src/api/lavorissce/ledger.js @@ -0,0 +1,38 @@ +import request from '@/utils/request' + +// 鍒嗛〉鏌ヨ +export function listPage(data) { + return request({ + url: '/lavorIssue/listPage', + method: 'get', + data + }) +} + +// 娣诲姞 +export function add(data) { + return request({ + url: '/lavorIssue/add', + method: 'post', + data + }) +} + +// 淇敼 +export function update(data) { + return request({ + url: '/lavorIssue/update', + method: 'post', + data + }) +} + +// 鍒犻櫎 +export function deleteLedger(data) { + return request({ + url: '/lavorIssue/delete', + method: 'delete', + data + }) +} + diff --git a/src/utils/util.js b/src/utils/util.js index 78846dc..fd3ef75 100644 --- a/src/utils/util.js +++ b/src/utils/util.js @@ -86,7 +86,21 @@ 'aplication/zip': 'zpi', } } - + export const deepCopySameProperties = (source, target) =>{ + for (const key in source) { + if (target.hasOwnProperty(key)) { + if (typeof source[key] === 'object' && source[key] !== null && + typeof target[key] === 'object' && target[key] !== null) { + // 閫掑綊澶勭悊瀵硅薄 + deepCopySameProperties(source[key], target[key]); + } else { + // 鍩烘湰绫诲瀷鐩存帴璧嬪�� + target[key] = source[key]; + } + } + } + return target; +} export function filterArr(arr) { return arr.filter(item => item.flag !== false); } \ No newline at end of file diff --git a/src/views/lavorissue/ledger/Form.vue b/src/views/lavorissue/ledger/Form.vue new file mode 100644 index 0000000..071bc66 --- /dev/null +++ b/src/views/lavorissue/ledger/Form.vue @@ -0,0 +1,128 @@ +<template> + <el-form :model="form" label-width="100px" :rules="formRules" ref="formRef"> + <el-form-item label="閮ㄩ棬鍚嶇О" prop="deptId"> + <el-select + v-model="form.deptId" + placeholder="璇烽�夋嫨" + clearable + disabled + > + <el-option :label="item.deptName" :value="item.deptId" v-for="(item,index) in productOptions" :key="deptId" /> + </el-select> + </el-form-item> + <el-form-item label="鍛樺伐鍚嶇О" prop="staffId"> + <el-select + v-model="form.staffId" + placeholder="璇烽�夋嫨" + clearable + > + <el-option :label="item.staffName" :value="item.id" v-for="(item,index) in personList" :key="id" /> + </el-select> + </el-form-item> + <el-form-item label="鍔充繚闃插叿" prop="dictId"> + <el-select + v-model="form.dictId" + placeholder="璇烽�夋嫨" + clearable + > + <el-option :label="item.label" :value="item.value" v-for="(item,index) in sys_lavor_issue" :key="value" /> + </el-select> + </el-form-item> + <el-form-item label="棰嗙敤鏁伴噺" prop="num"> + <el-input-number :step="1" :min="0" style="width: 100%" + v-model="form.num" + placeholder="璇疯緭鍏�" + /> + </el-form-item> + <el-form-item label="棰嗙敤鏃ユ湡" prop="adoptedDate"> + <el-date-picker + style="width: 100%" + v-model="form.adoptedDate" + format="YYYY-MM-DD" + value-format="YYYY-MM-DD" + type="date" + placeholder="璇烽�夋嫨鏃ユ湡" + clearable + /> + </el-form-item> + + </el-form> +</template> + +<script setup> +import useFormData from "@/hooks/useFormData"; +import {ref,onMounted} from "vue"; +import useUserStore from "@/store/modules/user"; +import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js"; +import {deepCopySameProperties} from '@/utils/util' +const userStore = useUserStore(); +import { + getDept +} from "@/api/collaborativeApproval/approvalProcess.js"; +const { proxy } = getCurrentInstance(); + + +defineOptions({ + name: "鏂板鏀跺叆", +}); +const { sys_lavor_issue } = proxy.useDict("sys_lavor_issue") +const formRef = ref(null); +const productOptions = ref([]); +const personList = ref([]); +const formRules = { + deptId: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }], + staffId: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }], + dictId: [{ required: true, trigger: "change", message: "璇烽�夋嫨" }], + num: [{ required: true, trigger: "change", message: "璇烽�夋嫨" }], + adoptedDate: [{ required: true, trigger: "change", message: "璇烽�夋嫨" }], +} + +const { form, resetForm } = useFormData({ + deptId: undefined, // + staffId: undefined, // + dictId: undefined, // + num: undefined, // + adoptedDate: undefined, +}); +const getPersonList = () => { + getStaffOnJob().then(res => { + personList.value = res.data + }) +}; +const loadForm = (data) => { + deepCopySameProperties(data, form) +}; + +const getProductOptions = () => { + getDept().then((res) => { + productOptions.value = res.data; + }); +} +// 娓呴櫎琛ㄥ崟鏍¢獙鐘舵�� +const clearValidate = () => { + formRef.value?.clearValidate(); +}; + +// 閲嶇疆琛ㄥ崟鏁版嵁鍜屾牎楠岀姸鎬� +const resetFormAndValidate = () => { + resetForm(); + clearValidate(); + form.deptId = userStore.currentDeptId + getProductOptions(); + getPersonList(); +}; +onMounted(() => { + console.log(sys_lavor_issue) + form.deptId = userStore.currentDeptId + getProductOptions(); + getPersonList(); +}) +defineExpose({ + form, + resetForm, + clearValidate, + loadForm, + resetFormAndValidate, + formRef, +}); +</script> diff --git a/src/views/lavorissue/ledger/Modal.vue b/src/views/lavorissue/ledger/Modal.vue new file mode 100644 index 0000000..5d63236 --- /dev/null +++ b/src/views/lavorissue/ledger/Modal.vue @@ -0,0 +1,70 @@ +<template> + <el-dialog :title="modalOptions.title" v-model="visible" @close="close" width="30%"> + <Form ref="formRef"></Form> + <template #footer> + <el-button type="primary" @click="sendForm" :loading="loading"> + {{ modalOptions.confirmText }} + </el-button> + <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button> + </template> + </el-dialog> +</template> + +<script setup> +import { useModal } from "@/hooks/useModal"; +import { add, update } from "@/api/lavorissce/ledger"; +import Form from "./Form.vue"; +import { ElMessage } from "element-plus"; +const { proxy } = getCurrentInstance() + +defineOptions({ + name: "鏀跺叆鏂板缂栬緫", +}); + +const emits = defineEmits(["success"]); + +const formRef = ref(); +const { + id, + visible, + loading, + openModal, + modalOptions, + handleConfirm, + closeModal, +} = useModal({ title: "鍔充繚鍙拌处" }); + +const sendForm = () => { + proxy.$refs.formRef.$refs.formRef.validate(async valid => { + if (valid) { + const {code} = id.value + ? await update({id: id.value, ...formRef.value.form}) + : await add(formRef.value.form); + if (code == 200) { + emits("success"); + ElMessage({message: "鎿嶄綔鎴愬姛", type: "success"}); + close(); + } else { + loading.value = false; + } + } + }) +}; + +const close = () => { + formRef.value.resetFormAndValidate(); + closeModal(); +}; + +const loadForm = async (row) => { + openModal(row.id); + await nextTick(); + formRef.value.loadForm(row); + +}; + +defineExpose({ + openModal, + loadForm, +}); +</script> diff --git a/src/views/lavorissue/ledger/filesDia.vue b/src/views/lavorissue/ledger/filesDia.vue new file mode 100644 index 0000000..f752496 --- /dev/null +++ b/src/views/lavorissue/ledger/filesDia.vue @@ -0,0 +1,202 @@ +<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" + > + </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/financialManagement/revenueManagement.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 accountType = ref('') +const headers = ref({ + Authorization: "Bearer " + getToken(), +}); +const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/file/upload"); // 涓婁紶鐨勫浘鐗囨湇鍔″櫒鍦板潃 + +// 鎵撳紑寮规 +const openDialog = (row,type) => { + accountType.value = type; + dialogFormVisible.value = true; + currentId.value = row.id; + getList() +} +const paginationSearch = (obj) => { + page.current = obj.page; + page.size = obj.limit; + getList(); +}; +const getList = () => { + fileListPage({accountId: currentId.value,accountType:accountType.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.accountId = currentId.value; + file.accountType = accountType.value; + fileAdd(file).then(res => { + proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛"); + getList() + }) +} +// 涓婁紶澶辫触澶勭悊 +function handleUploadError() { + proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触"); +} +// 涓嬭浇闄勪欢 +const downLoadFile = (row) => { + proxy.$download.name(row.url); +} +// 鍒犻櫎 +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/lavorissue/ledger/index.vue b/src/views/lavorissue/ledger/index.vue new file mode 100644 index 0000000..27cd948 --- /dev/null +++ b/src/views/lavorissue/ledger/index.vue @@ -0,0 +1,216 @@ +<template> + <div class="app-container"> + <el-form :model="filters" :inline="true"> + <el-form-item label="鍛樺伐鍚嶇О:"> + <el-input + v-model="filters.supplierName" + style="width: 240px" + placeholder="璇疯緭鍏�" + @change="handleQuery" + clearable + prefix-icon="Search" + /> + </el-form-item> + <el-form-item> + <el-button type="primary" @click="getTableData">鎼滅储</el-button> + <el-button @click="resetFilters">閲嶇疆</el-button> + </el-form-item> + </el-form> + <div class="table_list"> + <div class="actions"> + <div></div> + <div> + <el-button type="primary" @click="add" icon="Plus"> 鏂板 </el-button> + <el-button @click="handleOut" icon="download">瀵煎嚭</el-button> + <el-button + type="danger" + icon="Delete" + :disabled="multipleList.length <= 0" + @click="deleteRow(multipleList.map((item) => item.id))" + > + 鎵归噺鍒犻櫎 + </el-button> + </div> + </div> + <PIMTable + rowKey="id" + isSelection + :column="columns" + :tableData="dataList" + :page="{ + current: pagination.currentPage, + size: pagination.pageSize, + total: pagination.total, + }" + @selection-change="handleSelectionChange" + @pagination="changePage" + > + <template #operation="{ row }"> + <el-button type="primary" text @click="edit(row)" icon="editPen"> + 缂栬緫 + </el-button> + </template> + </PIMTable> + </div> + <Modal ref="modalRef" @success="getTableData"></Modal> + <files-dia ref="filesDia"></files-dia> + </div> +</template> + +<script setup> +import { usePaginationApi } from "@/hooks/usePaginationApi"; +import { listPage,deleteLedger } from "@/api/lavorissce/ledger"; +import { onMounted, getCurrentInstance } from "vue"; +import Modal from "./Modal.vue"; +import { ElMessageBox, ElMessage } from "element-plus"; +import dayjs from "dayjs"; +import FilesDia from "./filesDia.vue"; + +// 琛ㄦ牸澶氶�夋閫変腑椤� +const multipleList = ref([]); +const { proxy } = getCurrentInstance(); +const modalRef = ref(); +const { payment_methods } = proxy.useDict("payment_methods"); +const { income_types } = proxy.useDict("income_types"); +const filesDia = ref() + +const { + filters, + columns, + dataList, + pagination, + getTableData, + resetFilters, + onCurrentChange, +} = usePaginationApi( + listPage, + { + incomeMethod: undefined, + }, + [ + { + label: "鍛樺伐鍚嶇О", + align: "center", + prop: "staffName", + }, + { + label: "鍛樺伐缂栧彿", + align: "center", + prop: "staffNo" + }, + { + label: "鍔充繚闃插叿", + align: "center", + prop: "dictName", + + }, + { + label: "棰嗙敤鏁伴噺", + align: "center", + prop: "num", + + }, + { + label: "棰嗙敤鏃ユ湡", + align: "center", + prop: "adoptedDate", + + }, + { + fixed: "right", + label: "鎿嶄綔", + dataType: "slot", + slot: "operation", + align: "center", + width: "200px", + }, + ] +); + +// 澶氶�夊悗鍋氫粈涔� +const handleSelectionChange = (selectionList) => { + multipleList.value = selectionList; +}; + +const add = () => { + modalRef.value.openModal(); +}; +const edit = (row) => { + modalRef.value.loadForm(row); +}; +const changePage = ({ page, limit }) => { + pagination.currentPage = page; + pagination.pageSize = limit; + onCurrentChange(page); +}; +const deleteRow = (id) => { + ElMessageBox.confirm("姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ暟鎹�, 鏄惁缁х画?", "鎻愮ず", { + confirmButtonText: "纭畾", + cancelButtonText: "鍙栨秷", + type: "warning", + }).then(async () => { + const { code } = await deleteLedger(id); + if (code == 200) { + ElMessage({ + type: "success", + message: "鍒犻櫎鎴愬姛", + }); + getTableData(); + } + }); +}; + +const changeDaterange = (value) => { + if (value) { + filters.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); + filters.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD"); + } else { + filters.entryDateStart = undefined; + filters.entryDateEnd = undefined; + } + getTableData(); +}; + +const handleOut = () => { + ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", { + confirmButtonText: "纭", + cancelButtonText: "鍙栨秷", + type: "warning", + }) + .then(() => { + proxy.download(`/lavorIssue/export`, {}, "鍔充繚鍙拌处.xlsx"); + }) + .catch(() => { + proxy.$modal.msg("宸插彇娑�"); + }); +}; +// 鎵撳紑闄勪欢寮规 +const openFilesFormDia = (row) => { + nextTick(() => { + filesDia.value?.openDialog( row,'鏀跺叆') + }) +}; + +onMounted(() => { + console.log(12331) + filters.entryDate = [ + dayjs().format("YYYY-MM-DD"), + dayjs().add(1, "day").format("YYYY-MM-DD"), + ] + filters.entryDateStart = dayjs().format("YYYY-MM-DD") + filters.entryDateEnd = dayjs().add(1, "day").format("YYYY-MM-DD") + getTableData(); +}); +</script> + +<style lang="scss" scoped> +.table_list { + margin-top: unset; +} +.actions { + display: flex; + justify-content: space-between; + margin-bottom: 10px; +} +</style> + -- Gitblit v1.9.3