From ee6bc0af77ef179dda201c96c4cbc05817643d77 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期二, 19 八月 2025 09:13:12 +0800
Subject: [PATCH] Merge branch 'dev' of http://114.132.189.42:9002/r/product-inventory-APP-before into dev

---
 src/pages/index.vue                     |    4 
 src/api/salesManagement/salesLedger.js  |   16 
 src/api/system/user.js                  |    7 
 src/pages.json                          |    7 
 src/pages/sales/salesAccount/view.vue   |  311 ++++++++++++
 src/pages/sales/salesAccount/detail.vue |  987 ++++++++++++++++++++++++++++++++-------
 src/main.js                             |    4 
 src/config.js                           |    5 
 src/pages/sales/salesAccount/index.vue  |   86 ++-
 src/utils/summarizeTable.js             |   57 ++
 10 files changed, 1,267 insertions(+), 217 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..65baaa4 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.json b/src/pages.json
index 2427323..928af20 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -59,6 +59,13 @@
     {
       "path": "pages/sales/salesAccount/detail",
       "style": {
+        "navigationBarTitleText": "淇敼鍙拌处",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/sales/salesAccount/view",
+      "style": {
         "navigationBarTitleText": "鍙拌处璇︽儏",
         "navigationStyle": "custom"
       }
diff --git a/src/pages/index.vue b/src/pages/index.vue
index 1e51897..ff3036b 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">
@@ -598,7 +598,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..d5b2522 100644
--- a/src/pages/sales/salesAccount/detail.vue
+++ b/src/pages/sales/salesAccount/detail.vue
@@ -6,244 +6,845 @@
       <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="璇疯緭鍏�" 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="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"  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>
+						<!-- 鎿嶄綔鎸夐挳 -->
+						<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>
+					</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" 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>
   </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: '',
+	if (productData.value === null) {
+		productData.value = []
+	}
+	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'
+		});
+		return
+	}
+	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 !== 'add' && 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 +855,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..336e593 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,15 +92,18 @@
 		</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";
+import useUserStore from "@/store/modules/user";
+const userStore = useUserStore()
 
 // 鎼滅储鍏抽敭璇�
 const searchKeyword = ref('');
@@ -126,34 +129,59 @@
 			// tableLoading.value = false;
 	});
 };
-// 鏄剧ず绛涢�夐�夐」
-const showFilterOptions = () => {
-	uni.showActionSheet({
-		itemList: ['鎸夋棩鏈熺瓫閫�', '鎸夌姸鎬佺瓫閫�', '鎸夐噾棰濈瓫閫�'],
-		success: (res) => {
-			console.log('閫夋嫨浜嗙瓫閫夐�夐」:', res.tapIndex);
-		}
-	});
+
+// 澶勭悊鍙拌处淇℃伅鎿嶄綔锛堟煡鐪�/缂栬緫/鏂板锛�
+const handleInfo = (type, row) => {
+  try {
+    // 璁剧疆鎿嶄綔绫诲瀷
+    uni.setStorageSync('operationType', type);
+    
+    // 濡傛灉鏄煡鐪嬫垨缂栬緫鎿嶄綔
+    if (type !== 'add') {
+      // 楠岃瘉琛屾暟鎹槸鍚﹀瓨鍦�
+      if (!row) {
+        uni.showToast({
+          title: '鏁版嵁涓嶅瓨鍦�',
+          icon: 'error'
+        });
+        return;
+      }
+      
+      // 妫�鏌ユ潈闄愶細鍙湁褰曞叆浜烘墠鑳界紪杈�
+      if (row.entryPerson !== userStore.id) {
+        // 闈炲綍鍏ヤ汉璺宠浆鍒板彧璇昏鎯呴〉闈�
+        uni.setStorageSync('editData', JSON.stringify(row));
+        uni.navigateTo({
+          url: '/pages/sales/salesAccount/view'
+        });
+        return;
+      }
+      
+      // 褰曞叆浜虹紪杈戯細瀛樺偍鏁版嵁骞惰烦杞埌缂栬緫椤甸潰
+      uni.setStorageSync('editData', JSON.stringify(row));
+      uni.navigateTo({
+        url: '/pages/sales/salesAccount/detail'
+      });
+      return;
+    }
+    
+    // 鏂板鎿嶄綔锛氱洿鎺ヨ烦杞埌缂栬緫椤甸潰
+    uni.navigateTo({
+      url: '/pages/sales/salesAccount/detail'
+    });
+    
+  } catch (error) {
+    console.error('澶勭悊鍙拌处淇℃伅鎿嶄綔澶辫触:', error);
+    uni.showToast({
+      title: '鎿嶄綔澶辫触锛岃閲嶈瘯',
+      icon: 'error'
+    });
+  }
 };
 
-// 鐐瑰嚮鍒楄〃椤�
-const handleItemClick = (item) => {
-	uni.showToast({
-		title: `鏌ョ湅鍚堝悓: ${item.contractId}`,
-		icon: 'none'
-	});
-};
-
-// 娣诲姞鏂拌褰�
-const handleAdd = () => {
-  uni.navigateTo({
-    url: '/pages/sales/salesAccount/detail'
-  });
-};
-
-onMounted(() => {
-	// 椤甸潰鍔犺浇瀹屾垚鍚庣殑鍒濆鍖栭�昏緫
-	getList()
+onShow(() => {
+    // 椤甸潰鏄剧ず鏃跺埛鏂板垪琛�
+    getList();
 });
 </script>
 
diff --git a/src/pages/sales/salesAccount/view.vue b/src/pages/sales/salesAccount/view.vue
new file mode 100644
index 0000000..99a76b2
--- /dev/null
+++ b/src/pages/sales/salesAccount/view.vue
@@ -0,0 +1,311 @@
+<template>
+  <view class="account-view">
+    <!-- 椤堕儴鏍囬鏍� -->
+    <view class="header">
+      <up-icon name="arrow-left" size="20" color="#333" @click="goBack" />
+      <text class="title">鍙拌处璇︽儏</text>
+    </view>
+
+    <!-- 鍩烘湰淇℃伅灞曠ず -->
+    <view class="info-section">
+      <view class="section-title">鍩烘湰淇℃伅</view>
+      <view class="info-grid">
+        <view class="info-item">
+          <text class="info-label">閿�鍞悎鍚屽彿</text>
+          <text class="info-value">{{ form.salesContractNo }}</text>
+        </view>
+        <view class="info-item">
+          <text class="info-label">瀹㈡埛鍚堝悓鍙�</text>
+          <text class="info-value highlight">{{ form.customerContractNo }}</text>
+        </view>
+        <view class="info-item">
+          <text class="info-label">瀹㈡埛鍚嶇О</text>
+          <text class="info-value">{{ form.customerName }}</text>
+        </view>
+        <view class="info-item">
+          <text class="info-label">涓氬姟鍛�</text>
+          <text class="info-value">{{ form.salesman }}</text>
+        </view>
+        <view class="info-item">
+          <text class="info-label">椤圭洰鍚嶇О</text>
+          <text class="info-value">{{ form.projectName }}</text>
+        </view>
+        <view class="info-item">
+          <text class="info-label">绛捐鏃ユ湡</text>
+          <text class="info-value">{{ form.executionDate }}</text>
+        </view>
+        <view class="info-item">
+          <text class="info-label">浠樻鏂瑰紡</text>
+          <text class="info-value">{{ form.paymentMethod }}</text>
+        </view>
+        <view class="info-item">
+          <text class="info-label">褰曞叆浜�</text>
+          <text class="info-value">{{ form.entryPersonName }}</text>
+        </view>
+        <view class="info-item">
+          <text class="info-label">褰曞叆鏃ユ湡</text>
+          <text class="info-value">{{ form.entryDate }}</text>
+        </view>
+      </view>
+    </view>
+
+    <!-- 浜у搧淇℃伅灞曠ず -->
+    <view class="product-section" v-if="productData && productData.length > 0">
+      <view class="section-title">浜у搧淇℃伅</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>
+        
+        <view class="product-info">
+          <view class="info-grid">
+            <view class="info-item">
+              <text class="info-label">浜у搧澶х被</text>
+              <text class="info-value">{{ product.productCategory }}</text>
+            </view>
+            <view class="info-item">
+              <text class="info-label">瑙勬牸鍨嬪彿</text>
+              <text class="info-value">{{ product.specificationModel }}</text>
+            </view>
+            <view class="info-item">
+              <text class="info-label">鍗曚綅</text>
+              <text class="info-value">{{ product.unit }}</text>
+            </view>
+            <view class="info-item">
+              <text class="info-label">绋庣巼(%)</text>
+              <text class="info-value">{{ product.taxRate }}</text>
+            </view>
+            <view class="info-item">
+              <text class="info-label">鍚◣鍗曚环(鍏�)</text>
+              <text class="info-value highlight">{{ product.taxInclusiveUnitPrice }}</text>
+            </view>
+            <view class="info-item">
+              <text class="info-label">鏁伴噺</text>
+              <text class="info-value highlight">{{ product.quantity }}</text>
+            </view>
+            <view class="info-item">
+              <text class="info-label">鍚◣鎬讳环(鍏�)</text>
+              <text class="info-value highlight">{{ product.taxInclusiveTotalPrice }}</text>
+            </view>
+            <view class="info-item">
+              <text class="info-label">涓嶅惈绋庢�讳环(鍏�)</text>
+              <text class="info-value highlight">{{ product.taxExclusiveTotalPrice }}</text>
+            </view>
+            <view class="info-item">
+              <text class="info-label">鍙戠エ绫诲瀷</text>
+              <text class="info-value">{{ product.invoiceType }}</text>
+            </view>
+          </view>
+        </view>
+      </view>
+    </view>
+
+    <!-- 鏃犱骇鍝佷俊鎭彁绀� -->
+    <view class="no-product" v-else>
+      <text>鏆傛棤浜у搧淇℃伅</text>
+    </view>
+  </view>
+</template>
+
+<script setup>
+import { onMounted, ref } from 'vue';
+import { getSalesLedgerWithProducts } from "@/api/salesManagement/salesLedger";
+
+// 琛ㄥ崟鏁版嵁
+const form = ref({
+  id: '',
+  salesContractNo: '',
+  customerContractNo: '',
+  customerId: '',
+  customerName: '',
+  projectName: '',
+  executionDate: '',
+  paymentMethod: '',
+  entryPerson: '',
+  entryPersonName: '',
+  entryDate: '',
+  salesman: ''
+});
+
+// 浜у搧鏁版嵁
+const productData = ref([]);
+
+// 缂栬緫鏁版嵁
+const editData = ref(null);
+
+// 杩斿洖涓婁竴椤�
+const goBack = () => {
+  // 娓呯悊鏈湴瀛樺偍鐨勬暟鎹�
+  uni.removeStorageSync('editData');
+  uni.navigateBack();
+};
+
+// 濉厖琛ㄥ崟鏁版嵁
+const fillFormData = () => {
+  if (!editData.value) return;
+  
+  // 鑾峰彇瀹屾暣鐨勪骇鍝佷俊鎭�
+  getSalesLedgerWithProducts({ id: editData.value.id, type: 1 }).then((res) => {
+    productData.value = res.productData || [];
+  });
+  
+  // 濉厖鍩烘湰淇℃伅
+  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 || '';
+};
+
+onMounted(() => {
+  // 鑾峰彇缂栬緫鏁版嵁骞跺~鍏呰〃鍗�
+  const editDataStr = uni.getStorageSync('editData');
+  if (editDataStr) {
+    try {
+      editData.value = JSON.parse(editDataStr);
+      // 浣跨敤 nextTick 纭繚鏁版嵁鍔犺浇瀹屾垚鍚庡啀濉厖
+      setTimeout(() => {
+        fillFormData();
+      }, 100);
+    } catch (error) {
+      console.error('瑙f瀽缂栬緫鏁版嵁澶辫触:', error);
+    }
+  }
+});
+</script>
+
+<style scoped lang="scss">
+.account-view {
+  min-height: 100vh;
+  background: #f8f9fa;
+  padding-bottom: 2rem;
+}
+
+.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;
+}
+
+.info-section {
+  background: #fff;
+  margin: 1rem;
+  padding: 1rem;
+  border-radius: 0.5rem;
+  box-shadow: 0 0.125rem 0.5rem rgba(0,0,0,0.04);
+}
+
+.section-title {
+  font-size: 1rem;
+  font-weight: 600;
+  color: #333;
+  margin-bottom: 1rem;
+  padding-bottom: 1rem;
+  border-bottom: 0.0625rem solid #e8e8e8;
+}
+
+.info-grid {
+  display: grid;
+  grid-template-columns: 1fr 1fr;
+  gap: 0.75rem;
+}
+
+.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-section {
+  background: #fff;
+  margin: 1rem;
+  padding: 1rem;
+  border-radius: 0.5rem;
+  box-shadow: 0 0.125rem 0.5rem rgba(0,0,0,0.04);
+}
+
+.product-card {
+  background: #f8f9fa;
+  border-radius: 0.5rem;
+  padding: 1rem;
+  margin-bottom: 1rem;
+}
+
+.product-card:last-child {
+  margin-bottom: 0;
+}
+
+.product-header {
+  display: flex;
+  align-items: center;
+  padding-bottom: 0.75rem;
+  border-bottom: 0.0625rem solid #e8e8e8;
+  margin-bottom: 1rem;
+}
+
+.product-title {
+  display: flex;
+  align-items: center;
+  gap: 0.5rem;
+}
+
+.product-productCategory {
+  font-size: 0.875rem;
+  font-weight: 500;
+  color: #333;
+}
+
+.product-info .info-grid {
+  grid-template-columns: 1fr 1fr;
+  gap: 0.5rem;
+}
+
+.no-product {
+  text-align: center;
+  padding: 2rem;
+  color: #999;
+  font-size: 0.875rem;
+}
+</style>
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