From dc63a926bd3fff4fda282b88b203072a8874962a Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 12 八月 2025 17:45:05 +0800
Subject: [PATCH] 1.销售台账列表开发联调 2.新增、编辑销售台账页面开发联调
---
src/pages/index.vue | 4
src/api/salesManagement/salesLedger.js | 16
src/api/system/user.js | 7
src/pages/sales/salesAccount/detail.vue | 983 ++++++++++++++++++++++++++++++++++++++++++---------
src/main.js | 4
src/config.js | 5
src/pages/sales/salesAccount/index.vue | 19
src/utils/summarizeTable.js | 57 +++
8 files changed, 900 insertions(+), 195 deletions(-)
diff --git a/src/api/salesManagement/salesLedger.js b/src/api/salesManagement/salesLedger.js
index 3a2fa22..a6125f3 100644
--- a/src/api/salesManagement/salesLedger.js
+++ b/src/api/salesManagement/salesLedger.js
@@ -109,3 +109,19 @@
params: query,
});
}
+// 浜у搧鏍戞煡璇�
+export function productTreeList(query) {
+ return request({
+ url: '/basic/product/list',
+ method: 'get',
+ params: query
+ })
+}
+// 瑙勬牸鍨嬪彿鏌ヨ
+export function modelList(query) {
+ return request({
+ url: '/basic/product/modelList',
+ method: 'get',
+ params: query
+ })
+}
diff --git a/src/api/system/user.js b/src/api/system/user.js
index d961407..21d60bc 100644
--- a/src/api/system/user.js
+++ b/src/api/system/user.js
@@ -39,3 +39,10 @@
filePath: data.filePath
})
}
+// 鏌ヨ鐢ㄦ埛鍒楄〃
+export function userListNoPage() {
+ return request({
+ url: '/system/user/userListNoPage',
+ method: 'get'
+ })
+}
\ No newline at end of file
diff --git a/src/config.js b/src/config.js
index 6840f86..47daed0 100644
--- a/src/config.js
+++ b/src/config.js
@@ -1,8 +1,7 @@
// 搴旂敤鍏ㄥ眬閰嶇疆
const config = {
- // baseUrl: 'https://vue.ruoyi.vip/prod-api',
- // baseUrl: 'http://localhost/prod-api',
- baseUrl: 'http://114.132.189.42:8089',
+ // baseUrl: 'http://114.132.189.42:8089', // 娴嬭瘯搴�
+ baseUrl: 'http://192.168.1.147:7003', // 鏈湴鑱旇皟
//cloud鍚庡彴缃戝叧鍦板潃
// baseUrl: 'http://192.168.10.3:8080',
// 搴旂敤淇℃伅
diff --git a/src/main.js b/src/main.js
index fc8d022..b9b51f6 100644
--- a/src/main.js
+++ b/src/main.js
@@ -11,6 +11,9 @@
import { useDict } from '@/utils/dict'
import { parseTime, resetForm, addDateRange, handleTree, selectDictLabel, selectDictLabels } from '@/utils/ruoyi'
+import {
+ calculateTaxExclusiveTotalPrice,
+} from "@/utils/summarizeTable.js";
@@ -34,6 +37,7 @@
app.config.globalProperties.addDateRange = addDateRange
app.config.globalProperties.selectDictLabel = selectDictLabel
app.config.globalProperties.selectDictLabels = selectDictLabels
+ app.config.globalProperties.calculateTaxExclusiveTotalPrice = calculateTaxExclusiveTotalPrice;
return {
app
diff --git a/src/pages/index.vue b/src/pages/index.vue
index e35f5e3..64f9896 100644
--- a/src/pages/index.vue
+++ b/src/pages/index.vue
@@ -20,7 +20,7 @@
<view class="notice">
<view class="notice-content">
<view class="notice-left">
- <text class="notice-status">馃搳 瀹炴椂鐩戞帶</text>
+ <text class="notice-status">閫氱煡</text>
</view>
<view class="notice-separator"></view>
<view class="notice-right">
@@ -588,7 +588,7 @@
}
.notice-label {
- color: #1976d2;
+ color: #333;
font-size: 14px;
font-weight: 500;
margin-right: 12px;
diff --git a/src/pages/sales/salesAccount/detail.vue b/src/pages/sales/salesAccount/detail.vue
index 098c609..56c92a9 100644
--- a/src/pages/sales/salesAccount/detail.vue
+++ b/src/pages/sales/salesAccount/detail.vue
@@ -6,244 +6,841 @@
<text class="title">鍙拌处璇︽儏</text>
</view>
- <!-- 琛ㄥ崟鍖哄煙 -->
- <view class="form-section">
- <van-form ref="formRef" :modelValue="form" :rules="rules" label-width="100px" input-align="right">
- <van-field label="閿�鍞悎鍚屽彿" name="salesContractNo" borderBottom="true" v-model="form.salesContractNo" placeholder="璇疯緭鍏ラ攢鍞悎鍚屽彿">
- </van-field>
- <van-field label="閿�鍞悎鍚屽彿" name="salesContractNo" borderBottom="true" v-model="form.salesContractNo" placeholder="璇疯緭鍏ラ攢鍞悎鍚屽彿">
- </van-field>
- <van-field label="閿�鍞悎鍚屽彿" name="salesContractNo" borderBottom="true" v-model="form.salesContractNo" placeholder="璇疯緭鍏ラ攢鍞悎鍚屽彿">
- </van-field>
- <van-field label="閿�鍞悎鍚屽彿" name="salesContractNo" borderBottom="true" v-model="form.salesContractNo" placeholder="璇疯緭鍏ラ攢鍞悎鍚屽彿">
- </van-field>
- <van-field label="閿�鍞悎鍚屽彿" name="salesContractNo" borderBottom="true" v-model="form.salesContractNo" placeholder="璇疯緭鍏ラ攢鍞悎鍚屽彿">
- </van-field>
- <van-field label="閿�鍞悎鍚屽彿" name="salesContractNo" borderBottom="true" v-model="form.salesContractNo" placeholder="璇疯緭鍏ラ攢鍞悎鍚屽彿">
- </van-field>
- <van-field label="褰曞叆浜�" name="salesContractNo" borderBottom="true" v-model="form.salesContractNo" placeholder="璇疯緭鍏�" readonly>
- </van-field>
- <van-field label="褰曞叆鏃ユ湡" name="salesContractNo" borderBottom="true" v-model="form.salesContractNo" placeholder="璇疯緭鍏�" readonly>
- </van-field>
- </van-form>
- </view>
-
- <!-- 浜у搧淇℃伅 -->
- <view class="product-section">
- <view class="section-header">
- <text class="section-title">浜у搧淇℃伅</text>
- <button class="add-btn" @click="addProduct">鏂板</button>
- </view>
- <view class="product-card" v-for="(product, idx) in products" :key="idx">
- <view class="product-row">
- <text class="product-label">浜у搧绫�</text>
- <uni-easyinput v-model="product.type" placeholder="璇疯緭鍏ヤ骇鍝佺被" />
- </view>
- <view class="product-row">
- <text class="product-label">鍗曚綅</text>
- <uni-easyinput v-model="product.unit" placeholder="璇疯緭鍏ュ崟浣�" />
- <text class="product-label">鏁伴噺</text>
- <uni-easyinput v-model="product.amount" placeholder="璇疯緭鍏ユ暟閲�" type="number" />
- </view>
- <view class="product-row">
- <text class="product-label">绋庣巼</text>
- <uni-easyinput v-model="product.taxRate" placeholder="璇疯緭鍏ョ◣鐜�" />
- <text class="product-label">鍚◣鍗曚环</text>
- <uni-easyinput v-model="product.taxPrice" placeholder="璇疯緭鍏ュ惈绋庡崟浠�" />
- </view>
- <view class="product-row">
- <text class="product-label">鍚◣鎬讳环</text>
- <uni-easyinput v-model="product.taxTotal" placeholder="璇疯緭鍏ュ惈绋庢�讳环" />
- <text class="product-label">鍚堝悓閲戦</text>
- <uni-easyinput v-model="product.contractAmount" placeholder="璇疯緭鍏ュ悎鍚岄噾棰�" />
- </view>
- <view class="product-row">
- <text class="product-label">鎿嶄綔</text>
- <uni-easyinput v-model="product.operateDate" placeholder="璇疯緭鍏ユ搷浣滄椂闂�" />
- </view>
- <view class="product-row">
- <text class="product-label">澶囨敞</text>
- <uni-easyinput v-model="product.remark" placeholder="璇疯緭鍏ュ娉�" />
- </view>
- <view class="product-row del-row">
- <button class="del-btn" @click="removeProduct(idx)">鍒犻櫎</button>
- </view>
- </view>
- </view>
-
- <!-- 搴曢儴鎸夐挳 -->
- <view class="footer-btns">
- <van-button class="cancel-btn" @click="goBack">鍙栨秷</van-button>
- <van-button class="save-btn" @click="submitForm">淇濆瓨</van-button>
- </view>
+ <!-- 琛ㄥ崟鍖哄煙 -->
+ <van-form @submit="onSubmit" label-width="110px" input-align="right" style="margin-top: 10px" error-message-align="right" scroll-to-error scroll-to-error-position="center">
+ <van-field label="閿�鍞悎鍚屽彿" name="salesContractNo" borderBottom="true" v-model="form.salesContractNo" placeholder="鑷姩鐢熸垚" disabled>
+ </van-field>
+ <van-field
+ v-model="form.salesman"
+ is-link
+ readonly
+ name="salesman"
+ label="涓氬姟鍛�"
+ required
+ placeholder="鐐瑰嚮閫夋嫨涓氬姟鍛�"
+ :rules="[{ required: true, message: '璇烽�夋嫨涓氬姟鍛�' }]"
+ @click="showPicker = true"
+ />
+ <van-field label="瀹㈡埛鍚堝悓鍙�" name="customerContractNo" borderBottom="true"
+ v-model="form.customerContractNo" required
+ placeholder="璇疯緭鍏ュ鎴峰悎鍚屽彿" :rules="[{ required: true, message: '瀹㈡埛鍚堝悓鍙蜂笉鑳戒负绌�' }]">
+ </van-field>
+ <van-field
+ v-model="form.customerName"
+ is-link
+ readonly
+ required
+ name="customerName"
+ label="瀹㈡埛鍚嶇О"
+ placeholder="鐐瑰嚮閫夋嫨瀹㈡埛"
+ :rules="[{ required: true, message: '璇烽�夋嫨瀹㈡埛' }]"
+ @click="showCustomerPicker = true"
+ />
+ <van-field label="椤圭洰鍚嶇О" name="projectName" borderBottom="true" v-model="form.projectName" placeholder="璇疯緭鍏ラ」鐩悕绉�" :rules="[{ required: true, message: '椤圭洰鍚嶇О涓嶈兘涓虹┖' }]" required>
+ </van-field>
+ <van-field
+ v-model="form.executionDate"
+ is-link
+ readonly
+ required
+ name="executionDate"
+ label="绛捐鏃ユ湡"
+ placeholder="鐐瑰嚮閫夋嫨鏃堕棿"
+ :rules="[{ required: true, message: '绛捐鏃ユ湡涓嶈兘涓虹┖' }]"
+ @click="showDatePicker = true"
+ />
+ <van-popup v-model:show="showDatePicker" destroy-on-close position="bottom">
+ <van-date-picker
+ v-model="pickerDateValue"
+ @confirm="onDateConfirm"
+ @cancel="showDatePicker = false"
+ />
+ </van-popup>
+ <van-field label="浠樻鏂瑰紡" name="paymentMethod" borderBottom="true" v-model="form.paymentMethod" placeholder="璇疯緭鍏ヤ粯娆炬柟寮�">
+ </van-field>
+ <van-field label="褰曞叆浜�" name="entryPersonName" borderBottom="true" v-model="form.entryPersonName" placeholder="璇疯緭鍏�" readonly>
+ </van-field>
+ <van-field label="褰曞叆鏃ユ湡" name="entryDate" borderBottom="true" v-model="form.entryDate" placeholder="璇疯緭鍏�" readonly>
+ </van-field>
+ <van-popup v-model:show="showPicker" destroy-on-close position="bottom">
+ <van-picker
+ :columns="userList"
+ v-model="pickerValue"
+ @confirm="onConfirm"
+ @cancel="showPicker = false"
+ />
+ </van-popup>
+ <van-popup v-model:show="showCustomerPicker" destroy-on-close position="bottom">
+ <van-picker
+ :columns="customerOption"
+ v-model="pickerCustomerValue"
+ @confirm="onCustomerConfirm"
+ @cancel="showCustomerPicker = false"
+ />
+ </van-popup>
+
+ <!-- 浜у搧澶х被閫夋嫨鍣� -->
+ <van-popup v-model:show="showCategoryPicker" destroy-on-close position="bottom">
+ <!-- 澶撮儴鎸夐挳鍖哄煙 -->
+ <view class="popup-header">
+ <view @click="showCategoryPicker = false" class="cancelButton">鍙栨秷</view>
+ <view @click="confirmCategorySelection" class="confirmButton">纭畾</view>
+ </view>
+ <up-tree
+ :data="productOptions"
+ :props="defaultProps"
+ show-checkbox
+ default-expand-all
+ check-strictly
+ @check-change="onCategoryConfirm"
+ />
+ </van-popup>
+
+ <!-- 瑙勬牸鍨嬪彿閫夋嫨鍣� -->
+ <van-popup v-model:show="showSpecificationPicker" destroy-on-close position="bottom">
+ <van-picker
+ :columns="modelOptions"
+ v-model="pickerSpecificationValue"
+ @confirm="onSpecificationConfirm"
+ @cancel="showSpecificationPicker = false"
+ />
+ </van-popup>
+
+ <!-- 绋庣巼閫夋嫨鍣� -->
+ <van-popup v-model:show="showTaxRatePicker" destroy-on-close position="bottom">
+ <van-picker
+ :columns="taxRateOptions"
+ v-model="pickerTaxRateValue"
+ @confirm="onTaxRateConfirm"
+ @cancel="showTaxRatePicker = false"
+ />
+ </van-popup>
+
+ <!-- 鍙戠エ绫诲瀷閫夋嫨鍣� -->
+ <van-popup v-model:show="showInvoiceTypePicker" destroy-on-close position="bottom">
+ <van-picker
+ :columns="invoiceTypeOptions"
+ v-model="pickerInvoiceTypeValue"
+ @confirm="onInvoiceTypeConfirm"
+ @cancel="showInvoiceTypePicker = false"
+ />
+ </van-popup>
+ <!-- 浜у搧淇℃伅 -->
+ <view class="product-section">
+ <view class="section-header">
+ <text class="section-title">浜у搧淇℃伅</text>
+ <van-button type="primary" size="small" @click="addProduct" class="add-btn" icon="plus">鏂板</van-button>
+ </view>
+ <view class="product-card" v-for="(product, idx) in productData" :key="idx">
+ <!-- 浜у搧绫� -->
+ <view class="product-header">
+ <view class="product-title">
+ <van-icon name="description" color="#2979ff" size="15" />
+ <text class="product-productCategory">浜у搧 {{ idx + 1 }}</text>
+ </view>
+ <!-- 鎿嶄綔鎸夐挳 -->
+ <view class="product-actions">
+ <van-button type="danger" size="mini" @click="removeProduct(idx)" class="del-btn" icon="delete">鍒犻櫎</van-button>
+ </view>
+ </view>
+
+ <!-- 浜у搧淇℃伅琛ㄥ崟 -->
+ <view class="product-form">
+ <!-- 浜у搧澶х被 -->
+ <van-field
+ v-model="product.productCategory"
+ is-link
+ readonly
+ name="productCategory"
+ label="浜у搧澶х被"
+ required
+ placeholder="璇烽�夋嫨"
+ :rules="[{ required: true, message: '璇烽�夋嫨' }]"
+ @click="openCategoryPicker(idx)"
+ />
+
+ <!-- 瑙勬牸鍨嬪彿 -->
+ <van-field
+ v-model="product.specificationModel"
+ is-link
+ readonly
+ name="specificationModel"
+ label="瑙勬牸鍨嬪彿"
+ required
+ :rules="[{ required: true, message: '璇烽�夋嫨' }]"
+ placeholder="璇烽�夋嫨"
+ @click="openSpecificationPicker(idx)"
+ />
+
+ <!-- 鍗曚綅 -->
+ <van-field
+ v-model="product.unit"
+ name="unit"
+ label="鍗曚綅"
+ required
+ :rules="[{ required: true, message: '璇疯緭鍏�' }]"
+ placeholder="璇疯緭鍏�"
+ />
+
+ <!-- 绋庣巼 -->
+ <van-field
+ v-model="product.taxRate"
+ is-link
+ readonly
+ name="taxRate"
+ label="绋庣巼(%)"
+ required
+ :rules="[{ required: true, message: '璇烽�夋嫨' }]"
+ placeholder="璇烽�夋嫨"
+ @click="openTaxRatePicker(idx)"
+ />
+
+ <!-- 鍚◣鍗曚环 -->
+ <van-field
+ v-model="product.taxInclusiveUnitPrice"
+ name="taxInclusiveUnitPrice"
+ label="鍚◣鍗曚环(鍏�)"
+ type="number"
+ required
+ :rules="[{ required: true, message: '璇疯緭鍏�' }]"
+ placeholder="璇疯緭鍏�"
+ @blur="formatTaxPrice(idx)"
+ />
+
+ <!-- 鏁伴噺 -->
+ <van-field
+ v-model="product.quantity"
+ name="quantity"
+ label="鏁伴噺"
+ type="number"
+ :rules="[{ required: true, message: '璇疯緭鍏�' }]"
+ required
+ placeholder="璇疯緭鍏�"
+ @blur="formatAmount(idx)"
+ />
+
+ <!-- 鍚◣鎬讳环 -->
+ <van-field
+ v-model="product.taxInclusiveTotalPrice"
+ name="taxInclusiveTotalPrice"
+ label="鍚◣鎬讳环(鍏�)"
+ type="number"
+ :rules="[{ required: true, message: '璇疯緭鍏�' }]"
+ required
+ placeholder="璇疯緭鍏�"
+ @blur="formatTaxTotal(idx)"
+ />
+
+ <!-- 涓嶅惈绋庢�讳环 -->
+ <van-field
+ v-model="product.taxExclusiveTotalPrice"
+ name="taxExclusiveTotalPrice"
+ label="涓嶅惈绋庢�讳环(鍏�)"
+ type="number"
+ required
+ :rules="[{ required: true, message: '璇疯緭鍏�' }]"
+ placeholder="璇疯緭鍏�"
+ @blur="formatNoTaxTotal(idx)"
+ />
+
+ <!-- 鍙戠エ绫诲瀷 -->
+ <van-field
+ v-model="product.invoiceType"
+ is-link
+ readonly
+ name="invoiceType"
+ label="鍙戠エ绫诲瀷"
+ :rules="[{ required: true, message: '璇烽�夋嫨' }]"
+ required
+ placeholder="璇烽�夋嫨"
+ @click="openInvoiceTypePicker(idx)"
+ />
+ </view>
+ </view>
+ </view>
+ <view class="footer-btns">
+ <van-button class="cancel-btn" @click="goBack">鍙栨秷</van-button>
+ <van-button class="save-btn" native-type="submit" form-type="submit">淇濆瓨</van-button>
+ </view>
+ </van-form>
</view>
</template>
<script setup>
-import { ref } from 'vue';
-const goBack = () => {
- uni.navigateBack();
-};
-const formRef = ref();
-const paymentMethods = ['瀵瑰叕杞处', '鐜伴噾', '鍏朵粬'];
+import {onMounted, ref} from 'vue';
+import {userListNoPage} from "@/api/system/user";
+import {
+ addOrUpdateSalesLedger,
+ addOrUpdateSalesLedgerProduct,
+ customerList,
+ getSalesLedgerWithProducts,
+ modelList,
+ productTreeList
+} from "@/api/salesManagement/salesLedger";
+import useUserStore from "@/store/modules/user";
+import {calculateTaxExclusiveTotalPrice} from "@/utils/summarizeTable";
+
+// 鑾峰彇椤甸潰鍙傛暟
+const operationType = ref('');
+const editData = ref(null);
+
+const userStore = useUserStore()
const form = ref({
+ id: '',
salesContractNo: '',
- customerContract: '',
- projectName: '',
- contractAmount: '',
- executionDate: '',
+ customerContractNo: '',
+ customerId: '',
+ customerName: '',
+ projectName: '',
+ executionDate: '',
paymentMethod: '',
+ entryPerson: '',
+ entryPersonName: '',
+ entryDate: '',
});
-const rules = {
- salesContractNo: {
- rules: [{ required: true, errorMessage: '閿�鍞悎鍚屽彿涓嶈兘涓虹┖' }]
- },
- customerContract: {
- rules: [{ required: true, errorMessage: '瀹㈡埛鍚堝悓涓嶈兘涓虹┖' }]
- },
- projectName: {
- rules: [{ required: true, errorMessage: '椤圭洰鍚嶇О涓嶈兘涓虹┖' }]
- },
- contractAmount: {
- rules: [{ required: true, errorMessage: '鍚堝悓閲戦涓嶈兘涓虹┖' }]
- },
- executionDate: {
- rules: [{ required: true, errorMessage: '绛捐鏃ユ湡涓嶈兘涓虹┖' }]
- },
- paymentMethod: {
- rules: [{ required: true, errorMessage: '璇烽�夋嫨浠樻鏂瑰紡' }]
- }
-};
-const products = ref([
- {
- type: 'LS-29911',
- unit: '鍛ㄥ簞闀�',
- amount: '86590905972612',
- taxRate: '杩欓噷鏄」鐩悕绉�',
- taxPrice: '杩欓噷鏄」鐩悕绉�',
- taxTotal: '杩欓噷鏄」鐩悕绉�',
- contractAmount: '32011鍏�',
- operateDate: '2022-02-22 11:30:50',
- remark: '',
- },
- {
- type: 'LS-29911',
- unit: '鍛ㄥ簞闀�',
- amount: '86590905972612',
- taxRate: '杩欓噷鏄」鐩悕绉�',
- taxPrice: '杩欓噷鏄」鐩悕绉�',
- taxTotal: '杩欓噷鏄」鐩悕绉�',
- contractAmount: '32011鍏�',
- operateDate: '2022-02-22 11:30:50',
- remark: '',
- },
+const pickerValue = ref(['']);
+const pickerDateValue = ref([]);
+const showPicker = ref(false);
+const showDatePicker = ref(false);
+const pickerCustomerValue = ref(['']);
+const showCustomerPicker = ref(false);
+const userList = ref([]);
+const customerOption = ref([]);
+const productData = ref([]);
+
+// 閫夋嫨鍣ㄧ浉鍏冲彉閲�
+const showCategoryPicker = ref(false);
+const showSpecificationPicker = ref(false);
+const showTaxRatePicker = ref(false);
+const showInvoiceTypePicker = ref(false);
+const pickerCategoryValue = ref(['']);
+const pickerSpecificationValue = ref(['']);
+const pickerTaxRateValue = ref(['']);
+const pickerInvoiceTypeValue = ref(['']);
+const currentProductIndex = ref(0);
+
+// 閫夐」鏁版嵁
+const productOptions = ref([]);
+const selectedCategoryNode = ref(null);
+const defaultProps = ref({
+ children: 'children',
+ label: 'label',
+ nodeKey: 'id'
+});
+
+const modelOptions = ref([]);
+// 闃叉寰幆璁$畻鐨勬爣蹇�
+// const isCalculating = ref(false);
+const taxRateOptions = ref([
+ { text: '1', value: '1' },
+ { text: '6', value: '6' },
+ { text: '13', value: '13' },
]);
+
+const invoiceTypeOptions = ref([
+ { text: '澧炴櫘绁�', value: '澧炴櫘绁�' },
+ { text: '澧炰笓绁�', value: '澧炰笓绁�' },
+]);
+
const addProduct = () => {
- products.value.push({
- type: '',
+ productData.value.push({
+ productCategory: '',
+ specificationModel: '',
+ productModelId: '',
unit: '',
- amount: '',
taxRate: '',
- taxPrice: '',
- taxTotal: '',
- contractAmount: '',
- operateDate: '',
- remark: '',
+ taxInclusiveUnitPrice: '',
+ quantity: '',
+ taxInclusiveTotalPrice: '',
+ taxExclusiveTotalPrice: '',
+ invoiceType: ''
});
+};
+const onConfirm = ({ selectedValues, selectedOptions }) => {
+ form.value.salesman = selectedOptions[0]?.text;
+ pickerValue.value = [selectedValues[0]];
+ showPicker.value = false;
+};
+const onCustomerConfirm = ({ selectedValues, selectedOptions }) => {
+ form.value.customerName = selectedOptions[0]?.text;
+ form.value.customerId = selectedOptions[0]?.value;
+ pickerCustomerValue.value = [selectedValues[0]];
+ showCustomerPicker.value = false;
+};
+const onDateConfirm = ({ selectedValues }) => {
+ form.value.executionDate = selectedValues.join('-');
+ pickerDateValue.value = selectedValues;
+ showDatePicker.value = false;
};
const removeProduct = (idx) => {
- products.value.splice(idx, 1);
+ productData.value.splice(idx, 1);
};
-const submitForm = () => {
- formRef.value.validate().then(() => {
- uni.showToast({ title: '淇濆瓨鎴愬姛', icon: 'success' });
- });
+
+// 鏄剧ず閫夋嫨鍣�
+const openCategoryPicker = (idx) => {
+ currentProductIndex.value = idx;
+ showCategoryPicker.value = true;
};
+
+const openSpecificationPicker = (idx) => {
+ currentProductIndex.value = idx;
+ showSpecificationPicker.value = true;
+};
+
+const openTaxRatePicker = (idx) => {
+ currentProductIndex.value = idx;
+ showTaxRatePicker.value = true;
+};
+
+const openInvoiceTypePicker = (idx) => {
+ currentProductIndex.value = idx;
+ showInvoiceTypePicker.value = true;
+};
+
+// 閫夋嫨鍣ㄧ‘璁や簨浠�
+const onCategoryConfirm = (node) => {
+ // 鑾峰彇閫変腑鐨勮妭鐐逛俊鎭�
+ console.log('selected node---', node);
+ // 瀛樺偍閫変腑鐨勮妭鐐癸紝鐢ㄤ簬纭鏃惰幏鍙栨暟鎹�
+ selectedCategoryNode.value = node;
+};
+
+// 纭浜у搧澶х被閫夋嫨
+const confirmCategorySelection = () => {
+ if (selectedCategoryNode.value) {
+ // 璁剧疆閫変腑鐨勪骇鍝佸ぇ绫�
+ productData.value[currentProductIndex.value].productCategory = selectedCategoryNode.value.label;
+ const id = selectedCategoryNode.value.id
+ // 閲嶇疆閫変腑鐨勮妭鐐�
+ selectedCategoryNode.value = null;
+ productData.value[currentProductIndex.value].specificationModel = ''
+ productData.value[currentProductIndex.value].productModelId = ''
+ productData.value[currentProductIndex.value].pickerSpecificationValue = ['']
+ getModels(id)
+ }
+ showCategoryPicker.value = false;
+};
+// 鑾峰彇瑙勬牸鍨嬪彿
+const getModels = (value) => {
+ modelList({ id: value }).then((res) => {
+ modelOptions.value = res.map(user => ({
+ text: user.model,
+ value: user.id
+ }));
+ });
+};
+// 閫夋嫨瑙勬牸鍨嬪彿
+const onSpecificationConfirm = ({ selectedValues, selectedOptions }) => {
+ productData.value[currentProductIndex.value].specificationModel = selectedOptions[0]?.text;
+ productData.value[currentProductIndex.value].productModelId = selectedOptions[0]?.value;
+ productData.value[currentProductIndex.value].unit = selectedOptions[0]?.unit;
+ pickerSpecificationValue.value = [selectedValues[0]];
+ showSpecificationPicker.value = false;
+};
+// 閫夋嫨绋庣巼
+const onTaxRateConfirm = ({ selectedValues, selectedOptions }) => {
+ productData.value[currentProductIndex.value].taxRate = selectedOptions[0]?.value;
+ pickerTaxRateValue.value = [selectedValues[0]];
+ showTaxRatePicker.value = false;
+ // if (isCalculating.value) return;
+ const inclusiveTotalPrice = parseFloat(productData.value[currentProductIndex.value].taxInclusiveTotalPrice);
+ const taxRate = parseFloat(productData.value[currentProductIndex.value].taxRate);
+ if (!inclusiveTotalPrice || !taxRate) {
+ return;
+ }
+ // isCalculating.value = true;
+ // 璁$畻涓嶅惈绋庢�讳环
+ productData.value[currentProductIndex.value].taxExclusiveTotalPrice =
+ calculateTaxExclusiveTotalPrice(
+ inclusiveTotalPrice,
+ taxRate
+ );
+ // isCalculating.value = false;
+};
+
+const onInvoiceTypeConfirm = ({ selectedValues, selectedOptions }) => {
+ productData.value[currentProductIndex.value].invoiceType = selectedOptions[0]?.text;
+ pickerInvoiceTypeValue.value = [selectedValues[0]];
+ showInvoiceTypePicker.value = false;
+};
+
+// 鏍煎紡鍖栧嚱鏁� - 鍥哄畾涓や綅灏忔暟
+const formatTaxPrice = (idx) => {
+ if (productData.value[idx].taxInclusiveUnitPrice) {
+ const value = parseFloat(productData.value[idx].taxInclusiveUnitPrice);
+ if (!isNaN(value)) {
+ productData.value[idx].taxInclusiveUnitPrice = value.toFixed(2);
+ }
+ }
+ if (!productData.value[currentProductIndex.value].taxRate) {
+ uni.showToast({
+ title: '璇峰厛閫夋嫨绋庣巼',
+ icon: 'none'
+ });
+ return;
+ }
+ const quantity = parseFloat(productData.value[currentProductIndex.value].quantity);
+ const unitPrice = parseFloat(productData.value[currentProductIndex.value].taxInclusiveUnitPrice);
+
+ if (!quantity || quantity <= 0 || !unitPrice) {
+ return;
+ }
+ // 璁$畻鍚◣鎬讳环
+ productData.value[currentProductIndex.value].taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
+
+ // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
+ if (productData.value[currentProductIndex.value].taxRate) {
+ productData.value[currentProductIndex.value].taxExclusiveTotalPrice =
+ calculateTaxExclusiveTotalPrice(
+ productData.value[currentProductIndex.value].taxInclusiveTotalPrice,
+ productData.value[currentProductIndex.value].taxRate
+ );
+ }
+};
+// 鏁伴噺杈撳叆妗嗗け鐒�
+const formatAmount = (idx) => {
+ if (productData.value[idx].quantity) {
+ const value = parseFloat(productData.value[idx].quantity);
+ if (!isNaN(value)) {
+ productData.value[idx].quantity = value.toFixed(2);
+ }
+ }
+ if (!productData.value[currentProductIndex.value].taxRate) {
+ uni.showToast({
+ title: '璇峰厛閫夋嫨绋庣巼',
+ icon: 'none'
+ });
+ return;
+ }
+ const quantity = parseFloat(productData.value[currentProductIndex.value].quantity);
+ const unitPrice = parseFloat(productData.value[currentProductIndex.value].taxInclusiveUnitPrice);
+
+ if (!quantity || quantity <= 0 || !unitPrice) {
+ return;
+ }
+ // 璁$畻鍚◣鎬讳环
+ productData.value[currentProductIndex.value].taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
+ // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
+ if (productData.value[currentProductIndex.value].taxRate) {
+ productData.value[currentProductIndex.value].taxExclusiveTotalPrice =
+ calculateTaxExclusiveTotalPrice(
+ productData.value[currentProductIndex.value].taxInclusiveTotalPrice,
+ productData.value[currentProductIndex.value].taxRate
+ );
+ }
+};
+// 鍚◣鎬讳环澶辩劍锛屾牴鎹惈绋庢�讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
+const formatTaxTotal = (idx) => {
+ if (productData.value[idx].taxInclusiveTotalPrice) {
+ const value = parseFloat(productData.value[idx].taxInclusiveTotalPrice);
+ if (!isNaN(value)) {
+ productData.value[idx].taxInclusiveTotalPrice = value.toFixed(2);
+ }
+ }
+ const totalPrice = parseFloat(productData.value[currentProductIndex.value].taxInclusiveTotalPrice);
+ const quantity = parseFloat(productData.value[currentProductIndex.value].quantity);
+
+ if (!totalPrice || !quantity || quantity <= 0) {
+ return;
+ }
+ // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
+ productData.value[currentProductIndex.value].taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(2);
+ // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
+ if (productData.value[currentProductIndex.value].taxRate) {
+ productData.value[currentProductIndex.value].taxExclusiveTotalPrice =
+ calculateTaxExclusiveTotalPrice(
+ totalPrice,
+ productData.value[currentProductIndex.value].taxRate
+ );
+ }
+};
+// 涓嶅惈绋庢�讳环澶辩劍, 鏍规嵁涓嶅惈绋庢�讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
+const formatNoTaxTotal = (idx) => {
+ if (productData.value[idx].taxExclusiveTotalPrice) {
+ const value = parseFloat(productData.value[idx].taxExclusiveTotalPrice);
+ if (!isNaN(value)) {
+ productData.value[idx].taxExclusiveTotalPrice = value.toFixed(2);
+ }
+ }
+ if (!productData.value[currentProductIndex.value].taxRate) {
+ uni.showToast({
+ title: '璇峰厛閫夋嫨绋庣巼',
+ icon: 'none'
+ });
+ return;
+ }
+ const exclusiveTotalPrice = parseFloat(productData.value[currentProductIndex.value].taxExclusiveTotalPrice);
+ const quantity = parseFloat(productData.value[currentProductIndex.value].quantity);
+ const taxRate = parseFloat(productData.value[currentProductIndex.value].taxRate);
+ if (!exclusiveTotalPrice || !quantity || quantity <= 0 || !taxRate) {
+ return;
+ }
+ // 鍏堣绠楀惈绋庢�讳环 = 涓嶅惈绋庢�讳环 / (1 - 绋庣巼/100)
+ const taxRateDecimal = taxRate / 100;
+ const inclusiveTotalPrice = exclusiveTotalPrice / (1 - taxRateDecimal);
+ productData.value[currentProductIndex.value].taxInclusiveTotalPrice = inclusiveTotalPrice.toFixed(2);
+ // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
+ productData.value[currentProductIndex.value].taxInclusiveUnitPrice = (inclusiveTotalPrice / quantity).toFixed(2);
+};
+const goBack = () => {
+ // 娓呯悊鏈湴瀛樺偍鐨勬暟鎹�
+ uni.removeStorageSync('operationType');
+ uni.removeStorageSync('editData');
+ uni.navigateBack();
+};
+const onSubmit = () => {
+ if (productData.value !== null && productData.value.length > 0) {
+ form.value.productData = JSON.parse(JSON.stringify(productData.value));
+ } else {
+ uni.showToast({
+ title: '璇锋坊鍔犱骇鍝佷俊鎭�',
+ icon: 'none'
+ });
+ }
+ form.value.type = 1;
+ addOrUpdateSalesLedger(form.value).then((res) => {
+ uni.showToast({
+ title: '鎻愪氦鎴愬姛',
+ icon: 'success',
+ });
+ goBack();
+ });
+};
+const setUserInfo = () => {
+ form.value.entryPerson = userStore.id;
+ form.value.entryPersonName = userStore.name;
+ // 璁剧疆褰撳ぉ鏃ユ湡
+ const today = new Date()
+ const year = today.getFullYear()
+ const month = String(today.getMonth() + 1).padStart(2, '0')
+ const day = String(today.getDate()).padStart(2, '0')
+ form.value.entryDate = `${year}-${month}-${day}`
+ pickerDateValue.value = [year.toString(), month.toString(), day.toString()]
+}
+// 濉厖琛ㄥ崟鏁版嵁锛堢紪杈戞ā寮忥級
+const fillFormData = () => {
+ if (!editData.value) return;
+ getSalesLedgerWithProducts({ id: editData.value.id, type: 1 }).then((res) => {
+ productData.value = res.productData;
+ });
+ console.log(editData.value)
+ // 濉厖鍩烘湰淇℃伅
+ form.value.salesContractNo = editData.value.salesContractNo || '';
+ form.value.customerContractNo = editData.value.customerContractNo || '';
+ form.value.customerName = editData.value.customerName || '';
+ form.value.projectName = editData.value.projectName || '';
+ form.value.executionDate = editData.value.executionDate || '';
+ form.value.paymentMethod = editData.value.paymentMethod || '';
+ form.value.salesman = editData.value.salesman || '';
+ form.value.entryPerson = editData.value.entryPerson || '';
+ form.value.entryPersonName = editData.value.entryPersonName || '';
+ form.value.entryDate = editData.value.entryDate || '';
+ form.value.id = editData.value.id || '';
+ form.value.customerId = editData.value.customerId || '';
+
+ // 璁剧疆涓氬姟鍛橀�夋嫨鍣ㄧ殑鍊�
+ if (editData.value.salesman) {
+ const salesmanIndex = userList.value.findIndex(user => user.text === editData.value.salesman);
+ if (salesmanIndex !== -1) {
+ pickerValue.value = [userList.value[salesmanIndex].value];
+ }
+ }
+
+ // 璁剧疆瀹㈡埛閫夋嫨鍣ㄧ殑鍊�
+ if (editData.value.customerName) {
+ const customerIndex = customerOption.value.findIndex(customer => customer.text === editData.value.customerName);
+ if (customerIndex !== -1) {
+ pickerCustomerValue.value = [customerOption.value[customerIndex].value]
+ }
+ }
+
+ // 璁剧疆鏃ユ湡閫夋嫨鍣ㄧ殑鍊�
+ if (editData.value.executionDate) {
+ pickerDateValue.value = editData.value.executionDate.split('-').map(num => parseInt(num, 10))
+ console.log(pickerDateValue.value)
+ }
+};
+const getUserList = () => {
+ userListNoPage().then((res) => {
+ // 灏嗙敤鎴锋暟鎹粍瑁呮垚 picker 闇�瑕佺殑鏍煎紡
+ userList.value = res.data.map(user => ({
+ text: user.nickName,
+ value: user.nickName
+ }));
+ })
+}
+const getCustomerList = () => {
+ customerList().then((res) => {
+ // 灏嗙敤鎴锋暟鎹粍瑁呮垚 picker 闇�瑕佺殑鏍煎紡
+ customerOption.value = res.map(item => ({
+ text: item.customerName,
+ value: item.id
+ }));
+ })
+}
+const convertIdToValue = (data) => {
+ // 濡傛灉浼犲叆鐨勪笉鏄暟缁勶紝鍒欒繑鍥炵┖鏁扮粍
+ if (!Array.isArray(data)) {
+ return [];
+ }
+ // 閫掑綊鏄犲皠鍑芥暟
+ return data.map(item => {
+ // 鍒涘缓鏂板璞★紝鏄犲皠瀛楁
+ const mappedItem = {
+ label: item.label, // 鍏抽敭锛氬皢 label 鏄犲皠涓� text
+ id: item.id, // 淇濈暀 id
+ };
+ // 濡傛灉瀛樺湪 children 鏁扮粍锛屽垯閫掑綊澶勭悊
+ if (item.children && Array.isArray(item.children) && item.children.length > 0) {
+ mappedItem.children = convertIdToValue(item.children);
+ }
+ return mappedItem;
+ });
+};
+// 鑾峰彇浜у搧澶х被tree鏁版嵁
+const getProductOptions = () => {
+ productTreeList().then((res) => {
+ productOptions.value = convertIdToValue(res);
+ });
+};
+onMounted(() => {
+ // 鑾峰彇椤甸潰鍙傛暟
+ operationType.value = uni.getStorageSync('operationType') || '';
+
+ // 鑾峰彇浜哄憳鍒楄〃
+ getUserList()
+ // 鑾峰彇瀹㈡埛鍒楄〃
+ getCustomerList()
+ // 鑾峰彇浜у搧澶х被tree鏁版嵁
+ getProductOptions()
+ // 璧嬪�奸粯璁や俊鎭�
+ if (operationType.value === 'add') {
+ setUserInfo()
+ }
+
+ // 鑾峰彇缂栬緫鏁版嵁骞跺~鍏呰〃鍗�
+ const editDataStr = uni.getStorageSync('editData');
+ if (editDataStr) {
+ try {
+ editData.value = JSON.parse(editDataStr);
+ // 濡傛灉鏄紪杈戞ā寮忥紝绛夊緟鏁版嵁鍔犺浇瀹屾垚鍚庡~鍏呰〃鍗曟暟鎹�
+ if (operationType.value === 'edit' && editData.value) {
+ // 浣跨敤 nextTick 纭繚鏁版嵁鍔犺浇瀹屾垚鍚庡啀濉厖
+ setTimeout(() => {
+ fillFormData();
+ }, 100);
+ }
+ } catch (error) {
+ console.error('瑙f瀽缂栬緫鏁版嵁澶辫触:', error);
+ }
+ }
+});
</script>
<style scoped lang="scss">
.account-detail {
min-height: 100vh;
background: #f8f9fa;
- padding-bottom: 80px;
+ padding-bottom: 5rem;
}
.header {
display: flex;
align-items: center;
background: #fff;
- padding: 16px 20px;
- border-bottom: 1px solid #f0f0f0;
+ padding: 1rem 1.25rem;
+ border-bottom: 0.0625rem solid #f0f0f0;
position: sticky;
top: 0;
z-index: 100;
+ /* 鍏煎 iOS 鍒樻捣/鐏靛姩宀涘畨鍏ㄥ尯 */
+ padding-top: env(safe-area-inset-top);
}
.title {
flex: 1;
text-align: center;
- font-size: 18px;
+ font-size: 1.125rem;
font-weight: 600;
color: #333;
}
.form-section {
- margin-top: 16px;
+ margin-top: 1rem;
}
.van-field {
- height: 56px;
- line-height: 36px;
+ height: 3.4rem;
+}
+.van-cell {
+ align-items: center;
}
.product-section {
background: #fff;
- margin: 16px;
- border-radius: 16px;
- padding: 20px 16px 8px 16px;
- box-shadow: 0 2px 8px rgba(0,0,0,0.04);
+ margin-top: 1rem;
+ padding: 1rem;
+ box-shadow: 0 0.125rem 0.5rem rgba(0,0,0,0.04);
}
.section-header {
display: flex;
align-items: center;
justify-content: space-between;
- margin-bottom: 12px;
+ margin-bottom: 1rem;
}
.section-title {
- font-size: 16px;
+ font-size: 1rem;
font-weight: 600;
color: #333;
}
.add-btn {
- background: #2979ff;
- color: #fff;
- border-radius: 8px;
- padding: 4px 16px;
- font-size: 14px;
+ border-radius: 0.25rem;
}
.product-card {
- background: #f8f9fa;
- border-radius: 12px;
- padding: 12px;
- margin-bottom: 16px;
- box-shadow: 0 1px 4px rgba(41,121,255,0.06);
+ background: #FFFFFF;
+ box-shadow: 0 0 1.25rem 0 rgba(0,57,117,0.08);
+ border-radius: 0.5rem 0.5rem 0.5rem 0.5rem;
+ padding: 1rem 0.5rem 0 0.5rem;
position: relative;
}
-.product-row {
+.product-header {
display: flex;
align-items: center;
- margin-bottom: 8px;
+ justify-content: space-between;
+ padding: 0 0.5rem 0.75rem 0.5rem;
+ border-bottom: 0.0625rem solid #e8e8e8;
}
-.product-label {
- min-width: 60px;
- color: #888;
- font-size: 13px;
+.product-productCategory {
+ margin-left: 0.5rem;
+ font-size: 0.875rem;
+ font-weight: 500;
+ color: #333;
}
-.del-row {
- justify-content: flex-end;
+.info-grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 0.75rem;
+ margin-bottom: 1rem;
+}
+.info-item {
+ display: flex;
+ flex-direction: column;
+ gap: 0.25rem;
+}
+.info-label {
+ font-size: 0.75rem;
+ color: #666;
+ font-weight: 400;
+}
+.info-value {
+ font-size: 0.875rem;
+ color: #333;
+ font-weight: 500;
+}
+.info-value.highlight {
+ color: #2979ff;
+ font-weight: 600;
+}
+.product-form {
+ margin-bottom: 1rem;
}
.del-btn {
- background: #ff4d4f;
- color: #fff;
- border-radius: 8px;
- padding: 4px 16px;
- font-size: 13px;
- margin-top: 4px;
+ border-radius: 0.25rem;
}
.footer-btns {
position: fixed;
@@ -254,26 +851,46 @@
display: flex;
justify-content: space-around;
align-items: center;
- padding: 12px 0;
- box-shadow: 0 -2px 8px rgba(0,0,0,0.05);
+ padding: 0.75rem 0;
+ box-shadow: 0 -0.125rem 0.5rem rgba(0,0,0,0.05);
z-index: 1000;
}
.cancel-btn {
font-weight: 400;
- font-size: 16px;
+ font-size: 1rem;
color: #FFFFFF;
- width: 102px;
+ width: 6.375rem;
background: #C7C9CC;
- box-shadow: 0px 4px 10px 0px rgba(3,88,185,0.2);
- border-radius: 40px 40px 40px 40px;
+ box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2);
+ border-radius: 2.5rem 2.5rem 2.5rem 2.5rem;
}
.save-btn {
font-weight: 400;
- font-size: 16px;
+ font-size: 1rem;
color: #FFFFFF;
- width: 224px;
+ width: 14rem;
background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%);
- box-shadow: 0px 4px 10px 0px rgba(3,88,185,0.2);
- border-radius: 40px 40px 40px 40px;
+ box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2);
+ border-radius: 2.5rem 2.5rem 2.5rem 2.5rem;
+}
+
+.popup-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 1rem;
+ background: #fff;
+ position: sticky;
+ top: 0;
+ z-index: 10;
+}
+.cancelButton {
+ color: #969799
+}
+.confirmButton {
+ color: #1989FA
+}
+.u-tree {
+ height: 13rem;
}
</style>
diff --git a/src/pages/sales/salesAccount/index.vue b/src/pages/sales/salesAccount/index.vue
index e2e0b65..7f93241 100644
--- a/src/pages/sales/salesAccount/index.vue
+++ b/src/pages/sales/salesAccount/index.vue
@@ -29,7 +29,7 @@
<!-- 閿�鍞彴璐︾�戝竷娴� -->
<view class="ledger-list" v-if="total > 0">
<view v-for="(item, index) in ledgerList" :key="index">
- <view class="ledger-item" @click="handleItemClick(item)">
+ <view class="ledger-item" @click="handleInfo('edit', item)">
<view class="item-header">
<view class="item-left">
<view class="document-icon">
@@ -92,14 +92,15 @@
</view>
<!-- 娴姩鎿嶄綔鎸夐挳 -->
- <view class="fab-button" @click="handleAdd">
+ <view class="fab-button" @click="handleInfo('add')">
<up-icon name="plus" size="24" color="#ffffff"></up-icon>
</view>
</view>
</template>
<script setup>
-import { ref, reactive, onMounted } from 'vue';
+import { ref } from 'vue';
+import { onShow } from '@dcloudio/uni-app';
import {ledgerListPage} from "@/api/salesManagement/salesLedger";
// 鎼滅储鍏抽敭璇�
@@ -145,15 +146,19 @@
};
// 娣诲姞鏂拌褰�
-const handleAdd = () => {
+const handleInfo = (type, row) => {
+ uni.setStorageSync('operationType', type);
+ if (row) {
+ uni.setStorageSync('editData', JSON.stringify(row));
+ }
uni.navigateTo({
url: '/pages/sales/salesAccount/detail'
});
};
-onMounted(() => {
- // 椤甸潰鍔犺浇瀹屾垚鍚庣殑鍒濆鍖栭�昏緫
- getList()
+onShow(() => {
+ // 椤甸潰鏄剧ず鏃跺埛鏂板垪琛�
+ getList();
});
</script>
diff --git a/src/utils/summarizeTable.js b/src/utils/summarizeTable.js
new file mode 100644
index 0000000..1ad480d
--- /dev/null
+++ b/src/utils/summarizeTable.js
@@ -0,0 +1,57 @@
+/**
+ * 閫氱敤鐨勮〃鏍煎悎璁℃柟娉�
+ * @param {Object} param - 鍖呭惈琛ㄦ牸鍒楅厤缃拰鏁版嵁婧愮殑瀵硅薄
+ * @param {Array<string>} summaryProps - 闇�瑕佹眹鎬荤殑瀛楁鍚嶆暟缁�
+ * @param {Object} specialFormat - 鐗规畩鏍煎紡鍖栬鍒欙細瀛楁鍚� -> 鏍煎紡鍖栭�夐」锛堝鏄惁鍘绘帀灏忔暟锛�
+ * @returns {Array} 鍚堣琛屾暟鎹�
+ */
+const summarizeTable = (param, summaryProps, specialFormat = {}) => {
+ const { columns, data } = param;
+ const sums = [];
+ columns.forEach((column, index) => {
+ if (index === 0) {
+ sums[index] = "鍚堣";
+ return;
+ }
+ const prop = column.property;
+ if (summaryProps.includes(prop)) {
+ const values = data.map((item) => Number(item[prop]));
+ // 鍙鏈夋晥鏁板瓧杩涜姹傚拰
+ if (!values.every(isNaN)) {
+ const sum = values.reduce(
+ (acc, val) => (!isNaN(val) ? acc + val : acc),
+ 0
+ );
+ if (specialFormat[prop] && specialFormat[prop].noDecimal) {
+ // 濡傛灉鎸囧畾浜嗕笉闇�瑕佷繚鐣欏皬鏁帮紝鍒欑洿鎺ヨ浆鎹负鏁存暟
+ sums[index] = Math.round(sum).toString();
+ } else {
+ // 榛樿淇濈暀涓や綅灏忔暟
+ sums[index] = parseFloat(sum).toFixed(
+ specialFormat[prop]?.decimalPlaces ?? 2
+ );
+ }
+ } else {
+ sums[index] = "";
+ }
+ } else {
+ sums[index] = "";
+ }
+ });
+ return sums;
+};
+// 涓嶅惈绋庢�讳环璁$畻
+const calculateTaxExclusiveTotalPrice = (taxInclusiveTotalPrice, taxRate) => {
+ const taxRateDecimal = taxRate / 100;
+ return (taxInclusiveTotalPrice / (1 + taxRateDecimal)).toFixed(2);
+};
+// 鍚◣鎬讳环璁$畻
+const calculateTaxIncludeTotalPrice = (taxInclusiveUnitPrice, quantity) => {
+ return (taxInclusiveUnitPrice * quantity).toFixed(2);
+};
+// 瀵煎嚭鍑芥暟渚涘叾浠栨枃浠朵娇鐢�
+export {
+ summarizeTable,
+ calculateTaxExclusiveTotalPrice,
+ calculateTaxIncludeTotalPrice,
+};
--
Gitblit v1.9.3