From 025e46e11cb2962fd7692adfa401333758cc779b Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 02 九月 2025 14:00:34 +0800
Subject: [PATCH] 修改组件

---
 src/pages/procurementManagement/procurementLedger/detail.vue |  917 +++++++++++++++++++++++++++++----------------------------
 1 files changed, 465 insertions(+), 452 deletions(-)

diff --git a/src/pages/procurementManagement/procurementLedger/detail.vue b/src/pages/procurementManagement/procurementLedger/detail.vue
index 52aa35c..995cf3d 100644
--- a/src/pages/procurementManagement/procurementLedger/detail.vue
+++ b/src/pages/procurementManagement/procurementLedger/detail.vue
@@ -4,258 +4,345 @@
 		<PageHeader title="鍙拌处璇︽儏" @back="goBack" />
 
          <!-- 琛ㄥ崟鍖哄煙 -->
-		<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="purchaseContractNumber" borderBottom="true" v-model="form.purchaseContractNumber" placeholder="鑷姩鐢熸垚" :rules="[{ required: true, message: '璇疯緭鍏�' }]">
-			</van-field>
-			<van-field
-				v-model="form.salesContractNo"
-				is-link
-				readonly
-				name="salesContractNo"
-				label="閿�鍞悎鍚屽彿"
-				required
-				placeholder="鐐瑰嚮閫夋嫨閿�鍞悎鍚屽彿"
-				:rules="[{ required: true, message: '璇烽�夋嫨閿�鍞悎鍚屽彿' }]"
-				@click="showPicker = true"
-			/>
-			<van-field
-				v-model="form.supplierName"
-				is-link
-				readonly
-				required
-				name="supplierName"
-				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 label="浠樻鏂瑰紡" name="paymentMethod" borderBottom="true" v-model="form.paymentMethod" placeholder="璇疯緭鍏ヤ粯娆炬柟寮�">
-			</van-field>
-			<van-field label="褰曞叆浜�" name="recorderName" borderBottom="true" v-model="form.recorderName" placeholder="璇疯緭鍏�" disabled>
-			</van-field>
-			<van-field label="褰曞叆鏃ユ湡" name="entryDate" borderBottom="true" v-model="form.entryDate" placeholder="璇疯緭鍏�" disabled>
-			</van-field>
-			<van-popup v-model:show="showPicker" destroy-on-close position="bottom">
-				<van-picker
-					:columns="salesContractList"
-					v-model="pickerValue"
-					@confirm="onConfirm"
-					@cancel="showPicker = false"
+		<up-form @submit="onSubmit" label-width="110" ref="formRef" :rules="rules" :model="form">
+				<up-form-item label="閲囪喘鍚堝悓鍙�" prop="purchaseContractNumber">
+					<up-input v-model="form.purchaseContractNumber" placeholder="鑷姩鐢熸垚" disabled />
+				</up-form-item>
+				<up-form-item
+					label="閿�鍞悎鍚屽彿"
+					prop="salesContractNo"
+					required
+					@click="showPicker = true"
+				>
+					<up-input
+						v-model="form.salesContractNo"
+						readonly=""
+						@click="showPicker = true"
+						placeholder="鐐瑰嚮閫夋嫨閿�鍞悎鍚屽彿"
+					/>
+					<template #right>
+						<up-icon
+							name="arrow-right"
+							@click="showPicker = true"
+						></up-icon>
+					</template>
+				</up-form-item>
+				<up-form-item
+					label="渚涘簲鍟嗗悕绉�"
+					prop="supplierName"
+					required
+					@click="showCustomerPicker = true"
+				>
+					<up-input
+						v-model="form.supplierName"
+						readonly=""
+						@click="showCustomerPicker = true"
+						placeholder="鐐瑰嚮閫夋嫨渚涘簲鍟�"
+					/>
+					<template #right>
+						<up-icon
+							name="arrow-right"
+							@click="showCustomerPicker = true"
+						></up-icon>
+					</template>
+				</up-form-item>
+				<up-form-item label="椤圭洰鍚嶇О" prop="projectName" required >
+					<up-input
+						v-model="form.projectName"
+						placeholder="璇疯緭鍏ラ」鐩悕绉�"
+					/>
+				</up-form-item>
+				<up-form-item label="浠樻鏂瑰紡" prop="paymentMethod" >
+					<up-input v-model="form.paymentMethod" placeholder="璇疯緭鍏ヤ粯娆炬柟寮�" />
+				</up-form-item>
+				<up-form-item label="褰曞叆浜�" prop="recorderName" >
+					<up-input v-model="form.recorderName" placeholder="璇疯緭鍏�" disabled />
+				</up-form-item>
+				<up-form-item label="褰曞叆鏃ユ湡" prop="entryDate" >
+					<up-input v-model="form.entryDate" placeholder="璇疯緭鍏�" disabled />
+				</up-form-item>
+				
+				<!-- 閿�鍞悎鍚屽彿閫夋嫨 -->
+				<up-action-sheet
+					:show="showPicker"
+					:actions="salesContractActionList"
+					title="閫夋嫨閿�鍞悎鍚屽彿"
+					@select="onSalesmanSelect"
+					@close="showPicker = false"
 				/>
-			</van-popup>
-			<van-popup v-model:show="showCustomerPicker" destroy-on-close position="bottom">
-				<van-picker
-					:columns="supplierList"
-					v-model="pickerCustomerValue"
-					@confirm="onCustomerConfirm"
-					@cancel="showCustomerPicker = false"
+				
+				<!-- 渚涘簲鍟嗛�夋嫨 -->
+				<up-action-sheet 
+					:show="showCustomerPicker"
+					:actions="supplierActionList"
+					title="閫夋嫨渚涘簲鍟�"
+					@select="onCustomerSelect"
+					@close="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"
+				
+				<!-- 浜у搧澶х被閫夋嫨鍣� -->
+				<up-popup :show="showCategoryPicker" mode="bottom">
+					<!-- 澶撮儴鎸夐挳鍖哄煙 -->
+					<view class="popup-header">
+						<view @click="showCategoryPicker = false" class="cancelButton">鍙栨秷</view>
+						<view @click="confirmCategorySelection" class="confirmButton">纭畾</view>
+					</view>
+					<u-tree
+						:data="productOptions"
+						:props="defaultProps"
+						show-checkbox
+						default-expand-all
+						check-strictly
+						@check-change="onCategoryConfirm"
+					/>
+				</up-popup>
+				
+				<!-- 瑙勬牸鍨嬪彿閫夋嫨鍣� -->
+				<up-action-sheet
+					:show="showSpecificationPicker"
+					:actions="specificationActionList"
+					title="閫夋嫨瑙勬牸鍨嬪彿"
+					@select="onSpecificationSelect"
+					@close="showSpecificationPicker = false"
 				/>
-			</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"
+				
+				<!-- 绋庣巼閫夋嫨鍣� -->
+				<up-action-sheet
+					:show="showTaxRatePicker"
+					:actions="taxRateActionList"
+					title="閫夋嫨绋庣巼"
+					@select="onTaxRateSelect"
+					@close="showTaxRatePicker = 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"
+				
+				<!-- 鍙戠エ绫诲瀷閫夋嫨鍣� -->
+				<up-action-sheet
+					:show="showInvoiceTypePicker"
+					:actions="invoiceTypeActionList"
+					title="閫夋嫨鍙戠エ绫诲瀷"
+					@select="onInvoiceTypeSelect"
+					@close="showInvoiceTypePicker = 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"  v-if="operationType !== 'view'">鏂板</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 class="product-section">
+					<view class="section-header">
+						<view>
+						<text class="section-title">浜у搧淇℃伅</text>
 						</view>
-						<!-- 鎿嶄綔鎸夐挳 -->
-						<view class="product-actions"  v-if="operationType !== 'view'">
-							<van-button type="danger" size="mini" @click="removeProduct(idx)" class="del-btn" icon="delete">鍒犻櫎</van-button>
+						<view>
+							<up-button type="primary" size="small" @click="addProduct" class="add-btn" v-if="operationType !== 'view'">
+							鏂板
+						</up-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)"
-						/>
+					<view class="product-card" v-for="(product, idx) in productData" :key="idx">
+						<!-- 浜у搧绫� -->
+						<view class="product-header">
+							<view class="product-title">
+								<up-icon name="file-text" size="16" color="#2979ff"></up-icon>
+								<text class="product-productCategory">浜у搧 {{ idx + 1 }}</text>
+							</view>
+							<!-- 鎿嶄綔鎸夐挳 -->
+							<view class="product-actions" v-if="operationType !== 'view'">
+								<up-button type="error" size="mini" @click="removeProduct(idx)" class="del-btn">
+									鍒犻櫎
+								</up-button>
+							</view>
+						</view>
 						
-						<!-- 瑙勬牸鍨嬪彿 -->
-						<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 class="product-form">
+							<!-- 浜у搧澶х被 -->
+							<up-form-item
+								label="浜у搧澶х被"
+								prop="productCategory"
+								required
+								:rules="productRules"
+							>
+								<up-input
+									v-model="product.productCategory"
+									readonly
+									placeholder="璇烽�夋嫨"
+									@click="openCategoryPicker(idx)"
+								/>
+								<template #right>
+									<up-icon
+										name="arrow-right"
+										@click="showCategoryPicker = true"
+									></up-icon>
+								</template>
+							</up-form-item>
+							
+							<!-- 瑙勬牸鍨嬪彿 -->
+							<up-form-item
+								label="瑙勬牸鍨嬪彿"
+								prop="specificationModel"
+								required
+								:rules="productRules"
+							>
+								<up-input
+									v-model="product.specificationModel"
+									readonly
+									placeholder="璇烽�夋嫨"
+									@click="openSpecificationPicker(idx)"
+								/>
+								<template #right>
+									<up-icon
+										name="arrow-right"
+										@click="showSpecificationPicker = true"
+									></up-icon>
+								</template>
+							</up-form-item>
+							
+							<!-- 鍗曚綅 -->
+							<up-form-item
+								label="鍗曚綅"
+								prop="unit"
+								required
+								:rules="productRules"
+							>
+								<up-input
+									v-model="product.unit"
+									placeholder="璇疯緭鍏�"
+								/>
+							</up-form-item>
+							
+							<!-- 绋庣巼 -->
+							<up-form-item
+								label="绋庣巼(%)"
+								prop="taxRate"
+								required
+								:rules="productRules"
+							>
+								<up-input
+									v-model="product.taxRate"
+									readonly
+									placeholder="璇烽�夋嫨"
+									@click="openTaxRatePicker(idx)"
+								/>
+								<template #right>
+									<up-icon
+										name="arrow-right"
+										@click="showTaxRatePicker = true"
+									></up-icon>
+								</template>
+							</up-form-item>
+							
+							<!-- 鍚◣鍗曚环 -->
+							<up-form-item
+								label="鍚◣鍗曚环(鍏�)"
+								prop="taxInclusiveUnitPrice"
+								required
+								:rules="productRules"
+							>
+								<up-input
+									v-model="product.taxInclusiveUnitPrice"
+									type="number"
+									placeholder="璇疯緭鍏�"
+									@blur="formatTaxPrice(idx)"
+								/>
+							</up-form-item>
+							
+							<!-- 鏁伴噺 -->
+							<up-form-item
+								label="鏁伴噺"
+								prop="quantity"
+								required
+								:rules="productRules"
+							>
+								<up-input
+									v-model="product.quantity"
+									type="number"
+									placeholder="璇疯緭鍏�"
+									@blur="formatAmount(idx)"
+								/>
+							</up-form-item>
+							
+							<!-- 鍚◣鎬讳环 -->
+							<up-form-item
+								label="鍚◣鎬讳环(鍏�)"
+								prop="taxInclusiveTotalPrice"
+								required
+								:rules="productRules"
+							>
+								<up-input
+									v-model="product.taxInclusiveTotalPrice"
+									type="number"
+									placeholder="璇疯緭鍏�"
+									@blur="formatTaxTotal(idx)"
+								/>
+							</up-form-item>
+							
+							<!-- 涓嶅惈绋庢�讳环 -->
+							<up-form-item
+								label="涓嶅惈绋庢�讳环(鍏�)"
+								prop="taxExclusiveTotalPrice"
+								required
+								:rules="productRules"
+							>
+								<up-input
+									v-model="product.taxExclusiveTotalPrice"
+									type="number"
+									placeholder="璇疯緭鍏�"
+									@blur="formatNoTaxTotal(idx)"
+								/>
+							</up-form-item>
+							
+							<!-- 鍙戠エ绫诲瀷 -->
+							<up-form-item
+								label="鍙戠エ绫诲瀷"
+								prop="invoiceType"
+								required
+								:rules="productRules"
+							>
+								<up-input
+									v-model="product.invoiceType"
+									readonly
+									placeholder="璇烽�夋嫨"
+									@click="openInvoiceTypePicker(idx)"
+								/>
+								<template #right>
+									<up-icon
+										name="arrow-right"
+										@click="showInvoiceTypePicker = true"
+									></up-icon>
+								</template>
+							</up-form-item>
+						</view>
 					</view>
 				</view>
-			</view>
-			<view class="footer-btns" v-if="operationType !== 'view'">
-				<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>
+				
+				<!-- 浣跨敤鍏叡搴曢儴鎸夐挳缁勪欢 -->
+				<FooterButtons
+					:show="operationType !== 'view'"
+					cancelText="鍙栨秷"
+					confirmText="淇濆瓨"
+					@cancel="goBack"
+					@confirm="onSubmit"
+				/>
+		</up-form>
   </view>
 </template>
 
 <script setup>
-import {onMounted, ref} from 'vue';
+import {onMounted, ref, computed} from 'vue';
 import { modelList, productTreeList } from "@/api/basicData/product.js";
 import useUserStore from "@/store/modules/user";
 import {calculateTaxExclusiveTotalPrice} from "@/utils/summarizeTable";
+import {formatDateToYMD} from '@/utils/ruoyi'
 import {
 	addOrEditPurchase, createPurchaseNo,
 	getOptions,
 	getPurchaseById,
 	getSalesNo
 } from "@/api/procurementManagement/procurementLedger";
+import PageHeader from '@/components/PageHeader.vue';
+import FooterButtons from '@/components/FooterButtons.vue';
 
 // 鑾峰彇椤甸潰鍙傛暟
 const operationType = ref('');
 const editData = ref(null);
+const formRef = ref(null);
 
 const userStore = useUserStore()
 const form = ref({
@@ -270,23 +357,33 @@
 	recorderName: '',
 	entryDate: '',
 });
-const pickerValue = ref(['']);
-const pickerDateValue = ref([]);
 const showPicker = ref(false);
-const pickerCustomerValue = ref(['']);
 const showCustomerPicker = ref(false);
 const salesContractList = ref([]);
 const supplierList = ref([]);
 const productData = ref([]);
+
+// 璁$畻閿�鍞悎鍚屽彿閫夋嫨鍒楄〃
+const salesContractActionList = computed(() => {
+	return salesContractList.value.map(item => ({
+		name: item.text,
+		value: item.value
+	}))
+})
+
+// 璁$畻渚涘簲鍟嗛�夋嫨鍒楄〃
+const supplierActionList = computed(() => {
+	return supplierList.value.map(item => ({
+		name: item.text,
+		value: item.value
+	}))
+})
 
 // 閫夋嫨鍣ㄧ浉鍏冲彉閲�
 const showCategoryPicker = ref(false);
 const showSpecificationPicker = ref(false);
 const showTaxRatePicker = ref(false);
 const showInvoiceTypePicker = ref(false);
-const pickerSpecificationValue = ref(['']);
-const pickerTaxRateValue = ref(['']);
-const pickerInvoiceTypeValue = ref(['']);
 const currentProductIndex = ref(0);
 
 // 閫夐」鏁版嵁
@@ -299,7 +396,6 @@
 });
 
 const modelOptions = ref([]);
-// 闃叉寰幆璁$畻鐨勬爣蹇�
 const taxRateOptions = ref([
   { text: '1', value: '1' },
   { text: '6', value: '6' },
@@ -310,6 +406,79 @@
   { text: '澧炴櫘绁�', value: '澧炴櫘绁�' },
   { text: '澧炰笓绁�', value: '澧炰笓绁�' },
 ]);
+
+// 璁$畻瑙勬牸鍨嬪彿閫夋嫨鍒楄〃
+const specificationActionList = computed(() => {
+	return modelOptions.value.map(model => ({
+		name: model.text,
+		value: model.value,
+		unit: model.unit
+	}))
+})
+
+// 璁$畻绋庣巼閫夋嫨鍒楄〃
+const taxRateActionList = computed(() => {
+	return taxRateOptions.value.map(rate => ({
+		name: rate.text,
+		value: rate.value
+	}))
+})
+
+// 璁$畻鍙戠エ绫诲瀷閫夋嫨鍒楄〃
+const invoiceTypeActionList = computed(() => {
+	return invoiceTypeOptions.value.map(type => ({
+		name: type.text,
+		value: type.value
+	}))
+})
+
+// 琛ㄥ崟鏍¢獙瑙勫垯
+const rules = {
+	salesContractNo: [
+		{ required: true, message: '璇烽�夋嫨閿�鍞悎鍚屽彿', trigger: 'blur' }
+	],
+	supplierName: [
+		{ required: true, message: '璇烽�夋嫨渚涘簲鍟嗗悕绉�', trigger: 'blur' }
+	],
+	projectName: [
+		{ required: true, message: '璇疯緭鍏ラ」鐩悕绉�', trigger: 'blur' }
+	]
+};
+
+// 浜у搧淇℃伅鏍¢獙瑙勫垯
+const productRules = {
+	productCategory: [
+		{ required: true, message: '璇烽�夋嫨浜у搧澶х被', trigger: 'blur' }
+	],
+	specificationModel: [
+		{ required: true, message: '璇烽�夋嫨瑙勬牸鍨嬪彿', trigger: 'blur' }
+	],
+	unit: [
+		{ required: true, message: '璇疯緭鍏ュ崟浣�', trigger: 'blur' }
+	],
+	taxRate: [
+		{ required: true, message: '璇烽�夋嫨绋庣巼', trigger: 'blur' }
+	],
+	taxInclusiveUnitPrice: [
+		{ required: true, message: '璇疯緭鍏ュ惈绋庡崟浠�', trigger: 'blur' },
+		{ type: 'number', min: 0, message: '鍚◣鍗曚环蹇呴』澶т簬0', trigger: 'blur' }
+	],
+	quantity: [
+		{ required: true, message: '璇疯緭鍏ユ暟閲�', trigger: 'blur' },
+		{ type: 'number', min: 0, message: '鏁伴噺蹇呴』澶т簬0', trigger: 'blur' }
+	],
+	taxInclusiveTotalPrice: [
+		{ required: true, message: '璇疯緭鍏ュ惈绋庢�讳环', trigger: 'blur' },
+		{ type: 'number', min: 0, message: '鍚◣鎬讳环蹇呴』澶т簬0', trigger: 'blur' }
+	],
+	taxExclusiveTotalPrice: [
+		{ required: true, message: '璇疯緭鍏ヤ笉鍚◣鎬讳环', trigger: 'blur' },
+		{ type: 'number', min: 0, message: '涓嶅惈绋庢�讳环蹇呴』澶т簬0', trigger: 'blur' }
+	],
+	invoiceType: [
+		{ required: true, message: '璇烽�夋嫨鍙戠エ绫诲瀷', trigger: 'blur' }
+	]
+};
 
 const addProduct = () => {
 	if (productData.value === null) {
@@ -328,18 +497,29 @@
     invoiceType: ''
   });
 };
-const onConfirm = ({ selectedValues, selectedOptions }) => {
-	form.value.salesContractNo = selectedOptions[0]?.text;
-	form.value.salesLedgerId = selectedOptions[0]?.value;
-	pickerValue.value = [selectedValues[0]];
+
+// 閿�鍞悎鍚屽彿閫夋嫨浜嬩欢
+const onSalesmanSelect = (item) => {
+	form.value.salesContractNo = item.name
+	// 鏌ユ壘瀵瑰簲鐨刬d
+	const selectedItem = salesContractList.value.find(contract => contract.text === item.name);
+	if (selectedItem) {
+		form.value.salesLedgerId = selectedItem.value;
+	}
 	showPicker.value = false;
-};
-const onCustomerConfirm = ({ selectedValues, selectedOptions }) => {
-	form.value.supplierName = selectedOptions[0]?.text;
-	form.value.supplierId = selectedOptions[0]?.value;
-	pickerCustomerValue.value = [selectedValues[0]];
+}
+
+// 渚涘簲鍟嗛�夋嫨浜嬩欢
+const onCustomerSelect = (item) => {
+	form.value.supplierName = item.name
+	// 鏌ユ壘瀵瑰簲鐨刬d
+	const selectedItem = supplierList.value.find(supplier => supplier.text === item.name);
+	if (selectedItem) {
+		form.value.supplierId = selectedItem.value;
+	}
 	showCustomerPicker.value = false;
-};
+}
+
 const removeProduct = (idx) => {
 	productData.value.splice(idx, 1);
 };
@@ -383,11 +563,11 @@
 		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) => {
@@ -398,39 +578,32 @@
 		}));
 	});
 };
-// 閫夋嫨瑙勬牸鍨嬪彿
-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 onSpecificationSelect = (item) => {
+	productData.value[currentProductIndex.value].specificationModel = item.name
+	productData.value[currentProductIndex.value].productModelId = item.value
+	productData.value[currentProductIndex.value].unit = item.unit
+	showSpecificationPicker.value = false;
 };
 
-const onInvoiceTypeConfirm = ({ selectedValues, selectedOptions }) => {
-	productData.value[currentProductIndex.value].invoiceType = selectedOptions[0]?.text;
-  pickerInvoiceTypeValue.value = [selectedValues[0]];
-  showInvoiceTypePicker.value = false;
+// 绋庣巼閫夋嫨浜嬩欢
+const onTaxRateSelect = (item) => {
+	productData.value[currentProductIndex.value].taxRate = item.value
+	showTaxRatePicker.value = false;
+	// 閲嶆柊璁$畻涓嶅惈绋庢�讳环
+	const inclusiveTotalPrice = parseFloat(productData.value[currentProductIndex.value].taxInclusiveTotalPrice)
+	const taxRate = parseFloat(item.value)
+	if (inclusiveTotalPrice && taxRate) {
+		productData.value[currentProductIndex.value].taxExclusiveTotalPrice = 
+			calculateTaxExclusiveTotalPrice(inclusiveTotalPrice, taxRate)
+	}
+};
+
+// 鍙戠エ绫诲瀷閫夋嫨浜嬩欢
+const onInvoiceTypeSelect = (item) => {
+	productData.value[currentProductIndex.value].invoiceType = item.name
+	showInvoiceTypePicker.value = false;
 };
 
 // 鏍煎紡鍖栧嚱鏁� - 鍥哄畾涓や綅灏忔暟
@@ -459,13 +632,14 @@
 	
 	// 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
 	if (productData.value[currentProductIndex.value].taxRate) {
-		productData.value[currentProductIndex.value].taxExclusiveTotalPrice =
+		productData.value[currentProductIndex.value].taxExclusiveTotalPrice = 
 			calculateTaxExclusiveTotalPrice(
 				productData.value[currentProductIndex.value].taxInclusiveTotalPrice,
 				productData.value[currentProductIndex.value].taxRate
 			);
 	}
 };
+
 // 鏁伴噺杈撳叆妗嗗け鐒�
 const formatAmount = (idx) => {
   if (productData.value[idx].quantity) {
@@ -491,13 +665,14 @@
 	productData.value[currentProductIndex.value].taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
 	// 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
 	if (productData.value[currentProductIndex.value].taxRate) {
-		productData.value[currentProductIndex.value].taxExclusiveTotalPrice =
+		productData.value[currentProductIndex.value].taxExclusiveTotalPrice = 
 			calculateTaxExclusiveTotalPrice(
 				productData.value[currentProductIndex.value].taxInclusiveTotalPrice,
 				productData.value[currentProductIndex.value].taxRate
 			);
 	}
 };
+
 // 鍚◣鎬讳环澶辩劍锛屾牴鎹惈绋庢�讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
 const formatTaxTotal = (idx) => {
   if (productData.value[idx].taxInclusiveTotalPrice) {
@@ -516,13 +691,14 @@
 	productData.value[currentProductIndex.value].taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(2);
 	// 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
 	if (productData.value[currentProductIndex.value].taxRate) {
-		productData.value[currentProductIndex.value].taxExclusiveTotalPrice =
+		productData.value[currentProductIndex.value].taxExclusiveTotalPrice = 
 			calculateTaxExclusiveTotalPrice(
 				totalPrice,
 				productData.value[currentProductIndex.value].taxRate
 			);
 	}
 };
+
 // 涓嶅惈绋庢�讳环澶辩劍, 鏍规嵁涓嶅惈绋庢�讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
 const formatNoTaxTotal = (idx) => {
   if (productData.value[idx].taxExclusiveTotalPrice) {
@@ -551,12 +727,14 @@
 	// 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
 	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));
@@ -576,6 +754,7 @@
 		goBack();
 	});
 };
+
 const setUserInfo = () => {
 	form.value.recorderId = userStore.id;
 	form.value.recorderName = userStore.nickName;
@@ -585,8 +764,8 @@
 	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;
@@ -598,7 +777,6 @@
   form.value.salesContractNo = editData.value.salesContractNo || '';
   form.value.supplierName = editData.value.supplierName || '';
   form.value.projectName = editData.value.projectName || '';
-  form.value.executionDate = editData.value.executionDate || '';
   form.value.paymentMethod = editData.value.paymentMethod || '';
   form.value.salesLedgerId = editData.value.salesLedgerId || '';
   form.value.recorderId = editData.value.recorderId || '';
@@ -606,29 +784,8 @@
   form.value.entryDate = editData.value.entryDate || '';
   form.value.id = editData.value.id || '';
   form.value.supplierId = editData.value.supplierId || '';
-	
-  // 璁剧疆閿�鍞悎鍚屽彿閫夋嫨鍣ㄧ殑鍊�
-  if (editData.value.salesContractNo) {
-    const salesmanIndex = salesContractList.value.findIndex(user => user.text === editData.value.salesContractNo);
-    if (salesmanIndex !== -1) {
-      pickerValue.value = [salesContractList.value[salesmanIndex].value];
-    }
-  }
-  
-  // 璁剧疆渚涘簲鍟嗛�夋嫨鍣ㄧ殑鍊�
-  if (editData.value.supplierName) {
-    const customerIndex = supplierList.value.findIndex(customer => customer.text === editData.value.supplierName);
-    if (customerIndex !== -1) {
-      pickerCustomerValue.value = [supplierList.value[customerIndex].value]
-    }
-  }
-  
-  // 璁剧疆鏃ユ湡閫夋嫨鍣ㄧ殑鍊�
-  if (editData.value.executionDate) {
-		pickerDateValue.value = editData.value.executionDate.split('-').map(num => parseInt(num, 10))
-		console.log(pickerDateValue.value)
-	}
 };
+
 const getSalesNoList = () => {
 	getSalesNo().then((res) => {
 		// 灏嗙敤鎴锋暟鎹粍瑁呮垚 picker 闇�瑕佺殑鏍煎紡
@@ -637,7 +794,8 @@
 			value: user.id
 		}));
 	})
-}
+};
+
 const getOptionsLIst = () => {
 	getOptions().then((res) => {
 		// 灏嗙敤鎴锋暟鎹粍瑁呮垚 picker 闇�瑕佺殑鏍煎紡
@@ -646,7 +804,8 @@
 			value: item.id
 		}));
 	})
-}
+};
+
 const convertIdToValue = (data) => {
 	// 濡傛灉浼犲叆鐨勪笉鏄暟缁勶紝鍒欒繑鍥炵┖鏁扮粍
 	if (!Array.isArray(data)) {
@@ -666,12 +825,14 @@
 		return mappedItem;
 	});
 };
+
 // 鑾峰彇浜у搧澶х被tree鏁版嵁
 const getProductOptions = () => {
 	productTreeList().then((res) => {
 		productOptions.value = convertIdToValue(res);
 	});
 };
+
 onMounted(() => {
 	// 鑾峰彇椤甸潰鍙傛暟
 	operationType.value = uni.getStorageSync('operationType') || '';
@@ -710,153 +871,5 @@
 </script>
 
 <style scoped lang="scss">
-.account-detail {
-  min-height: 100vh;
-  background: #f8f9fa;
-  padding-bottom: 5rem;
-}
-.header {
-  display: flex;
-  align-items: center;
-  background: #fff;
-  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: 1.125rem;
-  font-weight: 600;
-  color: #333;
-}
-.form-section {
-	margin-top: 1rem;
-}
-.van-field {
-	height: 3.4rem;
-}
-.van-cell {
-	align-items: center;
-}
-.product-section {
-  background: #fff;
-	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: 1rem;
-}
-.section-title {
-  font-size: 1rem;
-  font-weight: 600;
-  color: #333;
-}
-.product-card {
-	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-header {
-  display: flex;
-  align-items: center;
-	justify-content: space-between;
-  padding: 0 0.5rem 0.75rem 0.5rem;
-  border-bottom: 0.0625rem solid #e8e8e8;
-}
-.product-productCategory {
-  margin-left: 0.5rem;
-  font-size: 0.875rem;
-  font-weight: 500;
-  color: #333;
-}
-.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;
-}
-.footer-btns {
-  position: fixed;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  background: #fff;
-  display: flex;
-  justify-content: space-around;
-  align-items: center;
-  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: 1rem;
-	color: #FFFFFF;
-	width: 6.375rem;
-	background: #C7C9CC;
-	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: 1rem;
-	color: #FFFFFF;
-	width: 14rem;
-	background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%);
-	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;
-}
+@import '@/static/scss/form-common.scss';
 </style>

--
Gitblit v1.9.3