From 845b15a472449bc8f2632ea80f339da15c3b6356 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期三, 08 四月 2026 10:54:27 +0800
Subject: [PATCH] fix: 不在销售台账处出库。在发货台账处导入excel,匹配客户进行出库。销售台账处的产品列表需要展示已发货/未发货数量。
---
src/views/index.vue | 2044 ++++++------
src/views/procurementManagement/procurementLedger/index.vue | 670 ++-
src/views/basicData/supplierManage/index.vue | 63
src/views/basicData/customerFile/index.vue | 71
src/views/productionManagement/productionReporting/index.vue | 15
src/views/productionManagement/productionCosting/index.vue | 692 ++--
src/views/productionManagement/productionOrder/index.vue | 140
src/views/salesManagement/receiptPaymentLedger/index.vue | 14
src/views/salesManagement/salesLedger/index.vue | 5107 +++++++++++++++++-------------
src/api/salesManagement/deliveryLedger.js | 9
src/views/basicData/supplierManage/components/HomeTab.vue | 948 ++--
11 files changed, 5,377 insertions(+), 4,396 deletions(-)
diff --git a/src/api/salesManagement/deliveryLedger.js b/src/api/salesManagement/deliveryLedger.js
index 58e84b0..88449c3 100644
--- a/src/api/salesManagement/deliveryLedger.js
+++ b/src/api/salesManagement/deliveryLedger.js
@@ -27,3 +27,12 @@
data: query,
});
}
+
+// 鍏煎鏃ч〉闈紙閿�鍞彴璐︼級鍙戣揣鎺ュ彛
+export function addShippingInfo(data) {
+ return request({
+ url: "/shippingInfo/add",
+ method: "post",
+ data,
+ });
+}
diff --git a/src/views/basicData/customerFile/index.vue b/src/views/basicData/customerFile/index.vue
index 79b1616..25ccc14 100644
--- a/src/views/basicData/customerFile/index.vue
+++ b/src/views/basicData/customerFile/index.vue
@@ -15,10 +15,10 @@
style="width: 240px"
clearable
@change="handleQuery">
- <el-option label="闆跺敭瀹㈡埛"
- value="闆跺敭瀹㈡埛" />
- <el-option label="杩涢攢鍟嗗鎴�"
- value="杩涢攢鍟嗗鎴�" />
+ <el-option label="瀵瑰叕"
+ value="1" />
+ <el-option label="瀵圭"
+ value="2" />
</el-select>
<el-button type="primary"
@click="handleQuery"
@@ -125,10 +125,10 @@
<el-select v-model="form.customerType"
placeholder="璇烽�夋嫨"
clearable>
- <el-option label="闆跺敭瀹㈡埛"
- value="闆跺敭瀹㈡埛" />
- <el-option label="杩涢攢鍟嗗鎴�"
- value="杩涢攢鍟嗗鎴�" />
+ <el-option label="瀵瑰叕"
+ :value="1" />
+ <el-option label="瀵圭"
+ :value="2" />
</el-select>
</el-form-item>
</el-col>
@@ -276,7 +276,8 @@
</el-form>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary" @click="submitReminderForm">纭</el-button>
+ <el-button type="primary"
+ @click="submitReminderForm">纭</el-button>
<el-button @click="closeReminderDialog">鍙栨秷</el-button>
</div>
</template>
@@ -359,7 +360,8 @@
</el-form>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary" @click="submitNegotiationForm">纭</el-button>
+ <el-button type="primary"
+ @click="submitNegotiationForm">纭</el-button>
<el-button @click="closeNegotiationDialog">鍙栨秷</el-button>
</div>
</template>
@@ -383,7 +385,7 @@
<el-col :span="12">
<div class="info-item">
<span class="info-label">瀹㈡埛鍒嗙被锛�</span>
- <span class="info-value">{{ detailForm.customerType }}</span>
+ <span class="info-value">{{ detailForm.customerType==1?"瀵瑰叕":"瀵圭" }}</span>
</div>
</el-col>
</el-row>
@@ -713,6 +715,9 @@
label: "瀹㈡埛鍒嗙被",
prop: "customerType",
width: 120,
+ formatData: params => {
+ return params == 1 ? "瀵瑰叕" : "瀵圭";
+ },
},
{
label: "瀹㈡埛鍚嶇О",
@@ -786,13 +791,13 @@
openForm("edit", row);
},
},
- {
- name: "娣诲姞娲借皥杩涘害",
- type: "text",
- clickFun: row => {
- openNegotiationDialog(row);
- },
- },
+ {
+ name: "娣诲姞娲借皥杩涘害",
+ type: "text",
+ clickFun: row => {
+ openNegotiationDialog(row);
+ },
+ },
{
name: "鍥炶鎻愰啋",
type: "text",
@@ -800,13 +805,13 @@
openReminderDialog(row);
},
},
- {
- name: "璇︽儏",
- type: "text",
- clickFun: row => {
- openDetailDialog(row);
- },
- },
+ {
+ name: "璇︽儏",
+ type: "text",
+ clickFun: row => {
+ openDetailDialog(row);
+ },
+ },
],
},
]);
@@ -854,20 +859,20 @@
},
rules: {
customerName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- taxpayerIdentificationNumber: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- companyAddress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- companyPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ // taxpayerIdentificationNumber: [
+ // { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ // ],
+ // companyAddress: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ // companyPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
// contactPerson: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
// contactPhone: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
maintainer: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
maintenanceTime: [
{ required: false, message: "璇烽�夋嫨", trigger: "change" },
],
- basicBankAccount: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- bankAccount: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- bankCode: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ // basicBankAccount: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ // bankAccount: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ // bankCode: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
customerType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
},
});
diff --git a/src/views/basicData/supplierManage/components/HomeTab.vue b/src/views/basicData/supplierManage/components/HomeTab.vue
index 85c3265..4ba1645 100644
--- a/src/views/basicData/supplierManage/components/HomeTab.vue
+++ b/src/views/basicData/supplierManage/components/HomeTab.vue
@@ -3,185 +3,172 @@
<div class="search_form">
<div>
<span class="search_title">渚涘簲鍟嗘。妗堬細</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
- >
+ <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 type="primary" @click="openForm('add')"
- >鏂板渚涘簲鍟�</el-button
- >
+ <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>
+ <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>
+ <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-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 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 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 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 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 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 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 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 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-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 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-form-item label="渚涘簲鍟嗙被鍨嬶細"
+ prop="supplierType">
+ <el-select v-model="form.supplierType"
+ placeholder="璇烽�夋嫨"
+ clearable>
+ <el-option label="瀵瑰叕"
+ :value="1" />
+ <el-option label="瀵圭"
+ :value="2" />
</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-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>
@@ -189,50 +176,44 @@
</el-form>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary" @click="submitForm">纭</el-button>
+ <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-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
- >
+ <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 type="primary"
+ @click="submitFileForm">纭� 瀹�</el-button>
<el-button @click="upload.open = false">鍙� 娑�</el-button>
</div>
</template>
@@ -242,349 +223,364 @@
</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";
-import FilesDia from "../filesDia.vue";
-const { proxy } = getCurrentInstance();
-const userStore = useUserStore();
+ 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";
+ import FilesDia from "../filesDia.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);
- },
+ const tableColumn = ref([
+ {
+ label: "渚涘簲鍟嗗悕绉�",
+ prop: "supplierName",
+ width: 250,
+ },
+ {
+ label: "渚涘簲鍟嗙被鍨�",
+ prop: "supplierType",
+ width: 120,
+ formatData: params => {
+ return params == 1 ? "瀵瑰叕" : "瀵圭";
},
- {
- //璧勮川闄勪欢
- name: "璧勮川鏂囦欢",
- type: "text",
- clickFun: (row) => {
- openFilesFormDia(row)
+ },
+ {
+ 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 => {
+ openFilesFormDia(row);
+ },
+ },
+ ],
+ },
+ ]);
+ const tableData = ref([]);
+ const selectedRows = ref([]);
+ const userList = ref([]);
+ const tableLoading = ref(false);
+ const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+ });
+ const filesDia = 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: 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 tableData = ref([]);
-const selectedRows = ref([]);
-const userList = ref([]);
-const tableLoading = ref(false);
-const page = reactive({
- current: 1,
- size: 100,
- total: 0,
-});
-const filesDia = 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: 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",
- })
+ };
+ // 鎻愪氦鏂板
+ 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 }, "渚涘簲鍟嗘。妗�.xlsx");
+ proxy.download(
+ "/system/supplier/export",
+ { isWhite: 0 },
+ "渚涘簲鍟嗘。妗�.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("涓嶅彲鍒犻櫎浠栦汉缁存姢鐨勬暟鎹�");
+ };
+ // 鍒犻櫎
+ 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;
}
- ids = selectedRows.value.map((item) => item.id);
- } else {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
tableLoading.value = true;
delSupplier(ids)
- .then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- })
- .finally(() => {
- tableLoading.value = false;
- });
+ .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 openFilesFormDia = (row) => {
- nextTick(() => {
- filesDia.value?.openDialog(row)
- })
-};
+ // 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� 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 openFilesFormDia = row => {
+ nextTick(() => {
+ filesDia.value?.openDialog(row);
+ });
+ };
-onMounted(() => {
- getList();
-});
+ onMounted(() => {
+ getList();
+ });
-defineExpose({
- getList,
-});
+ defineExpose({
+ getList,
+ });
</script>
diff --git a/src/views/basicData/supplierManage/index.vue b/src/views/basicData/supplierManage/index.vue
index d87a45b..0d4f1a0 100644
--- a/src/views/basicData/supplierManage/index.vue
+++ b/src/views/basicData/supplierManage/index.vue
@@ -1,11 +1,14 @@
<!-- 鍦ㄤ綘鐨勪富椤甸潰涓� -->
<template>
<div class="app-container">
- <el-tabs v-model="activeTab" @tab-change="handleTabChange">
- <el-tab-pane label="姝e父渚涘簲鍟�" name="home">
+ <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">
+ <el-tab-pane label="榛戝悕鍗�"
+ name="blacklist">
<BlacklistTab ref="blacklistTab" />
</el-tab-pane>
</el-tabs>
@@ -13,31 +16,35 @@
</template>
<script>
-import HomeTab from './components/HomeTab.vue'
-import BlacklistTab from './components/BlacklistTab.vue'
+ 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()
- }
- })
+ 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/index.vue b/src/views/index.vue
index 4ae5fe4..2535fe1 100644
--- a/src/views/index.vue
+++ b/src/views/index.vue
@@ -9,14 +9,15 @@
<div class="welcome-banner">
<div class="welcome-title">
<span class="welcome-user">{{ userStore.roleName || '绯荤粺绠$悊鍛�' }}</span>
- <span> 鎮ㄥソ锛佺鎮ㄥ紑蹇冩瘡涓�澶�</span>
+ <span> 鎮ㄥソ锛侊紒绁濇偍寮�蹇冩瘡涓�澶�</span>
</div>
<div class="welcome-time">鐧诲綍浜�: {{ userStore.currentLoginTime }}</div>
</div>
-
<!-- 鐢ㄦ埛淇℃伅鍗$墖 -->
<div class="user-card">
- <img :src="userStore.avatar" class="avatar" alt="" />
+ <img :src="userStore.avatar"
+ class="avatar"
+ alt="" />
<div class="user-card-main">
<div class="user-name">{{ userStore.name }}</div>
<div class="user-role">{{ userStore.roleName }}</div>
@@ -44,7 +45,6 @@
<div class="data-value">{{ businessInfo.monthSaleHaveMoney }}</div>
</div>
</div>
-
</div>
<div class="data-card purchase">
<div class="data-title">閲囪喘鏁版嵁</div>
@@ -76,8 +76,10 @@
<!-- 鍙筹細寰呭姙浜嬮」 -->
<div class="todo-panel">
<div class="section-title">寰呭姙浜嬮」</div>
- <ul class="todo-list" v-if="todoList.length > 0">
- <li v-for="item in todoList" :key="item.id">
+ <ul class="todo-list"
+ v-if="todoList.length > 0">
+ <li v-for="item in todoList"
+ :key="item.id">
<div style="display: flex;flex-direction: column;justify-content: space-between;width: 100%;gap: 20px">
<div style="display: flex;justify-content: space-between;align-items: center;">
<div class="todo-title">寰呭姙缂栧彿锛歿{ item.approveId }}</div>
@@ -88,7 +90,8 @@
</div>
</li>
</ul>
- <div v-else style="text-align: center">
+ <div v-else
+ style="text-align: center">
鏆傛棤鏁版嵁
</div>
</div>
@@ -98,23 +101,36 @@
<div class="process-panel__header">
<div class="section-title">宸ュ簭鏁版嵁鐢熶骇缁熻鏄庣粏</div>
<div style="display: flex; gap: 10px; align-items: center;">
- <el-button type="primary" size="small" plain icon="Filter" @click="openProcessDialog">閫夋嫨宸ュ簭</el-button>
- <el-button type="info" size="small" plain icon="Refresh" @click="resetProcessFilter">閲嶇疆</el-button>
- <el-radio-group v-model="processRange" size="small" @change="refreshProcessStats">
+ <el-button type="primary"
+ size="small"
+ plain
+ icon="Filter"
+ @click="openProcessDialog">閫夋嫨宸ュ簭</el-button>
+ <el-button type="info"
+ size="small"
+ plain
+ icon="Refresh"
+ @click="resetProcessFilter">閲嶇疆</el-button>
+ <el-radio-group v-model="processRange"
+ size="small"
+ @change="refreshProcessStats">
<el-radio-button :value="1">鏃�</el-radio-button>
<el-radio-button :value="2">鍛�</el-radio-button>
<el-radio-button :value="3">鏈�</el-radio-button>
</el-radio-group>
</div>
</div>
-
<div class="process-panel__body">
<div class="process-panel__chart">
- <Echarts :chartStyle="{ width: '100%', height: '100%' }" :grid="processGrid" :series="processSeries"
- :tooltip="processTooltip" :xAxis="processXAxis" :yAxis="processYAxis" style="height: 100%"
- @click="handleChartClick" />
+ <Echarts :chartStyle="{ width: '100%', height: '100%' }"
+ :grid="processGrid"
+ :series="processSeries"
+ :tooltip="processTooltip"
+ :xAxis="processXAxis"
+ :yAxis="processYAxis"
+ style="height: 100%"
+ @click="handleChartClick" />
</div>
-
<div class="process-panel__aside">
<div class="process-legend">
<div class="process-legend__item">
@@ -127,9 +143,7 @@
<span class="dot dot-teal"></span><span>浜у嚭閲�</span>
</div>
</div>
-
<div class="process-card process-card--name">{{ processAside.processName }}</div>
-
<div class="process-card">
<div class="process-card__label">绱鎬绘姇鍏�</div>
<div class="process-card__value">{{ formatAmount(processAside.totalInput) }}
@@ -149,13 +163,18 @@
</div>
</div>
</div>
-
<!-- 宸ュ簭閫夋嫨寮圭獥 -->
- <el-dialog v-model="processDialogVisible" title="閫夋嫨宸ュ簭" width="500px" append-to-body>
+ <el-dialog v-model="processDialogVisible"
+ title="閫夋嫨宸ュ簭"
+ width="500px"
+ append-to-body>
<div class="process-selection-wrapper">
<el-checkbox-group v-model="tempProcessIds">
<div class="process-grid">
- <el-checkbox v-for="item in processOptions" :key="item.id" :label="item.id" border>
+ <el-checkbox v-for="item in processOptions"
+ :key="item.id"
+ :label="item.id"
+ border>
{{ item.name }}
</el-checkbox>
</div>
@@ -164,7 +183,8 @@
<template #footer>
<span class="dialog-footer">
<el-button @click="processDialogVisible = false">鍙栨秷</el-button>
- <el-button type="primary" @click="handleProcessDialogConfirm">纭</el-button>
+ <el-button type="primary"
+ @click="handleProcessDialogConfirm">纭</el-button>
</span>
</template>
</el-dialog>
@@ -174,7 +194,9 @@
<div class="section-title">瀹㈡埛鍚堝悓閲戦鍒嗘瀽</div>
<div class="contract-summary">
<div class="contract-info">
- <img src="../assets/images/khtitle.png" alt="" style="width: 42px" />
+ <img src="../assets/images/khtitle.png"
+ alt=""
+ style="width: 42px" />
<div class="contract-card">
<div class="contract-name">鎬诲悎鍚岄噾棰�(鍏�)</div>
<div class="contract-meta">
@@ -184,16 +206,20 @@
</div>
</div>
</div>
- <div
- style="display: flex;align-items: center;gap: 20px;justify-content: space-evenly;height: 180px;margin-top: 20px">
+ <div style="display: flex;align-items: center;gap: 20px;justify-content: space-evenly;height: 180px;margin-top: 20px">
<div>
- <Echarts ref="chart" :legend="pieLegend" :chartStyle="chartStylePie" :series="materialPieSeries"
- :tooltip="pieTooltip"></Echarts>
+ <Echarts ref="chart"
+ :legend="pieLegend"
+ :chartStyle="chartStylePie"
+ :series="materialPieSeries"
+ :tooltip="pieTooltip"></Echarts>
</div>
<ul class="contract-list">
- <li v-for="item in materialPieSeries[0].data" :key="item.name">
+ <li v-for="item in materialPieSeries[0].data"
+ :key="item.name">
<div style="display: flex;align-items: center;justify-content: space-between;width: 100%">
- <div class="line" :style="{ color: item.itemStyle.color }">鈼弡{ item.name }}</div>
+ <div class="line"
+ :style="{ color: item.itemStyle.color }">鈼弡{ item.name }}</div>
<div style="width: 70px">{{ item.rate }}%</div>
<div>锟{ item.value }}</div>
</div>
@@ -210,17 +236,26 @@
<!-- <el-radio-button label="鎸夊搴�" :value="3" />-->
<!-- </el-radio-group>-->
</div>
- <Echarts ref="chart" :color="barColors2" :chartStyle="chartStyle" :grid="grid" :series="barSeries"
- :tooltip="tooltip" :xAxis="xAxis" :yAxis="yAxis" style="height: 260px"></Echarts>
+ <Echarts ref="chart"
+ :color="barColors2"
+ :chartStyle="chartStyle"
+ :grid="grid"
+ :series="barSeries"
+ :tooltip="tooltip"
+ :xAxis="xAxis"
+ :yAxis="yAxis"
+ style="height: 260px"></Echarts>
</div>
</div>
-
<!-- 搴曢儴妯悜涓ゆ爮 -->
<div class="dashboard-row">
<div class="main-panel">
<div style="display: flex;justify-content: space-between;align-items: center;margin-bottom: 10px;">
- <div class="section-title" style="margin-bottom: 0;">璐ㄩ噺缁熻</div>
- <el-radio-group v-model="qualityRange" size="small" @change="qualityStatisticsInfo">
+ <div class="section-title"
+ style="margin-bottom: 0;">璐ㄩ噺缁熻</div>
+ <el-radio-group v-model="qualityRange"
+ size="small"
+ @change="qualityStatisticsInfo">
<el-radio-button :value="1">鍛�</el-radio-button>
<el-radio-button :value="2">鏈�</el-radio-button>
<el-radio-button :value="3">瀛e害</el-radio-button>
@@ -231,1033 +266,1078 @@
<div class="quality-card two">杩囩▼妫�楠屾暟閲� <span>{{ qualityStatisticsObject.processNum }}浠�</span></div>
<div class="quality-card three">鍑哄巶宸叉鏁伴噺 <span>{{ qualityStatisticsObject.factoryNum }}浠�</span></div>
</div>
- <Echarts ref="chart" :chartStyle="chartStyle" :grid="grid" :legend="barLegend" :series="barSeries1"
- :tooltip="tooltip" :xAxis="xAxis1" :yAxis="yAxis1" style="height: 260px"></Echarts>
+ <Echarts ref="chart"
+ :chartStyle="chartStyle"
+ :grid="grid"
+ :legend="barLegend"
+ :series="barSeries1"
+ :tooltip="tooltip"
+ :xAxis="xAxis1"
+ :yAxis="yAxis1"
+ style="height: 260px"></Echarts>
</div>
-
<div class="main-panel">
<div class="section-title">鍥炴涓庡紑绁ㄥ垎鏋�</div>
- <Echarts ref="invoiceChart" :chartStyle="chartStyle" :grid="grid" :legend="lineLegend" :series="lineSeries"
- :tooltip="tooltipLine" :xAxis="xAxis2" :yAxis="yAxis2" style="height: 270px;" />
+ <Echarts ref="invoiceChart"
+ :chartStyle="chartStyle"
+ :grid="grid"
+ :legend="lineLegend"
+ :series="lineSeries"
+ :tooltip="tooltipLine"
+ :xAxis="xAxis2"
+ :yAxis="yAxis2"
+ style="height: 270px;" />
</div>
</div>
</div>
</template>
<script setup>
-import { ref, onMounted, computed, reactive } from 'vue'
-import Echarts from "@/components/Echarts/echarts.vue";
-import * as echarts from 'echarts';
-import useUserStore from "@/store/modules/user.js";
-import {
- analysisCustomerContractAmounts, getAmountHalfYear,
- getBusiness,
- homeTodos,
- processDataProductionStatistics,
- statisticsReceivablePayable,
- qualityInspectionStatistics
-} from "@/api/viewIndex.js";
-import { list } from '@/api/productionManagement/productionProcess';
+ import { ref, onMounted, computed, reactive } from "vue";
+ import Echarts from "@/components/Echarts/echarts.vue";
+ import * as echarts from "echarts";
+ import useUserStore from "@/store/modules/user.js";
+ import {
+ analysisCustomerContractAmounts,
+ getAmountHalfYear,
+ getBusiness,
+ homeTodos,
+ processDataProductionStatistics,
+ statisticsReceivablePayable,
+ qualityInspectionStatistics,
+ } from "@/api/viewIndex.js";
+ import { list } from "@/api/productionManagement/productionProcess";
+ const userStore = useUserStore();
-const userStore = useUserStore()
+ const processOptions = ref([]);
+ const selectedProcessIds = ref([]);
+ const tempProcessIds = ref([]);
+ const processDialogVisible = ref(false);
+ const activeProcessIndex = ref(0);
-const processOptions = ref([])
-const selectedProcessIds = ref([])
-const tempProcessIds = ref([])
-const processDialogVisible = ref(false)
-const activeProcessIndex = ref(0)
+ const businessInfo = ref({
+ inventoryNum: 0,
+ monthPurchaseHaveMoney: 0,
+ monthPurchaseMoney: 0,
+ monthSaleHaveMoney: 0,
+ monthSaleMoney: 0,
+ todayInventoryNum: 0,
+ });
+ const qualityStatisticsObject = ref({
+ supplierNum: 0,
+ processNum: 0,
+ factoryNum: 0,
+ });
+ const sum = ref(0);
+ const yny = ref(0);
+ const chain = ref(0);
-const businessInfo = ref({
- inventoryNum: 0,
- monthPurchaseHaveMoney: 0,
- monthPurchaseMoney: 0,
- monthSaleHaveMoney: 0,
- monthSaleMoney: 0,
- todayInventoryNum: 0,
-})
-const qualityStatisticsObject = ref({
- supplierNum: 0,
- processNum: 0,
- factoryNum: 0,
-})
-const sum = ref(0)
-const yny = ref(0)
-const chain = ref(0)
-
-const pieLegend = reactive({
- show: false,
-})
-const barSeries = ref([
- {
- type: 'bar',
- data: [],
- label: {
- show: true,
- }
- },
-])
-
-const barSeries1 = ref([
- {
- name: '鍘熸潗鏂欎笉鍚堟牸鏁�',
- type: 'bar',
- barGap: 0,
- emphasis: {
- focus: 'series'
- },
- data: []
- },
- {
- name: '杩囩▼涓嶅悎鏍兼暟',
- type: 'bar',
- emphasis: {
- focus: 'series'
- },
- data: []
- },
- {
- name: '鍑哄巶涓嶅悎鏍兼暟',
- type: 'bar',
- emphasis: {
- focus: 'series'
- },
- data: []
- },
-])
-const chartStyle = {
- width: '100%',
- height: '100%' // 璁剧疆鍥捐〃瀹瑰櫒鐨勯珮搴�
-}
-const chartStylePie = {
- width: '140%',
- height: '140%' // 璁剧疆鍥捐〃瀹瑰櫒鐨勯珮搴�
-}
-const grid = {
- left: '3%',
- right: '4%',
- bottom: '3%',
- containLabel: true
-}
-const barLegend = {
- show: true,
- data: ['鍘熸潗鏂欎笉鍚堟牸鏁�', '杩囩▼涓嶅悎鏍兼暟', '鍑哄巶涓嶅悎鏍兼暟']
-}
-const barLegend1 = {
- show: true,
- data: ['棰勪粯璐︽', '搴斾粯璐︽', '棰勬敹璐︽', '搴旀敹璐︽']
-}
-const lineLegend = {
- show: true,
- data: ['寮�绁�', '鍥炴']
-}
-const tooltip = {
- trigger: 'axis',
- axisPointer: {
- type: 'shadow'
- }
-}
-const xAxis = [{
- type: 'value',
-}]
-const xAxis1 = ref([{
- type: 'category',
- axisTick: { show: false },
- data: []
-}])
-const yAxis = [{
- type: 'category',
- data: ['搴斾粯璐︽', '搴旀敹璐︽',]
-}]
-const yAxis1 = [{
- type: 'value'
-}]
-const pieTooltip = reactive({
- trigger: 'item',
- formatter: function (params) {
- // 鍔ㄦ�佺敓鎴愭彁绀轰俊鎭紝鍩轰簬鏁版嵁椤圭殑 name 灞炴��
- const description = params.name === '鏈湀鍥炴閲戦' ? '鏈湀鍥炴閲戦' : '搴旀敹娆鹃噾棰�';
- return `${description} ${formatNumber(params.value)}鍏� ${params.percent}%`;
- },
- position: 'right'
-})
-const materialPieSeries = ref([
- {
- type: 'pie',
- radius: ['66%', '90%'],
- avoidLabelOverlap: false,
- itemStyle: {
- borderColor: '#fff',
- borderWidth: 2
- },
- label: {
- show: false
- },
- data: []
- }
-])
-const lineSeries = ref([
- {
- type: 'line',
- data: [],
- label: {
- show: true
- },
- showSymbol: true, // 鏄剧ず鍦嗙偣
- },
-])
-const tooltipLine = {
- trigger: 'axis',
-}
-const yAxis2 = ref([
- {
- type: 'value',
- }
-])
-const xAxis2 = ref([
- {
- type: 'category',
- data: [],
- axisLabel: {
- interval: 0,
- formatter: function (value) {
- return value.replace(/~/g, '\n');
- },
- }
- }
-])
-
-// 寰呭姙浜嬮」
-const todoList = ref([])
-const radio1 = ref(1)
-const qualityRange = ref(1)
-
-// 鍥捐〃寮曠敤
-const barChart = ref(null)
-const lineChart = ref(null)
-const barColors2 = ['#5181DB', '#D369E0', '#F2CA6D', '#60CCA8']
-
-// 闅忔満棰滆壊鐢熸垚鍑芥暟
-const getRandomColor = () => {
- return '#' + Math.floor(Math.random() * 0xffffff).toString(16).padStart(6, '0');
-}
-
-onMounted(() => {
- getBusinessData()
- analysisCustomer()
- todoInfoS()
- statisticsReceivable()
- qualityStatisticsInfo()
- getAmountHalfYearNum()
- getProcessList()
-})
-// 鏁版嵁缁熻
-const getBusinessData = () => {
- getBusiness().then((res) => {
- businessInfo.value = { ...res.data }
- })
-}
-// 鍚堝悓閲戦
-const analysisCustomer = () => {
- analysisCustomerContractAmounts().then((res) => {
- sum.value = res.data.sum
- yny.value = res.data.yny
- chain.value = res.data.chain
- // 涓烘瘡涓暟鎹」鍒嗛厤闅忔満棰滆壊
- materialPieSeries.value[0].data = res.data.item.map(item => ({
- ...item,
- itemStyle: { color: getRandomColor() }
- }))
- })
-}
-// 寰呭姙浜嬮」
-const todoInfoS = () => {
- homeTodos().then((res) => {
- todoList.value = res.data
- })
-}
-// 鑾峰彇宸ュ簭鍒楄〃
-const getProcessList = () => {
- list().then(res => {
- processOptions.value = res.data
- })
-}
-
-const openProcessDialog = () => {
- tempProcessIds.value = [...selectedProcessIds.value]
- processDialogVisible.value = true
-}
-
-const handleProcessDialogConfirm = () => {
- selectedProcessIds.value = [...tempProcessIds.value]
- processDialogVisible.value = false
- refreshProcessStats()
-}
-
-const resetProcessFilter = () => {
- selectedProcessIds.value = []
- tempProcessIds.value = []
- refreshProcessStats()
-}
-
-const handleChartClick = (params) => {
- if (params && params.dataIndex !== undefined) {
- activeProcessIndex.value = params.dataIndex
- }
-}
-// 搴斾粯搴旀敹缁熻
-const statisticsReceivable = () => {
- statisticsReceivablePayable({ type: radio1.value }).then((res) => {
- barSeries.value[0].data = [
- // { value: res.data.prepayMoney, itemStyle: { color: barColors2[0] } },
- { value: res.data.payableMoney, itemStyle: { color: barColors2[0] } },
- // { value: res.data.advanceMoney, itemStyle: { color: barColors2[2] } },
- { value: res.data.receivableMoney, itemStyle: { color: barColors2[1] } }
- ]
- })
-}
-// 璐ㄦ缁熻
-const qualityStatisticsInfo = () => {
- qualityInspectionStatistics({ type: qualityRange.value }).then((res) => {
- xAxis1.value[0].data = []
- barSeries1.value[0].data = []
- barSeries1.value[1].data = []
- barSeries1.value[2].data = []
- res.data.item.forEach(item => {
- xAxis1.value[0].data.push(item.date)
- barSeries1.value[0].data.push(item.supplierNum)
- barSeries1.value[1].data.push(item.processNum)
- barSeries1.value[2].data.push(item.factoryNum)
- })
- qualityStatisticsObject.value.supplierNum = res.data.supplierNum
- qualityStatisticsObject.value.processNum = res.data.processNum
- qualityStatisticsObject.value.factoryNum = res.data.factoryNum
- })
-}
-const getAmountHalfYearNum = async () => {
- const res = await getAmountHalfYear()
- console.log(res)
- const monthName = []
- const receiptAmount = []
- const invoiceAmount = []
- res.data.forEach(item => {
- monthName.push(item.month)
- receiptAmount.push(item.receiptAmount)
- invoiceAmount.push(item.invoiceAmount)
- })
- // 姝g‘鍝嶅簲寮忚祴鍊硷細鍒涘缓鏂扮殑 xAxis 鍜� series 瀵硅薄
- xAxis2.value[0].data = monthName
- xAxis2.value[0].data = monthName.map(item => item.replace(/~/g, '\n~'));
- lineSeries.value = [
+ const pieLegend = reactive({
+ show: false,
+ });
+ const barSeries = ref([
{
- name: '寮�绁�',
- type: 'line',
- data: invoiceAmount,
- stack: 'Total',
- areaStyle: {
- color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
- {
- offset: 0,
- color: 'rgba(131, 207, 255, 1)'
- },
- {
- offset: 1,
- color: 'rgba(186, 228, 255, 1)'
- }
- ])
+ type: "bar",
+ data: [],
+ label: {
+ show: true,
},
- itemStyle: {
- color: '#2D99FF',
- borderColor: '#2D99FF'
- },
+ },
+ ]);
+
+ const barSeries1 = ref([
+ {
+ name: "鍘熸潗鏂欎笉鍚堟牸鏁�",
+ type: "bar",
+ barGap: 0,
emphasis: {
- focus: 'series'
+ focus: "series",
},
- lineStyle: {
- width: 0
- },
- showSymbol: true,
+ data: [],
},
{
- name: '鍥炴',
- type: 'line',
- data: receiptAmount,
- stack: 'Total',
- lineStyle: {
- width: 0
- },
- itemStyle: {
- color: '#83CFFF',
- borderColor: '#83CFFF'
- },
- showSymbol: true,
- areaStyle: {
- color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
- {
- offset: 0,
- color: 'rgba(54, 153, 255, 1)'
- },
- {
- offset: 1,
- color: 'rgba(89, 169, 254, 1)'
- }
- ])
- },
+ name: "杩囩▼涓嶅悎鏍兼暟",
+ type: "bar",
emphasis: {
- focus: 'series'
+ focus: "series",
},
+ data: [],
+ },
+ {
+ name: "鍑哄巶涓嶅悎鏍兼暟",
+ type: "bar",
+ emphasis: {
+ focus: "series",
+ },
+ data: [],
+ },
+ ]);
+ const chartStyle = {
+ width: "100%",
+ height: "100%", // 璁剧疆鍥捐〃瀹瑰櫒鐨勯珮搴�
+ };
+ const chartStylePie = {
+ width: "140%",
+ height: "140%", // 璁剧疆鍥捐〃瀹瑰櫒鐨勯珮搴�
+ };
+ const grid = {
+ left: "3%",
+ right: "4%",
+ bottom: "3%",
+ containLabel: true,
+ };
+ const barLegend = {
+ show: true,
+ data: ["鍘熸潗鏂欎笉鍚堟牸鏁�", "杩囩▼涓嶅悎鏍兼暟", "鍑哄巶涓嶅悎鏍兼暟"],
+ };
+ const barLegend1 = {
+ show: true,
+ data: ["棰勪粯璐︽", "搴斾粯璐︽", "棰勬敹璐︽", "搴旀敹璐︽"],
+ };
+ const lineLegend = {
+ show: true,
+ data: ["寮�绁�", "鍥炴"],
+ };
+ const tooltip = {
+ trigger: "axis",
+ axisPointer: {
+ type: "shadow",
+ },
+ };
+ const xAxis = [
+ {
+ type: "value",
+ },
+ ];
+ const xAxis1 = ref([
+ {
+ type: "category",
+ axisTick: { show: false },
+ data: [],
+ },
+ ]);
+ const yAxis = [
+ {
+ type: "category",
+ data: ["搴斾粯璐︽", "搴旀敹璐︽"],
+ },
+ ];
+ const yAxis1 = [
+ {
+ type: "value",
+ },
+ ];
+ const pieTooltip = reactive({
+ trigger: "item",
+ formatter: function (params) {
+ // 鍔ㄦ�佺敓鎴愭彁绀轰俊鎭紝鍩轰簬鏁版嵁椤圭殑 name 灞炴��
+ const description =
+ params.name === "鏈湀鍥炴閲戦" ? "鏈湀鍥炴閲戦" : "搴旀敹娆鹃噾棰�";
+ return `${description} ${formatNumber(params.value)}鍏� ${params.percent}%`;
+ },
+ position: "right",
+ });
+ const materialPieSeries = ref([
+ {
+ type: "pie",
+ radius: ["66%", "90%"],
+ avoidLabelOverlap: false,
+ itemStyle: {
+ borderColor: "#fff",
+ borderWidth: 2,
+ },
+ label: {
+ show: false,
+ },
+ data: [],
+ },
+ ]);
+ const lineSeries = ref([
+ {
+ type: "line",
+ data: [],
+ label: {
+ show: true,
+ },
+ showSymbol: true, // 鏄剧ず鍦嗙偣
+ },
+ ]);
+ const tooltipLine = {
+ trigger: "axis",
+ };
+ const yAxis2 = ref([
+ {
+ type: "value",
+ },
+ ]);
+ const xAxis2 = ref([
+ {
+ type: "category",
+ data: [],
+ axisLabel: {
+ interval: 0,
+ formatter: function (value) {
+ return value.replace(/~/g, "\n");
+ },
+ },
+ },
+ ]);
+
+ // 寰呭姙浜嬮」
+ const todoList = ref([]);
+ const radio1 = ref(1);
+ const qualityRange = ref(1);
+
+ // 鍥捐〃寮曠敤
+ const barChart = ref(null);
+ const lineChart = ref(null);
+ const barColors2 = ["#5181DB", "#D369E0", "#F2CA6D", "#60CCA8"];
+
+ // 闅忔満棰滆壊鐢熸垚鍑芥暟
+ const getRandomColor = () => {
+ return (
+ "#" +
+ Math.floor(Math.random() * 0xffffff)
+ .toString(16)
+ .padStart(6, "0")
+ );
+ };
+
+ onMounted(() => {
+ getBusinessData();
+ analysisCustomer();
+ todoInfoS();
+ statisticsReceivable();
+ qualityStatisticsInfo();
+ getAmountHalfYearNum();
+ getProcessList();
+ });
+ // 鏁版嵁缁熻
+ const getBusinessData = () => {
+ getBusiness().then(res => {
+ businessInfo.value = { ...res.data };
+ });
+ };
+ // 鍚堝悓閲戦
+ const analysisCustomer = () => {
+ analysisCustomerContractAmounts().then(res => {
+ sum.value = res.data.sum;
+ yny.value = res.data.yny;
+ chain.value = res.data.chain;
+ // 涓烘瘡涓暟鎹」鍒嗛厤闅忔満棰滆壊
+ materialPieSeries.value[0].data = res.data.item.map(item => ({
+ ...item,
+ itemStyle: { color: getRandomColor() },
+ }));
+ });
+ };
+ // 寰呭姙浜嬮」
+ const todoInfoS = () => {
+ homeTodos().then(res => {
+ todoList.value = res.data;
+ });
+ };
+ // 鑾峰彇宸ュ簭鍒楄〃
+ const getProcessList = () => {
+ list().then(res => {
+ processOptions.value = res.data;
+ });
+ };
+
+ const openProcessDialog = () => {
+ tempProcessIds.value = [...selectedProcessIds.value];
+ processDialogVisible.value = true;
+ };
+
+ const handleProcessDialogConfirm = () => {
+ selectedProcessIds.value = [...tempProcessIds.value];
+ processDialogVisible.value = false;
+ refreshProcessStats();
+ };
+
+ const resetProcessFilter = () => {
+ selectedProcessIds.value = [];
+ tempProcessIds.value = [];
+ refreshProcessStats();
+ };
+
+ const handleChartClick = params => {
+ if (params && params.dataIndex !== undefined) {
+ activeProcessIndex.value = params.dataIndex;
}
- ]
-}
+ };
+ // 搴斾粯搴旀敹缁熻
+ const statisticsReceivable = () => {
+ statisticsReceivablePayable({ type: radio1.value }).then(res => {
+ barSeries.value[0].data = [
+ // { value: res.data.prepayMoney, itemStyle: { color: barColors2[0] } },
+ { value: res.data.payableMoney, itemStyle: { color: barColors2[0] } },
+ // { value: res.data.advanceMoney, itemStyle: { color: barColors2[2] } },
+ { value: res.data.receivableMoney, itemStyle: { color: barColors2[1] } },
+ ];
+ });
+ };
+ // 璐ㄦ缁熻
+ const qualityStatisticsInfo = () => {
+ qualityInspectionStatistics({ type: qualityRange.value }).then(res => {
+ xAxis1.value[0].data = [];
+ barSeries1.value[0].data = [];
+ barSeries1.value[1].data = [];
+ barSeries1.value[2].data = [];
+ res.data.item.forEach(item => {
+ xAxis1.value[0].data.push(item.date);
+ barSeries1.value[0].data.push(item.supplierNum);
+ barSeries1.value[1].data.push(item.processNum);
+ barSeries1.value[2].data.push(item.factoryNum);
+ });
+ qualityStatisticsObject.value.supplierNum = res.data.supplierNum;
+ qualityStatisticsObject.value.processNum = res.data.processNum;
+ qualityStatisticsObject.value.factoryNum = res.data.factoryNum;
+ });
+ };
+ const getAmountHalfYearNum = async () => {
+ const res = await getAmountHalfYear();
+ console.log(res);
+ const monthName = [];
+ const receiptAmount = [];
+ const invoiceAmount = [];
+ res.data.forEach(item => {
+ monthName.push(item.month);
+ receiptAmount.push(item.receiptAmount);
+ invoiceAmount.push(item.invoiceAmount);
+ });
+ // 姝g‘鍝嶅簲寮忚祴鍊硷細鍒涘缓鏂扮殑 xAxis 鍜� series 瀵硅薄
+ xAxis2.value[0].data = monthName;
+ xAxis2.value[0].data = monthName.map(item => item.replace(/~/g, "\n~"));
+ lineSeries.value = [
+ {
+ name: "寮�绁�",
+ type: "line",
+ data: invoiceAmount,
+ stack: "Total",
+ areaStyle: {
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+ {
+ offset: 0,
+ color: "rgba(131, 207, 255, 1)",
+ },
+ {
+ offset: 1,
+ color: "rgba(186, 228, 255, 1)",
+ },
+ ]),
+ },
+ itemStyle: {
+ color: "#2D99FF",
+ borderColor: "#2D99FF",
+ },
+ emphasis: {
+ focus: "series",
+ },
+ lineStyle: {
+ width: 0,
+ },
+ showSymbol: true,
+ },
+ {
+ name: "鍥炴",
+ type: "line",
+ data: receiptAmount,
+ stack: "Total",
+ lineStyle: {
+ width: 0,
+ },
+ itemStyle: {
+ color: "#83CFFF",
+ borderColor: "#83CFFF",
+ },
+ showSymbol: true,
+ areaStyle: {
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+ {
+ offset: 0,
+ color: "rgba(54, 153, 255, 1)",
+ },
+ {
+ offset: 1,
+ color: "rgba(89, 169, 254, 1)",
+ },
+ ]),
+ },
+ emphasis: {
+ focus: "series",
+ },
+ },
+ ];
+ };
-// 宸ュ簭鏁版嵁鐢熶骇缁熻鏄庣粏锛堝亣鏁版嵁 + 鍥捐〃锛�
-const processRange = ref(1)
-const processChartData = ref([])
+ // 宸ュ簭鏁版嵁鐢熶骇缁熻鏄庣粏锛堝亣鏁版嵁 + 鍥捐〃锛�
+ const processRange = ref(1);
+ const processChartData = ref([]);
-const processXAxis = ref([
- {
- nameTextStyle: { color: 'rgba(0,0,0,0.35)', fontSize: 12 },
- axisLabel: { color: 'rgba(0,0,0,0.35)' },
- splitLine: { lineStyle: { color: 'rgba(0,0,0,0.06)', type: 'dashed' } },
- },
-])
-
-const processYAxis = ref([
- {
- type: 'category',
- axisTick: { show: false },
- axisLine: { show: false },
- axisLabel: { color: 'rgba(0,0,0,0.45)' },
- data: [],
- },
-])
-
-const processGrid = reactive({ left: 0, right: 100, top: 30, bottom: 20, containLabel: true })
-
-const processTooltip = reactive({
- trigger: 'axis',
- axisPointer: { type: 'shadow' },
- formatter: (params) => {
- const name = params?.[0]?.name ?? ''
- const list = Array.isArray(params) ? params : []
- const lines = list
- .map((p) => {
- const colorBox = `<span style="display:inline-block;margin-right:6px;border-radius:2px;width:10px;height:10px;background:${p.color}"></span>`
- return `${colorBox}${p.seriesName} <b style="float:right;">${Number(p.value || 0).toFixed(2)}</b>`
- })
- .join('<br/>')
- return `<div style="min-width:140px;"><div style="font-weight:700;margin-bottom:6px;">${name}</div>${lines}</div>`
- },
-})
-
-const processSeries = computed(() => {
- const input = processChartData.value.map((i) => i.input)
- const scrap = processChartData.value.map((i) => i.scrap)
- const output = processChartData.value.map((i) => i.output)
-
- return [
+ const processXAxis = ref([
{
- name: '鎶曞叆閲�',
- type: 'bar',
- stack: 'total',
- barWidth: 22,
- itemStyle: { color: '#1E5BFF', borderRadius: [6, 0, 0, 6] },
- data: input,
+ nameTextStyle: { color: "rgba(0,0,0,0.35)", fontSize: 12 },
+ axisLabel: { color: "rgba(0,0,0,0.35)" },
+ splitLine: { lineStyle: { color: "rgba(0,0,0,0.06)", type: "dashed" } },
},
+ ]);
+
+ const processYAxis = ref([
{
- name: '鎶ュ簾閲�',
- type: 'bar',
- stack: 'total',
- barWidth: 22,
- itemStyle: { color: '#F7B500' },
- data: scrap,
+ type: "category",
+ axisTick: { show: false },
+ axisLine: { show: false },
+ axisLabel: { color: "rgba(0,0,0,0.45)" },
+ data: [],
},
- {
- name: '浜у嚭閲�',
- type: 'bar',
- stack: 'total',
- barWidth: 22,
- itemStyle: { color: '#19C6C6', borderRadius: [0, 6, 6, 0] },
- data: output,
+ ]);
+
+ const processGrid = reactive({
+ left: 0,
+ right: 100,
+ top: 30,
+ bottom: 20,
+ containLabel: true,
+ });
+
+ const processTooltip = reactive({
+ trigger: "axis",
+ axisPointer: { type: "shadow" },
+ formatter: params => {
+ const name = params?.[0]?.name ?? "";
+ const list = Array.isArray(params) ? params : [];
+ const lines = list
+ .map(p => {
+ const colorBox = `<span style="display:inline-block;margin-right:6px;border-radius:2px;width:10px;height:10px;background:${p.color}"></span>`;
+ return `${colorBox}${p.seriesName} <b style="float:right;">${Number(
+ p.value || 0
+ ).toFixed(2)}</b>`;
+ })
+ .join("<br/>");
+ return `<div style="min-width:140px;"><div style="font-weight:700;margin-bottom:6px;">${name}</div>${lines}</div>`;
},
- ]
-})
+ });
-const processAside = computed(() => {
- const list = processChartData.value
- const item = list[activeProcessIndex.value] || {}
- return {
- processName: item.name || '鏆傛棤鏁版嵁',
- totalInput: item.input || 0,
- totalScrap: item.scrap || 0,
- totalOutput: item.output || 0,
- }
-})
+ const processSeries = computed(() => {
+ const input = processChartData.value.map(i => i.input);
+ const scrap = processChartData.value.map(i => i.scrap);
+ const output = processChartData.value.map(i => i.output);
-const formatAmount = (n) => {
- const num = Number(n || 0)
- return num.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })
-}
+ return [
+ {
+ name: "鎶曞叆閲�",
+ type: "bar",
+ stack: "total",
+ barWidth: 22,
+ itemStyle: { color: "#1E5BFF", borderRadius: [6, 0, 0, 6] },
+ data: input,
+ },
+ {
+ name: "鎶ュ簾閲�",
+ type: "bar",
+ stack: "total",
+ barWidth: 22,
+ itemStyle: { color: "#F7B500" },
+ data: scrap,
+ },
+ {
+ name: "浜у嚭閲�",
+ type: "bar",
+ stack: "total",
+ barWidth: 22,
+ itemStyle: { color: "#19C6C6", borderRadius: [0, 6, 6, 0] },
+ data: output,
+ },
+ ];
+ });
-const refreshProcessStats = () => {
- processDataProductionStatistics({
- type: processRange.value,
- processIds: selectedProcessIds.value.length > 0 ? selectedProcessIds.value.join(',') : null
- }).then(res => {
- processChartData.value = res.data.map(item => ({
- name: item.processName,
- input: item.totalInput,
- scrap: item.totalScrap,
- output: item.totalOutput
- }))
- processYAxis.value[0].data = processChartData.value.map((i) => i.name)
- activeProcessIndex.value = 0
- })
-}
+ const processAside = computed(() => {
+ const list = processChartData.value;
+ const item = list[activeProcessIndex.value] || {};
+ return {
+ processName: item.name || "鏆傛棤鏁版嵁",
+ totalInput: item.input || 0,
+ totalScrap: item.scrap || 0,
+ totalOutput: item.output || 0,
+ };
+ });
-onMounted(() => {
- getBusinessData()
- analysisCustomer()
- todoInfoS()
- statisticsReceivable()
- qualityStatisticsInfo()
- getAmountHalfYearNum()
- refreshProcessStats()
-})
+ const formatAmount = n => {
+ const num = Number(n || 0);
+ return num.toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ });
+ };
+
+ const refreshProcessStats = () => {
+ processDataProductionStatistics({
+ type: processRange.value,
+ processIds:
+ selectedProcessIds.value.length > 0
+ ? selectedProcessIds.value.join(",")
+ : null,
+ }).then(res => {
+ processChartData.value = res.data.map(item => ({
+ name: item.processName,
+ input: item.totalInput,
+ scrap: item.totalScrap,
+ output: item.totalOutput,
+ }));
+ processYAxis.value[0].data = processChartData.value.map(i => i.name);
+ activeProcessIndex.value = 0;
+ });
+ };
+
+ onMounted(() => {
+ getBusinessData();
+ analysisCustomer();
+ todoInfoS();
+ statisticsReceivable();
+ qualityStatisticsInfo();
+ getAmountHalfYearNum();
+ refreshProcessStats();
+ });
</script>
<style scoped>
-.dashboard {
- background: #f5f7fa;
- min-height: 100vh;
- padding: 20px;
- box-sizing: border-box;
-}
+ .dashboard {
+ background: #f5f7fa;
+ min-height: 100vh;
+ padding: 20px;
+ box-sizing: border-box;
+ }
-.dashboard-top {
- display: flex;
- gap: 20px;
- margin-bottom: 20px;
- align-items: flex-start;
- justify-content: space-evenly;
-}
+ .dashboard-top {
+ display: flex;
+ gap: 20px;
+ margin-bottom: 20px;
+ align-items: flex-start;
+ justify-content: space-evenly;
+ }
-.company-info {
- padding: 0;
- overflow: hidden;
- border-radius: 12px;
- background: #fff;
- height: 100%;
-}
+ .company-info {
+ padding: 0;
+ overflow: hidden;
+ border-radius: 12px;
+ background: #fff;
+ height: 100%;
+ }
-.welcome-banner {
- padding: 10px 10px;
- background: linear-gradient(135deg, rgba(229, 240, 255, 0.9), rgba(214, 232, 255, 0.7), rgba(207, 236, 255, 0.9));
-}
+ .welcome-banner {
+ padding: 10px 10px;
+ background: linear-gradient(
+ 135deg,
+ rgba(229, 240, 255, 0.9),
+ rgba(214, 232, 255, 0.7),
+ rgba(207, 236, 255, 0.9)
+ );
+ }
-.welcome-title {
- font-size: 18px;
- font-weight: 700;
- color: #222;
- line-height: 1.3;
-}
+ .welcome-title {
+ font-size: 18px;
+ font-weight: 700;
+ color: #222;
+ line-height: 1.3;
+ }
-.welcome-user {
- margin-right: 6px;
-}
+ .welcome-user {
+ margin-right: 6px;
+ }
-.welcome-time {
- margin-top: 10px;
- font-size: 16px;
- color: rgba(0, 0, 0, 0.55);
-}
+ .welcome-time {
+ margin-top: 10px;
+ font-size: 16px;
+ color: rgba(0, 0, 0, 0.55);
+ }
-.user-card {
- display: flex;
- align-items: center;
- gap: 10px;
- padding: 18px 22px;
-}
+ .user-card {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 18px 22px;
+ }
-.user-card-main {
- display: flex;
- flex-direction: column;
- gap: 5px;
- min-width: 0;
-}
+ .user-card-main {
+ display: flex;
+ flex-direction: column;
+ gap: 5px;
+ min-width: 0;
+ }
-.user-name {
- font-size: 16px;
- font-weight: bold;
- color: #111;
- letter-spacing: 1px;
-}
+ .user-name {
+ font-size: 16px;
+ font-weight: bold;
+ color: #111;
+ letter-spacing: 1px;
+ }
-.user-role {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- height: 20px;
- padding: 5px 10px;
- background: rgba(245, 246, 248, 1);
- color: #333;
- width: fit-content;
- font-weight: 600;
-}
+ .user-role {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ height: 20px;
+ padding: 5px 10px;
+ background: rgba(245, 246, 248, 1);
+ color: #333;
+ width: fit-content;
+ font-weight: 600;
+ }
-.user-meta {
- font-size: 12px;
- color: rgba(0, 0, 0, 0.55);
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
+ .user-meta {
+ font-size: 12px;
+ color: rgba(0, 0, 0, 0.55);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
-.user-meta .sep {
- margin: 0 10px;
- color: rgba(0, 0, 0, 0.25);
-}
+ .user-meta .sep {
+ margin: 0 10px;
+ color: rgba(0, 0, 0, 0.25);
+ }
-.avatar {
- width: 90px;
- height: 90px;
- border-radius: 50%;
- object-fit: cover;
- flex: 0 0 auto;
-}
+ .avatar {
+ width: 90px;
+ height: 90px;
+ border-radius: 50%;
+ object-fit: cover;
+ flex: 0 0 auto;
+ }
-.data-cards {
- width: 50%;
- display: flex;
- gap: 16px;
- justify-content: flex-start;
- background: #ffffff;
- border-radius: 12px;
- padding: 20px;
-}
+ .data-cards {
+ width: 50%;
+ display: flex;
+ gap: 16px;
+ justify-content: flex-start;
+ background: #ffffff;
+ border-radius: 12px;
+ padding: 20px;
+ }
-.data-title {
- font-weight: 700;
- font-size: 26px;
- color: #FFFFFF;
-}
+ .data-title {
+ font-weight: 700;
+ font-size: 26px;
+ color: #ffffff;
+ }
-.data-num {
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-top: 20px;
-}
+ .data-num {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-top: 20px;
+ }
-.data-card {
- background: #fff;
- border-radius: 12px;
- padding: 14px 10px 10px 10px;
- min-width: 160px;
- box-shadow: 0 2px 8px #eee;
- display: flex;
- flex-direction: column;
- width: 32%;
- height: 140px;
-}
+ .data-card {
+ background: #fff;
+ border-radius: 12px;
+ padding: 14px 10px 10px 10px;
+ min-width: 160px;
+ box-shadow: 0 2px 8px #eee;
+ display: flex;
+ flex-direction: column;
+ width: 32%;
+ height: 140px;
+ }
-.data-card.sales {
- background-image: url("../assets/images/xioashoushuju.png");
- background-size: cover;
- background-position: center;
- background-repeat: no-repeat;
-}
+ .data-card.sales {
+ background-image: url("../assets/images/xioashoushuju.png");
+ background-size: cover;
+ background-position: center;
+ background-repeat: no-repeat;
+ }
-.data-card.purchase {
- background-image: url("../assets/images/caigou.png");
- background-size: cover;
- background-position: center;
- background-repeat: no-repeat;
-}
+ .data-card.purchase {
+ background-image: url("../assets/images/caigou.png");
+ background-size: cover;
+ background-position: center;
+ background-repeat: no-repeat;
+ }
-.data-card.inventory {
- background-image: url("../assets/images/kucun.png");
- background-size: cover;
- background-position: center;
- background-repeat: no-repeat;
-}
+ .data-card.inventory {
+ background-image: url("../assets/images/kucun.png");
+ background-size: cover;
+ background-position: center;
+ background-repeat: no-repeat;
+ }
-.data-desc {
- font-weight: 500;
- font-size: 13px;
- color: #FFFFFF;
-}
+ .data-desc {
+ font-weight: 500;
+ font-size: 13px;
+ color: #ffffff;
+ }
-.data-value {
- font-size: 18px;
- font-weight: 500;
- margin: 10px 0;
- color: #FFFFFF;
-}
+ .data-value {
+ font-size: 18px;
+ font-weight: 500;
+ margin: 10px 0;
+ color: #ffffff;
+ }
-.top-left {
- display: flex;
- flex-direction: column;
- gap: 20px;
- height: 180px;
- width: 20%;
-}
+ .top-left {
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+ height: 180px;
+ width: 20%;
+ }
-.todo-panel {
- background: #fff;
- border-radius: 12px;
- padding: 20px;
- height: 180px;
- width: 30%;
-}
+ .todo-panel {
+ background: #fff;
+ border-radius: 12px;
+ padding: 20px;
+ height: 180px;
+ width: 30%;
+ }
-.todo-list {
- height: 100px;
- list-style: none;
- padding: 0;
- margin: 0;
- font-size: 15px;
- overflow-y: auto;
-}
+ .todo-list {
+ height: 100px;
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ font-size: 15px;
+ overflow-y: auto;
+ }
-.todo-list li {
- border-radius: 8px;
- margin-bottom: 12px;
- padding: 8px 20px;
- height: 74px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- background: rgba(225, 227, 250, 0.62);
-}
-
-.todo-title {
- font-weight: 400;
- font-size: 12px;
- color: #000000;
- position: relative;
-}
-
-.todo-title::before {
- content: '';
- /* 蹇呴渶锛岃〃绀鸿繖閲屾湁涓�涓唴瀹� */
- position: absolute;
- left: -10px;
- /* 瀹氫綅鍒板乏渚� */
- top: 50%;
- /* 鍨傜洿灞呬腑 */
- transform: translateY(-50%);
- /* 寰皟鍨傜洿灞呬腑 */
- width: 6px;
- /* 鍦嗙殑鐩村緞 */
- height: 6px;
- /* 鍦嗙殑鐩村緞 */
- background: #498CEB;
- border-radius: 50%;
- /* 璁╁叾鍙樻垚鍦嗗舰 */
-}
-
-.todo-division {
- font-weight: 400;
- font-size: 12px;
- color: #000000;
-}
-
-.todo-time {
- font-weight: 400;
- font-size: 12px;
- color: #000000;
-}
-
-.todo-meta {
- color: #888;
- font-size: 13px;
-}
-
-.dashboard-row {
- display: flex;
- gap: 20px;
- margin-bottom: 20px;
-}
-
-.main-panel {
- background: #fff;
- border-radius: 12px;
- padding: 20px;
- flex: 1;
- min-width: 0;
- display: flex;
- flex-direction: column;
-}
-
-.section-title {
- position: relative;
- font-size: 18px;
- color: #333;
- padding-left: 10px;
- margin-bottom: 10px;
- font-weight: 700;
-}
-
-.section-title::before {
- position: absolute;
- left: 0;
- top: 4px;
- content: '';
- width: 4px;
- height: 18px;
- background-color: #002FA7;
- border-radius: 2px;
-}
-
-.contract-info {
- display: flex;
- align-items: center;
- gap: 20px;
- height: 90px;
- background: rgba(245, 245, 245, 0.59);
- width: 100%;
- border-radius: 10px;
- padding: 10px 30px;
-}
-
-.contract-summary {
- display: flex;
- align-items: center;
- gap: 30px;
-}
-
-.contract-card {
- display: flex;
- flex-direction: column;
- gap: 10px;
-}
-
-.contract-name {
- font-weight: 400;
- font-size: 14px;
- color: #050505;
-}
-
-.contract-meta {
- display: flex;
- align-items: center;
- width: 100%;
- gap: 80px;
-}
-
-.main-amount {
- font-size: 24px;
- color: rgba(51, 50, 50, 0.85);
-}
-
-.up {
- color: #e57373;
-}
-
-.contract-list {
- margin-top: 16px;
- font-size: 14px;
- color: #666;
- list-style: none;
- padding: 0;
- height: 190px;
- overflow-y: auto;
- width: 460px;
-}
-
-.line {
- position: relative;
- width: 230px;
-}
-
-.line::after {
- content: '';
- position: absolute;
- right: 2px;
- top: 0;
- bottom: 0;
- width: 1px;
- background-color: #C9C5C5;
- border-radius: 2px;
-}
-
-.contract-list li {
- margin-top: 10px;
-}
-
-.quality-cards {
- display: flex;
- gap: 12px;
- margin-bottom: 12px;
-}
-
-.quality-card {
- border-radius: 8px;
- padding: 15px 10px 10px 50px;
- font-weight: 400;
- font-size: 12px;
- color: rgba(0, 0, 0, 0.67);
- width: 236px;
- height: 49px;
- background-size: cover;
- background-position: center;
- background-repeat: no-repeat;
-}
-
-.quality-card.one {
- background-image: url("../assets/images/yuancailiao.png");
-}
-
-.quality-card.two {
- background-image: url("../assets/images/guocheng.png");
-}
-
-.quality-card.three {
- background-image: url("../assets/images/chuchang.png");
-
-}
-
-.quality-card span {
- color: #4fc3f7;
- font-weight: bold;
- margin-left: 6px;
-}
-
-.chart {
- width: 100%;
- height: 220px;
- margin-top: 10px;
-}
-
-.process-panel {
- padding-bottom: 10px;
-}
-
-.process-panel__header {
- display: flex;
- justify-content: space-between;
- align-items: center;
-}
-
-.process-panel__body {
- display: flex;
- gap: 24px;
- align-items: stretch;
- margin-top: 10px;
-}
-
-.process-panel__chart {
- flex: 1;
- min-width: 0;
- padding: 6px 0;
-}
-
-.process-panel__aside {
- width: 260px;
- display: flex;
- flex-direction: column;
- gap: 12px;
-}
-
-.process-legend {
- display: flex;
- flex-direction: column;
- gap: 10px;
- align-items: flex-start;
- padding: 8px 6px;
-}
-
-.process-legend__item {
- display: flex;
- align-items: center;
- gap: 8px;
- font-size: 13px;
- color: rgba(0, 0, 0, 0.55);
-}
-
-.dot {
- width: 10px;
- height: 10px;
- border-radius: 2px;
- display: inline-block;
-}
-
-.dot-blue {
- background: #1E5BFF;
-}
-
-.dot-yellow {
- background: #F7B500;
-}
+ .todo-list li {
+ border-radius: 8px;
+ margin-bottom: 12px;
+ padding: 8px 20px;
+ height: 74px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ background: rgba(225, 227, 250, 0.62);
+ }
-.dot-teal {
- background: #19C6C6;
-}
+ .todo-title {
+ font-weight: 400;
+ font-size: 12px;
+ color: #000000;
+ position: relative;
+ }
-.process-card {
- background: rgba(245, 247, 250, 0.9);
- border-radius: 10px;
- padding: 16px 16px;
-}
+ .todo-title::before {
+ content: "";
+ /* 蹇呴渶锛岃〃绀鸿繖閲屾湁涓�涓唴瀹� */
+ position: absolute;
+ left: -10px;
+ /* 瀹氫綅鍒板乏渚� */
+ top: 50%;
+ /* 鍨傜洿灞呬腑 */
+ transform: translateY(-50%);
+ /* 寰皟鍨傜洿灞呬腑 */
+ width: 6px;
+ /* 鍦嗙殑鐩村緞 */
+ height: 6px;
+ /* 鍦嗙殑鐩村緞 */
+ background: #498ceb;
+ border-radius: 50%;
+ /* 璁╁叾鍙樻垚鍦嗗舰 */
+ }
-.process-card--name {
- background: rgba(235, 242, 255, 1);
- color: #1E5BFF;
- font-weight: 800;
- font-size: 14px;
-}
+ .todo-division {
+ font-weight: 400;
+ font-size: 12px;
+ color: #000000;
+ }
-.process-card__label {
- font-size: 13px;
- color: rgba(0, 0, 0, 0.55);
- margin-bottom: 10px;
-}
+ .todo-time {
+ font-weight: 400;
+ font-size: 12px;
+ color: #000000;
+ }
-.process-card__value {
- font-size: 24px;
- font-weight: 800;
- color: rgba(0, 0, 0, 0.8);
-}
+ .todo-meta {
+ color: #888;
+ font-size: 13px;
+ }
-.process-card__value .unit {
- font-size: 12px;
- font-weight: 600;
- color: rgba(0, 0, 0, 0.45);
- margin-left: 6px;
-}
+ .dashboard-row {
+ display: flex;
+ gap: 20px;
+ margin-bottom: 20px;
+ }
-@media (max-width: 1200px) {
- .process-panel__body {
+ .main-panel {
+ background: #fff;
+ border-radius: 12px;
+ padding: 20px;
+ flex: 1;
+ min-width: 0;
+ display: flex;
flex-direction: column;
}
- .process-panel__aside {
+ .section-title {
+ position: relative;
+ font-size: 18px;
+ color: #333;
+ padding-left: 10px;
+ margin-bottom: 10px;
+ font-weight: 700;
+ }
+
+ .section-title::before {
+ position: absolute;
+ left: 0;
+ top: 4px;
+ content: "";
+ width: 4px;
+ height: 18px;
+ background-color: #002fa7;
+ border-radius: 2px;
+ }
+
+ .contract-info {
+ display: flex;
+ align-items: center;
+ gap: 20px;
+ height: 90px;
+ background: rgba(245, 245, 245, 0.59);
width: 100%;
- flex-direction: row;
- flex-wrap: wrap;
+ border-radius: 10px;
+ padding: 10px 30px;
+ }
+
+ .contract-summary {
+ display: flex;
+ align-items: center;
+ gap: 30px;
+ }
+
+ .contract-card {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ }
+
+ .contract-name {
+ font-weight: 400;
+ font-size: 14px;
+ color: #050505;
+ }
+
+ .contract-meta {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ gap: 80px;
+ }
+
+ .main-amount {
+ font-size: 24px;
+ color: rgba(51, 50, 50, 0.85);
+ }
+
+ .up {
+ color: #e57373;
+ }
+
+ .contract-list {
+ margin-top: 16px;
+ font-size: 14px;
+ color: #666;
+ list-style: none;
+ padding: 0;
+ height: 190px;
+ overflow-y: auto;
+ width: 460px;
+ }
+
+ .line {
+ position: relative;
+ width: 230px;
+ }
+
+ .line::after {
+ content: "";
+ position: absolute;
+ right: 2px;
+ top: 0;
+ bottom: 0;
+ width: 1px;
+ background-color: #c9c5c5;
+ border-radius: 2px;
+ }
+
+ .contract-list li {
+ margin-top: 10px;
+ }
+
+ .quality-cards {
+ display: flex;
+ gap: 12px;
+ margin-bottom: 12px;
+ }
+
+ .quality-card {
+ border-radius: 8px;
+ padding: 15px 10px 10px 50px;
+ font-weight: 400;
+ font-size: 12px;
+ color: rgba(0, 0, 0, 0.67);
+ width: 236px;
+ height: 49px;
+ background-size: cover;
+ background-position: center;
+ background-repeat: no-repeat;
+ }
+
+ .quality-card.one {
+ background-image: url("../assets/images/yuancailiao.png");
+ }
+
+ .quality-card.two {
+ background-image: url("../assets/images/guocheng.png");
+ }
+
+ .quality-card.three {
+ background-image: url("../assets/images/chuchang.png");
+ }
+
+ .quality-card span {
+ color: #4fc3f7;
+ font-weight: bold;
+ margin-left: 6px;
+ }
+
+ .chart {
+ width: 100%;
+ height: 220px;
+ margin-top: 10px;
+ }
+
+ .process-panel {
+ padding-bottom: 10px;
+ }
+
+ .process-panel__header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
+
+ .process-panel__body {
+ display: flex;
+ gap: 24px;
+ align-items: stretch;
+ margin-top: 10px;
+ }
+
+ .process-panel__chart {
+ flex: 1;
+ min-width: 0;
+ padding: 6px 0;
+ }
+
+ .process-panel__aside {
+ width: 260px;
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ }
+
+ .process-legend {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ align-items: flex-start;
+ padding: 8px 6px;
+ }
+
+ .process-legend__item {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ font-size: 13px;
+ color: rgba(0, 0, 0, 0.55);
+ }
+
+ .dot {
+ width: 10px;
+ height: 10px;
+ border-radius: 2px;
+ display: inline-block;
+ }
+
+ .dot-blue {
+ background: #1e5bff;
+ }
+
+ .dot-yellow {
+ background: #f7b500;
+ }
+
+ .dot-teal {
+ background: #19c6c6;
}
.process-card {
- flex: 1;
- min-width: 220px;
+ background: rgba(245, 247, 250, 0.9);
+ border-radius: 10px;
+ padding: 16px 16px;
}
-}
-.process-selection-wrapper {
- max-height: 400px;
- overflow-y: auto;
- padding: 10px;
-}
+ .process-card--name {
+ background: rgba(235, 242, 255, 1);
+ color: #1e5bff;
+ font-weight: 800;
+ font-size: 14px;
+ }
-.process-grid {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
- gap: 12px;
-}
+ .process-card__label {
+ font-size: 13px;
+ color: rgba(0, 0, 0, 0.55);
+ margin-bottom: 10px;
+ }
-:deep(.el-checkbox.is-bordered) {
- margin-left: 0 !important;
- width: 100%;
-}
+ .process-card__value {
+ font-size: 24px;
+ font-weight: 800;
+ color: rgba(0, 0, 0, 0.8);
+ }
+
+ .process-card__value .unit {
+ font-size: 12px;
+ font-weight: 600;
+ color: rgba(0, 0, 0, 0.45);
+ margin-left: 6px;
+ }
+
+ @media (max-width: 1200px) {
+ .process-panel__body {
+ flex-direction: column;
+ }
+
+ .process-panel__aside {
+ width: 100%;
+ flex-direction: row;
+ flex-wrap: wrap;
+ }
+
+ .process-card {
+ flex: 1;
+ min-width: 220px;
+ }
+ }
+
+ .process-selection-wrapper {
+ max-height: 400px;
+ overflow-y: auto;
+ padding: 10px;
+ }
+
+ .process-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
+ gap: 12px;
+ }
+
+ :deep(.el-checkbox.is-bordered) {
+ margin-left: 0 !important;
+ width: 100%;
+ }
</style>
\ No newline at end of file
diff --git a/src/views/procurementManagement/procurementLedger/index.vue b/src/views/procurementManagement/procurementLedger/index.vue
index 8a293fc..1eb1e39 100644
--- a/src/views/procurementManagement/procurementLedger/index.vue
+++ b/src/views/procurementManagement/procurementLedger/index.vue
@@ -33,6 +33,18 @@
prefix-icon="Search"
@change="handleQuery" />
</el-form-item>
+ <el-form-item label="渚涘簲鍟嗙被鍨嬶細">
+ <el-select v-model="searchForm.supplierType"
+ placeholder="璇烽�夋嫨"
+ style="width: 220px"
+ clearable
+ @change="handleQuery">
+ <el-option label="瀵瑰叕"
+ value="1" />
+ <el-option label="瀵圭"
+ value="2" />
+ </el-select>
+ </el-form-item>
<el-form-item label="褰曞叆鏃ユ湡锛�">
<el-date-picker v-model="searchForm.entryDate"
value-format="YYYY-MM-DD"
@@ -53,7 +65,9 @@
<div style="display: flex;justify-content: flex-end;margin-bottom: 20px;">
<el-button type="primary"
@click="openForm('add')">鏂板鍙拌处</el-button>
- <el-button type="primary" plain @click="handleImport">瀵煎叆</el-button>
+ <el-button type="primary"
+ plain
+ @click="handleImport">瀵煎叆</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
<el-button type="danger"
plain
@@ -94,18 +108,29 @@
prop="availableQuality" />
<el-table-column label="閫�璐ф暟閲�"
prop="returnQuality" />
-
<el-table-column label="绋庣巼(%)"
- prop="taxRate" />
+ prop="taxRate"
+ v-if="props.row.supplierType === 1" />
<el-table-column label="鍚◣鍗曚环(鍏�)"
prop="taxInclusiveUnitPrice"
- :formatter="formattedNumber" />
+ :formatter="formattedNumber"
+ v-if="props.row.supplierType === 1" />
<el-table-column label="鍚◣鎬讳环(鍏�)"
prop="taxInclusiveTotalPrice"
- :formatter="formattedNumber" />
+ :formatter="formattedNumber"
+ v-if="props.row.supplierType === 1" />
<el-table-column label="涓嶅惈绋庢�讳环(鍏�)"
prop="taxExclusiveTotalPrice"
- :formatter="formattedNumber" />
+ :formatter="formattedNumber"
+ v-if="props.row.supplierType === 1" />
+ <el-table-column label="鍗曚环锛堝绉侊級"
+ prop="unitPrice"
+ :formatter="formattedNumber"
+ v-if="props.row.supplierType === 2" />
+ <el-table-column label="鎬讳环锛堝绉侊級"
+ prop="totalPrice"
+ :formatter="formattedNumber"
+ v-if="props.row.supplierType === 2" />
</el-table>
</template>
</el-table-column>
@@ -119,12 +144,20 @@
show-overflow-tooltip />
<el-table-column label="閿�鍞悎鍚屽彿"
prop="salesContractNo"
- width="160"
+ width="160"
show-overflow-tooltip />
<el-table-column label="渚涘簲鍟嗗悕绉�"
prop="supplierName"
- width="160"
+ width="160"
show-overflow-tooltip />
+ <el-table-column label="渚涘簲鍟嗙被鍨�"
+ prop="supplierType"
+ width="100"
+ show-overflow-tooltip>
+ <template #default="scope">
+ {{ scope.row.supplierType === 1 ? '瀵瑰叕' : '瀵圭' }}
+ </template>
+ </el-table-column>
<el-table-column label="椤圭洰鍚嶇О"
prop="projectName"
width="320"
@@ -134,9 +167,8 @@
width="100"
show-overflow-tooltip>
<template #default="scope">
- <el-tag
- :type="getApprovalStatusType(scope.row.approvalStatus)"
- size="small">
+ <el-tag :type="getApprovalStatusType(scope.row.approvalStatus)"
+ size="small">
{{ approvalStatusText[scope.row.approvalStatus] || '鏈煡鐘舵��' }}
</el-tag>
</template>
@@ -189,12 +221,12 @@
@pagination="paginationChange" />
</div>
<FormDialog v-model="dialogFormVisible"
- :title="operationType === 'add' ? '鏂板閲囪喘鍙拌处椤甸潰' : '缂栬緫閲囪喘鍙拌处椤甸潰'"
- :width="'70%'"
- :operation-type="operationType"
- @close="closeDia"
- @confirm="submitForm"
- @cancel="closeDia">
+ :title="operationType === 'add' ? '鏂板閲囪喘鍙拌处椤甸潰' : '缂栬緫閲囪喘鍙拌处椤甸潰'"
+ :width="'70%'"
+ :operation-type="operationType"
+ @close="closeDia"
+ @confirm="submitForm"
+ @cancel="closeDia">
<el-form :model="form"
label-width="140px"
label-position="top"
@@ -232,11 +264,12 @@
<el-select v-model="form.supplierId"
placeholder="璇烽�夋嫨"
filterable
- clearable>
+ clearable
+ @change="handleSupplierChange">
<el-option v-for="item in supplierList"
:key="item.id"
:label="item.supplierName"
- :value="item.id" >{{item.supplierName + '---' + item.supplierType}}</el-option>
+ :value="item.id">{{item.supplierName + '---' + (item.supplierType === 1 ? item.taxpayerIdentificationNum || '鏃�' : '瀵圭')}}</el-option>
</el-select>
</el-form-item>
</el-col>
@@ -304,38 +337,33 @@
<template #label>
<div style="display: flex; align-items: center; justify-content: space-between; width: 100%;">
<span>瀹℃壒浜洪�夋嫨锛�</span>
- <el-button type="primary" size="small" @click="addApproverNode" icon="Plus">鏂板鑺傜偣</el-button>
+ <el-button type="primary"
+ size="small"
+ @click="addApproverNode"
+ icon="Plus">鏂板鑺傜偣</el-button>
</div>
</template>
<div class="approver-nodes-container">
- <div
- v-for="(node, index) in approverNodes"
- :key="node.id"
- class="approver-node-item"
- >
+ <div v-for="(node, index) in approverNodes"
+ :key="node.id"
+ class="approver-node-item">
<div class="approver-node-header">
<span class="approver-node-label">瀹℃壒鑺傜偣 {{ index + 1 }}</span>
- <el-button
- v-if="approverNodes.length > 1"
- type="danger"
- size="small"
- text
- @click="removeApproverNode(index)"
- icon="Delete"
- >鍒犻櫎</el-button>
+ <el-button v-if="approverNodes.length > 1"
+ type="danger"
+ size="small"
+ text
+ @click="removeApproverNode(index)"
+ icon="Delete">鍒犻櫎</el-button>
</div>
- <el-select
- v-model="node.userId"
- placeholder="璇烽�夋嫨瀹℃壒浜�"
- filterable
- style="width: 100%;"
- >
- <el-option
- v-for="user in userList"
- :key="user.userId"
- :label="user.nickName"
- :value="user.userId"
- />
+ <el-select v-model="node.userId"
+ placeholder="璇烽�夋嫨瀹℃壒浜�"
+ filterable
+ style="width: 100%;">
+ <el-option v-for="user in userList"
+ :key="user.userId"
+ :label="user.nickName"
+ :value="user.userId" />
</el-select>
</div>
</div>
@@ -346,6 +374,7 @@
<el-form-item label="浜у搧淇℃伅锛�"
prop="entryDate">
<el-button type="primary"
+ v-if="currentSupplierType"
@click="openProductForm('add')">娣诲姞</el-button>
<el-button plain
type="danger"
@@ -373,11 +402,10 @@
:value="item.templateName">
<div style="display: flex; justify-content: space-between; align-items: center;">
<span>{{ item.templateName }}</span>
- <el-icon
- v-if="item.id"
- class="delete-icon"
- @click.stop="handleDeleteTemplate(item)"
- style="cursor: pointer; color: #f56c6c; font-size: 14px; margin-left: 8px;">
+ <el-icon v-if="item.id"
+ class="delete-icon"
+ @click.stop="handleDeleteTemplate(item)"
+ style="cursor: pointer; color: #f56c6c; font-size: 14px; margin-left: 8px;">
<Delete />
</el-icon>
</div>
@@ -420,19 +448,33 @@
show-overflow-tooltip />
<el-table-column label="绋庣巼(%)"
prop="taxRate"
- width="80" />
+ width="80"
+ v-if="currentSupplierType === 1" />
<el-table-column label="鍚◣鍗曚环(鍏�)"
prop="taxInclusiveUnitPrice"
:formatter="formattedNumber"
- width="150" />
+ width="150"
+ v-if="currentSupplierType === 1" />
<el-table-column label="鍚◣鎬讳环(鍏�)"
prop="taxInclusiveTotalPrice"
:formatter="formattedNumber"
- width="150" />
+ width="150"
+ v-if="currentSupplierType === 1" />
<el-table-column label="涓嶅惈绋庢�讳环(鍏�)"
prop="taxExclusiveTotalPrice"
:formatter="formattedNumber"
- width="150" />
+ width="150"
+ v-if="currentSupplierType === 1" />
+ <el-table-column label="鍗曚环锛堝绉侊級"
+ prop="unitPrice"
+ :formatter="formattedNumber"
+ width="150"
+ v-if="currentSupplierType === 2" />
+ <el-table-column label="鎬讳环锛堝绉侊級"
+ prop="totalPrice"
+ :formatter="formattedNumber"
+ width="150"
+ v-if="currentSupplierType === 2" />
<el-table-column label="鏄惁璐ㄦ"
prop="isChecked"
width="150">
@@ -493,28 +535,24 @@
</el-form>
</FormDialog>
<!-- 瀵煎叆寮圭獥 -->
- <FormDialog
- v-model="importUpload.open"
- :title="importUpload.title"
- :width="'600px'"
- @close="importUpload.open = false"
- @confirm="submitImportFile"
- @cancel="importUpload.open = false"
- >
- <el-upload
- ref="importUploadRef"
- :limit="1"
- accept=".xlsx,.xls"
- :action="importUpload.url"
- :headers="importUpload.headers"
- :before-upload="importUpload.beforeUpload"
- :on-success="importUpload.onSuccess"
- :on-error="importUpload.onError"
- :on-progress="importUpload.onProgress"
- :on-change="importUpload.onChange"
- :auto-upload="false"
- drag
- >
+ <FormDialog v-model="importUpload.open"
+ :title="importUpload.title"
+ :width="'600px'"
+ @close="importUpload.open = false"
+ @confirm="submitImportFile"
+ @cancel="importUpload.open = false">
+ <el-upload ref="importUploadRef"
+ :limit="1"
+ accept=".xlsx,.xls"
+ :action="importUpload.url"
+ :headers="importUpload.headers"
+ :before-upload="importUpload.beforeUpload"
+ :on-success="importUpload.onSuccess"
+ :on-error="importUpload.onError"
+ :on-progress="importUpload.onProgress"
+ :on-change="importUpload.onChange"
+ :auto-upload="false"
+ drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text">
灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em>
@@ -522,22 +560,24 @@
<template #tip>
<div class="el-upload__tip">
浠呮敮鎸� xls/xlsx锛屽ぇ灏忎笉瓒呰繃 10MB銆�
- <el-button link type="primary" @click="downloadTemplate">涓嬭浇瀵煎叆妯℃澘</el-button>
+ <el-button link
+ type="primary"
+ @click="downloadTemplate">涓嬭浇瀵煎叆妯℃澘</el-button>
</div>
</template>
</el-upload>
</FormDialog>
<FormDialog v-model="productFormVisible"
- :title="productOperationType === 'add' ? '鏂板浜у搧' : '缂栬緫浜у搧'"
- :width="'40%'"
- :operation-type="productOperationType"
- @close="closeProductDia"
- @confirm="submitProduct"
- @cancel="closeProductDia">
+ :title="productOperationType === 'add' ? '鏂板浜у搧' : '缂栬緫浜у搧'"
+ :width="'40%'"
+ :operation-type="productOperationType"
+ @close="closeProductDia"
+ @confirm="submitProduct"
+ @cancel="closeProductDia">
<el-form :model="productForm"
label-width="140px"
label-position="top"
- :rules="productRules"
+ :rules="getProductRules()"
ref="productFormRef">
<el-row :gutter="30">
<el-col :span="24">
@@ -581,7 +621,8 @@
</el-col>
<el-col :span="12">
<el-form-item label="绋庣巼(%)锛�"
- prop="taxRate">
+ prop="taxRate"
+ v-if="currentSupplierType === 1">
<el-select v-model="productForm.taxRate"
placeholder="璇烽�夋嫨"
clearable
@@ -598,18 +639,6 @@
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="鍚◣鍗曚环(鍏�)锛�"
- prop="taxInclusiveUnitPrice">
- <el-input-number v-model="productForm.taxInclusiveUnitPrice"
- :precision="2"
- :step="0.1"
- :min="0"
- clearable
- style="width: 100%"
- @change="mathNum" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
<el-form-item label="鏁伴噺锛�"
prop="quantity">
<el-input-number :step="0.1"
@@ -619,14 +648,39 @@
style="width: 100%"
v-model="productForm.quantity"
placeholder="璇疯緭鍏�"
+ @change="currentSupplierType === 1 ? mathNum() : mathNumPrivate()" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍚◣鍗曚环(鍏�)锛�"
+ prop="taxInclusiveUnitPrice"
+ v-if="currentSupplierType === 1">
+ <el-input-number v-model="productForm.taxInclusiveUnitPrice"
+ :precision="2"
+ :step="0.1"
+ :min="0"
+ clearable
+ style="width: 100%"
@change="mathNum" />
+ </el-form-item>
+ <el-form-item label="鍗曚环锛堝绉侊級锛�"
+ prop="unitPrice"
+ v-else>
+ <el-input-number v-model="productForm.unitPrice"
+ :precision="2"
+ :step="0.1"
+ :min="0"
+ clearable
+ style="width: 100%"
+ @change="mathNumPrivate" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
<el-form-item label="鍚◣鎬讳环(鍏�)锛�"
- prop="taxInclusiveTotalPrice">
+ prop="taxInclusiveTotalPrice"
+ v-if="currentSupplierType === 1">
<el-input-number v-model="productForm.taxInclusiveTotalPrice"
:precision="2"
:step="0.1"
@@ -635,10 +689,34 @@
style="width: 100%"
@change="reverseMathNum('taxInclusiveTotalPrice')" />
</el-form-item>
+ <el-form-item label="鎬讳环锛堝绉侊級锛�"
+ prop="totalPrice"
+ v-else>
+ <el-input-number v-model="productForm.totalPrice"
+ :precision="2"
+ :step="0.1"
+ :min="0"
+ clearable
+ style="width: 100%"
+ @change="reverseMathNumPrivate('totalPrice')" />
+ </el-form-item>
+ </el-col>
+ <el-col v-if="currentSupplierType === 2"
+ :span="12">
+ <el-form-item label="搴撳瓨棰勮鏁伴噺锛�"
+ prop="warnNum">
+ <el-input-number v-model="productForm.warnNum"
+ :precision="2"
+ :step="0.1"
+ :min="0"
+ clearable
+ style="width: 100%" />
+ </el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="涓嶅惈绋庢�讳环(鍏�)锛�"
- prop="taxExclusiveTotalPrice">
+ prop="taxExclusiveTotalPrice"
+ v-if="currentSupplierType === 1">
<el-input-number v-model="productForm.taxExclusiveTotalPrice"
:precision="2"
:step="0.1"
@@ -652,7 +730,8 @@
<el-row :gutter="30">
<el-col :span="12">
<el-form-item label="鍙戠エ绫诲瀷锛�"
- prop="invoiceType">
+ prop="invoiceType"
+ v-if="currentSupplierType === 1">
<el-select v-model="productForm.invoiceType"
placeholder="璇烽�夋嫨"
clearable>
@@ -663,7 +742,8 @@
</el-select>
</el-form-item>
</el-col>
- <el-col :span="12">
+ <el-col v-if="currentSupplierType === 1"
+ :span="12">
<el-form-item label="搴撳瓨棰勮鏁伴噺锛�"
prop="warnNum">
<el-input-number v-model="productForm.warnNum"
@@ -690,11 +770,9 @@
</el-row>
</el-form>
</FormDialog>
- <FileListDialog
- ref="fileListRef"
- v-model="fileListDialogVisible"
- title="闄勪欢鍒楄〃"
- />
+ <FileListDialog ref="fileListRef"
+ v-model="fileListDialogVisible"
+ title="闄勪欢鍒楄〃" />
</div>
</template>
@@ -712,8 +790,8 @@
import { Search, Delete } from "@element-plus/icons-vue";
import { ElMessageBox, ElMessage } from "element-plus";
import { userListNoPage } from "@/api/system/user.js";
- import FormDialog from '@/components/Dialog/FormDialog.vue';
- import FileListDialog from '@/components/Dialog/FileListDialog.vue';
+ import FormDialog from "@/components/Dialog/FormDialog.vue";
+ import FileListDialog from "@/components/Dialog/FileListDialog.vue";
import {
getSalesLedgerWithProducts,
addOrUpdateSalesLedgerProduct,
@@ -748,6 +826,7 @@
const salesContractList = ref([]);
const supplierList = ref([]);
const tableLoading = ref(false);
+ const currentSupplierType = ref(null); // 璺熻釜褰撳墠閫夋嫨鐨勪緵搴斿晢绫诲瀷
const page = reactive({
current: 1,
size: 100,
@@ -766,11 +845,31 @@
const addApproverNode = () => {
approverNodes.value.push({ id: nextApproverId++, userId: null });
};
- const removeApproverNode = (index) => {
+ const removeApproverNode = index => {
approverNodes.value.splice(index, 1);
};
- // 璁㈠崟瀹℃壒鐘舵�佹樉绀烘枃鏈�
+ // 澶勭悊渚涘簲鍟嗛�夋嫨鍙樺寲
+ const handleSupplierChange = async supplierId => {
+ const selectedSupplier = supplierList.value.find(
+ item => item.id === supplierId
+ );
+ if (selectedSupplier) {
+ // 鍙湁褰撳綋鍓嶄緵搴斿晢绫诲瀷涓嶄负 null 涓斿彂鐢熷彉鍖栨椂锛屾墠娓呯┖浜у搧琛�
+ // 杩欐牱鍦ㄧ紪杈戞椂鍔犺浇鏁版嵁鍚庤皟鐢ㄨ鍑芥暟涓嶄細娓呯┖浜у搧鏁版嵁
+ if (
+ currentSupplierType.value !== null &&
+ currentSupplierType.value !== selectedSupplier.supplierType
+ ) {
+ productData.value = [];
+ }
+ currentSupplierType.value = selectedSupplier.supplierType;
+ } else {
+ currentSupplierType.value = null;
+ productData.value = [];
+ }
+ await getTemplateList();
+ };
const approvalStatusText = {
1: "寰呭鏍�",
2: "瀹℃壒涓�",
@@ -779,12 +878,12 @@
};
// 鑾峰彇瀹℃壒鐘舵�佹爣绛剧被鍨�
- const getApprovalStatusType = (status) => {
+ const getApprovalStatusType = status => {
const typeMap = {
- 1: "info", // 寰呭鏍� - 鐏拌壊
- 2: "warning", // 瀹℃壒涓� - 姗欒壊
- 3: "success", // 瀹℃壒閫氳繃 - 缁胯壊
- 4: "danger", // 瀹℃壒澶辫触 - 绾㈣壊
+ 1: "info", // 寰呭鏍� - 鐏拌壊
+ 2: "warning", // 瀹℃壒涓� - 姗欒壊
+ 3: "success", // 瀹℃壒閫氳繃 - 缁胯壊
+ 4: "danger", // 瀹℃壒澶辫触 - 绾㈣壊
};
return typeMap[status] || "";
};
@@ -866,7 +965,8 @@
form.value.paymentMethod = matchedTemplate.paymentMethod;
}
// 妯℃澘鏁版嵁涓殑浜у搧瀛楁鏄� productList锛岄渶瑕佽浆鎹负 productData
- productData.value = matchedTemplate.productList || matchedTemplate.productData || [];
+ productData.value =
+ matchedTemplate.productList || matchedTemplate.productData || [];
} else {
// 鏈尮閰嶅埌宸叉湁妯℃澘锛岃涓烘柊妯℃澘
currentTemplateId.value = null;
@@ -902,6 +1002,7 @@
entryDate: null, // 褰曞叆鏃ユ湡
entryDateStart: undefined,
entryDateEnd: undefined,
+ supplierType: "", // 渚涘簲鍟嗙被鍨�
},
form: {
purchaseContractNumber: "",
@@ -985,6 +1086,43 @@
},
});
const { productForm, productRules } = toRefs(productFormData);
+ const getProductRules = () => {
+ const baseRules = {
+ productId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ warnNum: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ isChecked: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ };
+
+ if (currentSupplierType.value === 1) {
+ // 瀵瑰叕渚涘簲鍟嗛渶瑕侀獙璇佺殑瀛楁
+ return {
+ ...baseRules,
+ taxInclusiveUnitPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ taxInclusiveTotalPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ taxExclusiveTotalPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ };
+ } else if (currentSupplierType.value === 2) {
+ // 瀵圭渚涘簲鍟嗛渶瑕侀獙璇佺殑瀛楁
+ return {
+ ...baseRules,
+ unitPrice: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ totalPrice: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ };
+ } else {
+ return baseRules;
+ }
+ };
const upload = reactive({
// 涓婁紶鐨勫湴鍧�
url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
@@ -1000,7 +1138,7 @@
url: import.meta.env.VITE_APP_BASE_API + "/purchase/ledger/import",
headers: { Authorization: "Bearer " + getToken() },
isUploading: false,
- beforeUpload: (file) => {
+ beforeUpload: file => {
const isExcel = file.name.endsWith(".xlsx") || file.name.endsWith(".xls");
const isLt10M = file.size / 1024 / 1024 < 10;
if (!isExcel) {
@@ -1049,7 +1187,11 @@
// 涓嬭浇瀵煎叆妯℃澘锛堝鍚庣璺緞涓嶅悓锛屽彲鍦ㄦ澶勮皟鏁达級
const downloadTemplate = () => {
- proxy.download("/purchase/ledger/exportTemplate", {}, "閲囪喘鍙拌处瀵煎叆妯℃澘.xlsx");
+ proxy.download(
+ "/purchase/ledger/exportTemplate",
+ {},
+ "閲囪喘鍙拌处瀵煎叆妯℃澘.xlsx"
+ );
};
const submitImportFile = () => {
@@ -1114,8 +1256,8 @@
// 妫�鏌ユ槸鍚︽湁浜у搧鏁版嵁
if (!productData.value || productData.value.length === 0) {
ElMessage({
- message: '璇峰厛娣诲姞浜у搧淇℃伅',
- type: 'warning',
+ message: "璇峰厛娣诲姞浜у搧淇℃伅",
+ type: "warning",
});
return;
}
@@ -1126,7 +1268,7 @@
.filter(node => node.userId)
.map(node => node.userId)
.join(",");
-
+
let params = {
productData: proxy.HaveJson(productData.value),
supplierId: form.value.supplierId,
@@ -1136,7 +1278,12 @@
approveUserIds: approveUserIds,
templateName: templateName.value.trim(),
};
- console.log("template params ===>", params, "currentTemplateId:", currentTemplateId.value);
+ console.log(
+ "template params ===>",
+ params,
+ "currentTemplateId:",
+ currentTemplateId.value
+ );
// 濡傛灉 currentTemplateId 鏈夊�硷紝璇存槑褰撳墠鏄�滅紪杈戝凡鏈夋ā鏉库�� 鈫� 璋冪敤鏇存柊鎺ュ彛
// 鍚﹀垯涓衡�滄柊寤烘ā鏉库�� 鈫� 璋冪敤鏂板鎺ュ彛
@@ -1147,7 +1294,10 @@
...params,
});
} else {
- res = await addPurchaseTemplate(params);
+ res = await addPurchaseTemplate({
+ ...params,
+ templateType: currentSupplierType.value,
+ });
}
if (res && res.code === 200) {
@@ -1179,22 +1329,34 @@
};
// 瀛愯〃鍚堣鏂规硶
const summarizeChildrenTable = param => {
- return proxy.summarizeTable(
- param,
- [
+ // 妫�鏌ユ槸鍚︽湁鏁版嵁锛屼互鍙婃暟鎹殑渚涘簲鍟嗙被鍨�
+ const hasData = param && param.data && param.data.length > 0;
+ const supplierType = hasData ? param.data[0].supplierType : null;
+
+ // 鏍规嵁渚涘簲鍟嗙被鍨嬬‘瀹氳鍚堣鐨勫瓧娈�
+ const fields = [
+ "ticketsNum",
+ "ticketsAmount",
+ "futureTickets",
+ "futureTicketsAmount",
+ ];
+
+ if (supplierType === 1) {
+ // 瀵瑰叕渚涘簲鍟�
+ fields.unshift(
"taxInclusiveUnitPrice",
"taxInclusiveTotalPrice",
- "taxExclusiveTotalPrice",
- "ticketsNum",
- "ticketsAmount",
- "futureTickets",
- "futureTicketsAmount",
- ],
- {
- ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
- }
- );
+ "taxExclusiveTotalPrice"
+ );
+ } else if (supplierType === 2) {
+ // 瀵圭渚涘簲鍟�
+ fields.unshift("unitPrice", "totalPrice");
+ }
+
+ return proxy.summarizeTable(param, fields, {
+ ticketsNum: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+ futureTickets: { noDecimal: true }, // 涓嶄繚鐣欏皬鏁�
+ });
};
const paginationChange = obj => {
page.current = obj.page;
@@ -1238,7 +1400,12 @@
const res = await productList({ salesLedgerId: row.id, type: 2 });
const index = tableData.value.findIndex(item => item.id === row.id);
if (index > -1) {
- tableData.value[index].children = res.data || [];
+ // 涓哄瓙琛ㄦ牸鏁版嵁娣诲姞渚涘簲鍟嗙被鍨嬩俊鎭�
+ const children = (res.data || []).map(item => ({
+ ...item,
+ supplierType: row.supplierType, // 浠庣埗琛岃幏鍙栦緵搴斿晢绫诲瀷
+ }));
+ tableData.value[index].children = children;
expandedRowKeys.value.push(row.id);
}
} catch (error) {
@@ -1260,11 +1427,17 @@
};
// 瀛愯〃鍚堣鏂规硶
const summarizeProTable = param => {
- return proxy.summarizeTable(param, [
- "taxInclusiveUnitPrice",
- "taxInclusiveTotalPrice",
- "taxExclusiveTotalPrice",
- ]);
+ const fields = [];
+ if (currentSupplierType.value === 1) {
+ fields.push(
+ "taxInclusiveUnitPrice",
+ "taxInclusiveTotalPrice",
+ "taxExclusiveTotalPrice"
+ );
+ } else if (currentSupplierType.value === 2) {
+ fields.push("unitPrice", "totalPrice");
+ }
+ return proxy.summarizeTable(param, fields);
};
// 鎵撳紑寮规
const openForm = async (type, row) => {
@@ -1275,8 +1448,8 @@
return;
}
}
-
- await getTemplateList();
+ currentSupplierType.value = null;
+
operationType.value = type;
form.value = {};
productData.value = [];
@@ -1307,6 +1480,7 @@
form.value.entryDate = getCurrentDate();
if (type === "add") {
+ await getTemplateList();
// 鏂板鏃剁敓鎴愰噰璐悎鍚屽彿
try {
const purchaseNoRes = await createPurchaseNo();
@@ -1330,9 +1504,13 @@
const approverIds = purchaseRes.approveUserIds.split(",");
approverNodes.value = approverIds.map((id, index) => ({
id: index + 1,
- userId: Number(id)
+ userId: Number(id),
}));
nextApproverId = approverIds.length + 1;
+ }
+ // 璁剧疆褰撳墠渚涘簲鍟嗙被鍨�
+ if (form.value.supplierId) {
+ handleSupplierChange(form.value.supplierId);
}
} catch (error) {
console.error("鍔犺浇閲囪喘鍙拌处鏁版嵁澶辫触:", error);
@@ -1408,8 +1586,10 @@
proxy.$modal.msgError("璇蜂负鎵�鏈夊鎵硅妭鐐归�夋嫨瀹℃壒浜猴紒");
return;
}
- const approveUserIds = approverNodes.value.map(node => node.userId).join(",");
-
+ const approveUserIds = approverNodes.value
+ .map(node => node.userId)
+ .join(",");
+
if (productData.value.length > 0) {
// 鏂板鏃讹紝闇�瑕佷粠姣忎釜浜у搧瀵硅薄涓垹闄� id 瀛楁
let processedProductData = productData.value;
@@ -1438,7 +1618,10 @@
}
// 鏂板鏃朵笉浼犻�抜d
- const submitData = { ...form.value };
+ const submitData = {
+ ...form.value,
+ purchaseType: currentSupplierType.value,
+ };
if (operationType.value === "add") {
delete submitData.id;
}
@@ -1463,20 +1646,39 @@
const openProductForm = async (type, row, index) => {
productOperationType.value = type;
productOperationIndex.value = index;
- productForm.value = {};
+ productForm.value = {
+ productId: "",
+ productCategory: "",
+ productModelId: "",
+ specificationModel: "",
+ unit: "",
+ quantity: "",
+ // 瀵瑰叕瀛楁
+ taxInclusiveUnitPrice: "",
+ taxRate: "",
+ taxInclusiveTotalPrice: "",
+ taxExclusiveTotalPrice: "",
+ invoiceType: "",
+ // 瀵圭瀛楁
+ unitPrice: "",
+ totalPrice: "",
+ // 鍏叡瀛楁
+ warnNum: "",
+ isChecked: true,
+ };
proxy.resetForm("productFormRef");
productFormVisible.value = true;
-
+
// 鍏堣幏鍙栦骇鍝侀�夐」锛岀‘淇濇暟鎹姞杞藉畬鎴�
await getProductOptions();
-
+
// 绛夊緟 DOM 鏇存柊
await nextTick();
-
+
if (type === "edit") {
// 澶嶅埗琛屾暟鎹�
productForm.value = { ...row };
-
+
// 濡傛灉鏄粠妯℃澘鍔犺浇鐨勬暟鎹紝鍙兘娌℃湁 productId 鍜� productModelId
// 闇�瑕佹牴鎹� productCategory 鍜� specificationModel 鏉ユ煡鎵惧搴旂殑 ID
if (!productForm.value.productId && productForm.value.productCategory) {
@@ -1487,25 +1689,34 @@
return nodes[i].value;
}
if (nodes[i].children && nodes[i].children.length > 0) {
- const found = findProductIdByCategory(nodes[i].children, categoryName);
+ const found = findProductIdByCategory(
+ nodes[i].children,
+ categoryName
+ );
if (found) return found;
}
}
return null;
};
-
- const productId = findProductIdByCategory(productOptions.value, productForm.value.productCategory);
+
+ const productId = findProductIdByCategory(
+ productOptions.value,
+ productForm.value.productCategory
+ );
if (productId) {
productForm.value.productId = productId;
// 鑾峰彇鍨嬪彿鍒楄〃骞剁瓑寰呭畬鎴�
const modelRes = await modelList({ id: productId });
modelOptions.value = modelRes;
-
+
// 绛夊緟 DOM 鏇存柊
await nextTick();
-
+
// 鏍规嵁 specificationModel 鏌ユ壘 productModelId
- if (productForm.value.specificationModel && modelOptions.value.length > 0) {
+ if (
+ productForm.value.specificationModel &&
+ modelOptions.value.length > 0
+ ) {
const modelItem = modelOptions.value.find(
item => item.model === productForm.value.specificationModel
);
@@ -1519,15 +1730,15 @@
} else if (productForm.value.productId) {
// 濡傛灉鏈� productId锛屾甯稿姞杞藉瀷鍙峰垪琛�
await getModels(productForm.value.productId);
-
+
// 绛夊緟 DOM 鏇存柊
await nextTick();
-
+
if (productForm.value.productModelId) {
getProductModel(productForm.value.productModelId);
}
}
-
+
// 鏈�鍚庡啀绛夊緟涓�娆� DOM 鏇存柊锛岀‘淇濇墍鏈夋暟鎹兘宸茶缃�
await nextTick();
}
@@ -1611,15 +1822,21 @@
});
};
const submitProductEdit = () => {
- productForm.value.salesLedgerId = currentId.value;
- productForm.value.type = 2;
- addOrUpdateSalesLedgerProduct(productForm.value).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeProductDia();
- getPurchaseById({ id: currentId.value, type: 2 }).then(res => {
- productData.value = res.productData;
- });
- });
+ // 鐩存帴淇敼鏈湴鏁版嵁锛屼笉鍐嶈皟鐢ㄦ帴鍙�
+ if (productOperationType.value === "add") {
+ // 鏂板浜у搧
+ productData.value.push({ ...productForm.value });
+ } else if (productOperationType.value === "edit") {
+ // 缂栬緫浜у搧
+ if (
+ productOperationIndex.value !== "" &&
+ productOperationIndex.value !== null
+ ) {
+ productData.value[productOperationIndex.value] = { ...productForm.value };
+ }
+ }
+ proxy.$modal.msgSuccess("鎿嶄綔鎴愬姛");
+ closeProductDia();
};
// 鍒犻櫎浜у搧
const deleteProduct = () => {
@@ -1627,40 +1844,27 @@
proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
return;
}
- if (operationType.value === "add") {
- productSelectedRows.value.forEach(selectedRow => {
- const index = productData.value.findIndex(
- product => product.id === selectedRow.id
- );
- if (index !== -1) {
- productData.value.splice(index, 1);
- }
- });
- } else {
- let ids = [];
- if (productSelectedRows.value.length > 0) {
- ids = productSelectedRows.value.map(item => item.id);
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- delProduct(ids).then(res => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- closeProductDia();
- getPurchaseById({ id: currentId.value, type: 2 }).then(
- res => {
- productData.value = res.productData;
- }
- );
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
+ // 鐩存帴浠庢湰鍦版暟鎹腑鍒犻櫎锛屼笉鍐嶈皟鐢ㄦ帴鍙�
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ productSelectedRows.value.forEach(selectedRow => {
+ const index = productData.value.findIndex(
+ product => product.id === selectedRow.id
+ );
+ if (index !== -1) {
+ productData.value.splice(index, 1);
+ }
});
- }
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ closeProductDia();
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
};
// 鍏抽棴浜у搧寮规
const closeProductDia = () => {
@@ -1826,6 +2030,27 @@
}
}
};
+
+ // 瀵圭渚涘簲鍟嗙殑浠锋牸璁$畻
+ const mathNumPrivate = () => {
+ const { unitPrice, quantity } = productForm.value;
+ if (unitPrice && quantity) {
+ productForm.value.totalPrice = (unitPrice * quantity).toFixed(2);
+ }
+ };
+
+ // 瀵圭渚涘簲鍟嗙殑鍙嶅悜浠锋牸璁$畻
+ const reverseMathNumPrivate = type => {
+ const { unitPrice, quantity, totalPrice } = productForm.value;
+ if (type === "totalPrice") {
+ if (quantity) {
+ productForm.value.unitPrice = (totalPrice / quantity).toFixed(2);
+ } else if (unitPrice) {
+ productForm.value.quantity = (totalPrice / unitPrice).toFixed(2);
+ }
+ }
+ };
+
// 閿�鍞悎鍚岄�夋嫨鏀瑰彉鏂规硶
const salesLedgerChange = async row => {
console.log("row", row);
@@ -1855,19 +2080,26 @@
// 鑾峰彇妯℃澘淇℃伅
const getTemplateList = async () => {
- let res = await getPurchaseTemplateList();
- if (res && res.code === 200 && Array.isArray(res.data)) {
- templateList.value = res.data;
+ console.log("currentSupplierType.value", currentSupplierType.value);
+ if (currentSupplierType.value) {
+ let res = await getPurchaseTemplateList({
+ templateType: currentSupplierType.value,
+ });
+ if (res && res.code === 200 && Array.isArray(res.data)) {
+ templateList.value = res.data;
+ }
+ } else {
+ templateList.value = [];
}
};
// 鍒犻櫎妯℃澘
- const handleDeleteTemplate = async (item) => {
+ const handleDeleteTemplate = async item => {
if (!item.id) {
proxy.$modal.msgWarning("鏃犳硶鍒犻櫎璇ユā鏉�");
return;
}
-
+
try {
await ElMessageBox.confirm(
`纭畾瑕佸垹闄ゆā鏉�"${item.templateName}"鍚楋紵`,
@@ -1878,7 +2110,7 @@
type: "warning",
}
);
-
+
const res = await delPurchaseTemplate([item.id]);
if (res && res.code === 200) {
ElMessage({
@@ -1931,7 +2163,7 @@
display: flex;
align-items: center;
}
-
+
// 瀹℃壒浜鸿妭鐐瑰鍣ㄦ牱寮�
.approver-nodes-container {
display: flex;
@@ -1942,7 +2174,7 @@
border-radius: 4px;
border: 1px solid #e4e7ed;
}
-
+
.approver-node-item {
flex: 0 0 calc(33.333% - 12px);
min-width: 200px;
@@ -1951,38 +2183,38 @@
border-radius: 4px;
border: 1px solid #dcdfe6;
transition: all 0.3s;
-
+
&:hover {
border-color: #409eff;
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1);
}
}
-
+
.approver-node-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
-
+
.approver-node-label {
font-size: 13px;
font-weight: 500;
color: #606266;
}
-
+
@media (max-width: 1200px) {
.approver-node-item {
flex: 0 0 calc(50% - 8px);
}
}
-
+
@media (max-width: 768px) {
.approver-node-item {
flex: 0 0 100%;
}
}
-
+
// 鍒犻櫎鍥炬爣鏍峰紡
.delete-icon {
transition: all 0.3s;
diff --git a/src/views/productionManagement/productionCosting/index.vue b/src/views/productionManagement/productionCosting/index.vue
index 8e1d40b..19736e3 100644
--- a/src/views/productionManagement/productionCosting/index.vue
+++ b/src/views/productionManagement/productionCosting/index.vue
@@ -1,371 +1,387 @@
<template>
- <div class="app-container">
- <el-row :gutter="16" class="content-row">
- <!-- 宸︿晶鍙拌处 + 椤堕儴绛涢�� -->
- <el-col :xs="24" :sm="24" :md="24" :lg="8" :xl="8" class="left-col">
- <div class="left-panel">
- <div class="left-header">
- <el-form :model="searchForm" inline>
- <el-form-item prop="dateType">
- <el-radio-group v-model="searchForm.dateType" size="small" @change="handleDateTypeChange">
- <el-radio-button label="day">鏃�</el-radio-button>
- <el-radio-button label="month">鏈�</el-radio-button>
- </el-radio-group>
- </el-form-item>
-
- <el-form-item label="鏃ユ湡锛�" prop="dateRange">
- <el-date-picker
- v-model="searchForm.dateRange"
- :type="searchForm.dateType === 'day' ? 'date' : 'daterange'"
- range-separator="鑷�"
- start-placeholder="寮�濮嬫棩鏈�"
- end-placeholder="缁撴潫鏃ユ湡"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- style="width: 200px"
- @change="handleDateRangeChange"
- />
+ <div class="app-container">
+ <el-row :gutter="16"
+ class="content-row">
+ <!-- 宸︿晶鍙拌处 + 椤堕儴绛涢�� -->
+ <el-col :xs="24"
+ :sm="24"
+ :md="24"
+ :lg="8"
+ :xl="8"
+ class="left-col">
+ <div class="left-panel">
+ <div class="left-header">
+ <el-form :model="searchForm"
+ inline>
+ <el-form-item prop="dateType">
+ <el-radio-group v-model="searchForm.dateType"
+ size="small"
+ @change="handleDateTypeChange">
+ <el-radio-button label="day">鏃�</el-radio-button>
+ <el-radio-button label="month">鏈�</el-radio-button>
+ </el-radio-group>
+ </el-form-item>
+ <el-form-item label="鏃ユ湡锛�"
+ prop="dateRange">
+ <el-date-picker v-model="searchForm.dateRange"
+ :type="searchForm.dateType === 'day' ? 'date' : 'daterange'"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
+ style="width: 200px"
+ @change="handleDateRangeChange" />
+ </el-form-item>
+ </el-form>
+ </div>
+ <PIMTable rowKey="id"
+ :column="leftTableColumn"
+ :tableData="leftTableData"
+ :tableLoading="tableLoading"
+ :page="page"
+ @row-click="handleLeftRowClick"
+ @pagination="pagination"></PIMTable>
+ </div>
+ </el-col>
+ <!-- 鍙充晶鏄庣粏 -->
+ <el-col :xs="24"
+ :sm="24"
+ :md="24"
+ :lg="16"
+ :xl="16"
+ class="right-col">
+ <div class="right-panel">
+ <el-form inline>
+ <el-form-item>
+ <el-button type="primary"
+ @click="handleOut">瀵煎嚭</el-button>
</el-form-item>
</el-form>
- </div>
- <PIMTable
- rowKey="id"
- :column="leftTableColumn"
- :tableData="leftTableData"
- :tableLoading="tableLoading"
- :page="page"
- @row-click="handleLeftRowClick"
- @pagination="pagination"
- ></PIMTable>
- </div>
- </el-col>
-
- <!-- 鍙充晶鏄庣粏 -->
- <el-col :xs="24" :sm="24" :md="24" :lg="16" :xl="16" class="right-col">
- <div class="right-panel">
-
- <el-form inline>
- <el-form-item>
- <el-button type="primary" @click="handleOut">瀵煎嚭</el-button>
- </el-form-item>
- </el-form>
- <PIMTable
- rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :page="page1"
- :tableLoading="tableLoading1"
- style="margin-right: 20px;"
- @pagination="pagination1"
- ></PIMTable>
- </div>
- </el-col>
- </el-row>
- </div>
+ <PIMTable rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page1"
+ :tableLoading="tableLoading1"
+ style="margin-right: 20px;"
+ @pagination="pagination1"></PIMTable>
+ </div>
+ </el-col>
+ </el-row>
+ </div>
</template>
<script setup>
-import {onMounted, ref} from "vue";
-import { ElMessageBox } from "element-plus";
-import dayjs from "dayjs";
-import {salesLedgerProductionAccountingListProductionDetails, salesLedgerProductionAccountingList} from "@/api/productionManagement/productionCosting.js";
-const { proxy } = getCurrentInstance();
+ import { onMounted, ref } from "vue";
+ import { ElMessageBox } from "element-plus";
+ import dayjs from "dayjs";
+ import {
+ salesLedgerProductionAccountingListProductionDetails,
+ salesLedgerProductionAccountingList,
+ } from "@/api/productionManagement/productionCosting.js";
+ const { proxy } = getCurrentInstance();
-const tableColumn = ref([
- {
- label: "鐢熶骇鏃ユ湡",
- prop: "schedulingDate",
- minWidth: 100,
- },
- {
- label: "鐢熶骇浜�",
- prop: "schedulingUserName",
- minWidth: 100,
- },
- {
- label: "鍚堝悓鍙�",
- prop: "salesContractNo",
- minWidth: 100,
- },
- {
- label: "瀹㈡埛鍚嶇О",
- prop: "customerName",
- minWidth: 100,
- },
- {
- label: "浜у搧澶х被",
- prop: "productName",
- minWidth: 100,
- },
- {
- label: "瑙勬牸鍨嬪彿",
- prop: "productModelName",
- minWidth: 100,
- },
- {
- label: "鍗曚綅",
- prop: "unit",
- minWidth: 100,
- },
- {
- label: "宸ュ簭",
- prop: "process",
- minWidth: 100,
- },
- {
- label: "鐢熶骇鏁伴噺",
- prop: "quantity",
- minWidth: 100,
- },
- {
- label: "宸ユ椂瀹氶",
- prop: "workHours",
- minWidth: 100,
- },
- {
- label: "宸ヨ祫",
- prop: "wages",
- minWidth: 100,
- },
-]);
-
-// 宸︿晶姹囨�诲彴璐﹀垪锛堢敓浜т汉銆佷骇閲忋�佸伐璧勩�佸悎鏍肩巼锛�
-const leftTableColumn = ref([
- {
- label: "鐢熶骇浜�",
- prop: "schedulingUserName",
- minWidth: 100,
- },
- {
- label: "浜ч噺",
- prop: "outputNum",
- minWidth: 100,
-
- },
- {
- label: "宸ヨ祫",
- prop: "wages",
- minWidth: 100,
-
- },
- {
- label: "鍚堟牸鐜�",
- prop: "outputRate",
- minWidth: 100,
- formatData: (val) => {
- if (val == null || val === '') return '-'
- return parseFloat(val).toFixed(2)
+ const tableColumn = ref([
+ {
+ label: "鐢熶骇鏃ユ湡",
+ prop: "schedulingDate",
+ minWidth: 100,
},
- },
-]);
+ {
+ label: "鐢熶骇浜�",
+ prop: "schedulingUserName",
+ minWidth: 100,
+ },
+ // {
+ // label: "鍚堝悓鍙�",
+ // prop: "salesContractNo",
+ // minWidth: 100,
+ // },
+ // {
+ // label: "瀹㈡埛鍚嶇О",
+ // prop: "customerName",
+ // minWidth: 100,
+ // },
+ {
+ label: "浜у搧澶х被",
+ prop: "productName",
+ minWidth: 100,
+ },
+ {
+ label: "瑙勬牸鍨嬪彿",
+ prop: "productModelName",
+ minWidth: 100,
+ },
+ {
+ label: "鍗曚綅",
+ prop: "unit",
+ minWidth: 100,
+ },
+ {
+ label: "宸ュ簭",
+ prop: "process",
+ minWidth: 100,
+ },
+ {
+ label: "鐢熶骇鏁伴噺",
+ prop: "quantity",
+ minWidth: 100,
+ },
+ {
+ label: "宸ユ椂瀹氶",
+ prop: "workHours",
+ minWidth: 100,
+ },
+ {
+ label: "宸ヨ祫",
+ prop: "wages",
+ minWidth: 100,
+ },
+ ]);
-const tableData = ref([]);
-const tableLoading = ref(false);
-const tableLoading1 = ref(false);
-const leftTableData = ref([]);
-// 鏃� / 鏈� 鍒囨崲锛堥粯璁ゆ寜鏃ワ級
-const page = reactive({
- current: 1,
- size: 100,
- total: 0,
-});
+ // 宸︿晶姹囨�诲彴璐﹀垪锛堢敓浜т汉銆佷骇閲忋�佸伐璧勩�佸悎鏍肩巼锛�
+ const leftTableColumn = ref([
+ {
+ label: "鐢熶骇浜�",
+ prop: "schedulingUserName",
+ minWidth: 100,
+ },
+ {
+ label: "浜ч噺",
+ prop: "outputNum",
+ minWidth: 100,
+ },
+ {
+ label: "宸ヨ祫",
+ prop: "wages",
+ minWidth: 100,
+ },
+ {
+ label: "鍚堟牸鐜�",
+ prop: "outputRate",
+ minWidth: 100,
+ formatData: val => {
+ if (val == null || val === "") return "-";
+ return parseFloat(val).toFixed(2);
+ },
+ },
+ ]);
-const page1 = reactive({
- current: 1,
- size: 100,
- total: 0,
-});
+ const tableData = ref([]);
+ const tableLoading = ref(false);
+ const tableLoading1 = ref(false);
+ const leftTableData = ref([]);
+ // 鏃� / 鏈� 鍒囨崲锛堥粯璁ゆ寜鏃ワ級
+ const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+ });
-const data = reactive({
- searchForm: {
- schedulingUserName: "",
- salesContractNo: "",
- dateType: "day",
- dateRange: dayjs().format("YYYY-MM-DD"),
- entryDate: dayjs().format("YYYY-MM-DD"),
- entryDateStart: undefined,
- entryDateEnd: undefined,
- },
-});
-const { searchForm } = toRefs(data);
+ const page1 = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+ });
-const pagination = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
+ const data = reactive({
+ searchForm: {
+ schedulingUserName: "",
+ salesContractNo: "",
+ dateType: "day",
+ dateRange: dayjs().format("YYYY-MM-DD"),
+ entryDate: dayjs().format("YYYY-MM-DD"),
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
+ },
+ });
+ const { searchForm } = toRefs(data);
-const pagination1 = (obj) => {
- page1.current = obj.page;
- page1.size = obj.limit;
- getList1();
-};
+ const pagination = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+ };
-const handleDateRangeChange = (value) => {
- if (value) {
- if (searchForm.value.dateType === "day") {
- searchForm.value.entryDate = value;
+ const pagination1 = obj => {
+ page1.current = obj.page;
+ page1.size = obj.limit;
+ getList1();
+ };
+
+ const handleDateRangeChange = value => {
+ if (value) {
+ if (searchForm.value.dateType === "day") {
+ searchForm.value.entryDate = value;
+ } else {
+ searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+ searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+ }
} else {
- searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
- searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+ searchForm.value.entryDate = undefined;
+ searchForm.value.entryDateStart = undefined;
+ searchForm.value.entryDateEnd = undefined;
+ }
+ reloadData();
+ };
+
+ const getList = () => {
+ tableLoading.value = true;
+ const params = { ...searchForm.value, ...page };
+
+ salesLedgerProductionAccountingList(params)
+ .then(res => {
+ const records = res.data.records || [];
+ leftTableData.value = records;
+ page.total = res.data.total || 0;
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ };
+
+ const getList1 = () => {
+ tableLoading1.value = true;
+ const params = { ...page1, ...searchForm.value };
+ salesLedgerProductionAccountingListProductionDetails(params)
+ .then(res => {
+ tableData.value = res.data.records || [];
+ page1.total = res.data.total || 0;
+ })
+ .finally(() => {
+ tableLoading1.value = false;
+ });
+ };
+
+ // 鏋勫缓宸︿晶姹囨�诲彴璐︼紙鎸夌敓浜т汉姹囨�讳骇閲忋�佸伐璧勭瓑锛�
+ const buildLeftTableData = records => {
+ const map = {};
+ records.forEach(item => {
+ const key = item.schedulingUserName || "鏈煡";
+ if (!map[key]) {
+ map[key] = {
+ id: key,
+ schedulingUserName: key,
+ finishedNum: 0,
+ wages: 0,
+ qualifiedRate: item.qualifiedRate ?? null,
+ };
+ }
+ map[key].finishedNum += Number(item.finishedNum || 0);
+ map[key].wages += Number(item.wages || 0);
+ if (item.qualifiedRate != null) {
+ map[key].qualifiedRate = item.qualifiedRate;
+ }
+ });
+ leftTableData.value = Object.values(map);
+ };
+
+ // 宸︿晶鏃�/鏈堝垏鎹�
+ const handleDateTypeChange = value => {
+ // 杩欓噷鍙綔涓虹瓫閫夋潯浠剁殑涓�閮ㄥ垎锛岀洿鎺ラ噸鏂版煡璇㈠垪琛�
+ if (value === "day") {
+ searchForm.value.entryDate = dayjs().format("YYYY-MM-DD");
+ searchForm.value.dateRange = searchForm.value.entryDate;
+ } else {
+ searchForm.value.entryDateStart = dayjs()
+ .startOf("month")
+ .format("YYYY-MM-DD");
+ searchForm.value.entryDateEnd = dayjs().endOf("month").format("YYYY-MM-DD");
+ searchForm.value.dateRange = [
+ searchForm.value.entryDateStart,
+ searchForm.value.entryDateEnd,
+ ];
}
- } else {
- searchForm.value.entryDate = undefined;
- searchForm.value.entryDateStart = undefined;
- searchForm.value.entryDateEnd = undefined;
- }
- reloadData()
-};
+ reloadData();
+ };
-const getList = () => {
- tableLoading.value = true;
- const params = { ...searchForm.value, ...page };
+ const reloadData = () => {
+ page.current = 1;
+ page1.current = 1;
+ getList();
+ tableData.value = [];
+ };
- salesLedgerProductionAccountingList(params).then((res) => {
- const records = res.data.records || [];
- leftTableData.value = records;
- page.total = res.data.total || 0;
- }).finally(() => {
- tableLoading.value = false;
- })
+ // 鐐瑰嚮宸︿晶琛岋紝鍒峰彸渚ф槑缁嗭紙鎸夌敓浜т汉杩囨护锛�
+ const handleLeftRowClick = row => {
+ searchForm.value.schedulingUserName = row.schedulingUserName || "";
+ handleQuery();
+ };
+ // 鏌ヨ鍒楄〃
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ const handleQuery = () => {
+ page1.current = 1;
+ getList1();
+ };
+ // 瀵煎嚭
+ const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download(
+ "/salesLedger/productionAccounting/export",
+ {},
+ "鐢熶骇鏍哥畻.xlsx"
+ );
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ };
-};
-
-const getList1 = () => {
- tableLoading1.value = true;
- const params = { ...page1, ...searchForm.value };
- salesLedgerProductionAccountingListProductionDetails(params).then((res) => {
- tableData.value = res.data.records || [];;
- page1.total = res.data.total || 0;
- }).finally(() => {
- tableLoading1.value = false;
- })
-};
-
-// 鏋勫缓宸︿晶姹囨�诲彴璐︼紙鎸夌敓浜т汉姹囨�讳骇閲忋�佸伐璧勭瓑锛�
-const buildLeftTableData = (records) => {
- const map = {};
- records.forEach((item) => {
- const key = item.schedulingUserName || "鏈煡";
- if (!map[key]) {
- map[key] = {
- id: key,
- schedulingUserName: key,
- finishedNum: 0,
- wages: 0,
- qualifiedRate: item.qualifiedRate ?? null,
- };
- }
- map[key].finishedNum += Number(item.finishedNum || 0);
- map[key].wages += Number(item.wages || 0);
- if (item.qualifiedRate != null) {
- map[key].qualifiedRate = item.qualifiedRate;
- }
- });
- leftTableData.value = Object.values(map);
-};
-
-// 宸︿晶鏃�/鏈堝垏鎹�
-const handleDateTypeChange = (value) => {
- // 杩欓噷鍙綔涓虹瓫閫夋潯浠剁殑涓�閮ㄥ垎锛岀洿鎺ラ噸鏂版煡璇㈠垪琛�
- if (value === "day") {
- searchForm.value.entryDate = dayjs().format("YYYY-MM-DD");
- searchForm.value.dateRange = searchForm.value.entryDate
- } else {
- searchForm.value.entryDateStart = dayjs().startOf("month").format("YYYY-MM-DD");
- searchForm.value.entryDateEnd = dayjs().endOf("month").format("YYYY-MM-DD");
- searchForm.value.dateRange = [searchForm.value.entryDateStart, searchForm.value.entryDateEnd]
- }
-
- reloadData()
-};
-
-const reloadData = () => {
- page.current = 1;
- page1.current = 1;
- getList();
- tableData.value = []
-}
-
-// 鐐瑰嚮宸︿晶琛岋紝鍒峰彸渚ф槑缁嗭紙鎸夌敓浜т汉杩囨护锛�
-const handleLeftRowClick = (row) => {
- searchForm.value.schedulingUserName = row.schedulingUserName || "";
- handleQuery();
-};
-
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- page1.current = 1;
- getList1();
-};
-
-
-// 瀵煎嚭
-const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download("/salesLedger/productionAccounting/export", {}, "鐢熶骇鏍哥畻.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-onMounted(() => {
- getList();
-});
+ onMounted(() => {
+ getList();
+ });
</script>
<style scoped lang="scss">
-.content-row {
- width: 100%;
-}
+ .content-row {
+ width: 100%;
+ }
-.content-row .left-col,
-.content-row .right-col {
- margin-bottom: 16px;
-}
+ .content-row .left-col,
+ .content-row .right-col {
+ margin-bottom: 16px;
+ }
-.left-panel,
-.right-panel {
- display: flex;
- flex-direction: column;
- gap: 10px;
- min-width: 0;
-}
+ .left-panel,
+ .right-panel {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ min-width: 0;
+ }
-.left-header {
- display: flex;
- align-items: center;
- gap: 12px;
-}
+ .left-header {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ }
-.left-title {
- font-size: 16px;
- color: #ffffff;
-}
+ .left-title {
+ font-size: 16px;
+ color: #ffffff;
+ }
-.header-filters {
- display: flex;
- align-items: center;
- flex: 1;
- justify-content: flex-end;
- gap: 8px;
-}
+ .header-filters {
+ display: flex;
+ align-items: center;
+ flex: 1;
+ justify-content: flex-end;
+ gap: 8px;
+ }
-.search_title {
- color: #ffffff;
-}
+ .search_title {
+ color: #ffffff;
+ }
-.ml10 {
- margin-left: 10px;
-}
+ .ml10 {
+ margin-left: 10px;
+ }
</style>
diff --git a/src/views/productionManagement/productionOrder/index.vue b/src/views/productionManagement/productionOrder/index.vue
index fc64063..1fa48be 100644
--- a/src/views/productionManagement/productionOrder/index.vue
+++ b/src/views/productionManagement/productionOrder/index.vue
@@ -11,14 +11,14 @@
style="width: 160px;"
@change="handleQuery" />
</el-form-item>
- <el-form-item label="鍚堝悓鍙�:">
+ <!-- <el-form-item label="鍚堝悓鍙�:">
<el-input v-model="searchForm.salesContractNo"
placeholder="璇疯緭鍏�"
clearable
prefix-icon="Search"
style="width: 160px;"
@change="handleQuery" />
- </el-form-item>
+ </el-form-item> -->
<el-form-item label="浜у搧鍚嶇О:">
<el-input v-model="searchForm.productCategory"
placeholder="璇疯緭鍏�"
@@ -41,8 +41,10 @@
</el-form-item>
</el-form>
<div>
- <el-button type="primary" @click="isShowNewModal = true">鏂板</el-button>
- <el-button type="danger" @click="handleDelete">鍒犻櫎</el-button>
+ <el-button type="primary"
+ @click="isShowNewModal = true">鏂板</el-button>
+ <el-button type="danger"
+ @click="handleDelete">鍒犻櫎</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
</div>
</div>
@@ -57,11 +59,9 @@
@selection-change="handleSelectionChange"
@pagination="pagination">
<template #completionStatus="{ row }">
- <el-progress
- :percentage="toProgressPercentage(row?.completionStatus)"
- :color="progressColor(toProgressPercentage(row?.completionStatus))"
- :status="toProgressPercentage(row?.completionStatus) >= 100 ? 'success' : ''"
- />
+ <el-progress :percentage="toProgressPercentage(row?.completionStatus)"
+ :color="progressColor(toProgressPercentage(row?.completionStatus))"
+ :status="toProgressPercentage(row?.completionStatus) >= 100 ? 'success' : ''" />
</template>
</PIMTable>
</div>
@@ -90,10 +90,9 @@
</span>
</template>
</el-dialog>
-
<new-product-order v-if="isShowNewModal"
- v-model:visible="isShowNewModal"
- @completed="handleQuery" />
+ v-model:visible="isShowNewModal"
+ @completed="handleQuery" />
</div>
</template>
@@ -106,12 +105,15 @@
productOrderListPage,
listProcessRoute,
bindingRoute,
- listProcessBom, delProductOrder,
+ listProcessBom,
+ delProductOrder,
} from "@/api/productionManagement/productionOrder.js";
import { listMain as getOrderProcessRouteMain } from "@/api/productionManagement/productProcessRoute.js";
- import {fileDel} from "@/api/financialManagement/revenueManagement.js";
+ import { fileDel } from "@/api/financialManagement/revenueManagement.js";
import PIMTable from "@/components/PIMTable/PIMTable.vue";
- const NewProductOrder = defineAsyncComponent(() => import("@/views/productionManagement/productionOrder/New.vue"));
+ const NewProductOrder = defineAsyncComponent(() =>
+ import("@/views/productionManagement/productionOrder/New.vue")
+ );
const { proxy } = getCurrentInstance();
@@ -122,32 +124,32 @@
{
label: "鐢熶骇璁㈠崟鍙�",
prop: "npsNo",
- width: '120px',
+ width: "120px",
},
- {
- label: "閿�鍞悎鍚屽彿",
- prop: "salesContractNo",
- width: '150px',
- },
- {
- label: "瀹㈡埛鍚嶇О",
- prop: "customerName",
- width: '200px',
- },
+ // {
+ // label: "閿�鍞悎鍚屽彿",
+ // prop: "salesContractNo",
+ // width: "150px",
+ // },
+ // {
+ // label: "瀹㈡埛鍚嶇О",
+ // prop: "customerName",
+ // width: "200px",
+ // },
{
label: "浜у搧鍚嶇О",
prop: "productCategory",
- width: '120px',
+ width: "120px",
},
{
label: "瑙勬牸",
prop: "specificationModel",
- width: '120px',
+ width: "120px",
},
{
label: "宸ヨ壓璺嚎缂栧彿",
prop: "processRouteCode",
- width: '200px',
+ width: "200px",
},
{
label: "闇�姹傛暟閲�",
@@ -176,12 +178,12 @@
formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
width: 120,
},
- {
- label: "浜や粯鏃ユ湡",
- prop: "deliveryDate",
- formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
- width: 120,
- },
+ // {
+ // label: "浜や粯鏃ユ湡",
+ // prop: "deliveryDate",
+ // formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
+ // width: 120,
+ // },
{
dataType: "action",
label: "鎿嶄綔",
@@ -253,18 +255,18 @@
// 娣诲姞琛ㄨ绫诲悕鏂规硶
const tableRowClassName = ({ row }) => {
- if (!row.deliveryDate) return '';
- if (row.isFh) return '';
+ if (!row.deliveryDate) return "";
+ if (row.isFh) return "";
const diff = row.deliveryDaysDiff;
if (diff === 15) {
- return 'yellow';
+ return "yellow";
} else if (diff === 10) {
- return 'pink';
+ return "pink";
} else if (diff === 2) {
- return 'purple';
+ return "purple";
} else if (diff < 2) {
- return 'red';
+ return "red";
}
};
@@ -402,14 +404,14 @@
};
// 琛ㄦ牸閫夋嫨鏁版嵁
- const handleSelectionChange = (selection) => {
+ const handleSelectionChange = selection => {
selectedRows.value = selection;
};
const handleDelete = () => {
let ids = [];
if (selectedRows.value.length > 0) {
- ids = selectedRows.value.map((item) => item.id);
+ ids = selectedRows.value.map(item => item.id);
} else {
proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
return;
@@ -418,14 +420,16 @@
confirmButtonText: "纭",
cancelButtonText: "鍙栨秷",
type: "warning",
- }).then(() => {
- delProductOrder(ids).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
+ })
+ .then(() => {
+ delProductOrder(ids).then(res => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
});
- }).catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
};
// 瀵煎嚭
@@ -436,7 +440,11 @@
type: "warning",
})
.then(() => {
- proxy.download("/productOrder/export", {...searchForm.value}, "鐢熶骇璁㈠崟.xlsx");
+ proxy.download(
+ "/productOrder/export",
+ { ...searchForm.value },
+ "鐢熶骇璁㈠崟.xlsx"
+ );
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
@@ -451,23 +459,23 @@
</script>
<style scoped lang="scss">
-.search_form{
- align-items: start;
-}
+ .search_form {
+ align-items: start;
+ }
-::v-deep .yellow {
- background-color: #FAF0DE;
-}
+ ::v-deep .yellow {
+ background-color: #faf0de;
+ }
-::v-deep .pink {
- background-color: #FAE1DE;
-}
+ ::v-deep .pink {
+ background-color: #fae1de;
+ }
-::v-deep .red {
- background-color: #f80202;
-}
+ ::v-deep .red {
+ background-color: #f80202;
+ }
-::v-deep .purple{
- background-color: #F4DEFA;
-}
+ ::v-deep .purple {
+ background-color: #f4defa;
+ }
</style>
diff --git a/src/views/productionManagement/productionReporting/index.vue b/src/views/productionManagement/productionReporting/index.vue
index 0b42dae..8790b19 100644
--- a/src/views/productionManagement/productionReporting/index.vue
+++ b/src/views/productionManagement/productionReporting/index.vue
@@ -99,8 +99,7 @@
style="width: 100%" />
</template>
</el-table-column>
- <el-table-column label="鎿嶄綔"
- >
+ <el-table-column label="鎿嶄綔">
<template #default="scope">
<el-button link
type="primary"
@@ -172,11 +171,11 @@
prop: "workOrderNo",
width: 120,
},
- {
- label: "閿�鍞悎鍚屽彿",
- prop: "salesContractNo",
- width: 120,
- },
+ // {
+ // label: "閿�鍞悎鍚屽彿",
+ // prop: "salesContractNo",
+ // width: 120,
+ // },
{
label: "浜у搧鍚嶇О",
prop: "productName",
@@ -202,7 +201,7 @@
prop: "unit",
width: 120,
},
-
+
{
label: "鍒涘缓鏃堕棿",
prop: "createTime",
diff --git a/src/views/salesManagement/receiptPaymentLedger/index.vue b/src/views/salesManagement/receiptPaymentLedger/index.vue
index 793e616..158b715 100644
--- a/src/views/salesManagement/receiptPaymentLedger/index.vue
+++ b/src/views/salesManagement/receiptPaymentLedger/index.vue
@@ -142,6 +142,8 @@
:data="salesRecord"
border
:row-key="(row) => row.id"
+ show-summary
+ :summary-method="summarizeSalesTable"
height="calc(100vh - 18.5em)"
>
<el-table-column align="center" label="搴忓彿" type="index" width="60" />
@@ -247,6 +249,18 @@
return summarizeTable;
};
+// 閿�鍞線鏉ヨ〃鍚堣锛堝凡鍙戣揣/鏈彂璐э級
+const summarizeSalesTable = (param) => {
+ return proxy.summarizeTable(
+ param,
+ ["shippedQuantity", "unshippedQuantity"],
+ {
+ shippedQuantity: { noDecimal: false },
+ unshippedQuantity: { noDecimal: false },
+ }
+ );
+};
+
const receiptPaymentList = (id) => {
const param = {
customerId: id,
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index c7981de..b80007c 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -1,25 +1,53 @@
<template>
<div class="app-container">
<div class="search_form">
- <el-form :model="searchForm" :inline="true">
+ <el-form :model="searchForm"
+ :inline="true">
<el-form-item label="瀹㈡埛鍚嶇О锛�">
- <el-input v-model="searchForm.customerName" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
- @change="handleQuery" />
+ <el-input v-model="searchForm.customerName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ prefix-icon="Search"
+ @change="handleQuery" />
</el-form-item>
<el-form-item label="閿�鍞悎鍚屽彿锛�">
- <el-input v-model="searchForm.salesContractNo" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
- @change="handleQuery" />
+ <el-input v-model="searchForm.salesContractNo"
+ placeholder="璇疯緭鍏�"
+ clearable
+ prefix-icon="Search"
+ @change="handleQuery" />
</el-form-item>
<el-form-item label="椤圭洰鍚嶇О锛�">
- <el-input v-model="searchForm.projectName" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
- @change="handleQuery" />
+ <el-input v-model="searchForm.projectName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ prefix-icon="Search"
+ @change="handleQuery" />
+ </el-form-item>
+ <el-form-item label="瀹㈡埛绫诲瀷锛�">
+ <el-select v-model="searchForm.customerType"
+ placeholder="璇烽�夋嫨"
+ style="width: 220px"
+ clearable
+ @change="handleQuery">
+ <el-option label="瀵瑰叕"
+ value="1" />
+ <el-option label="瀵圭"
+ value="2" />
+ </el-select>
</el-form-item>
<el-form-item label="褰曞叆鏃ユ湡锛�">
- <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
- placeholder="璇烽�夋嫨" clearable @change="changeDaterange" />
+ <el-date-picker v-model="searchForm.entryDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="daterange"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="changeDaterange" />
</el-form-item>
<el-form-item>
- <el-button type="primary" @click="handleQuery"> 鎼滅储 </el-button>
+ <el-button type="primary"
+ @click="handleQuery"> 鎼滅储 </el-button>
</el-form-item>
</el-form>
</div>
@@ -27,79 +55,146 @@
<div class="actions">
<div></div>
<div>
- <el-button type="primary" @click="openForm('add')">
+ <el-button type="primary"
+ @click="openForm('add')">
鏂板鍙拌处
</el-button>
- <el-button type="primary" plain @click="handleImport">瀵煎叆</el-button>
+ <el-button type="primary"
+ plain
+ @click="handleImport">瀵煎叆</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
- <el-button type="primary" plain @click="handlePrint">鎵撳嵃</el-button>
+ <el-button type="danger"
+ plain
+ @click="handleDelete">鍒犻櫎</el-button>
+ <el-button type="primary"
+ plain
+ @click="handlePrint">鎵撳嵃</el-button>
</div>
</div>
- <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
- :expand-row-keys="expandedRowKeys" :row-key="(row) => row.id" :row-class-name="tableRowClassName" show-summary style="width: 100%"
- :summary-method="summarizeMainTable" @expand-change="expandChange" height="calc(100vh - 18.5em)">
- <el-table-column align="center" type="selection" width="55" fixed="left"/>
- <el-table-column type="expand" width="60" fixed="left">
+ <el-table :data="tableData"
+ border
+ v-loading="tableLoading"
+ @selection-change="handleSelectionChange"
+ :expand-row-keys="expandedRowKeys"
+ :row-key="(row) => row.id"
+ :row-class-name="tableRowClassName"
+ show-summary
+ style="width: 100%"
+ :summary-method="summarizeMainTable"
+ @expand-change="expandChange"
+ height="calc(100vh - 18.5em)">
+ <el-table-column align="center"
+ type="selection"
+ width="55"
+ fixed="left" />
+ <el-table-column type="expand"
+ width="60"
+ fixed="left">
<template #default="props">
- <el-table :data="props.row.children" border show-summary :summary-method="summarizeChildrenTable">
- <el-table-column align="center" label="搴忓彿" type="index"/>
- <el-table-column label="浜у搧澶х被" prop="productCategory" />
- <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
- <el-table-column label="鍗曚綅" prop="unit" />
- <el-table-column label="浜у搧鐘舵��"
- width="100px"
- align="center">
+ <el-table :data="props.row.children"
+ border
+ show-summary
+ :summary-method="summarizeChildrenTable">
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index" />
+ <el-table-column label="浜у搧澶х被"
+ prop="productCategory" />
+ <el-table-column label="瑙勬牸鍨嬪彿"
+ prop="specificationModel" />
+ <el-table-column label="鍗曚綅"
+ prop="unit" />
+ <el-table-column label="浜у搧鐘舵��"
+ width="100px"
+ align="center">
<template #default="scope">
-
- <el-tag v-if="scope.row.approveStatus === 1 && (!scope.row.shippingDate || !scope.row.shippingCarNumber)"
- type="success">鍏呰冻</el-tag>
- <el-tag v-else-if="scope.row.approveStatus === 0 && (scope.row.shippingDate || scope.row.shippingCarNumber)"
- type="success">宸插嚭搴�</el-tag>
- <el-tag v-else type="danger">涓嶈冻</el-tag>
+ <el-tag v-if="scope.row.approveStatus === 1 && (!scope.row.shippingDate || !scope.row.shippingCarNumber)"
+ type="success">鍏呰冻</el-tag>
+ <el-tag v-else-if="scope.row.approveStatus === 0 && (scope.row.shippingDate || scope.row.shippingCarNumber)"
+ type="success">宸插嚭搴�</el-tag>
+ <el-tag v-else
+ type="danger">涓嶈冻</el-tag>
</template>
</el-table-column>
- <el-table-column label="鍙戣揣鐘舵��" width="140" align="center">
- <template #default="scope">
- <el-tag :type="getShippingStatusType(scope.row)" size="small">
- {{ getShippingStatusText(scope.row) }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column label="蹇�掑叕鍙�" prop="expressCompany" show-overflow-tooltip />
- <el-table-column label="蹇�掑崟鍙�" prop="expressNumber" show-overflow-tooltip />
- <el-table-column label="鍙戣揣杞︾墝" minWidth="100px" align="center">
+ <el-table-column label="鍙戣揣鐘舵��"
+ width="140"
+ align="center">
+ <template #default="scope">
+ <el-tag :type="getShippingStatusType(scope.row)"
+ size="small">
+ {{ getShippingStatusText(scope.row) }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column label="蹇�掑叕鍙�"
+ prop="expressCompany"
+ show-overflow-tooltip />
+ <el-table-column label="蹇�掑崟鍙�"
+ prop="expressNumber"
+ show-overflow-tooltip />
+ <el-table-column label="鍙戣揣杞︾墝"
+ minWidth="100px"
+ align="center">
<template #default="scope">
<div>
- <el-tag type="success" v-if="scope.row.shippingCarNumber">{{ scope.row.shippingCarNumber }}</el-tag>
- <el-tag v-else type="info">-</el-tag>
+ <el-tag type="success"
+ v-if="scope.row.shippingCarNumber">{{ scope.row.shippingCarNumber }}</el-tag>
+ <el-tag v-else
+ type="info">-</el-tag>
</div>
</template>
</el-table-column>
- <el-table-column label="鍙戣揣鏃ユ湡"
- minWidth="100px"
- align="center">
+ <el-table-column label="鍙戣揣鏃ユ湡"
+ minWidth="100px"
+ align="center">
<template #default="scope">
<div>
<div v-if="scope.row.shippingDate">{{ scope.row.shippingDate }}</div>
- <el-tag v-else
- type="info">-</el-tag>
+ <el-tag v-else
+ type="info">-</el-tag>
</div>
</template>
</el-table-column>
- <el-table-column label="鏁伴噺" prop="quantity" />
- <el-table-column label="绋庣巼(%)" prop="taxRate" />
- <el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" />
- <el-table-column label="鍚◣鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" />
- <el-table-column label="涓嶅惈绋庢�讳环(鍏�)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" />
- <!--鎿嶄綔-->
- <!-- <el-table-column Width="60px" label="鎿嶄綔" align="center">
+ <el-table-column label="鏁伴噺"
+ prop="quantity" />
+ <!-- 瀵瑰叕瀹㈡埛鏄剧ず鐨勫瓧娈� -->
+ <template v-if="props.row.customerType =='1'">
+ <el-table-column label="绋庣巼(%)"
+ prop="taxRate" />
+ <el-table-column label="鍚◣鍗曚环(鍏�)"
+ prop="taxInclusiveUnitPrice"
+ :formatter="formattedNumber" />
+ <el-table-column label="鍚◣鎬讳环(鍏�)"
+ prop="taxInclusiveTotalPrice"
+ :formatter="formattedNumber" />
+ <el-table-column label="涓嶅惈绋庢�讳环(鍏�)"
+ prop="taxExclusiveTotalPrice"
+ :formatter="formattedNumber" />
+ </template>
+ <!-- 瀵圭瀹㈡埛鏄剧ず鐨勫瓧娈� -->
+ <template v-else-if="props.row.customerType == 2">
+ <el-table-column label="鍗曚环"
+ prop="unitPrice"
+ :formatter="formattedNumber" />
+ <el-table-column label="鎬讳环"
+ prop="totalPrice"
+ :formatter="formattedNumber" />
+ <el-table-column label="杩愯垂"
+ prop="freight"
+ :formatter="formattedNumber" />
+ <el-table-column label="鍚繍璐瑰崟浠�"
+ prop="priceWithFreight"
+ :formatter="formattedNumber" />
+ </template>
+ <!--鎿嶄綔-->
+ <!-- <el-table-column Width="60px"
+ label="鎿嶄綔"
+ align="center">
<template #default="scope">
- <el-button
- link
- type="primary"
- :disabled="!canShip(scope.row)"
- @click="openDeliveryForm(scope.row)">
+ <el-button link
+ type="primary"
+ :disabled="!canShip(scope.row)"
+ @click="openDeliveryForm(scope.row)">
鍙戣揣
</el-button>
</template>
@@ -107,2040 +202,2555 @@
</el-table>
</template>
</el-table-column>
- <el-table-column align="center" label="搴忓彿" type="index" width="60" />
- <el-table-column label="閿�鍞悎鍚屽彿" prop="salesContractNo" width="180" show-overflow-tooltip />
- <el-table-column label="瀹㈡埛鍚嶇О" prop="customerName" width="300" show-overflow-tooltip />
- <el-table-column label="涓氬姟鍛�" prop="salesman" width="100" show-overflow-tooltip />
- <el-table-column label="椤圭洰鍚嶇О" prop="projectName" width="180" show-overflow-tooltip />
- <el-table-column label="浠樻鏂瑰紡" prop="paymentMethod" show-overflow-tooltip />
- <el-table-column label="鍚堝悓閲戦(鍏�)" prop="contractAmount" width="220" show-overflow-tooltip
- :formatter="formattedNumber" />
- <el-table-column label="褰曞叆浜�" prop="entryPersonName" width="100" show-overflow-tooltip />
- <el-table-column label="褰曞叆鏃ユ湡" prop="entryDate" width="120" show-overflow-tooltip />
- <el-table-column label="绛捐鏃ユ湡" prop="executionDate" width="120" show-overflow-tooltip />
- <el-table-column label="浜や粯鏃ユ湡" prop="deliveryDate" width="120" show-overflow-tooltip />
- <el-table-column label="澶囨敞" prop="remarks" width="200" show-overflow-tooltip />
- <el-table-column fixed="right" label="鎿嶄綔" width="130" align="center">
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index"
+ width="60" />
+ <el-table-column label="閿�鍞悎鍚屽彿"
+ prop="salesContractNo"
+ width="180"
+ show-overflow-tooltip />
+ <el-table-column label="瀹㈡埛鍚嶇О"
+ prop="customerName"
+ width="300"
+ show-overflow-tooltip />
+ <el-table-column label="瀹㈡埛绫诲瀷"
+ prop="customerType"
+ width="100">
<template #default="scope">
- <el-button link type="primary" @click="openForm('edit', scope.row)" :disabled="!scope.row.isEdit">缂栬緫</el-button>
- <el-button link type="primary" @click="downLoadFile(scope.row)">闄勪欢</el-button>
+ {{scope.row.customerType == 1 ? '瀵瑰叕' : '瀵圭'}}
+ </template>
+ </el-table-column>
+ <el-table-column label="涓氬姟鍛�"
+ prop="salesman"
+ width="100"
+ show-overflow-tooltip />
+ <el-table-column label="椤圭洰鍚嶇О"
+ prop="projectName"
+ width="180"
+ show-overflow-tooltip />
+ <el-table-column label="浠樻鏂瑰紡"
+ prop="paymentMethod"
+ show-overflow-tooltip />
+ <el-table-column label="鍚堝悓閲戦(鍏�)"
+ prop="contractAmount"
+ width="220"
+ show-overflow-tooltip
+ :formatter="formattedNumber" />
+ <el-table-column label="褰曞叆浜�"
+ prop="entryPersonName"
+ width="100"
+ show-overflow-tooltip />
+ <el-table-column label="褰曞叆鏃ユ湡"
+ prop="entryDate"
+ width="120"
+ show-overflow-tooltip />
+ <el-table-column label="绛捐鏃ユ湡"
+ prop="executionDate"
+ width="120"
+ show-overflow-tooltip />
+ <el-table-column label="浜や粯鏃ユ湡"
+ prop="deliveryDate"
+ width="120"
+ show-overflow-tooltip />
+ <el-table-column label="澶囨敞"
+ prop="remarks"
+ width="200"
+ show-overflow-tooltip />
+ <el-table-column fixed="right"
+ label="鎿嶄綔"
+ width="130"
+ align="center">
+ <template #default="scope">
+ <el-button link
+ type="primary"
+ @click="openForm('edit', scope.row)"
+ :disabled="!scope.row.isEdit">缂栬緫</el-button>
+ <el-button link
+ type="primary"
+ @click="downLoadFile(scope.row)">闄勪欢</el-button>
</template>
</el-table-column>
</el-table>
- <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
- :page="page.current" :limit="page.size" @pagination="paginationChange" />
+ <pagination v-show="total > 0"
+ :total="total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="page.current"
+ :limit="page.size"
+ @pagination="paginationChange" />
</div>
- <FormDialog v-model="dialogFormVisible" :title="operationType === 'add' ? '鏂板閿�鍞彴璐﹂〉闈�' : '缂栬緫閿�鍞彴璐﹂〉闈�'" :width="'70%'"
- :operation-type="operationType" @close="closeDia" @confirm="submitForm" @cancel="closeDia">
- <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
- <!-- 鎶ヤ环鍗曞鍏ュ叆鍙o細鏀惧湪琛ㄥ崟椤堕儴锛岄�夋嫨鍚庡弽鏄惧鎴�/涓氬姟鍛樼瓑 -->
- <el-row v-if="operationType === 'add'" style="margin-bottom: 10px;">
- <el-col :span="24" style="text-align: right;">
- <el-button type="primary" plain @click="openQuotationDialog">
- 浠庨攢鍞姤浠峰鍏�
- </el-button>
- </el-col>
- </el-row>
+ <FormDialog v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板閿�鍞彴璐﹂〉闈�' : '缂栬緫閿�鍞彴璐﹂〉闈�'"
+ :width="'70%'"
+ :operation-type="operationType"
+ @close="closeDia"
+ @confirm="submitForm"
+ @cancel="closeDia">
+ <el-form :model="form"
+ label-width="140px"
+ label-position="top"
+ :rules="rules"
+ ref="formRef">
+ <!-- 鎶ヤ环鍗曞鍏ュ叆鍙o細鏀惧湪琛ㄥ崟椤堕儴锛岄�夋嫨鍚庡弽鏄惧鎴�/涓氬姟鍛樼瓑 -->
+ <el-row v-if="operationType === 'add'"
+ style="margin-bottom: 10px;">
+ <el-col :span="24"
+ style="text-align: right;">
+ <el-button type="primary"
+ plain
+ @click="openQuotationDialog">
+ 浠庨攢鍞姤浠峰鍏�
+ </el-button>
+ </el-col>
+ </el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="閿�鍞悎鍚屽彿锛�" prop="salesContractNo">
- <el-input v-model="form.salesContractNo" placeholder="鑷姩鐢熸垚" clearable disabled />
+ <el-form-item label="閿�鍞悎鍚屽彿锛�"
+ prop="salesContractNo">
+ <el-input v-model="form.salesContractNo"
+ placeholder="鑷姩鐢熸垚"
+ clearable
+ disabled />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="涓氬姟鍛橈細" prop="salesman">
- <el-select v-model="form.salesman" placeholder="璇烽�夋嫨" clearable :disabled="operationType === 'view'">
- <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
- :value="item.nickName" />
+ <el-form-item label="涓氬姟鍛橈細"
+ prop="salesman">
+ <el-select v-model="form.salesman"
+ placeholder="璇烽�夋嫨"
+ clearable
+ :disabled="operationType === 'view'">
+ <el-option v-for="item in userList"
+ :key="item.nickName"
+ :label="item.nickName"
+ :value="item.nickName" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="瀹㈡埛鍚嶇О锛�" prop="customerId">
- <el-select v-model="form.customerId" placeholder="璇烽�夋嫨" clearable :disabled="operationType === 'view'">
- <el-option v-for="item in customerOption" :key="item.id" :label="item.customerName" :value="item.id">
- {{
- item.customerName + "鈥斺��" + item.taxpayerIdentificationNumber
- }}
+ <el-form-item label="瀹㈡埛鍚嶇О锛�"
+ prop="customerId">
+ <el-select v-model="form.customerId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ :disabled="operationType === 'view'"
+ @change="handleCustomerChange">
+ <el-option v-for="item in customerOption"
+ :key="item.id"
+ :label="item.customerName"
+ :value="item.id">
+ {{ item.customerName + "鈥斺��" }}
+ {{item.customerType=="1"?item.taxpayerIdentificationNumber || '鏃�':"瀵圭"}}
</el-option>
</el-select>
</el-form-item>
</el-col>
- <el-col :span="12">
- <el-form-item label="椤圭洰鍚嶇О锛�" prop="projectName">
- <el-input v-model="form.projectName" placeholder="璇疯緭鍏�" clearable :disabled="operationType === 'view'" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="绛捐鏃ユ湡锛�" prop="executionDate">
- <el-date-picker style="width: 100%" v-model="form.executionDate" value-format="YYYY-MM-DD"
- format="YYYY-MM-DD" type="date" placeholder="璇烽�夋嫨" clearable :disabled="operationType === 'view'" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="浠樻鏂瑰紡">
- <el-input v-model="form.paymentMethod" placeholder="璇疯緭鍏�" clearable :disabled="operationType === 'view'" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="褰曞叆浜猴細" prop="entryPerson">
- <el-select v-model="form.entryPerson"
- filterable
- default-first-option
- :reserve-keyword="false" placeholder="璇烽�夋嫨" clearable @change="changs">
- <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="褰曞叆鏃ユ湡锛�" prop="entryDate">
- <el-date-picker style="width: 100%" v-model="form.entryDate" 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="entryDate">
- <el-date-picker style="width: 100%" v-model="form.deliveryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
- type="date" placeholder="璇烽�夋嫨" clearable />
+ <el-form-item label="椤圭洰鍚嶇О锛�"
+ prop="projectName">
+ <el-input v-model="form.projectName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ :disabled="operationType === 'view'" />
</el-form-item>
</el-col>
</el-row>
- <el-row>
- <el-form-item label="浜у搧淇℃伅锛�" prop="entryDate">
- <el-button v-if="operationType !== 'view'" type="primary" @click="openProductForm('add')">娣诲姞</el-button>
- <el-button v-if="operationType !== 'view'" plain type="danger" @click="deleteProduct" >鍒犻櫎</el-button>
- </el-form-item>
- </el-row>
- <el-table :data="productData" border @selection-change="productSelected" show-summary
- :summary-method="summarizeMainTable">
- <el-table-column align="center" type="selection" width="55" v-if="operationType !== 'view'"
- :selectable="(row) => !isProductShipped(row)" />
- <el-table-column align="center" label="搴忓彿" type="index" width="60" />
- <el-table-column label="浜у搧澶х被" prop="productCategory" />
- <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
- <el-table-column label="鍗曚綅" prop="unit" />
- <el-table-column label="鏁伴噺" prop="quantity" />
- <el-table-column label="绋庣巼(%)" prop="taxRate" />
- <el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" />
- <el-table-column label="鍚◣鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" />
- <el-table-column label="涓嶅惈绋庢�讳环(鍏�)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" />
- <el-table-column fixed="right" label="鎿嶄綔" min-width="60" align="center" v-if="operationType !== 'view'">
- <template #default="scope">
- <el-button link type="primary" size="small"
- :disabled="isProductShipped(scope.row)"
- @click="openProductForm('edit', scope.row,scope.$index)">缂栬緫</el-button>
- </template>
- </el-table-column>
- </el-table>
- <el-row :gutter="30">
- <el-col :span="24">
- <el-form-item label="澶囨敞锛�" prop="remarks">
- <el-input v-model="form.remarks" placeholder="璇疯緭鍏�" clearable type="textarea" :rows="2" :disabled="operationType === 'view'" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="24">
- <el-form-item label="闄勪欢鏉愭枡锛�" prop="salesLedgerFiles">
- <el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload
- :headers="upload.headers" :before-upload="handleBeforeUpload" :on-error="handleUploadError"
- :on-success="handleUploadSuccess" :on-remove="handleRemove">
- <el-button type="primary" v-if="operationType !== 'view'">涓婁紶</el-button>
- <template #tip v-if="operationType !== 'view'">
- <div class="el-upload__tip">
- 鏂囦欢鏍煎紡鏀寔
- doc锛宒ocx锛寈ls锛寈lsx锛宲pt锛宲ptx锛宲df锛宼xt锛寈ml锛宩pg锛宩peg锛宲ng锛実if锛宐mp锛宺ar锛寊ip锛�7z
- </div>
- </template>
- </el-upload>
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- </FormDialog>
-
- <!-- 浠庢姤浠峰崟瀵煎叆锛堜粎瀹℃壒閫氳繃锛� -->
- <el-dialog
- v-model="quotationDialogVisible"
- title="閫夋嫨瀹℃壒閫氳繃鐨勯攢鍞姤浠峰崟"
- width="80%"
- :close-on-click-modal="false"
- >
- <div style="margin-bottom: 12px; display:flex; gap: 12px; align-items:center;">
- <el-input
- v-model="quotationSearchForm.quotationNo"
- placeholder="璇疯緭鍏ユ姤浠峰崟鍙�"
- clearable
- style="max-width: 260px;"
- @change="fetchQuotationList"
- />
- <el-input
- v-model="quotationSearchForm.customer"
- placeholder="璇疯緭鍏ュ鎴峰悕绉�"
- clearable
- style="max-width: 260px;"
- @change="fetchQuotationList"
- />
- <el-button type="primary" @click="fetchQuotationList">鎼滅储</el-button>
- <el-button @click="resetQuotationSearch">閲嶇疆</el-button>
- </div>
-
- <el-table
- :data="quotationList"
- border
- stripe
- v-loading="quotationLoading"
- height="420px"
- >
- <el-table-column align="center" label="搴忓彿" type="index" width="60" />
- <el-table-column prop="quotationNo" label="鎶ヤ环鍗曞彿" width="180" show-overflow-tooltip />
- <el-table-column prop="customer" label="瀹㈡埛鍚嶇О" min-width="220" show-overflow-tooltip />
- <el-table-column prop="salesperson" label="涓氬姟鍛�" width="120" show-overflow-tooltip />
- <el-table-column prop="quotationDate" label="鎶ヤ环鏃ユ湡" width="140" />
- <el-table-column prop="status" label="瀹℃壒鐘舵��" width="120" align="center" />
- <el-table-column prop="totalAmount" label="鎶ヤ环閲戦(鍏�)" width="160" align="right">
- <template #default="scope">
- {{ Number(scope.row.totalAmount ?? 0).toFixed(2) }}
- </template>
- </el-table-column>
- <el-table-column fixed="right" label="鎿嶄綔" width="120" align="center">
- <template #default="scope">
- <el-button type="primary" link @click="applyQuotation(scope.row)">閫夋嫨</el-button>
- </template>
- </el-table-column>
- </el-table>
-
- <pagination
- v-show="quotationPage.total > 0"
- :total="quotationPage.total"
- layout="total, sizes, prev, pager, next, jumper"
- :page="quotationPage.current"
- :limit="quotationPage.size"
- @pagination="quotationPaginationChange"
- />
-
- <template #footer>
- <el-button @click="quotationDialogVisible = false">鍏抽棴</el-button>
- </template>
- </el-dialog>
- <FormDialog
- v-model="productFormVisible"
- :title="productOperationType === 'add' ? '鏂板浜у搧' : '缂栬緫浜у搧'"
- :width="'40%'"
- :operation-type="productOperationType"
- @close="closeProductDia"
- @confirm="submitProduct"
- @cancel="closeProductDia">
- <el-form :model="productForm" label-width="140px" label-position="top" :rules="productRules" ref="productFormRef">
- <el-row :gutter="30">
- <el-col :span="24">
- <el-form-item label="浜у搧澶х被锛�" prop="productCategory">
- <!-- <el-select v-model="productForm.productCategory" placeholder="璇烽�夋嫨" clearable>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="绛捐鏃ユ湡锛�"
+ prop="executionDate">
+ <el-date-picker style="width: 100%"
+ v-model="form.executionDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ :disabled="operationType === 'view'" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="浠樻鏂瑰紡">
+ <el-input v-model="form.paymentMethod"
+ placeholder="璇疯緭鍏�"
+ clearable
+ :disabled="operationType === 'view'" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="褰曞叆浜猴細"
+ prop="entryPerson">
+ <el-select v-model="form.entryPerson"
+ filterable
+ default-first-option
+ :reserve-keyword="false"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="changs">
+ <el-option v-for="item in userList"
+ :key="item.userId"
+ :label="item.nickName"
+ :value="item.userId" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="褰曞叆鏃ユ湡锛�"
+ prop="entryDate">
+ <el-date-picker style="width: 100%"
+ v-model="form.entryDate"
+ 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="entryDate">
+ <el-date-picker style="width: 100%"
+ v-model="form.deliveryDate"
+ 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-form-item label="浜у搧淇℃伅锛�"
+ prop="entryDate">
+ <el-button v-if="operationType !== 'view' && currentCustomerType"
+ type="primary"
+ @click="openProductForm('add')">娣诲姞</el-button>
+ <el-button v-if="operationType !== 'view'"
+ plain
+ type="danger"
+ @click="deleteProduct"
+ :disabled="!productData.length">鍒犻櫎</el-button>
+ </el-form-item>
+ </el-row>
+ <el-table :data="productData"
+ border
+ @selection-change="productSelected"
+ show-summary
+ :summary-method="summarizeMainTable">
+ <el-table-column align="center"
+ type="selection"
+ width="55"
+ v-if="operationType !== 'view'"
+ :selectable="(row) => !isProductShipped(row)" />
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index"
+ width="60" />
+ <el-table-column label="浜у搧澶х被"
+ prop="productCategory" />
+ <el-table-column label="瑙勬牸鍨嬪彿"
+ prop="specificationModel" />
+ <el-table-column label="鍗曚綅"
+ prop="unit" />
+ <el-table-column label="鏁伴噺"
+ prop="quantity" />
+ <!-- 瀵瑰叕瀹㈡埛鏄剧ず鐨勫瓧娈� -->
+ <template v-if="currentCustomerType == 1">
+ <el-table-column label="绋庣巼(%)"
+ prop="taxRate" />
+ <el-table-column label="鍚◣鍗曚环(鍏�)"
+ prop="taxInclusiveUnitPrice"
+ :formatter="formattedNumber" />
+ <el-table-column label="鍚◣鎬讳环(鍏�)"
+ prop="taxInclusiveTotalPrice"
+ :formatter="formattedNumber" />
+ <el-table-column label="涓嶅惈绋庢�讳环(鍏�)"
+ prop="taxExclusiveTotalPrice"
+ :formatter="formattedNumber" />
+ </template>
+ <!-- 瀵圭瀹㈡埛鏄剧ず鐨勫瓧娈� -->
+ <template v-else-if="currentCustomerType == 2">
+ <el-table-column label="鍗曚环"
+ prop="unitPrice"
+ :formatter="formattedNumber" />
+ <el-table-column label="鎬讳环"
+ prop="totalPrice"
+ :formatter="formattedNumber" />
+ <el-table-column label="杩愯垂"
+ prop="freight"
+ :formatter="formattedNumber" />
+ <el-table-column label="鍚繍璐瑰崟浠�"
+ prop="priceWithFreight"
+ :formatter="formattedNumber" />
+ </template>
+ <el-table-column fixed="right"
+ label="鎿嶄綔"
+ min-width="60"
+ align="center"
+ v-if="operationType !== 'view'">
+ <template #default="scope">
+ <el-button link
+ type="primary"
+ size="small"
+ :disabled="isProductShipped(scope.row)"
+ @click="openProductForm('edit', scope.row,scope.$index)">缂栬緫</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="澶囨敞锛�"
+ prop="remarks">
+ <el-input v-model="form.remarks"
+ placeholder="璇疯緭鍏�"
+ clearable
+ type="textarea"
+ :rows="2"
+ :disabled="operationType === 'view'" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="闄勪欢鏉愭枡锛�"
+ prop="salesLedgerFiles">
+ <el-upload v-model:file-list="fileList"
+ :action="upload.url"
+ multiple
+ ref="fileUpload"
+ auto-upload
+ :headers="upload.headers"
+ :before-upload="handleBeforeUpload"
+ :on-error="handleUploadError"
+ :on-success="handleUploadSuccess"
+ :on-remove="handleRemove">
+ <el-button type="primary"
+ v-if="operationType !== 'view'">涓婁紶</el-button>
+ <template #tip
+ v-if="operationType !== 'view'">
+ <div class="el-upload__tip">
+ 鏂囦欢鏍煎紡鏀寔
+ doc锛宒ocx锛寈ls锛寈lsx锛宲pt锛宲ptx锛宲df锛宼xt锛寈ml锛宩pg锛宩peg锛宲ng锛実if锛宐mp锛宺ar锛寊ip锛�7z
+ </div>
+ </template>
+ </el-upload>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ </FormDialog>
+ <!-- 浠庢姤浠峰崟瀵煎叆锛堜粎瀹℃壒閫氳繃锛� -->
+ <el-dialog v-model="quotationDialogVisible"
+ title="閫夋嫨瀹℃壒閫氳繃鐨勯攢鍞姤浠峰崟"
+ width="80%"
+ :close-on-click-modal="false">
+ <div style="margin-bottom: 12px; display:flex; gap: 12px; align-items:center;">
+ <el-input v-model="quotationSearchForm.quotationNo"
+ placeholder="璇疯緭鍏ユ姤浠峰崟鍙�"
+ clearable
+ style="max-width: 260px;"
+ @change="fetchQuotationList" />
+ <el-input v-model="quotationSearchForm.customer"
+ placeholder="璇疯緭鍏ュ鎴峰悕绉�"
+ clearable
+ style="max-width: 260px;"
+ @change="fetchQuotationList" />
+ <el-button type="primary"
+ @click="fetchQuotationList">鎼滅储</el-button>
+ <el-button @click="resetQuotationSearch">閲嶇疆</el-button>
+ </div>
+ <el-table :data="quotationList"
+ border
+ stripe
+ v-loading="quotationLoading"
+ height="420px">
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index"
+ width="60" />
+ <el-table-column prop="quotationNo"
+ label="鎶ヤ环鍗曞彿"
+ width="180"
+ show-overflow-tooltip />
+ <el-table-column prop="customer"
+ label="瀹㈡埛鍚嶇О"
+ min-width="220"
+ show-overflow-tooltip />
+ <el-table-column prop="salesperson"
+ label="涓氬姟鍛�"
+ width="120"
+ show-overflow-tooltip />
+ <el-table-column prop="quotationDate"
+ label="鎶ヤ环鏃ユ湡"
+ width="140" />
+ <el-table-column prop="status"
+ label="瀹℃壒鐘舵��"
+ width="120"
+ align="center" />
+ <el-table-column prop="totalAmount"
+ label="鎶ヤ环閲戦(鍏�)"
+ width="160"
+ align="right">
+ <template #default="scope">
+ {{ Number(scope.row.totalAmount ?? 0).toFixed(2) }}
+ </template>
+ </el-table-column>
+ <el-table-column fixed="right"
+ label="鎿嶄綔"
+ width="120"
+ align="center">
+ <template #default="scope">
+ <el-button type="primary"
+ link
+ @click="applyQuotation(scope.row)">閫夋嫨</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <pagination v-show="quotationPage.total > 0"
+ :total="quotationPage.total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="quotationPage.current"
+ :limit="quotationPage.size"
+ @pagination="quotationPaginationChange" />
+ <template #footer>
+ <el-button @click="quotationDialogVisible = false">鍏抽棴</el-button>
+ </template>
+ </el-dialog>
+ <FormDialog v-model="productFormVisible"
+ :title="productOperationType === 'add' ? '鏂板浜у搧' : '缂栬緫浜у搧'"
+ :width="'40%'"
+ :operation-type="productOperationType"
+ @close="closeProductDia"
+ @confirm="submitProduct"
+ @cancel="closeProductDia">
+ <el-form :model="productForm"
+ label-width="140px"
+ label-position="top"
+ :rules="productRules"
+ ref="productFormRef">
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="浜у搧澶х被锛�"
+ prop="productCategory">
+ <!-- <el-select v-model="productForm.productCategory" placeholder="璇烽�夋嫨" clearable>
<el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/>
</el-select> -->
- <el-tree-select v-model="productForm.productCategory" placeholder="璇烽�夋嫨" clearable check-strictly
- @change="getModels" :data="productOptions" :render-after-expand="false" style="width: 100%" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="24">
- <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="productModelId">
- <el-select v-model="productForm.productModelId" placeholder="璇烽�夋嫨" clearable @change="getProductModel" filterable>
- <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鍗曚綅锛�" prop="unit">
- <el-input v-model="productForm.unit" placeholder="璇疯緭鍏�" clearable />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="绋庣巼(%)锛�" prop="taxRate">
- <el-select v-model="productForm.taxRate" placeholder="璇烽�夋嫨" clearable @change="calculateFromTaxRate">
- <el-option label="1" value="1" />
- <el-option label="6" value="6" />
- <el-option label="13" value="13" />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鍚◣鍗曚环(鍏�)锛�" prop="taxInclusiveUnitPrice">
- <el-input-number :step="0.01" :min="0" v-model="productForm.taxInclusiveUnitPrice" style="width: 100%"
- :precision="2"
- placeholder="璇疯緭鍏�" clearable @change="calculateFromUnitPrice" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鏁伴噺锛�" prop="quantity">
- <el-input-number :step="0.1" :min="0" v-model="productForm.quantity" placeholder="璇疯緭鍏�" clearable
- :precision="2"
- @change="calculateFromQuantity" style="width: 100%" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鍚◣鎬讳环(鍏�)锛�" prop="taxInclusiveTotalPrice">
- <el-input v-model="productForm.taxInclusiveTotalPrice" placeholder="璇疯緭鍏�" clearable @change="calculateFromTotalPrice" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="涓嶅惈绋庢�讳环(鍏�)锛�" prop="taxExclusiveTotalPrice">
- <el-input v-model="productForm.taxExclusiveTotalPrice" placeholder="璇疯緭鍏�" clearable @change="calculateFromExclusiveTotalPrice" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="30">
- <el-col :span="12">
- <el-form-item label="鍙戠エ绫诲瀷锛�" prop="invoiceType">
- <el-select v-model="productForm.invoiceType" placeholder="璇烽�夋嫨" clearable>
- <el-option label="澧炴櫘绁�" value="澧炴櫘绁�" />
- <el-option label="澧炰笓绁�" value="澧炰笓绁�" />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- </FormDialog>
- <!-- 瀵煎叆寮圭獥 -->
- <FormDialog
- v-model="importUpload.open"
- :title="importUpload.title"
- :width="'600px'"
- @close="importUpload.open = false"
- @confirm="submitImportFile"
- @cancel="importUpload.open = false"
- >
- <el-upload
- ref="importUploadRef"
- :limit="1"
- accept=".xlsx,.xls"
- :action="importUpload.url"
- :headers="importUpload.headers"
- :before-upload="importUpload.beforeUpload"
- :on-success="importUpload.onSuccess"
- :on-error="importUpload.onError"
- :on-progress="importUpload.onProgress"
- :on-change="importUpload.onChange"
- :auto-upload="false"
- drag
- >
- <i class="el-icon-upload"></i>
- <div class="el-upload__text">
- 灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em>
- </div>
- <template #tip>
- <div class="el-upload__tip">
- 浠呮敮鎸� xls/xlsx锛屽ぇ灏忎笉瓒呰繃 10MB銆�
- <el-button link type="primary" @click="downloadTemplate">涓嬭浇瀵煎叆妯℃澘</el-button>
- </div>
- </template>
- </el-upload>
- </FormDialog>
- <!-- 闄勪欢鍒楄〃寮圭獥 -->
- <FileListDialog
- ref="fileListRef"
- v-model="fileListDialogVisible"
- title="闄勪欢鍒楄〃"
- />
- <!-- 鎵撳嵃棰勮寮圭獥 -->
- <el-dialog
- v-model="printPreviewVisible"
- title="鎵撳嵃棰勮"
- width="90%"
- :close-on-click-modal="false"
- class="print-preview-dialog"
- >
- <div class="print-preview-container">
- <div class="print-preview-header">
- <el-button type="primary" @click="executePrint">鎵ц鎵撳嵃</el-button>
- <el-button @click="printPreviewVisible = false">鍏抽棴棰勮</el-button>
- </div>
- <div class="print-preview-content">
- <div v-if="printData.length === 0" style="text-align: center; padding: 50px; color: #999;">
- 鏆傛棤鎵撳嵃鏁版嵁
- </div>
- <div v-else style="text-align: center; padding: 10px; color: #666; font-size: 14px; background: #e8f4fd; margin-bottom: 10px;">
- 鍏� {{ printData.length }} 鏉℃暟鎹緟鎵撳嵃
- </div>
- <div v-for="(item, index) in printData" :key="index" class="print-page">
- <div class="delivery-note">
- <div class="header">
- <div class="document-title">闆跺敭鍙戣揣鍗�</div>
- </div>
-
- <div class="info-section">
- <div class="info-row">
- <div>
- <span class="label">鍙戣揣鏃ユ湡锛�</span>
- <span class="value">{{ formatDate(item.createTime) }}</span>
- </div>
- <div>
- <span class="label">鍙戣揣杞︾墝鍙凤細</span>
- <span class="value">{{ item.shippingCarNumber }}</span>
- </div>
- </div>
- <div class="info-row">
- <div>
- <span class="label">瀹㈡埛鍚嶇О锛�</span>
- <span class="value">{{ item.customerName }}</span>
- </div>
- <span class="label">鍗曞彿锛�</span>
- <span class="value">{{ item.salesContractNo }}</span>
- </div>
- </div>
-
- <div class="table-section">
- <table class="product-table">
- <thead>
- <tr>
- <th>浜у搧鍚嶇О</th>
- <th>瑙勬牸鍨嬪彿</th>
- <th>鍗曚綅</th>
- <th>鍗曚环</th>
- <th>闆跺敭鏁伴噺</th>
- <th>闆跺敭閲戦</th>
- </tr>
- </thead>
- <tbody>
- <tr v-for="product in item.products" :key="product.id">
- <td>{{ product.productCategory || '' }}</td>
- <td>{{ product.specificationModel || '' }}</td>
- <td>{{ product.unit || '' }}</td>
- <td>{{ product.taxInclusiveUnitPrice || '0' }}</td>
- <td>{{ product.quantity || '0' }}</td>
- <td>{{ product.taxInclusiveTotalPrice || '0' }}</td>
- </tr>
- <tr v-if="!item.products || item.products.length === 0">
- <td colspan="6" style="text-align: center; color: #999;">鏆傛棤浜у搧鏁版嵁</td>
- </tr>
- </tbody>
- <tfoot>
- <tr>
- <td class="label">鍚堣</td>
- <td class="total-value"></td>
- <td class="total-value"></td>
- <td class="total-value"></td>
- <td class="total-value">{{ getTotalQuantity(item.products) }}</td>
- <td class="total-value">{{ getTotalAmount(item.products) }}</td>
- </tr>
- </tfoot>
- </table>
- </div>
-
- <div class="footer-section">
- <div class="footer-row">
- <div class="footer-item">
- <span class="label">鏀惰揣鐢佃瘽锛�</span>
- <span class="value"></span>
- </div>
- <div class="footer-item">
- <span class="label">鏀惰揣浜猴細</span>
- <span class="value"></span>
- </div>
- <div class="footer-item address-item">
- <span class="label">鏀惰揣鍦板潃锛�</span>
- <span class="value address-value"></span>
- </div>
- </div>
- <div class="footer-row">
- <div class="footer-item">
- <span class="label">鎿嶄綔鍛橈細</span>
- <span class="value">{{ userStore.nickName || '鎾曞紑鍓�' }}</span>
- </div>
- <div class="footer-item">
- <span class="label">鎵撳嵃鏃ユ湡锛�</span>
- <span class="value">{{ formatDateTime(new Date()) }}</span>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </el-dialog>
- <!-- 鍙戣揣寮规 -->
- <el-dialog
- v-model="deliveryFormVisible"
- title="鍙戣揣淇℃伅"
- width="40%"
- @close="closeDeliveryDia"
- >
- <el-form :model="deliveryForm" label-width="120px" label-position="top" :rules="deliveryRules" ref="deliveryFormRef">
- <el-row :gutter="30">
- <el-col :span="24">
- <el-form-item label="鍙戣揣绫诲瀷锛�" prop="type">
- <el-select
- v-model="deliveryForm.type"
- placeholder="璇烽�夋嫨鍙戣揣绫诲瀷"
- style="width: 100%"
- >
- <el-option label="璐ц溅" value="璐ц溅" />
- <el-option label="蹇��" value="蹇��" />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
-
+ <el-tree-select v-model="productForm.productCategory"
+ placeholder="璇烽�夋嫨"
+ clearable
+ check-strictly
+ @change="getModels"
+ :data="productOptions"
+ :render-after-expand="false"
+ style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="瑙勬牸鍨嬪彿锛�"
+ prop="productModelId">
+ <el-select v-model="productForm.productModelId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="getProductModel"
+ filterable>
+ <el-option v-for="item in modelOptions"
+ :key="item.id"
+ :label="item.model"
+ :value="item.id" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍗曚綅锛�"
+ prop="unit">
+ <el-input v-model="productForm.unit"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鏁伴噺锛�"
+ prop="quantity">
+ <el-input-number :step="0.1"
+ :min="0"
+ v-model="productForm.quantity"
+ placeholder="璇疯緭鍏�"
+ clearable
+ :precision="2"
+ @change="calculateFromQuantity"
+ style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ <!-- <el-col :span="12">
+ <el-form-item label="绋庣巼(%)锛�"
+ prop="taxRate">
+ <el-select v-model="productForm.taxRate"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="calculateFromTaxRate">
+ <el-option label="1"
+ value="1" />
+ <el-option label="6"
+ value="6" />
+ <el-option label="13"
+ value="13" />
+ </el-select>
+ </el-form-item>
+ </el-col> -->
+ </el-row>
+ <el-row :gutter="30">
+ </el-row>
+ <!-- 瀵瑰叕瀹㈡埛鏄剧ず鐨勫瓧娈� -->
+ <template v-if="currentCustomerType == 1">
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="绋庣巼(%)锛�"
+ prop="taxRate">
+ <el-select v-model="productForm.taxRate"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="calculateFromTaxRate">
+ <el-option label="1"
+ value="1" />
+ <el-option label="6"
+ value="6" />
+ <el-option label="13"
+ value="13" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍚◣鍗曚环(鍏�)锛�"
+ prop="taxInclusiveUnitPrice">
+ <el-input-number :step="0.01"
+ :min="0"
+ v-model="productForm.taxInclusiveUnitPrice"
+ style="width: 100%"
+ :precision="2"
+ placeholder="璇疯緭鍏�"
+ clearable
+ @change="calculateFromUnitPrice" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍚◣鎬讳环(鍏�)锛�"
+ prop="taxInclusiveTotalPrice">
+ <el-input v-model="productForm.taxInclusiveTotalPrice"
+ placeholder="璇疯緭鍏�"
+ clearable
+ @change="calculateFromTotalPrice" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="涓嶅惈绋庢�讳环(鍏�)锛�"
+ prop="taxExclusiveTotalPrice">
+ <el-input v-model="productForm.taxExclusiveTotalPrice"
+ placeholder="璇疯緭鍏�"
+ clearable
+ @change="calculateFromExclusiveTotalPrice" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍙戠エ绫诲瀷锛�"
+ prop="invoiceType">
+ <el-select v-model="productForm.invoiceType"
+ placeholder="璇烽�夋嫨"
+ clearable>
+ <el-option label="澧炴櫘绁�"
+ value="澧炴櫘绁�" />
+ <el-option label="澧炰笓绁�"
+ value="澧炰笓绁�" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </template>
+ <!-- 瀵圭瀹㈡埛鏄剧ず鐨勫瓧娈� -->
+ <template v-else-if="currentCustomerType == 2">
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍗曚环锛�"
+ prop="unitPrice">
+ <el-input-number :step="0.01"
+ :min="0"
+ v-model="productForm.unitPrice"
+ style="width: 100%"
+ :precision="2"
+ placeholder="璇疯緭鍏�"
+ clearable
+ @change="calculatePrivatePrice" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鎬讳环锛�"
+ prop="totalPrice">
+ <el-input-number :step="0.01"
+ :min="0"
+ v-model="productForm.totalPrice"
+ style="width: 100%"
+ :precision="2"
+ placeholder="璇疯緭鍏�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="杩愯垂锛�"
+ prop="freight">
+ <el-input-number :step="0.01"
+ :min="0"
+ v-model="productForm.freight"
+ style="width: 100%"
+ :precision="2"
+ placeholder="璇疯緭鍏�"
+ clearable
+ @change="calculatePrivatePrice" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍚繍璐瑰崟浠凤細"
+ prop="priceWithFreight">
+ <el-input-number :step="0.01"
+ :min="0"
+ v-model="productForm.priceWithFreight"
+ style="width: 100%"
+ :precision="2"
+ placeholder="璇疯緭鍏�"
+ clearable
+ @change="calculatePrivateTotal" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </template>
+ </el-form>
+ </FormDialog>
+ <!-- 瀵煎叆寮圭獥 -->
+ <FormDialog v-model="importUpload.open"
+ :title="importUpload.title"
+ :width="'600px'"
+ @close="importUpload.open = false"
+ @confirm="submitImportFile"
+ @cancel="importUpload.open = false">
+ <el-upload ref="importUploadRef"
+ :limit="1"
+ accept=".xlsx,.xls"
+ :action="importUpload.url"
+ :headers="importUpload.headers"
+ :before-upload="importUpload.beforeUpload"
+ :on-success="importUpload.onSuccess"
+ :on-error="importUpload.onError"
+ :on-progress="importUpload.onProgress"
+ :on-change="importUpload.onChange"
+ :auto-upload="false"
+ drag>
+ <i class="el-icon-upload"></i>
+ <div class="el-upload__text">
+ 灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em>
+ </div>
+ <template #tip>
+ <div class="el-upload__tip">
+ 浠呮敮鎸� xls/xlsx锛屽ぇ灏忎笉瓒呰繃 10MB銆�
+ <el-button link
+ type="primary"
+ @click="downloadTemplate">涓嬭浇瀵煎叆妯℃澘</el-button>
+ </div>
+ </template>
+ </el-upload>
+ </FormDialog>
+ <!-- 闄勪欢鍒楄〃寮圭獥 -->
+ <FileListDialog ref="fileListRef"
+ v-model="fileListDialogVisible"
+ title="闄勪欢鍒楄〃" />
+ <!-- 鎵撳嵃棰勮寮圭獥 -->
+ <el-dialog v-model="printPreviewVisible"
+ title="鎵撳嵃棰勮"
+ width="90%"
+ :close-on-click-modal="false"
+ class="print-preview-dialog">
+ <div class="print-preview-container">
+ <div class="print-preview-header">
+ <el-button type="primary"
+ @click="executePrint">鎵ц鎵撳嵃</el-button>
+ <el-button @click="printPreviewVisible = false">鍏抽棴棰勮</el-button>
+ </div>
+ <div class="print-preview-content">
+ <div v-if="printData.length === 0"
+ style="text-align: center; padding: 50px; color: #999;">
+ 鏆傛棤鎵撳嵃鏁版嵁
+ </div>
+ <div v-else
+ style="text-align: center; padding: 10px; color: #666; font-size: 14px; background: #e8f4fd; margin-bottom: 10px;">
+ 鍏� {{ printData.length }} 鏉℃暟鎹緟鎵撳嵃
+ </div>
+ <div v-for="(item, index) in printData"
+ :key="index"
+ class="print-page">
+ <div class="delivery-note">
+ <div class="header">
+ <div class="document-title">闆跺敭鍙戣揣鍗�</div>
+ </div>
+ <div class="info-section">
+ <div class="info-row">
+ <div>
+ <span class="label">鍙戣揣鏃ユ湡锛�</span>
+ <span class="value">{{ formatDate(item.createTime) }}</span>
+ </div>
+ <div>
+ <span class="label">鍙戣揣杞︾墝鍙凤細</span>
+ <span class="value">{{ item.shippingCarNumber }}</span>
+ </div>
+ </div>
+ <div class="info-row">
+ <div>
+ <span class="label">瀹㈡埛鍚嶇О锛�</span>
+ <span class="value">{{ item.customerName }}</span>
+ </div>
+ <span class="label">鍗曞彿锛�</span>
+ <span class="value">{{ item.salesContractNo }}</span>
+ </div>
+ </div>
+ <div class="table-section">
+ <table class="product-table">
+ <thead>
+ <tr>
+ <th>浜у搧鍚嶇О</th>
+ <th>瑙勬牸鍨嬪彿</th>
+ <th>鍗曚綅</th>
+ <th>鍗曚环</th>
+ <th>闆跺敭鏁伴噺</th>
+ <th>闆跺敭閲戦</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr v-for="product in item.products"
+ :key="product.id">
+ <td>{{ product.productCategory || '' }}</td>
+ <td>{{ product.specificationModel || '' }}</td>
+ <td>{{ product.unit || '' }}</td>
+ <td>{{ product.taxInclusiveUnitPrice || '0' }}</td>
+ <td>{{ product.quantity || '0' }}</td>
+ <td>{{ product.taxInclusiveTotalPrice || '0' }}</td>
+ </tr>
+ <tr v-if="!item.products || item.products.length === 0">
+ <td colspan="6"
+ style="text-align: center; color: #999;">鏆傛棤浜у搧鏁版嵁</td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td class="label">鍚堣</td>
+ <td class="total-value"></td>
+ <td class="total-value"></td>
+ <td class="total-value"></td>
+ <td class="total-value">{{ getTotalQuantity(item.products) }}</td>
+ <td class="total-value">{{ getTotalAmount(item.products) }}</td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+ <div class="footer-section">
+ <div class="footer-row">
+ <div class="footer-item">
+ <span class="label">鏀惰揣鐢佃瘽锛�</span>
+ <span class="value"></span>
+ </div>
+ <div class="footer-item">
+ <span class="label">鏀惰揣浜猴細</span>
+ <span class="value"></span>
+ </div>
+ <div class="footer-item address-item">
+ <span class="label">鏀惰揣鍦板潃锛�</span>
+ <span class="value address-value"></span>
+ </div>
+ </div>
+ <div class="footer-row">
+ <div class="footer-item">
+ <span class="label">鎿嶄綔鍛橈細</span>
+ <span class="value">{{ userStore.nickName || '鎾曞紑鍓�' }}</span>
+ </div>
+ <div class="footer-item">
+ <span class="label">鎵撳嵃鏃ユ湡锛�</span>
+ <span class="value">{{ formatDateTime(new Date()) }}</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </el-dialog>
+ <!-- 鍙戣揣寮规 -->
+ <el-dialog v-model="deliveryFormVisible"
+ title="鍙戣揣淇℃伅"
+ width="40%"
+ @close="closeDeliveryDia">
+ <el-form :model="deliveryForm"
+ label-width="120px"
+ label-position="top"
+ :rules="deliveryRules"
+ ref="deliveryFormRef">
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="鍙戣揣绫诲瀷锛�"
+ prop="type">
+ <el-select v-model="deliveryForm.type"
+ placeholder="璇烽�夋嫨鍙戣揣绫诲瀷"
+ style="width: 100%">
+ <el-option label="璐ц溅"
+ value="璐ц溅" />
+ <el-option label="蹇��"
+ value="蹇��" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
<!-- 瀹℃壒浜洪�夋嫨锛堜豢鍗忓悓瀹℃壒閲岀殑瀹℃壒浜鸿妭鐐归�夋嫨锛� -->
<el-row>
<el-col :span="24">
<el-form-item>
<template #label>
<span>瀹℃壒浜洪�夋嫨锛�</span>
- <el-button type="primary" @click="addApproverNode" style="margin-left: 8px;">鏂板鑺傜偣</el-button>
+ <el-button type="primary"
+ @click="addApproverNode"
+ style="margin-left: 8px;">鏂板鑺傜偣</el-button>
</template>
<div style="display: flex; align-items: flex-end; flex-wrap: wrap;">
- <div
- v-for="(node, index) in approverNodes"
- :key="node.id"
- style="margin-right: 20px; text-align: center; margin-bottom: 10px;"
- >
+ <div v-for="(node, index) in approverNodes"
+ :key="node.id"
+ style="margin-right: 20px; text-align: center; margin-bottom: 10px;">
<div>
<span>瀹℃壒浜�</span>
鈫�
</div>
- <el-select
- v-model="node.userId"
- placeholder="閫夋嫨浜哄憳"
- filterable
- style="width: 140px; margin-bottom: 8px;"
- >
- <el-option
- v-for="user in userList"
- :key="user.userId"
- :label="user.nickName"
- :value="user.userId"
- />
+ <el-select v-model="node.userId"
+ placeholder="閫夋嫨浜哄憳"
+ filterable
+ style="width: 140px; margin-bottom: 8px;">
+ <el-option v-for="user in userList"
+ :key="user.userId"
+ :label="user.nickName"
+ :value="user.userId" />
</el-select>
<div>
- <el-button
- type="danger"
- @click="removeApproverNode(index)"
- v-if="approverNodes.length > 1"
- >鍒犻櫎</el-button>
+ <el-button type="danger"
+ @click="removeApproverNode(index)"
+ v-if="approverNodes.length > 1">鍒犻櫎</el-button>
</div>
</div>
</div>
</el-form-item>
</el-col>
</el-row>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="submitDelivery">纭鍙戣揣</el-button>
- <el-button @click="closeDeliveryDia">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary"
+ @click="submitDelivery">纭鍙戣揣</el-button>
+ <el-button @click="closeDeliveryDia">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
</template>
<script setup>
-import { getToken } from "@/utils/auth";
-import pagination from "@/components/PIMTable/Pagination.vue";
-import {onMounted, ref, getCurrentInstance} from "vue";
-import { addShippingInfo } from "@/api/salesManagement/deliveryLedger.js";
-import { ElMessageBox, ElMessage } from "element-plus";
-import { UploadFilled, Download } from "@element-plus/icons-vue";
-import useUserStore from "@/store/modules/user";
-import { userListNoPage } from "@/api/system/user.js";
-import FileListDialog from '@/components/Dialog/FileListDialog.vue';
-import FormDialog from '@/components/Dialog/FormDialog.vue';
-import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
-import {
- ledgerListPage,
- productList,
- customerList,
- addOrUpdateSalesLedger,
- getSalesLedgerWithProducts,
- delLedger,
- addOrUpdateSalesLedgerProduct,
- delProduct,
- delLedgerFile, getProductInventory,
-} from "@/api/salesManagement/salesLedger.js";
-import { modelList, productTreeList } from "@/api/basicData/product.js";
-import useFormData from "@/hooks/useFormData.js";
-import dayjs from "dayjs";
-import { getCurrentDate } from "@/utils/index.js";
+ import { getToken } from "@/utils/auth";
+ import pagination from "@/components/PIMTable/Pagination.vue";
+ import { onMounted, ref, getCurrentInstance } from "vue";
+ import { addShippingInfo } from "@/api/salesManagement/deliveryLedger.js";
+ import { ElMessageBox, ElMessage } from "element-plus";
+ import { UploadFilled, Download } from "@element-plus/icons-vue";
+ import useUserStore from "@/store/modules/user";
+ import { userListNoPage } from "@/api/system/user.js";
+ import FileListDialog from "@/components/Dialog/FileListDialog.vue";
+ import FormDialog from "@/components/Dialog/FormDialog.vue";
+ import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
+ import {
+ ledgerListPage,
+ productList,
+ customerList,
+ addOrUpdateSalesLedger,
+ getSalesLedgerWithProducts,
+ delLedger,
+ addOrUpdateSalesLedgerProduct,
+ delProduct,
+ delLedgerFile,
+ getProductInventory,
+ } from "@/api/salesManagement/salesLedger.js";
+ import { modelList, productTreeList } from "@/api/basicData/product.js";
+ import useFormData from "@/hooks/useFormData.js";
+ import dayjs from "dayjs";
+ import { getCurrentDate } from "@/utils/index.js";
-const userStore = useUserStore();
-const { proxy } = getCurrentInstance();
-const tableData = ref([]);
-const productData = ref([]);
-const selectedRows = ref([]);
-const productSelectedRows = ref([]);
-const userList = ref([]);
-const customerOption = ref([]);
-const productOptions = ref([]);
-const modelOptions = ref([]);
-const tableLoading = ref(false);
-const page = reactive({
- current: 1,
- size: 100,
-});
-const total = ref(0);
-const fileList = ref([]);
+ const userStore = useUserStore();
+ const { proxy } = getCurrentInstance();
+ const tableData = ref([]);
+ const productData = ref([]);
+ const selectedRows = ref([]);
+ const productSelectedRows = ref([]);
+ const userList = ref([]);
+ const customerOption = ref([]);
+ const productOptions = ref([]);
+ const modelOptions = ref([]);
+ const tableLoading = ref(false);
+ const page = reactive({
+ current: 1,
+ size: 100,
+ });
+ const total = ref(0);
+ const fileList = ref([]);
-// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
-const operationType = ref("");
-const dialogFormVisible = ref(false);
-const data = reactive({
- searchForm: {
- customerName: "", // 瀹㈡埛鍚嶇О
- salesContractNo: "", // 閿�鍞悎鍚岀紪鍙�
- entryDate: null, // 褰曞叆鏃ユ湡
- entryDateStart: undefined,
- entryDateEnd: undefined,
- },
- form: {
- salesContractNo: "",
- salesman: "",
- customerId: "",
- entryPerson: "",
- entryDate: "",
- deliveryDate: "",
- maintenanceTime: "",
- productData: [],
- executionDate: "",
- },
- rules: {
- salesman: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- customerId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- entryPerson: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- deliveryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- },
-});
-const { form, rules } = toRefs(data);
-const { form: searchForm } = useFormData(data.searchForm);
-// 浜у搧琛ㄥ崟寮规鏁版嵁
-const productFormVisible = ref(false);
-const productOperationType = ref("");
-const currentId = ref("");
-const productFormData = reactive({
- productForm: {
- productCategory: "",
- specificationModel: "",
- unit: "",
- quantity: "",
- taxInclusiveUnitPrice: "",
- taxRate: "",
- taxInclusiveTotalPrice: "",
- taxExclusiveTotalPrice: "",
- invoiceType: "",
- },
- productRules: {
- productCategory: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- specificationModel: [
- { required: true, message: "璇烽�夋嫨", trigger: "change" },
- ],
- unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- taxInclusiveUnitPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- taxInclusiveTotalPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- taxExclusiveTotalPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- },
-});
-const { productForm, productRules } = toRefs(productFormData);
-// 闃叉寰幆璁$畻鐨勬爣蹇�
-const isCalculating = ref(false);
-const upload = reactive({
- // 涓婁紶鐨勫湴鍧�
- url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
- // 璁剧疆涓婁紶鐨勮姹傚ご閮�
- headers: { Authorization: "Bearer " + getToken() },
-});
-// 鎵撳嵃鐩稿叧
-const printPreviewVisible = ref(false);
-const printData = ref([]);
+ // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+ const operationType = ref("");
+ const dialogFormVisible = ref(false);
+ const currentCustomerType = ref(""); // 褰撳墠瀹㈡埛绫诲瀷锛氬鍏�/瀵圭
+ const data = reactive({
+ searchForm: {
+ customerName: "", // 瀹㈡埛鍚嶇О
+ salesContractNo: "", // 閿�鍞悎鍚岀紪鍙�
+ entryDate: null, // 褰曞叆鏃ユ湡
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
+ customerType: "",
+ },
+ form: {
+ salesContractNo: "",
+ salesman: "",
+ customerId: "",
+ entryPerson: "",
+ entryDate: "",
+ deliveryDate: "",
+ maintenanceTime: "",
+ productData: [],
+ executionDate: "",
+ },
+ rules: {
+ salesman: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ customerId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ entryPerson: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ deliveryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ },
+ });
+ const { form, rules } = toRefs(data);
+ const { form: searchForm } = useFormData(data.searchForm);
+ // 浜у搧琛ㄥ崟寮规鏁版嵁
+ const productFormVisible = ref(false);
+ const productOperationType = ref("");
+ const currentId = ref("");
+ const productFormData = reactive({
+ productForm: {
+ productCategory: "",
+ specificationModel: "",
+ unit: "",
+ quantity: "",
+ // 瀵瑰叕瀛楁
+ taxInclusiveUnitPrice: "",
+ taxRate: "",
+ taxInclusiveTotalPrice: "",
+ taxExclusiveTotalPrice: "",
+ invoiceType: "",
+ // 瀵圭瀛楁
+ unitPrice: "",
+ totalPrice: "",
+ freight: 0,
+ priceWithFreight: "",
+ },
+ productRules: {
+ productCategory: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ specificationModel: [
+ { required: true, message: "璇烽�夋嫨", trigger: "change" },
+ ],
+ unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ // 瀵瑰叕瀛楁楠岃瘉
+ taxInclusiveUnitPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ taxInclusiveTotalPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ taxExclusiveTotalPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ // 瀵圭瀛楁楠岃瘉
+ unitPrice: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ totalPrice: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ freight: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ priceWithFreight: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ },
+ });
+ const { productForm, productRules } = toRefs(productFormData);
+ // 闃叉寰幆璁$畻鐨勬爣蹇�
+ const isCalculating = ref(false);
+ const upload = reactive({
+ // 涓婁紶鐨勫湴鍧�
+ url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
+ // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+ headers: { Authorization: "Bearer " + getToken() },
+ });
+ // 鎵撳嵃鐩稿叧
+ const printPreviewVisible = ref(false);
+ const printData = ref([]);
-// 鎶ヤ环鍗曞鍏ョ浉鍏�
-const quotationDialogVisible = ref(false);
-const quotationLoading = ref(false);
-const quotationList = ref([]);
-const quotationSearchForm = reactive({
- quotationNo: "",
- customer: "",
-});
-// 鎶ヤ环鍗曞脊妗嗗垎椤�
-const quotationPage = reactive({
- current: 1,
- size: 10,
- total: 0,
-});
-const selectedQuotation = ref(null);
+ // 鎶ヤ环鍗曞鍏ョ浉鍏�
+ const quotationDialogVisible = ref(false);
+ const quotationLoading = ref(false);
+ const quotationList = ref([]);
+ const quotationSearchForm = reactive({
+ quotationNo: "",
+ customer: "",
+ });
+ // 鎶ヤ环鍗曞脊妗嗗垎椤�
+ const quotationPage = reactive({
+ current: 1,
+ size: 10,
+ total: 0,
+ });
+ const selectedQuotation = ref(null);
-// 鍙戣揣鐩稿叧
-const deliveryFormVisible = ref(false);
-const currentDeliveryRow = ref(null);
-const deliveryFormData = reactive({
- deliveryForm: {
- type: "璐ц溅", // 璐ц溅, 蹇��
- },
- deliveryRules: {
- type: [
- { required: true, message: "璇烽�夋嫨鍙戣揣绫诲瀷", trigger: "change" }
- ]
- },
-});
-const { deliveryForm, deliveryRules } = toRefs(deliveryFormData);
+ // 鍙戣揣鐩稿叧
+ const deliveryFormVisible = ref(false);
+ const currentDeliveryRow = ref(null);
+ const deliveryFormData = reactive({
+ deliveryForm: {
+ type: "璐ц溅", // 璐ц溅, 蹇��
+ },
+ deliveryRules: {
+ type: [{ required: true, message: "璇烽�夋嫨鍙戣揣绫诲瀷", trigger: "change" }],
+ },
+ });
+ const { deliveryForm, deliveryRules } = toRefs(deliveryFormData);
-// 鍙戣揣瀹℃壒浜鸿妭鐐癸紙浠垮崗鍚屽鎵� infoFormDia.vue锛�
-const approverNodes = ref([{ id: 1, userId: null }]);
-let nextApproverId = 2;
-const addApproverNode = () => {
- approverNodes.value.push({ id: nextApproverId++, userId: null });
-};
-const removeApproverNode = (index) => {
- approverNodes.value.splice(index, 1);
-};
-
-// 瀵煎叆鐩稿叧
-const importUploadRef = ref(null);
-const importUpload = reactive({
- title: "瀵煎叆閿�鍞彴璐�",
- open: false,
- url: import.meta.env.VITE_APP_BASE_API + "/sales/ledger/import",
- headers: { Authorization: "Bearer " + getToken() },
- isUploading: false,
- beforeUpload: (file) => {
- const isExcel = file.name.endsWith('.xlsx') || file.name.endsWith('.xls');
- const isLt10M = file.size / 1024 / 1024 < 10;
- if (!isExcel) {
- proxy.$modal.msgError("涓婁紶鏂囦欢鍙兘鏄� xlsx/xls 鏍煎紡!");
- return false;
- }
- if (!isLt10M) {
- proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 10MB!");
- return false;
- }
- return true;
- },
- onChange: (file, fileList) => {
- console.log('鏂囦欢鐘舵�佹敼鍙�', file, fileList);
- },
- onProgress: (event, file, fileList) => {
- console.log('涓婁紶涓�...', event.percent);
- },
- onSuccess: (response, file, fileList) => {
- console.log('涓婁紶鎴愬姛', response, file, fileList);
- importUpload.isUploading = false;
- if (response.code === 200) {
- proxy.$modal.msgSuccess("瀵煎叆鎴愬姛");
- importUpload.open = false;
- if (importUploadRef.value) {
- importUploadRef.value.clearFiles();
- }
- getList();
- } else {
- proxy.$modal.msgError(response.msg || "瀵煎叆澶辫触");
- }
- },
- onError: (error, file, fileList) => {
- console.error('涓婁紶澶辫触', error, file, fileList);
- importUpload.isUploading = false;
- proxy.$modal.msgError("瀵煎叆澶辫触锛岃閲嶈瘯");
- },
-});
-
-const changeDaterange = (value) => {
- if (value) {
- searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
- searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
- } else {
- searchForm.entryDateStart = undefined;
- searchForm.entryDateEnd = undefined;
- }
- handleQuery();
-};
-
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- // 鍙湁鍦ㄧ偣鍑绘悳绱㈡寜閽椂鎵嶉噸缃〉鐮佸埌绗竴椤�
- // 閬垮厤琛ㄥ崟瀛楁change浜嬩欢骞叉壈鍒嗛〉
- if (arguments.length === 0) {
- page.current = 1;
- }
- expandedRowKeys.value = [];
- getList();
-};
-const paginationChange = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
-const getList = () => {
- tableLoading.value = true;
- const { entryDate, ...rest } = searchForm;
- // 灏嗚寖鍥存棩鏈熷瓧娈典紶閫掔粰鍚庣
- const params = { ...rest, ...page };
- // 绉婚櫎褰曞叆鏃ユ湡鐨勯粯璁ゅ�艰缃紝鍙繚鐣欒寖鍥存棩鏈熷瓧娈�
- delete params.entryDate;
- return ledgerListPage(params)
- .then((res) => {
- tableLoading.value = false;
- tableData.value = res.records;
- tableData.value.map((item) => {
- item.children = [];
- });
- total.value = res.total;
- return res;
- })
- .catch(() => {
- tableLoading.value = false;
- });
-};
-// 鑾峰彇浜у搧澶х被tree鏁版嵁
-const getProductOptions = () => {
- // 杩斿洖 Promise锛屼究浜庡湪缂栬緫浜у搧鏃剁瓑寰呭姞杞藉畬鎴�
- return productTreeList().then((res) => {
- productOptions.value = convertIdToValue(res);
- return productOptions.value;
- });
-};
-const formattedNumber = (row, column, cellValue) => {
- return parseFloat(cellValue).toFixed(2);
-};
-// 鑾峰彇tree瀛愭暟鎹�
-const getModels = (value) => {
- productForm.value.productCategory = findNodeById(productOptions.value, value);
- modelList({ id: value }).then((res) => {
- modelOptions.value = res;
- });
-};
-const getProductModel = (value) => {
- const index = modelOptions.value.findIndex((item) => item.id === value);
- if (index !== -1) {
- productForm.value.specificationModel = modelOptions.value[index].model;
- productForm.value.unit = modelOptions.value[index].unit;
- } else {
- productForm.value.specificationModel = null;
- productForm.value.unit = null;
- }
-};
-const findNodeById = (nodes, productId) => {
- for (let i = 0; i < nodes.length; i++) {
- if (nodes[i].value === productId) {
- return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
- }
- if (nodes[i].children && nodes[i].children.length > 0) {
- const foundNode = findNodeById(nodes[i].children, productId);
- if (foundNode) {
- return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖璇ヨ妭鐐�
- }
- }
- }
- return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
-};
-function convertIdToValue(data) {
- return data.map((item) => {
- const { id, children, ...rest } = item;
- const newItem = {
- ...rest,
- value: id, // 灏� id 鏀逛负 value
- };
- if (children && children.length > 0) {
- newItem.children = convertIdToValue(children);
- }
-
- return newItem;
- });
-}
-// 鏍规嵁鍚嶇О鍙嶆煡浜у搧澶х被 id锛屼究浜庝粎瀛樺悕绉版椂鐨勫弽鏄�
-function findNodeIdByLabel(nodes, label) {
- if (!label) return null;
- for (let i = 0; i < nodes.length; i++) {
- const node = nodes[i];
- if (node.label === label) return node.value;
- if (node.children && node.children.length > 0) {
- const found = findNodeIdByLabel(node.children, label);
- if (found !== null && found !== undefined) return found;
- }
- }
- return null;
-}
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = (selection) => {
- // 杩囨护鎺夊瓙鏁版嵁
- selectedRows.value = selection.filter((item) => item.children !== undefined);
- console.log("selection", selectedRows.value);
-};
-const productSelected = (selectedRows) => {
- productSelectedRows.value = selectedRows;
-};
-const expandedRowKeys = ref([]);
-// 灞曞紑琛�
-const expandChange = (row, expandedRows) => {
- if (expandedRows.length > 0) {
- expandedRowKeys.value = [];
- try {
- productList({ salesLedgerId: row.id, type: 1 }).then((res) => {
- const index = tableData.value.findIndex((item) => item.id === row.id);
- if (index > -1) {
- tableData.value[index].children = res.data;
- }
- expandedRowKeys.value.push(row.id);
- });
- } catch (error) {
- console.log(error);
- }
- } else {
- expandedRowKeys.value = [];
- }
-};
-
-// 娣诲姞琛ㄨ绫诲悕鏂规硶
-const tableRowClassName = ({ row }) => {
- if (!row.deliveryDate) return '';
- if (row.isFh) return '';
-
- const diff = row.deliveryDaysDiff;
- if (diff === 15) {
- return 'yellow';
- } else if (diff === 10) {
- return 'pink';
- } else if (diff === 2) {
- return 'purple';
- } else if (diff < 2) {
- return 'red';
- }
-};
-// 涓昏〃鍚堣鏂规硶
-const summarizeMainTable = (param) => {
- return proxy.summarizeTable(param, [
- "contractAmount",
- "taxInclusiveTotalPrice",
- "taxExclusiveTotalPrice",
- ]);
-};
-// 瀛愯〃鍚堣鏂规硶
-const summarizeChildrenTable = (param) => {
- return proxy.summarizeTable(param, [
- "taxInclusiveUnitPrice",
- "taxInclusiveTotalPrice",
- "taxExclusiveTotalPrice",
- ]);
-};
-// 鎵撳紑寮规
-const openForm = async (type, row) => {
- operationType.value = type;
- form.value = {};
- productData.value = [];
- selectedQuotation.value = null;
- let userLists = await userListNoPage();
- userList.value = userLists.data;
- customerList().then((res) => {
- customerOption.value = res;
- });
- form.value.entryPerson = userStore.id;
- if (type === "add") {
- // 鏂板鏃惰缃綍鍏ユ棩鏈熶负褰撳ぉ
- form.value.entryDate = getCurrentDate();
- // 绛捐鏃ユ湡榛樿涓哄綋澶�
- form.value.executionDate = getCurrentDate();
- } else {
- currentId.value = row.id;
- getSalesLedgerWithProducts({ id: row.id, type: 1 }).then((res) => {
- form.value = { ...res };
- form.value.entryPerson = Number(res.entryPerson);
- productData.value = form.value.productData;
- fileList.value = form.value.salesLedgerFiles;
- });
- }
- // let userAll = await userStore.getInfo()
- // userList.value.forEach(element => {
- // if(userAll.user.nickName === element.nickName && userAll.user.userName === element.userName) {
- // form.value.entryPerson = userAll.user.userId // 璁剧疆榛樿涓氬姟鍛樹负褰撳墠鐢ㄦ埛
- // }
- // });
- form.value.entryDate = getCurrentDate(); // 璁剧疆榛樿褰曞叆鏃ユ湡涓哄綋鍓嶆棩鏈�
- dialogFormVisible.value = true;
-};
-
-// 鎵撳紑鎶ヤ环鍗曢�夋嫨寮圭獥锛堜粎瀹℃壒閫氳繃锛�
-const openQuotationDialog = async () => {
- if (operationType.value === "view") return;
- quotationDialogVisible.value = true;
- // 鎵撳紑寮圭獥鏃堕噸缃垎椤靛埌绗竴椤�
- quotationPage.current = 1;
- // 鍏堢‘淇濆鎴峰垪琛ㄥ凡鍔犺浇锛屼究浜庡悗缁洖濉� customerId
- if (!customerOption.value || customerOption.value.length === 0) {
- try {
- const res = await customerList();
- customerOption.value = res;
- } catch (e) {
- // ignore锛屽厑璁哥敤鎴峰悗缁墜鍔ㄩ�夋嫨瀹㈡埛
- }
- }
- await fetchQuotationList();
-};
-
-const fetchQuotationList = async () => {
- quotationLoading.value = true;
- try {
- const params = {
- // 鍚庣鍒嗛〉瀛楁锛歝urrent / size
- current: quotationPage.current,
- size: quotationPage.size,
- ...quotationSearchForm,
- status: "閫氳繃",
- };
- const res = await getQuotationList(params);
- quotationList.value = res?.data?.records || [];
- quotationPage.total = res?.data?.total || 0;
- } finally {
- quotationLoading.value = false;
- }
-};
-
-const resetQuotationSearch = async () => {
- quotationSearchForm.quotationNo = "";
- quotationSearchForm.customer = "";
- quotationPage.current = 1;
- await fetchQuotationList();
-};
-
-// 鎶ヤ环鍗曞脊妗嗗垎椤靛垏鎹�
-const quotationPaginationChange = (obj) => {
- quotationPage.current = obj.page;
- quotationPage.size = obj.limit;
- fetchQuotationList();
-};
-
-// 閫変腑鎶ヤ环鍗曞悗鍥炲~鍒板彴璐﹁〃鍗�
-const applyQuotation = (row) => {
- if (!row) return;
- selectedQuotation.value = row;
-
- // 涓氬姟鍛�
- form.value.salesman = (row.salesperson || "").trim();
-
- // 瀹㈡埛鍚嶇О -> customerId
- const qCustomerName = String(row.customer || "").trim();
- const customer = (customerOption.value || []).find((c) => {
- const name = String(c.customerName || "").trim();
- return name === qCustomerName || name.includes(qCustomerName) || qCustomerName.includes(name);
- });
- if (customer?.id) {
- form.value.customerId = customer.id;
- } else {
- // 濡傛灉鎵句笉鍒帮紝淇濈暀鍘熷�硷紙鍏佽鐢ㄦ埛鎵嬪姩閫夋嫨/涓嶆墦鏂凡鏈夎緭鍏ワ級
- form.value.customerId = form.value.customerId || "";
- }
-
- // 浜у搧淇℃伅鏄犲皠锛氭姤浠� products -> 鍙拌处 productData
- const products = Array.isArray(row.products) ? row.products : [];
- productData.value = products.map((p) => {
- const quantity = Number(p.quantity ?? 0) || 0;
- const unitPrice = Number(p.unitPrice ?? 0) || 0;
- const taxRate = "13"; // 榛樿 13%锛屼究浜庣洿鎺ユ彁浜わ紙濡傞渶鍙湪浜у搧涓嚜琛屼慨鏀癸級
- const taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
- const taxExclusiveTotalPrice = proxy.calculateTaxExclusiveTotalPrice(taxInclusiveTotalPrice, taxRate);
- return {
- // 鍙拌处瀛楁
- productCategory: p.product || p.productName || "",
- specificationModel: p.specification || "",
- unit: p.unit || "",
- quantity: quantity,
- taxRate: taxRate,
- taxInclusiveUnitPrice: unitPrice.toFixed(2),
- taxInclusiveTotalPrice: taxInclusiveTotalPrice,
- taxExclusiveTotalPrice: taxExclusiveTotalPrice,
- invoiceType: "澧炴櫘绁�",
- };
- });
-
- quotationDialogVisible.value = false;
-};
-function changs(val) {
- console.log(val);
-}
-// 涓婁紶鍓嶆牎妫�
-function handleBeforeUpload(file) {
- // 鏍℃鏂囦欢澶у皬
- // if (file.size > 1024 * 1024 * 10) {
- // proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃10MB!");
- // return false;
- // }
- proxy.$modal.loading("姝e湪涓婁紶鏂囦欢锛岃绋嶅��...");
- return true;
-}
-// 涓婁紶澶辫触
-function handleUploadError(err) {
- proxy.$modal.msgError("涓婁紶鏂囦欢澶辫触");
- proxy.$modal.closeLoading();
-}
-// 涓婁紶鎴愬姛鍥炶皟
-function handleUploadSuccess(res, file, uploadFiles) {
- proxy.$modal.closeLoading();
- if (res.code === 200) {
- file.tempId = res.data.tempId;
- proxy.$modal.msgSuccess("涓婁紶鎴愬姛");
- } else {
- proxy.$modal.msgError(res.msg);
- proxy.$refs.fileUpload.handleRemove(file);
- }
-}
-// 绉婚櫎鏂囦欢
-function handleRemove(file) {
- if (operationType.value === "edit") {
- let ids = [];
- ids.push(file.id);
- delLedgerFile(ids).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- });
- }
-}
-// 鎻愪氦琛ㄥ崟
-const submitForm = () => {
- proxy.$refs["formRef"].validate((valid) => {
- if (valid) {
- console.log('productData.value--', productData.value)
- if (productData.value !== null && productData.value.length > 0) {
- form.value.productData = proxy.HaveJson(productData.value);
- } else {
- proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
- return;
- }
- let tempFileIds = [];
- if (fileList.value !== null && fileList.value.length > 0) {
- tempFileIds = fileList.value.map((item) => item.tempId);
- }
- form.value.tempFileIds = tempFileIds;
- form.value.type = 1;
- addOrUpdateSalesLedger(form.value).then((res) => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- getList();
- });
- }
- });
-};
-// 鍏抽棴寮规
-const closeDia = () => {
- proxy.resetForm("formRef");
- dialogFormVisible.value = false;
-};
-
-const productIndex = ref(0);
-// 鎵撳紑浜у搧寮规
-const openProductForm = async (type, row, index) => {
- // 缂栬緫鏃舵鏌ヤ骇鍝佹槸鍚﹀凡鍙戣揣鎴栧鏍搁�氳繃
- if (type === "edit" && isProductShipped(row)) {
- proxy.$modal.msgWarning("宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝佷笉鑳界紪杈�");
- return;
- }
-
- productOperationType.value = type;
- productForm.value = {};
- proxy.resetForm("productFormRef");
- if (type === "edit") {
- productForm.value = { ...row };
- productIndex.value = index;
- // 缂栬緫鏃舵牴鎹骇鍝佸ぇ绫诲悕绉板弽鏌� tree 鑺傜偣 id锛屽苟鍔犺浇瑙勬牸鍨嬪彿鍒楄〃
- try {
- const options = productOptions.value && productOptions.value.length > 0
- ? productOptions.value
- : await getProductOptions();
- const categoryId = findNodeIdByLabel(options, productForm.value.productCategory);
- if (categoryId) {
- const models = await modelList({ id: categoryId });
- modelOptions.value = models || [];
- // 鏍规嵁褰撳墠瑙勬牸鍨嬪彿鍚嶇О鍙嶆煡骞惰缃� productModelId锛屼究浜庝笅鎷夋鏄剧ず宸查�夊��
- const currentModel = (modelOptions.value || []).find(
- (m) => m.model === productForm.value.specificationModel
- );
- if (currentModel) {
- productForm.value.productModelId = currentModel.id;
- }
- }
- } catch (e) {
- // 鍔犺浇澶辫触鏃朵繚鎸佸彲缂栬緫锛屼笉涓柇寮圭獥
- console.error("鍔犺浇浜у搧瑙勬牸鍨嬪彿澶辫触", e);
- }
- } else {
- getProductOptions()
- }
- productFormVisible.value = true;
-};
-// 鎻愪氦浜у搧琛ㄥ崟
-const submitProduct = () => {
- proxy.$refs["productFormRef"].validate((valid) => {
- if (valid) {
- if (operationType.value === "edit") {
- submitProductEdit();
- } else {
- if(productOperationType.value === "add"){
- productData.value.push({ ...productForm.value });
- }else{
- productData.value[productIndex.value] = { ...productForm.value }
- }
- closeProductDia();
- }
- }
- });
-};
-const submitProductEdit = () => {
- productForm.value.salesLedgerId = currentId.value;
- productForm.value.type = 1
- addOrUpdateSalesLedgerProduct(productForm.value).then((res) => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeProductDia();
- getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then((res) => {
- productData.value = res.productData;
- });
- });
-};
-// 鍒犻櫎浜у搧
-const deleteProduct = () => {
- if (productSelectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
-
- // 妫�鏌ユ槸鍚︽湁宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝�
- const shippedProducts = productSelectedRows.value.filter(row => isProductShipped(row));
- if (shippedProducts.length > 0) {
- proxy.$modal.msgWarning("宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝佷笉鑳藉垹闄�");
- return;
- }
-
- if (operationType.value === "add") {
- productSelectedRows.value.forEach((selectedRow) => {
- const index = productData.value.findIndex(
- (product) => product.id === selectedRow.id
- );
- if (index !== -1) {
- productData.value.splice(index, 1);
- }
- });
- } else {
- let ids = [];
- if (productSelectedRows.value.length > 0) {
- ids = productSelectedRows.value.map((item) => item.id);
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- delProduct(ids).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- closeProductDia();
- getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then(
- (res) => {
- productData.value = res.productData;
- }
- );
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
- }
-};
-// 鍏抽棴浜у搧寮规
-const closeProductDia = () => {
- proxy.resetForm("productFormRef");
- productFormVisible.value = false;
-};
-// 瀵煎叆
-const handleImport = () => {
- importUpload.title = "瀵煎叆閿�鍞彴璐�";
- importUpload.open = true;
- if (importUploadRef.value) {
- importUploadRef.value.clearFiles();
- }
-};
-
-// 涓嬭浇瀵煎叆妯℃澘
-const downloadTemplate = () => {
- proxy.download("/sales/ledger/exportTemplate", {}, "閿�鍞彴璐﹀鍏ユā鏉�.xlsx");
-};
-
-// 鎻愪氦瀵煎叆鏂囦欢
-const submitImportFile = () => {
- importUpload.isUploading = true;
- proxy.$refs["importUploadRef"].submit();
-};
-
-// 瀵煎嚭
-const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download("/sales/ledger/export", {}, "閿�鍞彴璐�.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-/** 鍒ゆ柇鍗曚釜浜у搧鏄惁宸插彂璐э紙鏍规嵁shippingStatus鍒ゆ柇锛屽凡鍙戣揣鎴栧鏍搁�氳繃涓嶅彲缂栬緫鍜屽垹闄わ級 */
-const isProductShipped = (product) => {
- if (!product) return false;
- const status = String(product.shippingStatus || "").trim();
- // 濡傛灉鍙戣揣鐘舵�佹槸"宸插彂璐�"鎴�"瀹℃牳閫氳繃"锛屽垯涓嶅彲缂栬緫鍜屽垹闄�
- return status === "宸插彂璐�" || status === "瀹℃牳閫氳繃";
-};
-
-/** 鍒ゆ柇閿�鍞鍗曚笅鏄惁瀛樺湪宸插彂璐�/鍙戣揣瀹屾垚鐨勪骇鍝侊紙涓嶅彲鍒犻櫎锛� */
-const hasShippedProducts = (products) => {
- if (!products || !products.length) return false;
- return products.some((p) => {
- const status = String(p.shippingStatus || "").trim();
- // 鏈夊彂璐ф棩鏈熸垨杞︾墝鍙疯涓哄凡鍙戣揣
- if (p.shippingDate || p.shippingCarNumber) return true;
- // 宸茶繘琛屽彂璐с�佸彂璐у畬鎴愩�佸凡鍙戣揣 鍧囦笉鍙垹闄�
- return status === "宸茶繘琛屽彂璐�" || status === "鍙戣揣瀹屾垚" || status === "宸插彂璐�";
- });
-};
-
-// 鍒犻櫎
-const handleDelete = async () => {
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- const ids = selectedRows.value.map((item) => item.id);
-
- // 妫�鏌ユ槸鍚︽湁宸茶繘琛屽彂璐ф垨鍙戣揣瀹屾垚鐨勯攢鍞鍗曪紝鑻ユ湁鍒欎笉鍏佽鍒犻櫎
- const cannotDeleteNames = [];
- for (const row of selectedRows.value) {
- let products = row.children && row.children.length > 0 ? row.children : null;
- if (!products) {
- try {
- const res = await productList({ salesLedgerId: row.id, type: 1 });
- products = res.data || [];
- } catch {
- products = [];
- }
- }
- if (hasShippedProducts(products)) {
- cannotDeleteNames.push(row.salesContractNo || `ID:${row.id}`);
- }
- }
- if (cannotDeleteNames.length > 0) {
- proxy.$modal.msgWarning("宸茶繘琛屽彂璐ф垨鍙戣揣瀹屾垚鐨勯攢鍞鍗曚笉鑳藉垹闄わ細" + cannotDeleteNames.join("銆�"));
- return;
- }
-
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- delLedger(ids).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-// 鎵撳嵃鍔熻兘
-const handlePrint = async () => {
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
- return;
- }
-
- // 鏄剧ず鍔犺浇鐘舵��
- proxy.$modal.loading("姝e湪鑾峰彇浜у搧鏁版嵁锛岃绋嶅��...");
-
- try {
- // 涓烘瘡涓�変腑鐨勯攢鍞彴璐﹁褰曟煡璇㈠搴旂殑浜у搧鏁版嵁
- const printDataWithProducts = [];
-
- for (const row of selectedRows.value) {
- try {
- // 璋冪敤productList鎺ュ彛鏌ヨ浜у搧鏁版嵁
- const productRes = await productList({ salesLedgerId: row.id, type: 1 });
-
- // 灏嗕骇鍝佹暟鎹暣鍚堝埌閿�鍞彴璐﹁褰曚腑
- const rowWithProducts = {
- ...row,
- products: productRes.data || []
- };
-
- printDataWithProducts.push(rowWithProducts);
- } catch (error) {
- console.error(`鑾峰彇閿�鍞彴璐� ${row.id} 鐨勪骇鍝佹暟鎹け璐�:`, error);
- // 鍗充娇鏌愪釜璁板綍鐨勪骇鍝佹暟鎹幏鍙栧け璐ワ紝涔熻鍖呭惈璇ヨ褰�
- printDataWithProducts.push({
- ...row,
- products: []
- });
- }
- }
-
- printData.value = printDataWithProducts;
- console.log('鎵撳嵃鏁版嵁锛堝寘鍚骇鍝侊級:', printData.value);
- printPreviewVisible.value = true;
-
- } catch (error) {
- console.error('鑾峰彇浜у搧鏁版嵁澶辫触:', error);
- proxy.$modal.msgError("鑾峰彇浜у搧鏁版嵁澶辫触锛岃閲嶈瘯");
- } finally {
- proxy.$modal.closeLoading();
- }
-};
-// 鎵ц鎵撳嵃
-const executePrint = () => {
- console.log('寮�濮嬫墽琛屾墦鍗帮紝鏁版嵁鏉℃暟:', printData.value.length);
- console.log('鎵撳嵃鏁版嵁:', printData.value);
-
- // 鍒涘缓涓�涓柊鐨勬墦鍗扮獥鍙�
- const printWindow = window.open('', '_blank', 'width=800,height=600');
-
- // 鏋勫缓鎵撳嵃鍐呭
- let printContent = `
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>鎵撳嵃棰勮</title>
- <style>
- body {
- margin: 0;
- padding: 0;
- font-family: "SimSun", serif;
- background: white;
- }
- .print-page {
- width: 200mm;
- height: 75mm;
- padding: 10mm;
- padding-left: 20mm;
- background: white;
- box-sizing: border-box;
- page-break-after: always;
- page-break-inside: avoid;
- }
- .print-page:last-child {
- page-break-after: avoid;
- }
- .delivery-note {
- width: 100%;
- height: 100%;
- font-size: 12px;
- line-height: 1.2;
- display: flex;
- flex-direction: column;
- color: #000;
- }
- .header {
- text-align: center;
- margin-bottom: 8px;
- }
- .company-name {
- font-size: 18px;
- font-weight: bold;
- margin-bottom: 4px;
- }
- .document-title {
- font-size: 16px;
- font-weight: bold;
- }
- .info-section {
- margin-bottom: 8px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- }
- .info-row {
- line-height: 20px;
- }
- .label {
- font-weight: bold;
- width: 60px;
- font-size: 12px;
- }
- .value {
- margin-right: 20px;
- min-width: 80px;
- font-size: 12px;
- }
- .table-section {
- margin-bottom: 40px;
- // flex: 0.6;
- }
- .product-table {
- width: 100%;
- border-collapse: collapse;
- border: 1px solid #000;
- }
- .product-table th, .product-table td {
- border: 1px solid #000;
- padding: 6px;
- text-align: center;
- font-size: 12px;
- line-height: 1.4;
- }
- .product-table th {
- font-weight: bold;
- }
- .total-value {
- font-weight: bold;
- }
- .footer-section {
- margin-top: auto;
- }
- .footer-row {
- display: flex;
- margin-bottom: 3px;
- line-height: 22px;
- justify-content: space-between;
- }
- .footer-item {
- display: flex;
- margin-right: 20px;
- }
- .footer-item .label {
- font-weight: bold;
- width: 80px;
- font-size: 12px;
- }
- .footer-item .value {
- min-width: 80px;
- font-size: 12px;
- }
- .address-item .address-value {
- min-width: 200px;
- }
- @media print {
- body {
- margin: 0;
- padding: 0;
- }
- .print-page {
- margin: 0;
- padding: 10mm;
- /* padding-left: 20mm; */
- page-break-inside: avoid;
- page-break-after: always;
- }
- .print-page:last-child {
- page-break-after: avoid;
- }
- }
- </style>
- </head>
- <body>
- `;
-
- // 涓烘瘡鏉℃暟鎹敓鎴愭墦鍗伴〉闈�
- printData.value.forEach((item, index) => {
- printContent += `
- <div class="print-page">
- <div class="delivery-note">
- <div class="header">
- <div class="document-title">闆跺敭鍙戣揣鍗�</div>
- </div>
-
- <div class="info-section">
- <div class="info-row">
- <div>
- <span class="label">鍙戣揣鏃ユ湡锛�</span>
- <span class="value">${formatDate(item.createTime)}</span>
- </div>
- <div>
- <span class="label">瀹㈡埛鍚嶇О锛�</span>
- <span class="value">${item.customerName}</span>
- </div>
- </div>
- <div class="info-row">
- <span class="label">鍗曞彿锛�</span>
- <span class="value">${item.salesContractNo || ''}</span>
- </div>
- </div>
-
- <div class="table-section">
- <table class="product-table">
- <thead>
- <tr>
- <th>浜у搧鍚嶇О</th>
- <th>瑙勬牸鍨嬪彿</th>
- <th>鍗曚綅</th>
- <th>鍗曚环</th>
- <th>闆跺敭鏁伴噺</th>
- <th>闆跺敭閲戦</th>
- </tr>
- </thead>
- <tbody>
- ${item.products && item.products.length > 0 ?
- item.products.map(product => `
- <tr>
- <td>${product.productCategory || ''}</td>
- <td>${product.specificationModel || ''}</td>
- <td>${product.unit || ''}</td>
- <td>${product.taxInclusiveUnitPrice || '0'}</td>
- <td>${product.quantity || '0'}</td>
- <td>${product.taxInclusiveTotalPrice || '0'}</td>
- </tr>
- `).join('') :
- '<tr><td colspan="6" style="text-align: center; color: #999;">鏆傛棤浜у搧鏁版嵁</td></tr>'
- }
- </tbody>
- <tfoot>
- <tr>
- <td class="label">鍚堣</td>
- <td class="total-value"></td>
- <td class="total-value"></td>
- <td class="total-value"></td>
- <td class="total-value">${getTotalQuantityForPrint(item.products)}</td>
- <td class="total-value">${getTotalAmountForPrint(item.products)}</td>
- </tr>
- </tfoot>
- </table>
- </div>
-
- <div class="footer-section">
- <div class="footer-row">
- <div class="footer-item">
- <span class="label">鏀惰揣鐢佃瘽锛�</span>
- <span class="value"></span>
- </div>
- <div class="footer-item">
- <span class="label">鏀惰揣浜猴細</span>
- <span class="value"></span>
- </div>
- <div class="footer-item address-item">
- <span class="label">鏀惰揣鍦板潃锛�</span>
- <span class="value address-value"></span>
- </div>
- </div>
- <div class="footer-row">
- <div class="footer-item">
- <span class="label">鎿嶄綔鍛橈細</span>
- <span class="value">${userStore.nickName || '鎾曞紑鍓�'}</span>
- </div>
- <div class="footer-item">
- <span class="label">鎵撳嵃鏃ユ湡锛�</span>
- <span class="value">${formatDateTime(new Date())}</span>
- </div>
- </div>
- </div>
- </div>
- </div>
- `;
- });
-
- printContent += `
- </body>
- </html>
- `;
-
- // 鍐欏叆鍐呭鍒版柊绐楀彛
- printWindow.document.write(printContent);
- printWindow.document.close();
-
- // 绛夊緟鍐呭鍔犺浇瀹屾垚鍚庢墦鍗�
- printWindow.onload = () => {
- setTimeout(() => {
- printWindow.print();
- printWindow.close();
- printPreviewVisible.value = false;
- }, 500);
- };
-};
-// 鏍煎紡鍖栨棩鏈�
-const formatDate = (dateString) => {
- if (!dateString) return getCurrentDate();
- const date = new Date(dateString);
- const year = date.getFullYear();
- const month = String(date.getMonth() + 1).padStart(2, "0");
- const day = String(date.getDate()).padStart(2, "0");
- return `${year}/${month}/${day}`;
-};
-// 鏍煎紡鍖栨棩鏈熸椂闂�
-const formatDateTime = (date) => {
- const year = date.getFullYear();
- const month = String(date.getMonth() + 1).padStart(2, "0");
- const day = String(date.getDate()).padStart(2, "0");
- const hours = String(date.getHours()).padStart(2, "0");
- const minutes = String(date.getMinutes()).padStart(2, "0");
- const seconds = String(date.getSeconds()).padStart(2, "0");
- return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
-};
-// 璁$畻浜у搧鎬绘暟閲�
-const getTotalQuantity = (products) => {
- if (!products || products.length === 0) return '0';
- const total = products.reduce((sum, product) => {
- return sum + (parseFloat(product.quantity) || 0);
- }, 0);
- return total.toFixed(2);
-};
-
-// 璁$畻浜у搧鎬婚噾棰�
-const getTotalAmount = (products) => {
- if (!products || products.length === 0) return '0';
- const total = products.reduce((sum, product) => {
- return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
- }, 0);
- return total.toFixed(2);
-};
-
-// 鐢ㄤ簬鎵撳嵃鐨勮绠楀嚱鏁�
-const getTotalQuantityForPrint = (products) => {
- if (!products || products.length === 0) return '0';
- const total = products.reduce((sum, product) => {
- return sum + (parseFloat(product.quantity) || 0);
- }, 0);
- return total.toFixed(2);
-};
-
-const getTotalAmountForPrint = (products) => {
- if (!products || products.length === 0) return '0';
- const total = products.reduce((sum, product) => {
- return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
- }, 0);
- return total.toFixed(2);
-};
-
-const mathNum = () => {
- console.log("productForm.value", productForm.value);
- if (!productForm.value.taxInclusiveUnitPrice) {
- return;
- }
- if (!productForm.value.quantity) {
- return;
- }
- // 鍚◣鎬讳环璁$畻
- productForm.value.taxInclusiveTotalPrice =
- proxy.calculateTaxIncludeTotalPrice(
- productForm.value.taxInclusiveUnitPrice,
- productForm.value.quantity
- );
- if (productForm.value.taxRate) {
- // 涓嶅惈绋庢�讳环璁$畻
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- productForm.value.taxInclusiveTotalPrice,
- productForm.value.taxRate
- );
- }
-};
-
-// 鏍规嵁鍚◣鎬讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
-const calculateFromTotalPrice = () => {
- if (isCalculating.value) return;
-
- const totalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
- const quantity = parseFloat(productForm.value.quantity);
-
- if (!totalPrice || !quantity || quantity <= 0) {
- return;
- }
-
- isCalculating.value = true;
-
- // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
- productForm.value.taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(2);
-
- // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
- if (productForm.value.taxRate) {
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- totalPrice,
- productForm.value.taxRate
- );
- }
-
- isCalculating.value = false;
-};
-
-// 鏍规嵁涓嶅惈绋庢�讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
-const calculateFromExclusiveTotalPrice = () => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- if (isCalculating.value) return;
-
- const exclusiveTotalPrice = parseFloat(productForm.value.taxExclusiveTotalPrice);
- const quantity = parseFloat(productForm.value.quantity);
- const taxRate = parseFloat(productForm.value.taxRate);
-
- if (!exclusiveTotalPrice || !quantity || quantity <= 0 || !taxRate) {
- return;
- }
-
- isCalculating.value = true;
-
- // 鍏堣绠楀惈绋庢�讳环 = 涓嶅惈绋庢�讳环 / (1 - 绋庣巼/100)
- const taxRateDecimal = taxRate / 100;
- const inclusiveTotalPrice = exclusiveTotalPrice / (1 - taxRateDecimal);
- productForm.value.taxInclusiveTotalPrice = inclusiveTotalPrice.toFixed(2);
-
- // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
- productForm.value.taxInclusiveUnitPrice = (inclusiveTotalPrice / quantity).toFixed(2);
-
- isCalculating.value = false;
-};
-
-// 鏍规嵁鏁伴噺鍙樺寲璁$畻鎬讳环
-const calculateFromQuantity = () => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- if (isCalculating.value) return;
-
- const quantity = parseFloat(productForm.value.quantity);
- const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
-
- if (!quantity || quantity <= 0 || !unitPrice) {
- return;
- }
-
- isCalculating.value = true;
-
- // 璁$畻鍚◣鎬讳环
- productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
-
- // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
- if (productForm.value.taxRate) {
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- productForm.value.taxInclusiveTotalPrice,
- productForm.value.taxRate
- );
- }
-
- isCalculating.value = false;
-};
-
-// 鏍规嵁鍚◣鍗曚环鍙樺寲璁$畻鎬讳环
-const calculateFromUnitPrice = () => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- if (isCalculating.value) return;
-
- const quantity = parseFloat(productForm.value.quantity);
- const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
-
- if (!quantity || quantity <= 0 || !unitPrice) {
- return;
- }
-
- isCalculating.value = true;
-
- // 璁$畻鍚◣鎬讳环
- productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
-
- // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
- if (productForm.value.taxRate) {
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- productForm.value.taxInclusiveTotalPrice,
- productForm.value.taxRate
- );
- }
-
- isCalculating.value = false;
-};
-
-// 鏍规嵁绋庣巼鍙樺寲璁$畻涓嶅惈绋庢�讳环
-const calculateFromTaxRate = () => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- if (isCalculating.value) return;
-
- const inclusiveTotalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
- const taxRate = parseFloat(productForm.value.taxRate);
-
- if (!inclusiveTotalPrice || !taxRate) {
- return;
- }
-
- isCalculating.value = true;
-
- // 璁$畻涓嶅惈绋庢�讳环
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- inclusiveTotalPrice,
- taxRate
- );
-
- isCalculating.value = false;
-};
-/**
- * 鑾峰彇鍙戣揣鐘舵�佹枃鏈�
- * @param row 琛屾暟鎹�
- */
-const getShippingStatusText = (row) => {
- // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屾樉绀�"宸插彂璐�"
- if (row.shippingDate || row.shippingCarNumber) {
- return '宸插彂璐�';
- }
-
- // 鑾峰彇鍙戣揣鐘舵�佸瓧娈�
- const status = row.shippingStatus;
-
- // 濡傛灉鐘舵�佷负绌烘垨鏈畾涔夛紝榛樿涓�"寰呭彂璐�"
- if (status === null || status === undefined || status === '') {
- return '寰呭彂璐�';
- }
-
- // 鐘舵�佹槸瀛楃涓�
- const statusStr = String(status).trim();
- const statusTextMap = {
- '寰呭彂璐�': '寰呭彂璐�',
- '寰呭鏍�': '寰呭鏍�',
- '瀹℃牳涓�': '瀹℃牳涓�',
- '瀹℃牳鎷掔粷': '瀹℃牳鎷掔粷',
- '瀹℃牳閫氳繃': '瀹℃牳閫氳繃',
- '宸插彂璐�': '宸插彂璐�'
- };
- return statusTextMap[statusStr] || '寰呭彂璐�';
-};
-
-/**
- * 鑾峰彇鍙戣揣鐘舵�佹爣绛剧被鍨嬶紙棰滆壊锛�
- * @param row 琛屾暟鎹�
- */
-const getShippingStatusType = (row) => {
- // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屾樉绀虹豢鑹�
- if (row.shippingDate || row.shippingCarNumber) {
- return 'success';
- }
-
- // 鑾峰彇鍙戣揣鐘舵�佸瓧娈�
- const status = row.shippingStatus;
-
- // 濡傛灉鐘舵�佷负绌烘垨鏈畾涔夛紝榛樿涓虹伆鑹诧紙寰呭彂璐э級
- if (status === null || status === undefined || status === '') {
- return 'info';
- }
-
- // 鐘舵�佹槸瀛楃涓�
- const statusStr = String(status).trim();
- const typeTextMap = {
- '寰呭彂璐�': 'info',
- '寰呭鏍�': 'info',
- '瀹℃牳涓�': 'warning',
- '瀹℃牳鎷掔粷': 'danger',
- '瀹℃牳閫氳繃': 'success',
- '宸插彂璐�': 'success'
- };
- return typeTextMap[statusStr] || 'info';
-};
-
-/**
- * 鍒ゆ柇鏄惁鍙互鍙戣揣
- * 鍙湁鍦ㄤ骇鍝佺姸鎬佹槸鍏呰冻锛屽彂璐х姸鎬佹槸寰呭彂璐у拰瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣
- * @param row 琛屾暟鎹�
- */
-const canShip = (row) => {
- // 浜у搧鐘舵�佸繀椤绘槸鍏呰冻锛坅pproveStatus === 1锛�
- if (row.approveStatus !== 1) {
- return false;
- }
-
- // 鑾峰彇鍙戣揣鐘舵��
- const shippingStatus = row.shippingStatus;
-
- // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屼笉鑳藉啀娆″彂璐�
- if (row.shippingDate || row.shippingCarNumber) {
- return false;
- }
-
- // 鍙戣揣鐘舵�佸繀椤绘槸"寰呭彂璐�"鎴�"瀹℃牳鎷掔粷"
- const statusStr = shippingStatus ? String(shippingStatus).trim() : '';
- return statusStr === '寰呭彂璐�' || statusStr === '瀹℃牳鎷掔粷';
-};
-
-/**
- * 涓嬭浇鏂囦欢
- *
- * @param row 涓嬭浇鏂囦欢鐨勭浉鍏充俊鎭璞�
- */
-const fileListRef = ref(null)
-const fileListDialogVisible = ref(false)
-const downLoadFile = (row) => {
- getSalesLedgerWithProducts({ id: row.id, type: 1 }).then((res) => {
- if (fileListRef.value) {
- fileListRef.value.open(res.salesLedgerFiles)
- }
- });
-}
-
-// 鎵撳紑鍙戣揣寮规
-const openDeliveryForm = (row) => {
- // 妫�鏌ユ槸鍚﹀彲浠ュ彂璐�
- if (!canShip(row)) {
- proxy.$modal.msgWarning("鍙湁鍦ㄤ骇鍝佺姸鎬佹槸鍏呰冻锛屽彂璐х姸鎬佹槸寰呭彂璐ф垨瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣");
- return;
- }
-
- currentDeliveryRow.value = row;
- deliveryForm.value = {
- type: "璐ц溅",
+ // 鍙戣揣瀹℃壒浜鸿妭鐐癸紙浠垮崗鍚屽鎵� infoFormDia.vue锛�
+ const approverNodes = ref([{ id: 1, userId: null }]);
+ let nextApproverId = 2;
+ const addApproverNode = () => {
+ approverNodes.value.push({ id: nextApproverId++, userId: null });
};
- // 閲嶇疆瀹℃壒浜鸿妭鐐癸紙榛樿涓�涓┖鑺傜偣锛�
- approverNodes.value = [{ id: 1, userId: null }];
- nextApproverId = 2;
- deliveryFormVisible.value = true;
-};
+ const removeApproverNode = index => {
+ approverNodes.value.splice(index, 1);
+ };
-// 鎻愪氦鍙戣揣琛ㄥ崟
-const submitDelivery = () => {
- proxy.$refs["deliveryFormRef"].validate((valid) => {
- if (valid) {
- // 瀹℃壒浜哄繀濉牎楠岋紙鎵�鏈夎妭鐐归兘瑕侀�変汉锛�
- const hasEmptyApprover = approverNodes.value.some(node => !node.userId);
- if (hasEmptyApprover) {
- proxy.$modal.msgError("璇蜂负鎵�鏈夊鎵硅妭鐐归�夋嫨瀹℃壒浜猴紒");
- return;
+ // 瀵煎叆鐩稿叧
+ const importUploadRef = ref(null);
+ const importUpload = reactive({
+ title: "瀵煎叆閿�鍞彴璐�",
+ open: false,
+ url: import.meta.env.VITE_APP_BASE_API + "/sales/ledger/import",
+ headers: { Authorization: "Bearer " + getToken() },
+ isUploading: false,
+ beforeUpload: file => {
+ const isExcel = file.name.endsWith(".xlsx") || file.name.endsWith(".xls");
+ const isLt10M = file.size / 1024 / 1024 < 10;
+ if (!isExcel) {
+ proxy.$modal.msgError("涓婁紶鏂囦欢鍙兘鏄� xlsx/xls 鏍煎紡!");
+ return false;
}
- const approveUserIds = approverNodes.value.map(node => node.userId).join(",");
- // 淇濆瓨褰撳墠灞曞紑鐨勮ID锛屼互渚垮彂璐у悗閲嶆柊鍔犺浇瀛愯〃鏍兼暟鎹�
- const currentExpandedKeys = [...expandedRowKeys.value];
- const salesLedgerId = currentDeliveryRow.value.salesLedgerId;
- addShippingInfo({
- salesLedgerId: salesLedgerId,
- salesLedgerProductId: currentDeliveryRow.value.id,
- type: deliveryForm.value.type,
- approveUserIds,
+ if (!isLt10M) {
+ proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 10MB!");
+ return false;
+ }
+ return true;
+ },
+ onChange: (file, fileList) => {
+ console.log("鏂囦欢鐘舵�佹敼鍙�", file, fileList);
+ },
+ onProgress: (event, file, fileList) => {
+ console.log("涓婁紶涓�...", event.percent);
+ },
+ onSuccess: (response, file, fileList) => {
+ console.log("涓婁紶鎴愬姛", response, file, fileList);
+ importUpload.isUploading = false;
+ if (response.code === 200) {
+ proxy.$modal.msgSuccess("瀵煎叆鎴愬姛");
+ importUpload.open = false;
+ if (importUploadRef.value) {
+ importUploadRef.value.clearFiles();
+ }
+ getList();
+ } else {
+ proxy.$modal.msgError(response.msg || "瀵煎叆澶辫触");
+ }
+ },
+ onError: (error, file, fileList) => {
+ console.error("涓婁紶澶辫触", error, file, fileList);
+ importUpload.isUploading = false;
+ proxy.$modal.msgError("瀵煎叆澶辫触锛岃閲嶈瘯");
+ },
+ });
+
+ const changeDaterange = value => {
+ if (value) {
+ searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+ searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+ } else {
+ searchForm.entryDateStart = undefined;
+ searchForm.entryDateEnd = undefined;
+ }
+ handleQuery();
+ };
+
+ // 鏌ヨ鍒楄〃
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ const handleQuery = () => {
+ // 鍙湁鍦ㄧ偣鍑绘悳绱㈡寜閽椂鎵嶉噸缃〉鐮佸埌绗竴椤�
+ // 閬垮厤琛ㄥ崟瀛楁change浜嬩欢骞叉壈鍒嗛〉
+ if (arguments.length === 0) {
+ page.current = 1;
+ }
+ expandedRowKeys.value = [];
+ getList();
+ };
+ const paginationChange = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+ };
+ const getList = () => {
+ tableLoading.value = true;
+ const { entryDate, ...rest } = searchForm;
+ // 灏嗚寖鍥存棩鏈熷瓧娈典紶閫掔粰鍚庣
+ const params = { ...rest, ...page };
+ // 绉婚櫎褰曞叆鏃ユ湡鐨勯粯璁ゅ�艰缃紝鍙繚鐣欒寖鍥存棩鏈熷瓧娈�
+ delete params.entryDate;
+ return ledgerListPage(params)
+ .then(res => {
+ tableLoading.value = false;
+ tableData.value = res.records;
+ tableData.value.map(item => {
+ item.children = [];
+ });
+ total.value = res.total;
+ return res;
})
- .then(() => {
+ .catch(() => {
+ tableLoading.value = false;
+ });
+ };
+ // 鑾峰彇浜у搧澶х被tree鏁版嵁
+ const getProductOptions = () => {
+ // 杩斿洖 Promise锛屼究浜庡湪缂栬緫浜у搧鏃剁瓑寰呭姞杞藉畬鎴�
+ return productTreeList().then(res => {
+ productOptions.value = convertIdToValue(res);
+ return productOptions.value;
+ });
+ };
+ const formattedNumber = (row, column, cellValue) => {
+ return parseFloat(cellValue).toFixed(2);
+ };
+ // 鑾峰彇tree瀛愭暟鎹�
+ const getModels = value => {
+ productForm.value.productCategory = findNodeById(productOptions.value, value);
+ modelList({ id: value }).then(res => {
+ modelOptions.value = res;
+ });
+ };
+ const getProductModel = value => {
+ const index = modelOptions.value.findIndex(item => item.id === value);
+ if (index !== -1) {
+ productForm.value.specificationModel = modelOptions.value[index].model;
+ productForm.value.unit = modelOptions.value[index].unit;
+ } else {
+ productForm.value.specificationModel = null;
+ productForm.value.unit = null;
+ }
+ };
+ const findNodeById = (nodes, productId) => {
+ for (let i = 0; i < nodes.length; i++) {
+ if (nodes[i].value === productId) {
+ return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
+ }
+ if (nodes[i].children && nodes[i].children.length > 0) {
+ const foundNode = findNodeById(nodes[i].children, productId);
+ if (foundNode) {
+ return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖璇ヨ妭鐐�
+ }
+ }
+ }
+ return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
+ };
+ function convertIdToValue(data) {
+ return data.map(item => {
+ const { id, children, ...rest } = item;
+ const newItem = {
+ ...rest,
+ value: id, // 灏� id 鏀逛负 value
+ };
+ if (children && children.length > 0) {
+ newItem.children = convertIdToValue(children);
+ }
+
+ return newItem;
+ });
+ }
+ // 鏍规嵁鍚嶇О鍙嶆煡浜у搧澶х被 id锛屼究浜庝粎瀛樺悕绉版椂鐨勫弽鏄�
+ function findNodeIdByLabel(nodes, label) {
+ if (!label) return null;
+ for (let i = 0; i < nodes.length; i++) {
+ const node = nodes[i];
+ if (node.label === label) return node.value;
+ if (node.children && node.children.length > 0) {
+ const found = findNodeIdByLabel(node.children, label);
+ if (found !== null && found !== undefined) return found;
+ }
+ }
+ return null;
+ }
+ // 琛ㄦ牸閫夋嫨鏁版嵁
+ const handleSelectionChange = selection => {
+ // 杩囨护鎺夊瓙鏁版嵁
+ selectedRows.value = selection.filter(item => item.children !== undefined);
+ console.log("selection", selectedRows.value);
+ };
+ const productSelected = selectedRows => {
+ productSelectedRows.value = selectedRows;
+ };
+ const expandedRowKeys = ref([]);
+ // 灞曞紑琛�
+ const expandChange = (row, expandedRows) => {
+ if (expandedRows.length > 0) {
+ expandedRowKeys.value = [];
+ try {
+ productList({ salesLedgerId: row.id, type: 1 }).then(res => {
+ const index = tableData.value.findIndex(item => item.id === row.id);
+ if (index > -1) {
+ // 涓哄瓙琛ㄦ牸鏁版嵁娣诲姞瀹㈡埛绫诲瀷淇℃伅
+ const childrenData = res.data.map(item => ({
+ ...item,
+ customerType: row.customerType,
+ }));
+ tableData.value[index].children = childrenData;
+ }
+ expandedRowKeys.value.push(row.id);
+ });
+ } catch (error) {
+ console.log(error);
+ }
+ } else {
+ expandedRowKeys.value = [];
+ }
+ };
+
+ // 娣诲姞琛ㄨ绫诲悕鏂规硶
+ const tableRowClassName = ({ row }) => {
+ if (!row.deliveryDate) return "";
+ if (row.isFh) return "";
+
+ const diff = row.deliveryDaysDiff;
+ if (diff === 15) {
+ return "yellow";
+ } else if (diff === 10) {
+ return "pink";
+ } else if (diff === 2) {
+ return "purple";
+ } else if (diff < 2) {
+ return "red";
+ }
+ };
+ // 涓昏〃鍚堣鏂规硶
+ const summarizeMainTable = param => {
+ return proxy.summarizeTable(param, [
+ "contractAmount",
+ "taxInclusiveTotalPrice",
+ "taxExclusiveTotalPrice",
+ ]);
+ };
+ // 瀛愯〃鍚堣鏂规硶
+ const summarizeChildrenTable = param => {
+ return proxy.summarizeTable(param, [
+ "taxInclusiveUnitPrice",
+ "taxInclusiveTotalPrice",
+ "taxExclusiveTotalPrice",
+ ]);
+ };
+ // 瀹㈡埛閫夋嫨鍙樺寲澶勭悊
+ const handleCustomerChange = customerId => {
+ if (customerId) {
+ const customer = customerOption.value.find(item => item.id === customerId);
+ if (customer) {
+ // 濡傛灉瀹㈡埛绫诲瀷鍙戠敓鍙樺寲锛屾竻绌鸿〃鏍兼暟鎹�
+ if (
+ currentCustomerType.value &&
+ currentCustomerType.value !== customer.customerType
+ ) {
+ productData.value = [];
+ }
+ currentCustomerType.value = customer.customerType;
+ }
+ } else {
+ currentCustomerType.value = "";
+ productData.value = [];
+ }
+ };
+
+ // 鎵撳紑寮规
+ const openForm = async (type, row) => {
+ operationType.value = type;
+ form.value = {};
+ productData.value = [];
+ selectedQuotation.value = null;
+ currentCustomerType.value = "";
+ let userLists = await userListNoPage();
+ userList.value = userLists.data;
+ customerList().then(res => {
+ customerOption.value = res;
+ // 濡傛灉鏄紪杈戞ā寮忎笖鏈夊鎴稩D锛岃缃鎴风被鍨�
+ if (type === "edit" && form.value.customerId) {
+ handleCustomerChange(form.value.customerId);
+ }
+ });
+ form.value.entryPerson = userStore.id;
+ if (type === "add") {
+ // 鏂板鏃惰缃綍鍏ユ棩鏈熶负褰撳ぉ
+ form.value.entryDate = getCurrentDate();
+ // 绛捐鏃ユ湡榛樿涓哄綋澶�
+ form.value.executionDate = getCurrentDate();
+ } else {
+ currentId.value = row.id;
+ getSalesLedgerWithProducts({ id: row.id, type: 1 }).then(res => {
+ form.value = { ...res };
+ form.value.entryPerson = Number(res.entryPerson);
+ productData.value = JSON.parse(
+ JSON.stringify(form.value.productData || [])
+ );
+ fileList.value = form.value.salesLedgerFiles
+ ? form.value.salesLedgerFiles
+ : [];
+ // 璁剧疆瀹㈡埛绫诲瀷
+ handleCustomerChange(form.value.customerId);
+ });
+ }
+ // let userAll = await userStore.getInfo()
+ // userList.value.forEach(element => {
+ // if(userAll.user.nickName === element.nickName && userAll.user.userName === element.userName) {
+ // form.value.entryPerson = userAll.user.userId // 璁剧疆榛樿涓氬姟鍛樹负褰撳墠鐢ㄦ埛
+ // }
+ // });
+ form.value.entryDate = getCurrentDate(); // 璁剧疆榛樿褰曞叆鏃ユ湡涓哄綋鍓嶆棩鏈�
+ dialogFormVisible.value = true;
+ };
+
+ // 鎵撳紑鎶ヤ环鍗曢�夋嫨寮圭獥锛堜粎瀹℃壒閫氳繃锛�
+ const openQuotationDialog = async () => {
+ if (operationType.value === "view") return;
+ quotationDialogVisible.value = true;
+ // 鎵撳紑寮圭獥鏃堕噸缃垎椤靛埌绗竴椤�
+ quotationPage.current = 1;
+ // 鍏堢‘淇濆鎴峰垪琛ㄥ凡鍔犺浇锛屼究浜庡悗缁洖濉� customerId
+ if (!customerOption.value || customerOption.value.length === 0) {
+ try {
+ const res = await customerList();
+ customerOption.value = res;
+ } catch (e) {
+ // ignore锛屽厑璁哥敤鎴峰悗缁墜鍔ㄩ�夋嫨瀹㈡埛
+ }
+ }
+ await fetchQuotationList();
+ };
+
+ const fetchQuotationList = async () => {
+ quotationLoading.value = true;
+ try {
+ const params = {
+ // 鍚庣鍒嗛〉瀛楁锛歝urrent / size
+ current: quotationPage.current,
+ size: quotationPage.size,
+ ...quotationSearchForm,
+ status: "閫氳繃",
+ };
+ const res = await getQuotationList(params);
+ quotationList.value = res?.data?.records || [];
+ quotationPage.total = res?.data?.total || 0;
+ } finally {
+ quotationLoading.value = false;
+ }
+ };
+
+ const resetQuotationSearch = async () => {
+ quotationSearchForm.quotationNo = "";
+ quotationSearchForm.customer = "";
+ quotationPage.current = 1;
+ await fetchQuotationList();
+ };
+
+ // 鎶ヤ环鍗曞脊妗嗗垎椤靛垏鎹�
+ const quotationPaginationChange = obj => {
+ quotationPage.current = obj.page;
+ quotationPage.size = obj.limit;
+ fetchQuotationList();
+ };
+
+ // 閫変腑鎶ヤ环鍗曞悗鍥炲~鍒板彴璐﹁〃鍗�
+ const applyQuotation = row => {
+ if (!row) return;
+ selectedQuotation.value = row;
+
+ // 涓氬姟鍛�
+ form.value.salesman = (row.salesperson || "").trim();
+
+ // 瀹㈡埛鍚嶇О -> customerId
+ const qCustomerName = String(row.customer || "").trim();
+ const customer = (customerOption.value || []).find(c => {
+ const name = String(c.customerName || "").trim();
+ return (
+ name === qCustomerName ||
+ name.includes(qCustomerName) ||
+ qCustomerName.includes(name)
+ );
+ });
+ if (customer?.id) {
+ form.value.customerId = customer.id;
+ } else {
+ // 濡傛灉鎵句笉鍒帮紝淇濈暀鍘熷�硷紙鍏佽鐢ㄦ埛鎵嬪姩閫夋嫨/涓嶆墦鏂凡鏈夎緭鍏ワ級
+ form.value.customerId = form.value.customerId || "";
+ }
+
+ // 浜у搧淇℃伅鏄犲皠锛氭姤浠� products -> 鍙拌处 productData
+ const products = Array.isArray(row.products) ? row.products : [];
+ productData.value = products.map(p => {
+ const quantity = Number(p.quantity ?? 0) || 0;
+ const unitPrice = Number(p.unitPrice ?? 0) || 0;
+ const taxRate = "13"; // 榛樿 13%锛屼究浜庣洿鎺ユ彁浜わ紙濡傞渶鍙湪浜у搧涓嚜琛屼慨鏀癸級
+ const taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
+ const taxExclusiveTotalPrice = proxy.calculateTaxExclusiveTotalPrice(
+ taxInclusiveTotalPrice,
+ taxRate
+ );
+ return {
+ // 鍙拌处瀛楁
+ productCategory: p.product || p.productName || "",
+ specificationModel: p.specification || "",
+ unit: p.unit || "",
+ quantity: quantity,
+ taxRate: taxRate,
+ taxInclusiveUnitPrice: unitPrice.toFixed(2),
+ taxInclusiveTotalPrice: taxInclusiveTotalPrice,
+ taxExclusiveTotalPrice: taxExclusiveTotalPrice,
+ invoiceType: "澧炴櫘绁�",
+ };
+ });
+
+ quotationDialogVisible.value = false;
+ };
+ function changs(val) {
+ console.log(val);
+ }
+ // 涓婁紶鍓嶆牎妫�
+ function handleBeforeUpload(file) {
+ // 鏍℃鏂囦欢澶у皬
+ // if (file.size > 1024 * 1024 * 10) {
+ // proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃10MB!");
+ // return false;
+ // }
+ proxy.$modal.loading("姝e湪涓婁紶鏂囦欢锛岃绋嶅��...");
+ return true;
+ }
+ // 涓婁紶澶辫触
+ function handleUploadError(err) {
+ proxy.$modal.msgError("涓婁紶鏂囦欢澶辫触");
+ proxy.$modal.closeLoading();
+ }
+ // 涓婁紶鎴愬姛鍥炶皟
+ function handleUploadSuccess(res, file, uploadFiles) {
+ proxy.$modal.closeLoading();
+ if (res.code === 200) {
+ file.tempId = res.data.tempId;
+ proxy.$modal.msgSuccess("涓婁紶鎴愬姛");
+ } else {
+ proxy.$modal.msgError(res.msg);
+ proxy.$refs.fileUpload.handleRemove(file);
+ }
+ }
+ // 绉婚櫎鏂囦欢
+ function handleRemove(file) {
+ if (operationType.value === "edit") {
+ let ids = [];
+ ids.push(file.id);
+ delLedgerFile(ids).then(res => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ });
+ }
+ }
+ // 鎻愪氦琛ㄥ崟
+ const submitForm = () => {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ console.log("productData.value--", productData.value);
+ if (productData.value !== null && productData.value.length > 0) {
+ form.value.productData = proxy.HaveJson(productData.value);
+ } else {
+ proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
+ return;
+ }
+ let tempFileIds = [];
+ if (fileList.value !== null && fileList.value.length > 0) {
+ tempFileIds = fileList.value.map(item => item.tempId);
+ }
+ form.value.tempFileIds = tempFileIds;
+ form.value.type = 1;
+ form.value.salesType = currentCustomerType.value;
+ addOrUpdateSalesLedger(form.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+ }
+ });
+ };
+ // 鍏抽棴寮规
+ const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+ };
+
+ const productIndex = ref(0);
+ // 鎵撳紑浜у搧寮规
+ const openProductForm = async (type, row, index) => {
+ // 缂栬緫鏃舵鏌ヤ骇鍝佹槸鍚﹀凡鍙戣揣鎴栧鏍搁�氳繃
+ if (type === "edit" && isProductShipped(row)) {
+ proxy.$modal.msgWarning("宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝佷笉鑳界紪杈�");
+ return;
+ }
+
+ productOperationType.value = type;
+ productForm.value = {};
+ proxy.resetForm("productFormRef");
+ if (type === "edit") {
+ productForm.value = { ...row };
+ productIndex.value = index;
+ // 缂栬緫鏃舵牴鎹骇鍝佸ぇ绫诲悕绉板弽鏌� tree 鑺傜偣 id锛屽苟鍔犺浇瑙勬牸鍨嬪彿鍒楄〃
+ try {
+ const options =
+ productOptions.value && productOptions.value.length > 0
+ ? productOptions.value
+ : await getProductOptions();
+ const categoryId = findNodeIdByLabel(
+ options,
+ productForm.value.productCategory
+ );
+ if (categoryId) {
+ const models = await modelList({ id: categoryId });
+ modelOptions.value = models || [];
+ // 鏍规嵁褰撳墠瑙勬牸鍨嬪彿鍚嶇О鍙嶆煡骞惰缃� productModelId锛屼究浜庝笅鎷夋鏄剧ず宸查�夊��
+ const currentModel = (modelOptions.value || []).find(
+ m => m.model === productForm.value.specificationModel
+ );
+ if (currentModel) {
+ productForm.value.productModelId = currentModel.id;
+ }
+ }
+ } catch (e) {
+ // 鍔犺浇澶辫触鏃朵繚鎸佸彲缂栬緫锛屼笉涓柇寮圭獥
+ console.error("鍔犺浇浜у搧瑙勬牸鍨嬪彿澶辫触", e);
+ }
+ } else {
+ getProductOptions();
+ }
+ productFormVisible.value = true;
+ };
+ // 鎻愪氦浜у搧琛ㄥ崟
+ const submitProduct = () => {
+ // 鍔ㄦ�侀獙璇佽鍒�
+ const dynamicRules = { ...productRules.value };
+
+ // 鏍规嵁瀹㈡埛绫诲瀷璋冩暣楠岃瘉瑙勫垯
+ if (currentCustomerType.value == 1) {
+ // 瀵圭瀛楁涓嶉渶瑕侀獙璇�
+ delete dynamicRules.unitPrice;
+ delete dynamicRules.totalPrice;
+ delete dynamicRules.freight;
+ delete dynamicRules.priceWithFreight;
+ } else if (currentCustomerType.value == 2) {
+ // 瀵瑰叕瀛楁涓嶉渶瑕侀獙璇�
+ delete dynamicRules.taxInclusiveUnitPrice;
+ delete dynamicRules.taxRate;
+ delete dynamicRules.taxInclusiveTotalPrice;
+ delete dynamicRules.taxExclusiveTotalPrice;
+ delete dynamicRules.invoiceType;
+ }
+
+ proxy.$refs["productFormRef"].validate((valid, fields) => {
+ if (valid) {
+ if (operationType.value === "edit") {
+ // 缂栬緫妯″紡涓嬬洿鎺ヤ慨鏀规湰鍦拌〃鏍兼暟鎹�
+ if (productOperationType.value === "add") {
+ productData.value.push({ ...productForm.value });
+ } else {
+ productData.value.splice(productIndex.value, 1, {
+ ...productForm.value,
+ });
+ }
+ closeProductDia();
+ } else {
+ if (productOperationType.value === "add") {
+ productData.value.push({ ...productForm.value });
+ } else {
+ productData.value.splice(productIndex.value, 1, {
+ ...productForm.value,
+ });
+ }
+ closeProductDia();
+ }
+ }
+ });
+ };
+ const submitProductEdit = () => {
+ // 鏍规嵁瀹㈡埛绫诲瀷璋冩暣鎻愪氦鐨勬暟鎹�
+ const productDataToSubmit = { ...productForm.value };
+
+ if (currentCustomerType.value == 1) {
+ // 瀵圭瀛楁涓嶉渶瑕佹彁浜�
+ delete productDataToSubmit.unitPrice;
+ delete productDataToSubmit.totalPrice;
+ delete productDataToSubmit.freight;
+ delete productDataToSubmit.priceWithFreight;
+ } else if (currentCustomerType.value == 2) {
+ // 瀵瑰叕瀛楁涓嶉渶瑕佹彁浜�
+ delete productDataToSubmit.taxInclusiveUnitPrice;
+ delete productDataToSubmit.taxRate;
+ delete productDataToSubmit.taxInclusiveTotalPrice;
+ delete productDataToSubmit.taxExclusiveTotalPrice;
+ delete productDataToSubmit.invoiceType;
+ }
+
+ productDataToSubmit.salesLedgerId = currentId.value;
+ productDataToSubmit.type = 1;
+ addOrUpdateSalesLedgerProduct(productDataToSubmit).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeProductDia();
+ getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then(res => {
+ productData.value = JSON.parse(JSON.stringify(res.productData || []));
+ });
+ });
+ };
+ // 鍒犻櫎浜у搧
+ const deleteProduct = () => {
+ if (productSelectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+
+ // 妫�鏌ユ槸鍚︽湁宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝�
+ const shippedProducts = productSelectedRows.value.filter(row =>
+ isProductShipped(row)
+ );
+ if (shippedProducts.length > 0) {
+ proxy.$modal.msgWarning("宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝佷笉鑳藉垹闄�");
+ return;
+ }
+
+ // 鏃犺鏄柊澧炶繕鏄紪杈戞ā寮忥紝閮界洿鎺ヤ慨鏀规湰鍦拌〃鏍兼暟鎹�
+ productSelectedRows.value.forEach(selectedRow => {
+ const index = productData.value.findIndex(
+ product => product.id === selectedRow.id
+ );
+ if (index !== -1) {
+ productData.value.splice(index, 1);
+ }
+ });
+ };
+ // 鍏抽棴浜у搧寮规
+ const closeProductDia = () => {
+ proxy.resetForm("productFormRef");
+ productFormVisible.value = false;
+ };
+ // 瀵煎叆
+ const handleImport = () => {
+ importUpload.title = "瀵煎叆閿�鍞彴璐�";
+ importUpload.open = true;
+ if (importUploadRef.value) {
+ importUploadRef.value.clearFiles();
+ }
+ };
+
+ // 涓嬭浇瀵煎叆妯℃澘
+ const downloadTemplate = () => {
+ proxy.download("/sales/ledger/exportTemplate", {}, "閿�鍞彴璐﹀鍏ユā鏉�.xlsx");
+ };
+
+ // 鎻愪氦瀵煎叆鏂囦欢
+ const submitImportFile = () => {
+ importUpload.isUploading = true;
+ proxy.$refs["importUploadRef"].submit();
+ };
+
+ // 瀵煎嚭
+ const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/sales/ledger/export", {}, "閿�鍞彴璐�.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ };
+ /** 鍒ゆ柇鍗曚釜浜у搧鏄惁宸插彂璐э紙鏍规嵁shippingStatus鍒ゆ柇锛屽凡鍙戣揣鎴栧鏍搁�氳繃涓嶅彲缂栬緫鍜屽垹闄わ級 */
+ const isProductShipped = product => {
+ if (!product) return false;
+ const status = String(product.shippingStatus || "").trim();
+ // 濡傛灉鍙戣揣鐘舵�佹槸"宸插彂璐�"鎴�"瀹℃牳閫氳繃"锛屽垯涓嶅彲缂栬緫鍜屽垹闄�
+ return status === "宸插彂璐�" || status === "瀹℃牳閫氳繃";
+ };
+
+ /** 鍒ゆ柇閿�鍞鍗曚笅鏄惁瀛樺湪宸插彂璐�/鍙戣揣瀹屾垚鐨勪骇鍝侊紙涓嶅彲鍒犻櫎锛� */
+ const hasShippedProducts = products => {
+ if (!products || !products.length) return false;
+ return products.some(p => {
+ const status = String(p.shippingStatus || "").trim();
+ // 鏈夊彂璐ф棩鏈熸垨杞︾墝鍙疯涓哄凡鍙戣揣
+ if (p.shippingDate || p.shippingCarNumber) return true;
+ // 宸茶繘琛屽彂璐с�佸彂璐у畬鎴愩�佸凡鍙戣揣 鍧囦笉鍙垹闄�
+ return (
+ status === "宸茶繘琛屽彂璐�" || status === "鍙戣揣瀹屾垚" || status === "宸插彂璐�"
+ );
+ });
+ };
+
+ // 鍒犻櫎
+ const handleDelete = async () => {
+ if (selectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ const ids = selectedRows.value.map(item => item.id);
+
+ // 妫�鏌ユ槸鍚︽湁宸茶繘琛屽彂璐ф垨鍙戣揣瀹屾垚鐨勯攢鍞鍗曪紝鑻ユ湁鍒欎笉鍏佽鍒犻櫎
+ const cannotDeleteNames = [];
+ for (const row of selectedRows.value) {
+ let products =
+ row.children && row.children.length > 0 ? row.children : null;
+ if (!products) {
+ try {
+ const res = await productList({ salesLedgerId: row.id, type: 1 });
+ products = res.data || [];
+ } catch {
+ products = [];
+ }
+ }
+ if (hasShippedProducts(products)) {
+ cannotDeleteNames.push(row.salesContractNo || `ID:${row.id}`);
+ }
+ }
+ if (cannotDeleteNames.length > 0) {
+ proxy.$modal.msgWarning(
+ "宸茶繘琛屽彂璐ф垨鍙戣揣瀹屾垚鐨勯攢鍞鍗曚笉鑳藉垹闄わ細" + cannotDeleteNames.join("銆�")
+ );
+ return;
+ }
+
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ delLedger(ids).then(res => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ };
+
+ // 鎵撳嵃鍔熻兘
+ const handlePrint = async () => {
+ if (selectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
+ return;
+ }
+
+ // 鏄剧ず鍔犺浇鐘舵��
+ proxy.$modal.loading("姝e湪鑾峰彇浜у搧鏁版嵁锛岃绋嶅��...");
+
+ try {
+ // 涓烘瘡涓�変腑鐨勯攢鍞彴璐﹁褰曟煡璇㈠搴旂殑浜у搧鏁版嵁
+ const printDataWithProducts = [];
+
+ for (const row of selectedRows.value) {
+ try {
+ // 璋冪敤productList鎺ュ彛鏌ヨ浜у搧鏁版嵁
+ const productRes = await productList({
+ salesLedgerId: row.id,
+ type: 1,
+ });
+
+ // 灏嗕骇鍝佹暟鎹暣鍚堝埌閿�鍞彴璐﹁褰曚腑
+ const rowWithProducts = {
+ ...row,
+ products: productRes.data || [],
+ };
+
+ printDataWithProducts.push(rowWithProducts);
+ } catch (error) {
+ console.error(`鑾峰彇閿�鍞彴璐� ${row.id} 鐨勪骇鍝佹暟鎹け璐�:`, error);
+ // 鍗充娇鏌愪釜璁板綍鐨勪骇鍝佹暟鎹幏鍙栧け璐ワ紝涔熻鍖呭惈璇ヨ褰�
+ printDataWithProducts.push({
+ ...row,
+ products: [],
+ });
+ }
+ }
+
+ printData.value = printDataWithProducts;
+ console.log("鎵撳嵃鏁版嵁锛堝寘鍚骇鍝侊級:", printData.value);
+ printPreviewVisible.value = true;
+ } catch (error) {
+ console.error("鑾峰彇浜у搧鏁版嵁澶辫触:", error);
+ proxy.$modal.msgError("鑾峰彇浜у搧鏁版嵁澶辫触锛岃閲嶈瘯");
+ } finally {
+ proxy.$modal.closeLoading();
+ }
+ };
+ // 鎵ц鎵撳嵃
+ const executePrint = () => {
+ console.log("寮�濮嬫墽琛屾墦鍗帮紝鏁版嵁鏉℃暟:", printData.value.length);
+ console.log("鎵撳嵃鏁版嵁:", printData.value);
+
+ // 鍒涘缓涓�涓柊鐨勬墦鍗扮獥鍙�
+ const printWindow = window.open("", "_blank", "width=800,height=600");
+
+ // 鏋勫缓鎵撳嵃鍐呭
+ let printContent = `
+ <!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset="UTF-8">
+ <title>鎵撳嵃棰勮</title>
+ <style>
+ body {
+ margin: 0;
+ padding: 0;
+ font-family: "SimSun", serif;
+ background: white;
+ }
+ .print-page {
+ width: 200mm;
+ height: 75mm;
+ padding: 10mm;
+ padding-left: 20mm;
+ background: white;
+ box-sizing: border-box;
+ page-break-after: always;
+ page-break-inside: avoid;
+ }
+ .print-page:last-child {
+ page-break-after: avoid;
+ }
+ .delivery-note {
+ width: 100%;
+ height: 100%;
+ font-size: 12px;
+ line-height: 1.2;
+ display: flex;
+ flex-direction: column;
+ color: #000;
+ }
+ .header {
+ text-align: center;
+ margin-bottom: 8px;
+ }
+ .company-name {
+ font-size: 18px;
+ font-weight: bold;
+ margin-bottom: 4px;
+ }
+ .document-title {
+ font-size: 16px;
+ font-weight: bold;
+ }
+ .info-section {
+ margin-bottom: 8px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
+ .info-row {
+ line-height: 20px;
+ }
+ .label {
+ font-weight: bold;
+ width: 60px;
+ font-size: 12px;
+ }
+ .value {
+ margin-right: 20px;
+ min-width: 80px;
+ font-size: 12px;
+ }
+ .table-section {
+ margin-bottom: 40px;
+ // flex: 0.6;
+ }
+ .product-table {
+ width: 100%;
+ border-collapse: collapse;
+ border: 1px solid #000;
+ }
+ .product-table th, .product-table td {
+ border: 1px solid #000;
+ padding: 6px;
+ text-align: center;
+ font-size: 12px;
+ line-height: 1.4;
+ }
+ .product-table th {
+ font-weight: bold;
+ }
+ .total-value {
+ font-weight: bold;
+ }
+ .footer-section {
+ margin-top: auto;
+ }
+ .footer-row {
+ display: flex;
+ margin-bottom: 3px;
+ line-height: 22px;
+ justify-content: space-between;
+ }
+ .footer-item {
+ display: flex;
+ margin-right: 20px;
+ }
+ .footer-item .label {
+ font-weight: bold;
+ width: 80px;
+ font-size: 12px;
+ }
+ .footer-item .value {
+ min-width: 80px;
+ font-size: 12px;
+ }
+ .address-item .address-value {
+ min-width: 200px;
+ }
+ @media print {
+ body {
+ margin: 0;
+ padding: 0;
+ }
+ .print-page {
+ margin: 0;
+ padding: 10mm;
+ /* padding-left: 20mm; */
+ page-break-inside: avoid;
+ page-break-after: always;
+ }
+ .print-page:last-child {
+ page-break-after: avoid;
+ }
+ }
+ </style>
+ </head>
+ <body>
+ `;
+
+ // 涓烘瘡鏉℃暟鎹敓鎴愭墦鍗伴〉闈�
+ printData.value.forEach((item, index) => {
+ printContent += `
+ <div class="print-page">
+ <div class="delivery-note">
+ <div class="header">
+ <div class="document-title">闆跺敭鍙戣揣鍗�</div>
+ </div>
+
+ <div class="info-section">
+ <div class="info-row">
+ <div>
+ <span class="label">鍙戣揣鏃ユ湡锛�</span>
+ <span class="value">${formatDate(
+ item.createTime
+ )}</span>
+ </div>
+ <div>
+ <span class="label">瀹㈡埛鍚嶇О锛�</span>
+ <span class="value">${
+ item.customerName
+ }</span>
+ </div>
+ </div>
+ <div class="info-row">
+ <span class="label">鍗曞彿锛�</span>
+ <span class="value">${
+ item.salesContractNo ||
+ ""
+ }</span>
+ </div>
+ </div>
+
+ <div class="table-section">
+ <table class="product-table">
+ <thead>
+ <tr>
+ <th>浜у搧鍚嶇О</th>
+ <th>瑙勬牸鍨嬪彿</th>
+ <th>鍗曚綅</th>
+ <th>鍗曚环</th>
+ <th>闆跺敭鏁伴噺</th>
+ <th>闆跺敭閲戦</th>
+ </tr>
+ </thead>
+ <tbody>
+ ${
+ item.products &&
+ item
+ .products
+ .length >
+ 0
+ ? item.products
+ .map(
+ product => `
+ <tr>
+ <td>${
+ product.productCategory ||
+ ""
+ }</td>
+ <td>${
+ product.specificationModel ||
+ ""
+ }</td>
+ <td>${
+ product.unit ||
+ ""
+ }</td>
+ <td>${
+ product.taxInclusiveUnitPrice ||
+ "0"
+ }</td>
+ <td>${
+ product.quantity ||
+ "0"
+ }</td>
+ <td>${
+ product.taxInclusiveTotalPrice ||
+ "0"
+ }</td>
+ </tr>
+ `
+ )
+ .join(
+ ""
+ )
+ : '<tr><td colspan="6" style="text-align: center; color: #999;">鏆傛棤浜у搧鏁版嵁</td></tr>'
+ }
+ </tbody>
+ <tfoot>
+ <tr>
+ <td class="label">鍚堣</td>
+ <td class="total-value"></td>
+ <td class="total-value"></td>
+ <td class="total-value"></td>
+ <td class="total-value">${getTotalQuantityForPrint(
+ item.products
+ )}</td>
+ <td class="total-value">${getTotalAmountForPrint(
+ item.products
+ )}</td>
+ </tr>
+ </tfoot>
+ </table>
+ </div>
+
+ <div class="footer-section">
+ <div class="footer-row">
+ <div class="footer-item">
+ <span class="label">鏀惰揣鐢佃瘽锛�</span>
+ <span class="value"></span>
+ </div>
+ <div class="footer-item">
+ <span class="label">鏀惰揣浜猴細</span>
+ <span class="value"></span>
+ </div>
+ <div class="footer-item address-item">
+ <span class="label">鏀惰揣鍦板潃锛�</span>
+ <span class="value address-value"></span>
+ </div>
+ </div>
+ <div class="footer-row">
+ <div class="footer-item">
+ <span class="label">鎿嶄綔鍛橈細</span>
+ <span class="value">${
+ userStore.nickName ||
+ "鎾曞紑鍓�"
+ }</span>
+ </div>
+ <div class="footer-item">
+ <span class="label">鎵撳嵃鏃ユ湡锛�</span>
+ <span class="value">${formatDateTime(
+ new Date()
+ )}</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ `;
+ });
+
+ printContent += `
+ </body>
+ </html>
+ `;
+
+ // 鍐欏叆鍐呭鍒版柊绐楀彛
+ printWindow.document.write(printContent);
+ printWindow.document.close();
+
+ // 绛夊緟鍐呭鍔犺浇瀹屾垚鍚庢墦鍗�
+ printWindow.onload = () => {
+ setTimeout(() => {
+ printWindow.print();
+ printWindow.close();
+ printPreviewVisible.value = false;
+ }, 500);
+ };
+ };
+ // 鏍煎紡鍖栨棩鏈�
+ const formatDate = dateString => {
+ if (!dateString) return getCurrentDate();
+ const date = new Date(dateString);
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, "0");
+ const day = String(date.getDate()).padStart(2, "0");
+ return `${year}/${month}/${day}`;
+ };
+ // 鏍煎紡鍖栨棩鏈熸椂闂�
+ const formatDateTime = date => {
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, "0");
+ const day = String(date.getDate()).padStart(2, "0");
+ const hours = String(date.getHours()).padStart(2, "0");
+ const minutes = String(date.getMinutes()).padStart(2, "0");
+ const seconds = String(date.getSeconds()).padStart(2, "0");
+ return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
+ };
+ // 璁$畻浜у搧鎬绘暟閲�
+ const getTotalQuantity = products => {
+ if (!products || products.length === 0) return "0";
+ const total = products.reduce((sum, product) => {
+ return sum + (parseFloat(product.quantity) || 0);
+ }, 0);
+ return total.toFixed(2);
+ };
+
+ // 璁$畻浜у搧鎬婚噾棰�
+ const getTotalAmount = products => {
+ if (!products || products.length === 0) return "0";
+ const total = products.reduce((sum, product) => {
+ return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
+ }, 0);
+ return total.toFixed(2);
+ };
+
+ // 鐢ㄤ簬鎵撳嵃鐨勮绠楀嚱鏁�
+ const getTotalQuantityForPrint = products => {
+ if (!products || products.length === 0) return "0";
+ const total = products.reduce((sum, product) => {
+ return sum + (parseFloat(product.quantity) || 0);
+ }, 0);
+ return total.toFixed(2);
+ };
+
+ const getTotalAmountForPrint = products => {
+ if (!products || products.length === 0) return "0";
+ const total = products.reduce((sum, product) => {
+ return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
+ }, 0);
+ return total.toFixed(2);
+ };
+
+ const mathNum = () => {
+ console.log("productForm.value", productForm.value);
+ if (!productForm.value.taxInclusiveUnitPrice) {
+ return;
+ }
+ if (!productForm.value.quantity) {
+ return;
+ }
+ // 鍚◣鎬讳环璁$畻
+ productForm.value.taxInclusiveTotalPrice =
+ proxy.calculateTaxIncludeTotalPrice(
+ productForm.value.taxInclusiveUnitPrice,
+ productForm.value.quantity
+ );
+ if (productForm.value.taxRate) {
+ // 涓嶅惈绋庢�讳环璁$畻
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(
+ productForm.value.taxInclusiveTotalPrice,
+ productForm.value.taxRate
+ );
+ }
+ };
+
+ // 鏍规嵁鍚◣鎬讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
+ const calculateFromTotalPrice = () => {
+ if (isCalculating.value) return;
+
+ const totalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
+ const quantity = parseFloat(productForm.value.quantity);
+
+ if (!totalPrice || !quantity || quantity <= 0) {
+ return;
+ }
+
+ isCalculating.value = true;
+
+ // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
+ productForm.value.taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(2);
+
+ // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
+ if (productForm.value.taxRate) {
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(
+ totalPrice,
+ productForm.value.taxRate
+ );
+ }
+
+ isCalculating.value = false;
+ };
+
+ // 鏍规嵁涓嶅惈绋庢�讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
+ const calculateFromExclusiveTotalPrice = () => {
+ if (!productForm.value.taxRate) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ return;
+ }
+ if (isCalculating.value) return;
+
+ const exclusiveTotalPrice = parseFloat(
+ productForm.value.taxExclusiveTotalPrice
+ );
+ const quantity = parseFloat(productForm.value.quantity);
+ const taxRate = parseFloat(productForm.value.taxRate);
+
+ if (!exclusiveTotalPrice || !quantity || quantity <= 0 || !taxRate) {
+ return;
+ }
+
+ isCalculating.value = true;
+
+ // 鍏堣绠楀惈绋庢�讳环 = 涓嶅惈绋庢�讳环 / (1 - 绋庣巼/100)
+ const taxRateDecimal = taxRate / 100;
+ const inclusiveTotalPrice = exclusiveTotalPrice / (1 - taxRateDecimal);
+ productForm.value.taxInclusiveTotalPrice = inclusiveTotalPrice.toFixed(2);
+
+ // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
+ productForm.value.taxInclusiveUnitPrice = (
+ inclusiveTotalPrice / quantity
+ ).toFixed(2);
+
+ isCalculating.value = false;
+ };
+
+ // 瀵圭瀹㈡埛浠锋牸璁$畻锛氬崟浠峰拰杩愯垂鍙樺寲鏃惰绠楀惈杩愯垂鍗曚环鍜屾�讳环
+ const calculatePrivatePrice = () => {
+ if (currentCustomerType.value == 2) {
+ const unitPrice = parseFloat(productForm.value.unitPrice) || 0;
+ const freight = parseFloat(productForm.value.freight) || 0;
+ const quantity = parseFloat(productForm.value.quantity) || 0;
+
+ // 璁$畻鍚繍璐瑰崟浠�
+ productForm.value.priceWithFreight = (unitPrice + freight).toFixed(2);
+
+ // 璁$畻鎬讳环
+ productForm.value.totalPrice = (
+ parseFloat(productForm.value.priceWithFreight) * quantity
+ ).toFixed(2);
+ }
+ };
+
+ // 瀵圭瀹㈡埛浠锋牸璁$畻锛氬惈杩愯垂鍗曚环鍙樺寲鏃惰绠楁�讳环
+ const calculatePrivateTotal = () => {
+ if (currentCustomerType.value == 2) {
+ const priceWithFreight =
+ parseFloat(productForm.value.priceWithFreight) || 0;
+ const quantity = parseFloat(productForm.value.quantity) || 0;
+
+ // 璁$畻鎬讳环
+ productForm.value.totalPrice = (priceWithFreight * quantity).toFixed(2);
+ }
+ };
+
+ // 鏍规嵁鏁伴噺鍙樺寲璁$畻鎬讳环
+ const calculateFromQuantity = () => {
+ // 瀵圭瀹㈡埛浣跨敤瀵圭璁$畻閫昏緫
+ if (currentCustomerType.value == 2) {
+ calculatePrivatePrice();
+ return;
+ }
+
+ // 瀵瑰叕瀹㈡埛浣跨敤鍘熸湁鐨勮绠楅�昏緫
+ if (!productForm.value.taxRate) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ return;
+ }
+ if (isCalculating.value) return;
+
+ const quantity = parseFloat(productForm.value.quantity);
+ const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
+
+ if (!quantity || quantity <= 0 || !unitPrice) {
+ return;
+ }
+
+ isCalculating.value = true;
+
+ // 璁$畻鍚◣鎬讳环
+ productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
+
+ // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
+ if (productForm.value.taxRate) {
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(
+ productForm.value.taxInclusiveTotalPrice,
+ productForm.value.taxRate
+ );
+ }
+
+ isCalculating.value = false;
+ };
+
+ // 鏍规嵁鍚◣鍗曚环鍙樺寲璁$畻鎬讳环
+ const calculateFromUnitPrice = () => {
+ // 瀵圭瀹㈡埛浣跨敤瀵圭璁$畻閫昏緫
+ if (currentCustomerType.value == 2) {
+ calculatePrivatePrice();
+ return;
+ }
+
+ // 瀵瑰叕瀹㈡埛浣跨敤鍘熸湁鐨勮绠楅�昏緫
+ if (!productForm.value.taxRate) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ return;
+ }
+ if (isCalculating.value) return;
+
+ const quantity = parseFloat(productForm.value.quantity);
+ const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
+
+ if (!quantity || quantity <= 0 || !unitPrice) {
+ return;
+ }
+
+ isCalculating.value = true;
+
+ // 璁$畻鍚◣鎬讳环
+ productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
+
+ // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
+ if (productForm.value.taxRate) {
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(
+ productForm.value.taxInclusiveTotalPrice,
+ productForm.value.taxRate
+ );
+ }
+
+ isCalculating.value = false;
+ };
+
+ // 鏍规嵁绋庣巼鍙樺寲璁$畻涓嶅惈绋庢�讳环
+ const calculateFromTaxRate = () => {
+ // 瀵圭瀹㈡埛涓嶉渶瑕佺◣鐜囪绠�
+ if (currentCustomerType.value == 2) {
+ return;
+ }
+
+ // 瀵瑰叕瀹㈡埛浣跨敤鍘熸湁鐨勮绠楅�昏緫
+ if (!productForm.value.taxRate) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ return;
+ }
+ if (isCalculating.value) return;
+
+ const inclusiveTotalPrice = parseFloat(
+ productForm.value.taxInclusiveTotalPrice
+ );
+ const taxRate = parseFloat(productForm.value.taxRate);
+
+ if (!inclusiveTotalPrice || !taxRate) {
+ return;
+ }
+
+ isCalculating.value = true;
+
+ // 璁$畻涓嶅惈绋庢�讳环
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(inclusiveTotalPrice, taxRate);
+
+ isCalculating.value = false;
+ };
+ /**
+ * 鑾峰彇鍙戣揣鐘舵�佹枃鏈�
+ * @param row 琛屾暟鎹�
+ */
+ const getShippingStatusText = row => {
+ // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屾樉绀�"宸插彂璐�"
+ if (row.shippingDate || row.shippingCarNumber) {
+ return "宸插彂璐�";
+ }
+
+ // 鑾峰彇鍙戣揣鐘舵�佸瓧娈�
+ const status = row.shippingStatus;
+
+ // 濡傛灉鐘舵�佷负绌烘垨鏈畾涔夛紝榛樿涓�"寰呭彂璐�"
+ if (status === null || status === undefined || status === "") {
+ return "寰呭彂璐�";
+ }
+
+ // 鐘舵�佹槸瀛楃涓�
+ const statusStr = String(status).trim();
+ const statusTextMap = {
+ 寰呭彂璐�: "寰呭彂璐�",
+ 寰呭鏍�: "寰呭鏍�",
+ 瀹℃牳涓�: "瀹℃牳涓�",
+ 瀹℃牳鎷掔粷: "瀹℃牳鎷掔粷",
+ 瀹℃牳閫氳繃: "瀹℃牳閫氳繃",
+ 宸插彂璐�: "宸插彂璐�",
+ };
+ return statusTextMap[statusStr] || "寰呭彂璐�";
+ };
+
+ /**
+ * 鑾峰彇鍙戣揣鐘舵�佹爣绛剧被鍨嬶紙棰滆壊锛�
+ * @param row 琛屾暟鎹�
+ */
+ const getShippingStatusType = row => {
+ // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屾樉绀虹豢鑹�
+ if (row.shippingDate || row.shippingCarNumber) {
+ return "success";
+ }
+
+ // 鑾峰彇鍙戣揣鐘舵�佸瓧娈�
+ const status = row.shippingStatus;
+
+ // 濡傛灉鐘舵�佷负绌烘垨鏈畾涔夛紝榛樿涓虹伆鑹诧紙寰呭彂璐э級
+ if (status === null || status === undefined || status === "") {
+ return "info";
+ }
+
+ // 鐘舵�佹槸瀛楃涓�
+ const statusStr = String(status).trim();
+ const typeTextMap = {
+ 寰呭彂璐�: "info",
+ 寰呭鏍�: "info",
+ 瀹℃牳涓�: "warning",
+ 瀹℃牳鎷掔粷: "danger",
+ 瀹℃牳閫氳繃: "success",
+ 宸插彂璐�: "success",
+ };
+ return typeTextMap[statusStr] || "info";
+ };
+
+ /**
+ * 鍒ゆ柇鏄惁鍙互鍙戣揣
+ * 鍙湁鍦ㄤ骇鍝佺姸鎬佹槸鍏呰冻锛屽彂璐х姸鎬佹槸寰呭彂璐у拰瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣
+ * @param row 琛屾暟鎹�
+ */
+ const canShip = row => {
+ // 浜у搧鐘舵�佸繀椤绘槸鍏呰冻锛坅pproveStatus === 1锛�
+ if (row.approveStatus !== 1) {
+ return false;
+ }
+
+ // 鑾峰彇鍙戣揣鐘舵��
+ const shippingStatus = row.shippingStatus;
+
+ // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屼笉鑳藉啀娆″彂璐�
+ if (row.shippingDate || row.shippingCarNumber) {
+ return false;
+ }
+
+ // 鍙戣揣鐘舵�佸繀椤绘槸"寰呭彂璐�"鎴�"瀹℃牳鎷掔粷"
+ const statusStr = shippingStatus ? String(shippingStatus).trim() : "";
+ return statusStr === "寰呭彂璐�" || statusStr === "瀹℃牳鎷掔粷";
+ };
+
+ /**
+ * 涓嬭浇鏂囦欢
+ *
+ * @param row 涓嬭浇鏂囦欢鐨勭浉鍏充俊鎭璞�
+ */
+ const fileListRef = ref(null);
+ const fileListDialogVisible = ref(false);
+ const downLoadFile = row => {
+ getSalesLedgerWithProducts({ id: row.id, type: 1 }).then(res => {
+ if (fileListRef.value) {
+ fileListRef.value.open(res.salesLedgerFiles);
+ }
+ });
+ };
+
+ // 鎵撳紑鍙戣揣寮规
+ const openDeliveryForm = row => {
+ // 妫�鏌ユ槸鍚﹀彲浠ュ彂璐�
+ if (!canShip(row)) {
+ proxy.$modal.msgWarning(
+ "鍙湁鍦ㄤ骇鍝佺姸鎬佹槸鍏呰冻锛屽彂璐х姸鎬佹槸寰呭彂璐ф垨瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣"
+ );
+ return;
+ }
+
+ currentDeliveryRow.value = row;
+ deliveryForm.value = {
+ type: "璐ц溅",
+ };
+ // 閲嶇疆瀹℃壒浜鸿妭鐐癸紙榛樿涓�涓┖鑺傜偣锛�
+ approverNodes.value = [{ id: 1, userId: null }];
+ nextApproverId = 2;
+ deliveryFormVisible.value = true;
+ };
+
+ // 鎻愪氦鍙戣揣琛ㄥ崟
+ const submitDelivery = () => {
+ proxy.$refs["deliveryFormRef"].validate(valid => {
+ if (valid) {
+ // 瀹℃壒浜哄繀濉牎楠岋紙鎵�鏈夎妭鐐归兘瑕侀�変汉锛�
+ const hasEmptyApprover = approverNodes.value.some(node => !node.userId);
+ if (hasEmptyApprover) {
+ proxy.$modal.msgError("璇蜂负鎵�鏈夊鎵硅妭鐐归�夋嫨瀹℃壒浜猴紒");
+ return;
+ }
+ const approveUserIds = approverNodes.value
+ .map(node => node.userId)
+ .join(",");
+ // 淇濆瓨褰撳墠灞曞紑鐨勮ID锛屼互渚垮彂璐у悗閲嶆柊鍔犺浇瀛愯〃鏍兼暟鎹�
+ const currentExpandedKeys = [...expandedRowKeys.value];
+ const salesLedgerId = currentDeliveryRow.value.salesLedgerId;
+ addShippingInfo({
+ salesLedgerId: salesLedgerId,
+ salesLedgerProductId: currentDeliveryRow.value.id,
+ type: deliveryForm.value.type,
+ approveUserIds,
+ }).then(() => {
proxy.$modal.msgSuccess("鍙戣揣鎴愬姛");
closeDeliveryDia();
// 鍒锋柊涓昏〃鏁版嵁
@@ -2149,12 +2759,16 @@
if (currentExpandedKeys.length > 0) {
// 浣跨敤 Promise.all 骞惰鍔犺浇鎵�鏈夊睍寮�琛岀殑瀛愯〃鏍兼暟鎹�
const loadPromises = currentExpandedKeys.map(ledgerId => {
- return productList({ salesLedgerId: ledgerId, type: 1 }).then((res) => {
- const index = tableData.value.findIndex((item) => item.id === ledgerId);
- if (index > -1) {
- tableData.value[index].children = res.data;
+ return productList({ salesLedgerId: ledgerId, type: 1 }).then(
+ res => {
+ const index = tableData.value.findIndex(
+ item => item.id === ledgerId
+ );
+ if (index > -1) {
+ tableData.value[index].children = res.data;
+ }
}
- });
+ );
});
Promise.all(loadPromises).then(() => {
// 鎭㈠灞曞紑鐘舵��
@@ -2162,225 +2776,226 @@
});
}
});
- })
- }
- });
-};
+ });
+ }
+ });
+ };
-// 鍏抽棴鍙戣揣寮规
-const closeDeliveryDia = () => {
- proxy.resetForm("deliveryFormRef");
- deliveryFormVisible.value = false;
- currentDeliveryRow.value = null;
-};
-const currentFactoryName = ref("");
-const getCurrentFactoryName = async () => {
- let res = await userStore.getInfo();
- currentFactoryName.value = res.user.currentFactoryName;
-};
-onMounted(() => {
- getList();
- userListNoPage().then(res => {
- userList.value = res.data;
- })
- getCurrentFactoryName();
-});
+ // 鍏抽棴鍙戣揣寮规
+ const closeDeliveryDia = () => {
+ proxy.resetForm("deliveryFormRef");
+ deliveryFormVisible.value = false;
+ currentDeliveryRow.value = null;
+ };
+ const currentFactoryName = ref("");
+ const getCurrentFactoryName = async () => {
+ let res = await userStore.getInfo();
+ currentFactoryName.value = res.user.currentFactoryName;
+ };
+ onMounted(() => {
+ getList();
+ userListNoPage().then(res => {
+ userList.value = res.data;
+ });
+ getCurrentFactoryName();
+ });
</script>
<style scoped lang="scss">
-.ml-10 {
- margin-left: 10px;
-}
+ .ml-10 {
+ margin-left: 10px;
+ }
-::v-deep .yellow {
- background-color: #FAF0DE;
-}
+ ::v-deep .yellow {
+ background-color: #faf0de;
+ }
-::v-deep .pink {
- background-color: #FAE1DE;
-}
+ ::v-deep .pink {
+ background-color: #fae1de;
+ }
-::v-deep .red {
- background-color: #FAE1DE;
-}
+ ::v-deep .red {
+ background-color: #fae1de;
+ }
-::v-deep .purple{
- background-color: #F4DEFA;
-}
+ ::v-deep .purple {
+ background-color: #f4defa;
+ }
-.table_list {
- margin-top: unset;
-}
+ .table_list {
+ margin-top: unset;
+ }
-.actions {
- display: flex;
- justify-content: space-between;
- margin-bottom: 10px;
-}
-.print-preview-dialog {
- .el-dialog__body {
- padding: 0;
- max-height: 80vh;
- overflow-y: auto;
- }
-}
+ .actions {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 10px;
+ }
+ .print-preview-dialog {
+ .el-dialog__body {
+ padding: 0;
+ max-height: 80vh;
+ overflow-y: auto;
+ }
+ }
-.print-preview-container {
- .print-preview-header {
- padding: 15px;
- border-bottom: 1px solid #e4e7ed;
- text-align: center;
-
- .el-button {
- margin: 0 10px;
- }
- }
-
- .print-preview-content {
- padding: 20px;
- background-color: #f5f5f5;
- min-height: 400px;
- }
-}
+ .print-preview-container {
+ .print-preview-header {
+ padding: 15px;
+ border-bottom: 1px solid #e4e7ed;
+ text-align: center;
-.print-page {
- width: 220mm;
- height: 90mm;
- padding: 10mm;
- margin: 0 auto;
- background: white;
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
- margin-bottom: 10px;
- box-sizing: border-box;
-}
+ .el-button {
+ margin: 0 10px;
+ }
+ }
-.delivery-note {
- width: 100%;
- height: 100%;
- font-family: "SimSun", serif;
- font-size: 10px;
- line-height: 1.2;
- display: flex;
- flex-direction: column;
-}
+ .print-preview-content {
+ padding: 20px;
+ background-color: #f5f5f5;
+ min-height: 400px;
+ }
+ }
-.header {
- text-align: center;
- margin-bottom: 8px;
-
- .company-name {
- font-size: 18px;
- font-weight: bold;
- margin-bottom: 4px;
- }
-
- .document-title {
- font-size: 16px;
- font-weight: bold;
- }
-}
+ .print-page {
+ width: 220mm;
+ height: 90mm;
+ padding: 10mm;
+ margin: 0 auto;
+ background: white;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+ margin-bottom: 10px;
+ box-sizing: border-box;
+ }
-.info-section {
- margin-bottom: 8px;
- display: flex;
- justify-content: space-between;
- align-items: center;
-
- .info-row {
- line-height: 20px;
-
- .label {
- font-weight: bold;
- width: 60px;
- font-size: 14px;
- }
-
- .value {
- margin-right: 20px;
- min-width: 80px;
- font-size: 14px;
- }
- }
-}
+ .delivery-note {
+ width: 100%;
+ height: 100%;
+ font-family: "SimSun", serif;
+ font-size: 10px;
+ line-height: 1.2;
+ display: flex;
+ flex-direction: column;
+ }
-.table-section {
- margin-bottom: 4px;
- flex: 1;
-
- .product-table {
- width: 100%;
- border-collapse: collapse;
- border: 1px solid #000;
-
- th, td {
- border: 1px solid #000;
- padding: 6px;
- text-align: center;
- font-size: 14px;
- line-height: 1.4;
- }
-
- th {
- font-weight: bold;
- }
-
- .total-label {
- text-align: right;
- font-weight: bold;
- }
-
- .total-value {
- font-weight: bold;
- }
- }
-}
+ .header {
+ text-align: center;
+ margin-bottom: 8px;
-.footer-section {
- .footer-row {
- display: flex;
- margin-bottom: 3px;
- line-height: 20px;
- justify-content: space-between;
-
- .footer-item {
- display: flex;
- margin-right: 20px;
-
- .label {
- font-weight: bold;
- width: 80px;
- font-size: 14px;
- }
-
- .value {
- min-width: 80px;
- font-size: 14px;
- }
-
- &.address-item {
- .address-value {
- min-width: 200px;
- }
- }
- }
- }
-}
+ .company-name {
+ font-size: 18px;
+ font-weight: bold;
+ margin-bottom: 4px;
+ }
-@media print {
- .app-container {
- display: none;
- }
-
- .print-page {
- box-shadow: none;
- margin: 0;
- padding: 10mm;
- padding-left: 20mm;
- page-break-inside: avoid;
- page-break-after: always;
- }
- .print-page:last-child {
- page-break-after: avoid;
- }
-}
+ .document-title {
+ font-size: 16px;
+ font-weight: bold;
+ }
+ }
+
+ .info-section {
+ margin-bottom: 8px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ .info-row {
+ line-height: 20px;
+
+ .label {
+ font-weight: bold;
+ width: 60px;
+ font-size: 14px;
+ }
+
+ .value {
+ margin-right: 20px;
+ min-width: 80px;
+ font-size: 14px;
+ }
+ }
+ }
+
+ .table-section {
+ margin-bottom: 4px;
+ flex: 1;
+
+ .product-table {
+ width: 100%;
+ border-collapse: collapse;
+ border: 1px solid #000;
+
+ th,
+ td {
+ border: 1px solid #000;
+ padding: 6px;
+ text-align: center;
+ font-size: 14px;
+ line-height: 1.4;
+ }
+
+ th {
+ font-weight: bold;
+ }
+
+ .total-label {
+ text-align: right;
+ font-weight: bold;
+ }
+
+ .total-value {
+ font-weight: bold;
+ }
+ }
+ }
+
+ .footer-section {
+ .footer-row {
+ display: flex;
+ margin-bottom: 3px;
+ line-height: 20px;
+ justify-content: space-between;
+
+ .footer-item {
+ display: flex;
+ margin-right: 20px;
+
+ .label {
+ font-weight: bold;
+ width: 80px;
+ font-size: 14px;
+ }
+
+ .value {
+ min-width: 80px;
+ font-size: 14px;
+ }
+
+ &.address-item {
+ .address-value {
+ min-width: 200px;
+ }
+ }
+ }
+ }
+ }
+
+ @media print {
+ .app-container {
+ display: none;
+ }
+
+ .print-page {
+ box-shadow: none;
+ margin: 0;
+ padding: 10mm;
+ padding-left: 20mm;
+ page-break-inside: avoid;
+ page-break-after: always;
+ }
+ .print-page:last-child {
+ page-break-after: avoid;
+ }
+ }
</style>
--
Gitblit v1.9.3