From c725eaac2daac0d1a789750ff4a04479b0a0c5b9 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期三, 06 八月 2025 17:22:28 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev' into dev_7004
---
src/views/financialManagement/expenseManagement/Modal.vue | 69 ++
src/assets/styles/element-ui.scss | 18
src/views/financialManagement/revenueManagement/index.vue | 279 +++++++++
src/api/financialManagement/expenseManagement.js | 78 ++
src/views/financialManagement/revenueManagement/Modal.vue | 69 ++
src/views/financialManagement/expenseManagement/Form.vue | 123 ++++
src/views/financialManagement/revenueManagement/filesDia.vue | 202 +++++++
src/views/financialManagement/expenseManagement/index.vue | 279 +++++++++
src/api/financialManagement/revenueManagement.js | 78 ++
src/main.js | 129 ++--
package.json | 2
src/views/financialManagement/revenueManagement/Form.vue | 123 ++++
src/views/salesManagement/salesLedger/fileList.vue | 9
src/components/filePreview/index.vue | 202 +++++++
src/views/financialManagement/financialStatements/index.vue | 0
15 files changed, 1,592 insertions(+), 68 deletions(-)
diff --git a/package.json b/package.json
index 871409b..15334fa 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,8 @@
},
"dependencies": {
"@element-plus/icons-vue": "2.3.1",
+ "@vue-office/docx": "^1.6.3",
+ "@vue-office/excel": "^1.7.14",
"@vueup/vue-quill": "1.2.0",
"@vueuse/core": "10.11.0",
"axios": "0.28.1",
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/api/financialManagement/revenueManagement.js b/src/api/financialManagement/revenueManagement.js
new file mode 100644
index 0000000..090ddf8
--- /dev/null
+++ b/src/api/financialManagement/revenueManagement.js
@@ -0,0 +1,78 @@
+import request from "@/utils/request";
+
+// 鏌ヨ鍒楄〃
+export const listPage = (params) => {
+ return request({
+ url: "/account/accountIncome/listPage",
+ method: "get",
+ params,
+ });
+};
+
+// 鏂板
+export function add(data) {
+ return request({
+ url: "/account/accountIncome/add",
+ method: "post",
+ data: data,
+ });
+}
+
+// 缂栬緫
+export function update(data) {
+ return request({
+ url: "/account/accountIncome/update",
+ method: "post",
+ data: data,
+ });
+}
+
+//瀵煎嚭
+export const exportAccountIncome = (query) => {
+ return request({
+ url: "/account/accountIncome/export",
+ method: "post",
+ data: query,
+ responseType: "blob",
+ });
+};
+
+export const delAccountIncome = (query) => {
+ return request({
+ url: `account/accountIncome/del`,
+ method: "delete",
+ data: query,
+ });
+};
+
+export const getAccountIncome = (id) => {
+ return request({
+ url: `/account/accountIncome/${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/assets/styles/element-ui.scss b/src/assets/styles/element-ui.scss
index 0c4c3de..4eae8b2 100644
--- a/src/assets/styles/element-ui.scss
+++ b/src/assets/styles/element-ui.scss
@@ -56,18 +56,18 @@
padding: 0 !important;
}
.el-dialog__header {
- background: #F5F6F7;
+ background: #f5f6f7;
padding: 12px 16px;
border-radius: 8px 8px 0 0;
}
.el-dialog__title {
font-weight: 400;
font-size: 16px;
- color: #2E3033;
+ color: #2e3033;
}
.el-dialog__body {
padding: 16px 40px 0 40px;
- max-height: 680px;
+ max-height: 90vh;
overflow-y: auto;
}
.el-dialog__footer {
@@ -79,14 +79,14 @@
border-radius: 8px;
}
.el-message-box__header {
- background: #F5F6F7;
+ background: #f5f6f7;
padding: 12px 16px;
border-radius: 8px 8px 0 0;
}
.el-message-box__title {
font-weight: 400;
font-size: 16px;
- color: #2E3033;
+ color: #2e3033;
}
.el-message-box__content {
padding: 16px 40px 0 40px;
@@ -108,7 +108,7 @@
.el-table__expanded-cell {
padding: 0 !important;
.el-table__header-wrapper {
- background-color: #F5F8FF !important;
+ background-color: #f5f8ff !important;
}
}
@@ -127,7 +127,7 @@
// dropdown
.el-dropdown-menu {
a {
- display: block
+ display: block;
}
}
@@ -149,6 +149,6 @@
display: none;
}
-.el-dropdown .el-dropdown-link{
+.el-dropdown .el-dropdown-link {
color: var(--el-color-primary) !important;
-}
\ No newline at end of file
+}
diff --git a/src/components/filePreview/index.vue b/src/components/filePreview/index.vue
new file mode 100644
index 0000000..cda5b56
--- /dev/null
+++ b/src/components/filePreview/index.vue
@@ -0,0 +1,202 @@
+<template>
+ <el-dialog v-model="dialogVisible" title="棰勮" width="100%" fullscreen align-center :before-close="handleClose" append-to-body>
+ <div>
+ <!-- 鍥剧墖棰勮 -->
+ <div v-if="isImage">
+ <img :src="imgUrl" alt="Image Preview" />
+ </div>
+
+ <!-- PDF棰勮鎻愮ず -->
+ <div v-if="isPdf" style="height: 100vh; display: flex; align-items: center; justify-content: center;">
+ <p>姝e湪鍑嗗PDF棰勮...</p>
+ </div>
+
+ <!-- Word鏂囨。棰勮 -->
+ <div v-if="isDoc">
+ <p v-if="!isDocShow">鏂囨。鏃犳硶鐩存帴棰勮锛岃涓嬭浇鏌ョ湅銆�</p>
+ <a :href="fileUrl" v-if="!isDocShow">涓嬭浇鏂囦欢</a>
+ <vue-office-docx
+ v-else
+ :src="fileUrl"
+ style="height: 100vh;"
+ @rendered="renderedHandler"
+ @error="errorHandler"
+ />
+ </div>
+
+ <!-- Excel鏂囨。棰勮 -->
+ <div v-if="isXls">
+ <p v-if="!isDocShow">鏂囨。鏃犳硶鐩存帴棰勮锛岃涓嬭浇鏌ョ湅銆�</p>
+ <a :href="fileUrl" v-if="!isDocShow">涓嬭浇鏂囦欢</a>
+ <vue-office-excel
+ v-else
+ :src="fileUrl"
+ :options="options"
+ style="height: 100vh;"
+ @rendered="renderedHandler"
+ @error="errorHandler"
+ />
+ </div>
+
+ <!-- 鍘嬬缉鏂囦欢澶勭悊 -->
+ <div v-if="isZipOrRar">
+ <p>鍘嬬缉鏂囦欢鏃犳硶鐩存帴棰勮锛岃涓嬭浇鏌ョ湅銆�</p>
+ <a :href="fileUrl">涓嬭浇鏂囦欢</a>
+ </div>
+
+ <!-- 涓嶆敮鎸佺殑鏍煎紡 -->
+ <div v-if="!isSupported">
+ <p>涓嶆敮鎸佺殑鏂囦欢鏍煎紡</p>
+ </div>
+ </div>
+ </el-dialog>
+</template>
+
+<script setup>
+import { ref, computed, getCurrentInstance, watch } from 'vue';
+import VueOfficeDocx from '@vue-office/docx';
+import '@vue-office/docx/lib/index.css';
+import VueOfficeExcel from '@vue-office/excel';
+import '@vue-office/excel/lib/index.css';
+
+// 鍝嶅簲寮忓彉閲�
+const fileUrl = ref('')
+const dialogVisible = ref(false)
+const { proxy } = getCurrentInstance();
+const javaApi = proxy.javaApi;
+
+// 鏂囨。棰勮鐘舵��
+const isDocShow = ref(true);
+const imgUrl = ref('');
+const options = ref({
+ xls: false,
+ minColLength: 0,
+ minRowLength: 0,
+ widthOffset: 10,
+ heightOffset: 10,
+ beforeTransformData: (workbookData) => workbookData,
+ transformData: (workbookData) => workbookData,
+});
+
+// 璁$畻灞炴�� - 鍒ゆ柇鏂囦欢绫诲瀷
+const isImage = computed(() => {
+ const state = /\.(jpg|jpeg|png|gif)$/i.test(fileUrl.value);
+ if (state) {
+ imgUrl.value = fileUrl.value.replaceAll('word', 'img');
+ }
+ return state;
+});
+
+const isPdf = computed(() => {
+ console.log(fileUrl.value)
+ return /\.pdf$/i.test(fileUrl.value);
+});
+
+const isDoc = computed(() => {
+ return /\.(doc|docx)$/i.test(fileUrl.value);
+});
+
+const isXls = computed(() => {
+ const state = /\.(xls|xlsx)$/i.test(fileUrl.value);
+ if (state) {
+ options.value.xls = /\.(xls)$/i.test(fileUrl.value);
+ }
+ return state;
+});
+
+const isZipOrRar = computed(() => {
+ return /\.(zip|rar)$/i.test(fileUrl.value);
+});
+
+const isSupported = computed(() => {
+ return isImage.value || isPdf.value || isDoc.value || isXls.value || isZipOrRar.value;
+});
+
+// 鍔ㄦ�佸垱寤篴鏍囩骞惰烦杞瑙圥DF
+const previewPdf = (url) => {
+ // 鍒涘缓a鏍囩
+ const link = document.createElement('a');
+ // 璁剧疆PDF鏂囦欢URL
+ link.href = url;
+ // 鍦ㄦ柊鏍囩椤垫墦寮�
+ link.target = '_blank';
+ // 瀹夊叏灞炴�э紝闃叉鏂伴〉闈㈣闂師椤甸潰
+ link.rel = 'noopener noreferrer';
+ // 鍙�夛細璁剧疆閾炬帴鏂囨湰
+ link.textContent = '棰勮PDF';
+ // 灏哸鏍囩娣诲姞鍒伴〉闈紙閮ㄥ垎娴忚鍣ㄨ姹傚繀椤诲湪DOM涓級
+ document.body.appendChild(link);
+ // 瑙﹀彂鐐瑰嚮浜嬩欢
+ link.click();
+ // 绉婚櫎a鏍囩锛屾竻鐞咲OM
+ document.body.removeChild(link);
+};
+
+
+// 鐩戝惉PDF鐘舵�佸彉鍖栵紝鑷姩瑙﹀彂璺宠浆
+watch(
+ () => isPdf.value,
+ (newVal) => {
+
+ // 褰撶‘璁ゆ槸PDF涓旀枃浠禪RL鏈夋晥鏃�
+ if (newVal && fileUrl.value) {
+ // 鍏抽棴瀵硅瘽妗�
+ dialogVisible.value = false;
+ // 鍔犱釜灏忓欢杩熺‘淇濈姸鎬佹洿鏂板畬鎴�
+ setTimeout(() => {
+ previewPdf(fileUrl.value);
+ fileUrl.value = '';
+ }, 100);
+ }
+ }
+);
+
+// 鏂规硶瀹氫箟
+const renderedHandler = () => {
+ console.log("娓叉煋瀹屾垚");
+ isDocShow.value = true;
+ resetStyle();
+};
+
+const errorHandler = () => {
+ console.log("娓叉煋澶辫触");
+ isDocShow.value = false;
+};
+
+const open = (url) => {
+ fileUrl.value = window.location.protocol+'//'+window.location.host+ url;
+ dialogVisible.value = true;
+};
+const handleClose = () => {
+ dialogVisible.value = false;
+};
+
+const resetStyle = () => {
+ const elements = document.querySelectorAll('[style*="pt"]');
+ for (const element of elements) {
+ const style = element.getAttribute('style');
+ if (style) {
+ element.setAttribute('style', style.replace(/pt/g, 'px'));
+ }
+ }
+};
+
+// 鏆撮湶open鏂规硶渚涘閮ㄨ皟鐢�
+defineExpose({
+ open
+})
+</script>
+
+<style scoped>
+img {
+ max-width: 100%;
+ display: block;
+ margin: 0 auto;
+}
+
+.oneLine {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+</style>
diff --git a/src/main.js b/src/main.js
index 48ee15c..014954c 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,68 +1,81 @@
-import { createApp } from 'vue'
+import { createApp } from "vue";
-import Cookies from 'js-cookie'
+import Cookies from "js-cookie";
-import ElementPlus from 'element-plus'
-import 'element-plus/dist/index.css'
-import 'element-plus/theme-chalk/dark/css-vars.css'
-import locale from 'element-plus/es/locale/lang/zh-cn'
+import ElementPlus from "element-plus";
+import "element-plus/dist/index.css";
+import "element-plus/theme-chalk/dark/css-vars.css";
+import locale from "element-plus/es/locale/lang/zh-cn";
-import '@/assets/styles/index.scss' // global css
+import "@/assets/styles/index.scss"; // global css
-import App from './App'
-import store from './store'
-import router from './router'
-import directive from './directive' // directive
+import App from "./App";
+import store from "./store";
+import router from "./router";
+import directive from "./directive"; // directive
// 娉ㄥ唽鎸囦护
-import plugins from './plugins' // plugins
-import { download } from '@/utils/request'
+import plugins from "./plugins"; // plugins
+import { download } from "@/utils/request";
// svg鍥炬爣
-import 'virtual:svg-icons-register'
-import SvgIcon from '@/components/SvgIcon'
-import elementIcons from '@/components/SvgIcon/svgicon'
+import "virtual:svg-icons-register";
+import SvgIcon from "@/components/SvgIcon";
+import elementIcons from "@/components/SvgIcon/svgicon";
-import './permission' // permission control
+import "./permission"; // permission control
-import { useDict } from '@/utils/dict'
-import { parseTime, resetForm, addDateRange, handleTree, selectDictLabel, selectDictLabels } from '@/utils/ruoyi'
+import { useDict } from "@/utils/dict";
+import {
+ parseTime,
+ resetForm,
+ addDateRange,
+ handleTree,
+ selectDictLabel,
+ selectDictLabels,
+} from "@/utils/ruoyi";
// 鍒嗛〉缁勪欢
-import Pagination from '@/components/Pagination'
+import Pagination from "@/components/Pagination";
// 鑷畾涔夎〃鏍煎伐鍏风粍浠�
-import RightToolbar from '@/components/RightToolbar'
+import RightToolbar from "@/components/RightToolbar";
// 瀵屾枃鏈粍浠�
-import Editor from "@/components/Editor"
+import Editor from "@/components/Editor";
// 鏂囦欢涓婁紶缁勪欢
-import FileUpload from "@/components/FileUpload"
+import FileUpload from "@/components/FileUpload";
// 鍥剧墖涓婁紶缁勪欢
-import ImageUpload from "@/components/ImageUpload"
+import ImageUpload from "@/components/ImageUpload";
// 鍥剧墖棰勮缁勪欢
-import ImagePreview from "@/components/ImagePreview"
+import ImagePreview from "@/components/ImagePreview";
// 瀛楀吀鏍囩缁勪欢
-import DictTag from '@/components/DictTag'
+import DictTag from "@/components/DictTag";
// 琛ㄦ牸缁勪欢
import PIMTable from "@/components/PIMTable/PIMTable.vue";
import { getToken } from "@/utils/auth";
-import {calculateTaxExclusiveTotalPrice, summarizeTable,calculateTaxIncludeTotalPrice} from "@/utils/summarizeTable.js";
+import {
+ calculateTaxExclusiveTotalPrice,
+ summarizeTable,
+ calculateTaxIncludeTotalPrice,
+} from "@/utils/summarizeTable.js";
-const app = createApp(App)
+const app = createApp(App);
// 鍏ㄥ眬鏂规硶鎸傝浇
-app.config.globalProperties.useDict = useDict
-app.config.globalProperties.download = download
-app.config.globalProperties.parseTime = parseTime
-app.config.globalProperties.resetForm = resetForm
-app.config.globalProperties.summarizeTable = summarizeTable
-app.config.globalProperties.calculateTaxExclusiveTotalPrice = calculateTaxExclusiveTotalPrice
-app.config.globalProperties.calculateTaxIncludeTotalPrice = calculateTaxIncludeTotalPrice
-app.config.globalProperties.handleTree = handleTree
-app.config.globalProperties.addDateRange = addDateRange
-app.config.globalProperties.selectDictLabel = selectDictLabel
-app.config.globalProperties.selectDictLabels = selectDictLabels
-app.config.globalProperties.javaApi = 'http://114.132.189.42:8078'
+app.config.globalProperties.useDict = useDict;
+app.config.globalProperties.download = download;
+app.config.globalProperties.parseTime = parseTime;
+app.config.globalProperties.resetForm = resetForm;
+app.config.globalProperties.summarizeTable = summarizeTable;
+app.config.globalProperties.calculateTaxExclusiveTotalPrice =
+ calculateTaxExclusiveTotalPrice;
+app.config.globalProperties.calculateTaxIncludeTotalPrice =
+ calculateTaxIncludeTotalPrice;
+app.config.globalProperties.handleTree = handleTree;
+app.config.globalProperties.addDateRange = addDateRange;
+app.config.globalProperties.selectDictLabel = selectDictLabel;
+app.config.globalProperties.selectDictLabels = selectDictLabels;
+app.config.globalProperties.javaApi = "http://114.132.189.42:8099";
app.config.globalProperties.HaveJson = (val) => {
return JSON.parse(JSON.stringify(val));
};
@@ -71,29 +84,29 @@
};
// 鍏ㄥ眬缁勪欢鎸傝浇
-app.component('DictTag', DictTag)
-app.component('Pagination', Pagination)
-app.component('FileUpload', FileUpload)
-app.component('ImageUpload', ImageUpload)
-app.component('ImagePreview', ImagePreview)
-app.component('RightToolbar', RightToolbar)
-app.component('Editor', Editor)
-app.component('PIMTable', PIMTable)
+app.component("DictTag", DictTag);
+app.component("Pagination", Pagination);
+app.component("FileUpload", FileUpload);
+app.component("ImageUpload", ImageUpload);
+app.component("ImagePreview", ImagePreview);
+app.component("RightToolbar", RightToolbar);
+app.component("Editor", Editor);
+app.component("PIMTable", PIMTable);
-app.use(router)
-app.use(store)
-app.use(plugins)
-app.use(elementIcons)
-app.component('svg-icon', SvgIcon)
+app.use(router);
+app.use(store);
+app.use(plugins);
+app.use(elementIcons);
+app.component("svg-icon", SvgIcon);
-directive(app)
+directive(app);
// 浣跨敤element-plus 骞朵笖璁剧疆鍏ㄥ眬鐨勫ぇ灏�
app.use(ElementPlus, {
locale: locale,
// 鏀寔 large銆乨efault銆乻mall
- size: Cookies.get('size') || 'default'
-})
-app._context.components.ElDialog.props.closeOnClickModal.default = false
+ size: Cookies.get("size") || "default",
+});
+app._context.components.ElDialog.props.closeOnClickModal.default = false;
-app.mount('#app')
+app.mount("#app");
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
new file mode 100644
index 0000000..0c6cbde
--- /dev/null
+++ 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/financialStatements/index.vue b/src/views/financialManagement/financialStatements/index.vue
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/views/financialManagement/financialStatements/index.vue
diff --git a/src/views/financialManagement/revenueManagement/Form.vue b/src/views/financialManagement/revenueManagement/Form.vue
new file mode 100644
index 0000000..67b175e
--- /dev/null
+++ b/src/views/financialManagement/revenueManagement/Form.vue
@@ -0,0 +1,123 @@
+<template>
+ <el-form :model="form" label-width="100px" :rules="formRules" ref="formRef">
+ <el-form-item label="鏀跺叆鏃ユ湡" prop="incomeDate">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.incomeDate"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨鏃ユ湡"
+ clearable
+ />
+ </el-form-item>
+ <el-form-item label="鏀跺叆绫诲瀷" prop="incomeType">
+ <el-select
+ v-model="form.incomeType"
+ placeholder="璇烽�夋嫨"
+ clearable
+ >
+ <el-option :label="item.label" :value="item.value" v-for="(item,index) in income_types" :key="index" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="瀹㈡埛鍚嶇О" prop="customerName">
+ <el-input v-model="form.customerName" placeholder="璇疯緭鍏�" />
+ </el-form-item>
+ <el-form-item label="鏀跺叆閲戦" prop="incomeMoney">
+ <el-input-number :step="0.01" :min="0" style="width: 100%"
+ v-model="form.incomeMoney"
+ placeholder="璇疯緭鍏�"
+ />
+ </el-form-item>
+ <el-form-item label="鏀跺叆鎻忚堪" prop="incomeDescribed">
+ <el-input v-model="form.incomeDescribed" placeholder="璇疯緭鍏�" />
+ </el-form-item>
+ <el-form-item label="鏀舵鏂瑰紡" prop="incomeMethod">
+ <el-select
+ v-model="form.incomeMethod"
+ placeholder="璇烽�夋嫨"
+ clearable
+ >
+ <el-option :label="item.label" :value="item.value" v-for="(item,index) in payment_methods" :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 { getAccountIncome } from "@/api/financialManagement/revenueManagement";
+import {ref} from "vue";
+const { proxy } = getCurrentInstance();
+
+
+defineOptions({
+ name: "鏂板鏀跺叆",
+});
+const { income_types } = proxy.useDict("income_types");
+const { payment_methods } = proxy.useDict("payment_methods");
+const formRef = ref(null);
+const formRules = {
+ customerName: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
+ incomeMoney: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
+ incomeDescribed: [{ required: true, trigger: "blur", message: "璇疯緭鍏�" }],
+ incomeDate: [{ required: true, trigger: "change", message: "璇烽�夋嫨" }],
+ incomeType: [{ required: true, trigger: "change", message: "璇烽�夋嫨" }],
+ incomeMethod: [{ required: true, trigger: "change", message: "璇烽�夋嫨" }],
+}
+
+const { form, resetForm } = useFormData({
+ incomeDate: undefined, // 鏀跺叆鏃ユ湡
+ incomeType: undefined, // 鏀跺叆绫诲瀷
+ customerName: undefined, // 瀹㈡埛鍚嶇О
+ incomeMoney: undefined, // 鏀跺叆閲戦
+ incomeDescribed: undefined, // 鏀跺叆鎻忚堪
+ incomeMethod: undefined, // 鏀舵鏂瑰紡
+ invoiceNumber: undefined, // 鍙戠エ鍙风爜
+ note: undefined, // 澶囨敞
+});
+
+const loadForm = async (id) => {
+ const { code, data } = await getAccountIncome(id);
+ if (code == 200) {
+ form.incomeDate = data.incomeDate;
+ form.incomeType = data.incomeType;
+ form.customerName = data.customerName;
+ form.incomeMoney = data.incomeMoney;
+ form.incomeDescribed = data.incomeDescribed;
+ form.incomeMethod = data.incomeMethod;
+ 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/revenueManagement/Modal.vue b/src/views/financialManagement/revenueManagement/Modal.vue
new file mode 100644
index 0000000..480b4fd
--- /dev/null
+++ b/src/views/financialManagement/revenueManagement/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/revenueManagement";
+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/revenueManagement/filesDia.vue b/src/views/financialManagement/revenueManagement/filesDia.vue
new file mode 100644
index 0000000..f752496
--- /dev/null
+++ b/src/views/financialManagement/revenueManagement/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/financialManagement/revenueManagement/index.vue b/src/views/financialManagement/revenueManagement/index.vue
new file mode 100644
index 0000000..984d9de
--- /dev/null
+++ b/src/views/financialManagement/revenueManagement/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.incomeMethod"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 200px;"
+ >
+ <el-option
+ v-for="item in payment_methods"
+ :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, delAccountIncome } from "@/api/financialManagement/revenueManagement";
+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";
+
+defineOptions({
+ name: "鏀跺叆绠$悊",
+});
+
+// 琛ㄦ牸澶氶�夋閫変腑椤�
+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: "incomeDate",
+ },
+ {
+ label: "鏀跺叆绫诲瀷",
+ align: "center",
+ prop: "incomeType",
+ dataType: "tag",
+ formatData: (params) => {
+ if (income_types.value.find((m) => m.value == params)) {
+ return income_types.value.find((m) => m.value == params).label;
+ } else {
+ return null
+ }
+ },
+ },
+ {
+ label: "瀹㈡埛鍚嶇О",
+ align: "center",
+ prop: "customerName",
+
+ },
+ {
+ label: "鏀跺叆閲戦",
+ align: "center",
+ prop: "incomeMoney",
+
+ },
+ {
+ label: "鏀跺叆鎻忚堪",
+ align: "center",
+ prop: "incomeDescribed",
+
+ },
+ {
+ label: "鏀舵鏂瑰紡",
+ align: "center",
+ prop: "incomeMethod",
+ dataType: "tag",
+ formatData: (params) => {
+ if (payment_methods.value.find((m) => m.value == params)) {
+ return payment_methods.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 delAccountIncome(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/accountIncome/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/salesManagement/salesLedger/fileList.vue b/src/views/salesManagement/salesLedger/fileList.vue
index d1c0cdd..da37db2 100644
--- a/src/views/salesManagement/salesLedger/fileList.vue
+++ b/src/views/salesManagement/salesLedger/fileList.vue
@@ -1,22 +1,26 @@
<template>
- <el-dialog v-model="dialogVisible" title="闄勪欢" width="30%" :before-close="handleClose">
+ <el-dialog v-model="dialogVisible" title="闄勪欢" width="40%" :before-close="handleClose">
<el-table :data="tableData" border height="40vh">
<el-table-column label="闄勪欢鍚嶇О" prop="name" min-width="400" show-overflow-tooltip />
<el-table-column fixed="right" label="鎿嶄綔" width="100" align="center">
<template #default="scope">
<el-button link type="primary" size="small" @click="downLoadFile(scope.row)">涓嬭浇</el-button>
+ <el-button link type="primary" size="small" @click="lookFile(scope.row)">棰勮</el-button>
</template>
</el-table-column>
</el-table>
</el-dialog>
+ <filePreview ref="filePreviewRef" />
</template>
<script setup>
import { ref } from 'vue'
+import filePreview from '@/components/filePreview/index.vue'
const dialogVisible = ref(false)
const tableData = ref([])
const { proxy } = getCurrentInstance();
+const filePreviewRef = ref()
const handleClose = () => {
dialogVisible.value = false
}
@@ -28,6 +32,9 @@
proxy.$download.name(row.url);
}
+const lookFile = (row) => {
+ filePreviewRef.value.open(row.url)
+}
defineExpose({
open
})
--
Gitblit v1.9.3