From a6011b5117fd3d19f3d9d0b75103e1d32808326e Mon Sep 17 00:00:00 2001 From: spring <2396852758@qq.com> Date: 星期三, 06 八月 2025 09:52:06 +0800 Subject: [PATCH] 完成支出管理 --- src/views/financialManagement/expenseManagement/index.vue | 279 +++++++++++++++++++++++++++ src/views/financialManagement/expenseManagement/Modal.vue | 69 ++++++ src/views/financialManagement/revenueManagement/index.vue | 2 src/api/financialManagement/expenseManagement.js | 78 +++++++ src/views/financialManagement/expenseManagement/Form.vue | 123 ++++++++++++ 5 files changed, 550 insertions(+), 1 deletions(-) diff --git a/src/api/financialManagement/expenseManagement.js b/src/api/financialManagement/expenseManagement.js new file mode 100644 index 0000000..317dc47 --- /dev/null +++ b/src/api/financialManagement/expenseManagement.js @@ -0,0 +1,78 @@ +import request from "@/utils/request"; + +// 鏌ヨ鍒楄〃 +export const listPage = (params) => { + return request({ + url: "/account/accountExpense/listPage", + method: "get", + params, + }); +}; + +// 鏂板 +export function add(data) { + return request({ + url: "/account/accountExpense/add", + method: "post", + data: data, + }); +} + +// 缂栬緫 +export function update(data) { + return request({ + url: "/account/accountExpense/update", + method: "post", + data: data, + }); +} + +//瀵煎嚭 +export const exportAccountExpense = (query) => { + return request({ + url: "/account/accountExpense/export", + method: "post", + data: query, + responseType: "blob", + }); +}; + +export const delAccountExpense = (query) => { + return request({ + url: `account/accountExpense/del`, + method: "delete", + data: query, + }); +}; + +export const getAccountExpense = (id) => { + return request({ + url: `/account/accountExpense/${id}`, + method: "get", + }); +}; + +// 鏌ヨ闄勪欢鍒楄〃 +export function fileListPage(query) { + return request({ + url: "/account/accountFile/listPage", + method: "get", + params: query, + }); +} +// 淇濆瓨闄勪欢鍒楄〃 +export function fileAdd(query) { + return request({ + url: "/account/accountFile/add", + method: "post", + data: query, + }); +} +// 鍒犻櫎闄勪欢鍒楄〃 +export function fileDel(query) { + return request({ + url: "/account/accountFile/del", + method: "delete", + data: query, + }); +} diff --git a/src/views/financialManagement/expenseManagement/Form.vue b/src/views/financialManagement/expenseManagement/Form.vue new file mode 100644 index 0000000..9cfe5da --- /dev/null +++ b/src/views/financialManagement/expenseManagement/Form.vue @@ -0,0 +1,123 @@ +<template> + <el-form :model="form" label-width="100px" :rules="formRules" ref="formRef"> + <el-form-item label="鏀嚭鏃ユ湡" prop="expenseDate"> + <el-date-picker + style="width: 100%" + v-model="form.expenseDate" + format="YYYY-MM-DD" + value-format="YYYY-MM-DD" + type="date" + placeholder="璇烽�夋嫨鏃ユ湡" + clearable + /> + </el-form-item> + <el-form-item label="鏀嚭绫诲瀷" prop="expenseType"> + <el-select + v-model="form.expenseType" + placeholder="璇烽�夋嫨" + clearable + > + <el-option :label="item.label" :value="item.value" v-for="(item,index) in expense_types" :key="index" /> + </el-select> + </el-form-item> + <el-form-item label="渚涘簲鍟嗗悕绉�" prop="supplierName"> + <el-input v-model="form.supplierName" placeholder="璇疯緭鍏�" /> + </el-form-item> + <el-form-item label="鏀嚭閲戦" prop="expenseMoney"> + <el-input-number :step="0.01" :min="0" style="width: 100%" + v-model="form.expenseMoney" + placeholder="璇疯緭鍏�" + /> + </el-form-item> + <el-form-item label="鏀嚭鎻忚堪" prop="expenseDescribed"> + <el-input v-model="form.expenseDescribed" placeholder="璇疯緭鍏�" /> + </el-form-item> + <el-form-item label="浠樻鏂瑰紡" prop="expenseMethod"> + <el-select + v-model="form.expenseMethod" + placeholder="璇烽�夋嫨" + clearable + > + <el-option :label="item.label" :value="item.value" v-for="(item,index) in checkout_payment" :key="index" /> + </el-select> + </el-form-item> + <el-form-item label="鍙戠エ鍙风爜" prop="invoiceNumber"> + <el-input v-model="form.invoiceNumber" placeholder="璇疯緭鍏�" /> + </el-form-item> + <el-form-item label="澶囨敞" prop="note"> + <el-input + v-model="form.note" + placeholder="澶囨敞" + /> + </el-form-item> + + </el-form> +</template> + +<script setup> +import useFormData from "@/hooks/useFormData"; +import { getAccountExpense } from "@/api/financialManagement/expenseManagement"; +import {ref} from "vue"; +const { proxy } = getCurrentInstance(); + + +defineOptions({ + name: "鏂板鏀嚭", +}); +const { expense_types } = proxy.useDict("expense_types"); +const { checkout_payment } = proxy.useDict("checkout_payment"); +const formRef = ref(null); +const formRules = { + supplierName: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }], + expenseMoney: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }], + expenseDescribed: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }], + expenseDate: [{ required: true, trigger: "change", message: "璇烽�夋嫨" }], + expenseType: [{ required: true, trigger: "change", message: "璇烽�夋嫨" }], + expenseMethod: [{ required: true, trigger: "change", message: "璇烽�夋嫨" }], +} + +const { form, resetForm } = useFormData({ + expenseDate: undefined, // 鏀嚭鏃ユ湡 + expenseType: undefined, // 鏀嚭绫诲瀷 + supplierName: undefined, // 瀹㈡埛鍚嶇О + expenseMoney: undefined, // 鏀嚭閲戦 + expenseDescribed: undefined, // 鏀嚭鎻忚堪 + expenseMethod: undefined, // 鏀舵鏂瑰紡 + invoiceNumber: undefined, // 鍙戠エ鍙风爜 + note: undefined, // 澶囨敞 +}); + +const loadForm = async (id) => { + const { code, data } = await getAccountExpense(id); + if (code == 200) { + form.expenseDate = data.expenseDate; + form.expenseType = data.expenseType; + form.supplierName = data.supplierName; + form.expenseMoney = data.expenseMoney; + form.expenseDescribed = data.expenseDescribed; + form.expenseMethod = data.expenseMethod; + form.invoiceNumber = data.invoiceNumber; + form.note = data.note; + } +}; + +// 娓呴櫎琛ㄥ崟鏍¢獙鐘舵�� +const clearValidate = () => { + formRef.value?.clearValidate(); +}; + +// 閲嶇疆琛ㄥ崟鏁版嵁鍜屾牎楠岀姸鎬� +const resetFormAndValidate = () => { + resetForm(); + clearValidate(); +}; + +defineExpose({ + form, + loadForm, + resetForm, + clearValidate, + resetFormAndValidate, + formRef, +}); +</script> diff --git a/src/views/financialManagement/expenseManagement/Modal.vue b/src/views/financialManagement/expenseManagement/Modal.vue new file mode 100644 index 0000000..8e5b171 --- /dev/null +++ b/src/views/financialManagement/expenseManagement/Modal.vue @@ -0,0 +1,69 @@ +<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/financialManagement/expenseManagement"; +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 (id) => { + openModal(id); + await nextTick(); + formRef.value.loadForm(id); +}; + +defineExpose({ + openModal, + loadForm, +}); +</script> diff --git a/src/views/financialManagement/expenseManagement/index.vue b/src/views/financialManagement/expenseManagement/index.vue index e69de29..0c6cbde 100644 --- a/src/views/financialManagement/expenseManagement/index.vue +++ b/src/views/financialManagement/expenseManagement/index.vue @@ -0,0 +1,279 @@ +<template> + <div class="app-container"> + <el-form :model="filters" :inline="true"> + <el-form-item label="褰曞叆鏃ユ湡:"> + <el-date-picker v-model="filters.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange" + placeholder="璇烽�夋嫨" clearable @change="changeDaterange" /> + </el-form-item> + <el-form-item label="浠樻鏂瑰紡:"> + <el-select + v-model="filters.expenseMethod" + placeholder="璇烽�夋嫨" + clearable + style="width: 200px;" + > + <el-option + v-for="item in checkout_payment" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </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.id)" icon="editPen"> + 缂栬緫 + </el-button> + <el-button + type="primary" + text + @click="openFilesFormDia(row)" + > + 闄勪欢 + </el-button> + </template> + </PIMTable> + </div> + <Modal ref="modalRef" @success="getTableData"></Modal> + <files-dia ref="filesDia" @close="handleQuery"></files-dia> + </div> +</template> + +<script setup> +import { usePaginationApi } from "@/hooks/usePaginationApi"; +import { listPage, delAccountExpense } from "@/api/financialManagement/expenseManagement"; +import { onMounted, getCurrentInstance } from "vue"; +import Modal from "./Modal.vue"; +import { ElMessageBox, ElMessage } from "element-plus"; +import dayjs from "dayjs"; +import FilesDia from "../revenueManagement/filesDia.vue"; + +defineOptions({ + name: "鏀嚭绠$悊", +}); + +// 琛ㄦ牸澶氶�夋閫変腑椤� +const multipleList = ref([]); +const { proxy } = getCurrentInstance(); +const modalRef = ref(); +const { checkout_payment } = proxy.useDict("checkout_payment"); +const { expense_types } = proxy.useDict("expense_types"); +const filesDia = ref() + +const { + filters, + columns, + dataList, + pagination, + getTableData, + resetFilters, + onCurrentChange, +} = usePaginationApi( + listPage, + { + expenseMethod: undefined, + }, + [ + { + label: "鏀嚭鏃ユ湡", + align: "center", + prop: "expenseDate", + }, + { + label: "鏀嚭绫诲瀷", + align: "center", + prop: "expenseType", + dataType: "tag", + formatData: (params) => { + if (expense_types.value.find((m) => m.value == params)) { + return expense_types.value.find((m) => m.value == params).label; + } else { + return null + } + }, + }, + { + label: "渚涘簲鍟嗗悕绉�", + align: "center", + prop: "supplierName", + + }, + { + label: "鏀嚭閲戦", + align: "center", + prop: "expenseMoney", + + }, + { + label: "鏀嚭鎻忚堪", + align: "center", + prop: "expenseDescribed", + + }, + { + label: "浠樻鏂瑰紡", + align: "center", + prop: "expenseMethod", + dataType: "tag", + formatData: (params) => { + if (checkout_payment.value.find((m) => m.value == params)) { + return checkout_payment.value.find((m) => m.value == params).label; + } else { + return null + } + }, + }, + { + label: "鍙戠エ鍙风爜", + align: "center", + prop: "invoiceNumber", + + }, + { + label: "澶囨敞", + align: "center", + prop: "note", + + }, + { + label: "褰曞叆浜�", + align: "center", + prop: "inputUser", + }, + { + label: "褰曞叆鏃ユ湡", + align: "center", + prop: "inputTime", + + }, + { + fixed: "right", + label: "鎿嶄綔", + dataType: "slot", + slot: "operation", + align: "center", + width: "200px", + }, + ] +); + +// 澶氶�夊悗鍋氫粈涔� +const handleSelectionChange = (selectionList) => { + multipleList.value = selectionList; +}; + +const add = () => { + modalRef.value.openModal(); +}; +const edit = (id) => { + modalRef.value.loadForm(id); +}; +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 delAccountExpense(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(`/account/accountExpense/export`, {}, "鏀嚭鍙拌处.xlsx"); + }) + .catch(() => { + proxy.$modal.msg("宸插彇娑�"); + }); +}; +// 鎵撳紑闄勪欢寮规 +const openFilesFormDia = (row) => { + nextTick(() => { + filesDia.value?.openDialog( row,'鏀嚭') + }) +}; + +onMounted(() => { + 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> + diff --git a/src/views/financialManagement/revenueManagement/index.vue b/src/views/financialManagement/revenueManagement/index.vue index f653c15..984d9de 100644 --- a/src/views/financialManagement/revenueManagement/index.vue +++ b/src/views/financialManagement/revenueManagement/index.vue @@ -105,7 +105,7 @@ } = usePaginationApi( listPage, { - searchText: undefined, + incomeMethod: undefined, }, [ { -- Gitblit v1.9.3