From bd125eecd57d2f4e559c6170d20157591300fe3d Mon Sep 17 00:00:00 2001
From: p-honggang.li <p-honggang.li@pcitc.com>
Date: 星期四, 04 九月 2025 20:57:44 +0800
Subject: [PATCH] 修改购物车等BUG

---
 src/views/productManage/price/index.vue |  515 ++++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 342 insertions(+), 173 deletions(-)

diff --git a/src/views/productManage/price/index.vue b/src/views/productManage/price/index.vue
index 0cecbf8..6c6701c 100644
--- a/src/views/productManage/price/index.vue
+++ b/src/views/productManage/price/index.vue
@@ -18,15 +18,15 @@
       </template>
 
       <el-descriptions v-if="productDetail" :column="2" border>
-        <el-descriptions-item label="浜у搧鍚嶇О">{{ productDetail.name }}</el-descriptions-item>
-        <el-descriptions-item label="鎻愭姤鍗曚綅">{{ productDetail.submitUnit }}</el-descriptions-item>
-        <el-descriptions-item label="鎻愭姤浜�">{{ productDetail.submitter }}</el-descriptions-item>
-        <el-descriptions-item label="琛屼笟棰嗗煙">{{ productDetail.industry }}</el-descriptions-item>
-        <el-descriptions-item label="鍗曚綅宸ョ▼">{{ productDetail.projectUnit }}</el-descriptions-item>
-        <el-descriptions-item label="浜т笟闃舵">{{ productDetail.industryStage }}</el-descriptions-item>
-        <el-descriptions-item label="浜у搧绫诲瀷">{{ productDetail.productType }}</el-descriptions-item>
+        <el-descriptions-item label="浜у搧鍚嶇О" label-width="10%">{{ productDetail.name }}</el-descriptions-item>
+        <el-descriptions-item label="鎻愭姤鍗曚綅" label-width="10%">{{ productDetail.submissionUnit }}</el-descriptions-item>
+        <el-descriptions-item label="鎻愭姤浜�" label-width="10%">{{ productDetail.createBy }}</el-descriptions-item>
+        <el-descriptions-item label="琛屼笟棰嗗煙" label-width="10%">{{ productDetail.industrialChainName }}</el-descriptions-item>
+        <el-descriptions-item label="鍗曚綅宸ョ▼" label-width="10%">{{ productDetail.importantAreaName }}</el-descriptions-item>
+        <el-descriptions-item label="浜т笟闃舵" label-width="10%">{{ productDetail.businessProcessName }}</el-descriptions-item>
+        <el-descriptions-item label="浜у搧绫诲瀷"label-width="10%">{{ productDetail.typeName }}</el-descriptions-item>
         <el-descriptions-item label="浜у搧绠�浠�" :span="3">
-          <div class="intro">{{ productDetail.description }}</div>
+          <div class="intro">{{ productDetail.describe }}</div>
         </el-descriptions-item>
       </el-descriptions>
       <el-empty v-else description="鏈壘鍒拌浜у搧鐨勮鎯�" />
@@ -43,9 +43,15 @@
           </div>
         </template>
         <div class="pricing-cards-container" v-if="priceList.length > 0">
+          <div
+            v-for="group in priceList"
+            :key="group.suiteName"
+            class="pricing-group"
+          >
+            <div class="group-header">{{ group.suiteName }}</div>
           <div class="pricing-cards-wrapper">
             <div
-              v-for="pricing in priceList"
+                v-for="pricing in group.items"
               :key="pricing.id"
               class="pricing-card"
               :class="{
@@ -71,19 +77,19 @@
                   <div class="pricing-cell value-cell purchase-methods-cell">
                     <div class="method-item">
                       <span class="method-label">绉垎:</span>
-                      <span class="method-value points">{{ pricing.priceSettings?.includes('POINTS') ? (pricing.pointsAmount || '-') + '/濂�' : '-' }}</span>
+                      <span class="method-value points">{{ pricing.priceSettings?.includes('POINTS') ? (pricing.pointsPrice || '-') + '/' + getPriceUnitText(pricing.priceUnit) : '-' }}</span>
                     </div>
-                    <div class="method-item">
+                    <div class="method-item" v-if="pricing.priceSettings?.includes('CURRENCY')">
                       <span class="method-label">璐у竵:</span>
-                      <span class="method-value currency">{{ pricing.priceSettings?.includes('CURRENCY') ? (pricing.currencyAmount || '-') + '/濂�' : '-' }}</span>
+                      <span class="method-value currency">{{ (pricing.currencyPrice || '-') + '/' + getPriceUnitText(pricing.priceUnit) }}</span>
                     </div>
-                    <div class="method-item">
+                    <div class="method-item" v-if="pricing.priceSettings?.includes('AGREEMENT')">
                       <span class="method-label">鍗忚:</span>
-                      <span class="method-value agreement">{{ pricing.priceSettings?.includes('AGREEMENT') ? '姣忓' : '-' }}</span>
+                      <span class="method-value agreement">{{ '/' + getPriceUnitText(pricing.priceUnit) }}</span>
                     </div>
-                    <div class="method-item">
+                    <div class="method-item" v-if="pricing.priceSettings?.includes('FREE')">
                       <span class="method-label">鍏嶈垂:</span>
-                      <span class="method-value free">{{ pricing.priceSettings?.includes('FREE') ? '鍏嶈垂' : '-' }}</span>
+                      <span class="method-value free">{{ '/' + getPriceUnitText(pricing.priceUnit) }}</span>
                     </div>
                   </div>
                 </div>
@@ -109,6 +115,7 @@
                   </el-icon>
                   {{ pricing.enableStatus === 'ENABLED' ? '鍋滅敤' : '鍚敤' }}
                 </span>
+              </div>
               </div>
             </div>
           </div>
@@ -136,57 +143,48 @@
         size="large"
         class="price-form"
       >
-        <el-row :gutter="8">
-          <el-col :span="12">
+
             <el-form-item label="浜у搧濂椾欢" prop="productSuite">
-              <el-select v-model="formData.productSuite" placeholder="璇烽�夋嫨" style="width: 100%">
+              <el-select v-model="formData.productSuite" placeholder="璇烽�夋嫨" style="width: 60%">
                 <el-option v-for="opt in productSuiteOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
               </el-select>
             </el-form-item>
-          </el-col>
-          <el-col :span="12">
             <el-form-item label="瀹㈡埛瀵硅薄" prop="customerObject">
               <el-radio-group v-model="formData.customerObject">
                 <el-radio v-for="opt in customerObjectOptions" :key="opt.value" :label="opt.value">{{ opt.label }}</el-radio>
               </el-radio-group>
             </el-form-item>
-          </el-col>
-        </el-row>
-
         <el-form-item label="閿�鍞舰寮�" prop="salesForm" class="sales-form-item">
           <el-radio-group v-model="formData.salesForm" class="sales-form-group">
             <el-radio v-for="opt in salesFormOptions" :key="opt.value" :label="opt.value">{{ opt.label }}</el-radio>
           </el-radio-group>
         </el-form-item>
 
-        <el-row :gutter="8">
-          <el-col :span="12">
+        
             <el-form-item label="璐︽埛鏁伴噺" prop="accountQuantity">
               <div class="quantity-input-group">
                 <el-input-number v-model="formData.accountQuantity" :min="1" :controls="false" style="width: 180px" :disabled="formData.accountQuantityUnlimited" />
                 <el-checkbox v-model="formData.accountQuantityUnlimited" style="margin-left: 6px">涓嶉檺</el-checkbox>
               </div>
             </el-form-item>
-          </el-col>
-          <el-col :span="12">
+     
             <el-form-item label="骞跺彂鑺傜偣" prop="concurrentNodeQuantity">
               <div class="quantity-input-group">
                 <el-input-number v-model="formData.concurrentNodeQuantity" :min="1" :controls="false" style="width: 180px" :disabled="formData.concurrentNodeQuantityUnlimited" />
                 <el-checkbox v-model="formData.concurrentNodeQuantityUnlimited" style="margin-left: 6px">涓嶉檺</el-checkbox>
               </div>
             </el-form-item>
-          </el-col>
-        </el-row>
+  
 
         <el-form-item label="浠锋牸璁剧疆" prop="priceSettings">
           <div class="price-settings">
             <div class="price-setting-item">
               <el-checkbox label="POINTS" :disabled="formData.priceSettings.includes('FREE')" v-model="checkboxPoints">绉垎</el-checkbox>
-              <el-input-number v-if="formData.priceSettings.includes('POINTS')" v-model="formData.pointsAmount" :min="0" :precision="2" :controls="false" placeholder="绉垎閲戦" style="width: 120px; margin-left: 6px" />
+              <el-input-number v-if="formData.priceSettings.includes('POINTS')" v-model="formData.pointsPrice" :min="0" :precision="2" :controls="false" placeholder="绉垎閲戦" style="width: 120px; margin-left: 6px" />
             </div>
             <div class="price-setting-item">
               <el-checkbox label="CURRENCY" :disabled="formData.priceSettings.includes('FREE')" v-model="checkboxCurrency">璐у竵</el-checkbox>
-              <el-input-number v-if="formData.priceSettings.includes('CURRENCY')" v-model="formData.currencyAmount" :min="0" :precision="2" :controls="false" placeholder="璐у竵閲戦" style="width: 120px; margin-left: 6px" />
+              <el-input-number v-if="formData.priceSettings.includes('CURRENCY')" v-model="formData.currencyPrice" :min="0" :precision="2" :controls="false" placeholder="璐у竵閲戦" style="width: 120px; margin-left: 6px" />
             </div>
             <div class="price-setting-item">
               <el-checkbox label="AGREEMENT" :disabled="formData.priceSettings.includes('FREE')" v-model="checkboxAgreement">鍗忚</el-checkbox>
@@ -197,23 +195,19 @@
           </div>
         </el-form-item>
 
-        <el-row :gutter="8">
-          <el-col :span="12">
+        
+         
             <el-form-item label="浠锋牸鍗曚綅" prop="priceUnit">
               <el-select v-model="formData.priceUnit" placeholder="璇烽�夋嫨" style="width: 100%">
                 <el-option v-for="opt in priceUnitOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
               </el-select>
             </el-form-item>
-          </el-col>
-          <el-col :span="12">
+      
             <el-form-item label="鍚敤鐘舵��" prop="enableStatus">
               <el-radio-group v-model="formData.enableStatus">
                 <el-radio v-for="opt in enableStatusOptions" :key="opt.value" :label="opt.value">{{ opt.label }}</el-radio>
               </el-radio-group>
             </el-form-item>
-          </el-col>
-        </el-row>
-
         
 
         <el-form-item label="澶囨敞">
@@ -229,12 +223,6 @@
       </template>
     </el-dialog>
 
-    <!-- 浠锋牸鏌ョ湅鍣� -->
-    <ProductPriceViewer
-      v-model="showPriceViewer"
-      :product-id="currentProductId"
-      @order="handleOrderResult"
-    />
   </div>
 </template>
 
@@ -244,18 +232,22 @@
 import { useRoute } from 'vue-router'
 import { Goods, Lock, Unlock } from '@element-plus/icons-vue'
 import ProductPriceViewer from '@/views/productManage/productPriceViewer/index.vue'
+import productPricingApi from '@/api/productPricingApi'
+import productApi from '@/api/productApi'
+
 
 interface ProductDetail {
   id: string
   name: string
-  submitUnit: string
-  submitter: string
-  industry: string
-  projectUnit: string
-  industryStage: string
-  productType: string
-  description: string
+  submissionUnit: string
+  createBy: string
+  industrialChainName: string
+  importantAreaName: string
+  businessProcessName: string
+  typeName: string
+  describe: string
   shelfStatus?: '寰呬笂鏋�' | '宸蹭笂鏋�' | '宸蹭笅鏋�'
+  listingStatusName?: ''
 }
 
 interface PriceItem {
@@ -269,8 +261,8 @@
   concurrentNodeQuantity: number | ''
   concurrentNodeQuantityUnlimited: boolean
   priceSettings: Array<'POINTS' | 'CURRENCY' | 'AGREEMENT' | 'FREE'>
-  pointsAmount: number | ''
-  currencyAmount: number | ''
+  pointsPrice: number | ''
+  currencyPrice: number | ''
   priceUnit: '' | 'SET' | 'SET_PER_YEAR' | 'YEAR'
   enableStatus: 'ENABLED' | 'DISABLED'
   authorizationStartTime?: string
@@ -286,7 +278,7 @@
 })
 
 const productDetail = ref<ProductDetail | null>(null)
-const shelfStatus = computed(() => productDetail.value?.shelfStatus || '寰呬笂鏋�')
+const shelfStatus = computed(() => productDetail.value?.listingStatusName || '寰呬笂鏋�')
 const statusClass = computed(() => {
   switch (shelfStatus.value) {
     case '宸蹭笂鏋�':
@@ -301,32 +293,32 @@
 })
 
 // 妯℃嫙浜у搧璇︽儏鏁版嵁婧�
-const mockProductMap: Record<string, ProductDetail> = {
-  '10001': {
-    id: '10001',
-    name: '鏁板瓧鍖栦骇鍝丄',
-    submitUnit: '涓氦涓�鍏眬',
-    submitter: '寮犱笁',
-    industry: '浜ら�氬熀纭�璁炬柦',
-    projectUnit: '鏌愰珮閫熷叕璺伐绋�',
-    industryStage: '搴旂敤闃舵',
-    productType: '杞欢/骞冲彴',
-    description: '鏈骇鍝佸畾浣嶄负浠ュ缓璁炬湡BIM鏁板瓧璧勪骇浣滀负鏁板瓧搴曠洏锛岀粨鍚堥」鐩繍钀ョ淮淇濋渶姹傜殑瀹炴椂鎬с�佷氦浜掓�с�佷究鎹锋�х殑涓夌淮鍙鍖栬繍缁寸鐞嗙郴缁熴�傜郴缁熸彁渚涢」鐩暟瀛楀寲銆佹櫤鑳藉寲杩愮淮绠$悊鍔熻兘锛岃兘澶熻В鍐冲缓绛戣繍琛岀淮鎶ょ鐞嗕腑鐨勫疄闄呴棶棰橈紝瀹炵幇淇℃伅蹇�熸暣鍚堜笌鏌ヨ銆佷俊鎭湁鏁堝叡浜笌浼犻�掞紝鎻愬崌椤圭洰缁煎悎绠$悊涓庣淮鎶ゆ按骞炽��',
-    shelfStatus: '寰呬笂鏋�'
-  },
-  '10002': {
-    id: '10002',
-    name: '鏁板瓧鍖栦骇鍝丅',
-    submitUnit: '涓氦浜岃埅灞�',
-    submitter: '鏉庡洓',
-    industry: '甯傛斂宸ョ▼',
-    projectUnit: '鏅烘収绠″粖椤圭洰',
-    industryStage: '鐮斿彂闃舵',
-    productType: '纭欢/浼犳劅',
-    description: '闈㈠悜鍩庡競绠″粖鐩戞祴鐨勪紶鎰熻澶囦笌閲囬泦缃戝叧锛屾敮鎸佽竟缂樿绠椾笌杩滅▼杩愮淮銆�',
-    shelfStatus: '宸蹭笂鏋�'
-  }
-}
+// const mockProductMap: Record<string, ProductDetail> = {
+//   '1': {
+//     id: '1',
+//     name: '鏁板瓧鍖栦骇鍝丄',
+//     submitUnit: '涓氦涓�鍏眬',
+//     submitter: '寮犱笁',
+//     industry: '浜ら�氬熀纭�璁炬柦',
+//     projectUnit: '鏌愰珮閫熷叕璺伐绋�',
+//     industryStage: '搴旂敤闃舵',
+//     productType: '杞欢/骞冲彴',
+//     description: '鏈骇鍝佸畾浣嶄负浠ュ缓璁炬湡BIM鏁板瓧璧勪骇浣滀负鏁板瓧搴曠洏锛岀粨鍚堥」鐩繍钀ョ淮淇濋渶姹傜殑瀹炴椂鎬с�佷氦浜掓�с�佷究鎹锋�х殑涓夌淮鍙鍖栬繍缁寸鐞嗙郴缁熴�傜郴缁熸彁渚涢」鐩暟瀛楀寲銆佹櫤鑳藉寲杩愮淮绠$悊鍔熻兘锛岃兘澶熻В鍐冲缓绛戣繍琛岀淮鎶ょ鐞嗕腑鐨勫疄闄呴棶棰橈紝瀹炵幇淇℃伅蹇�熸暣鍚堜笌鏌ヨ銆佷俊鎭湁鏁堝叡浜笌浼犻�掞紝鎻愬崌椤圭洰缁煎悎绠$悊涓庣淮鎶ゆ按骞炽��',
+//     shelfStatus: '寰呬笂鏋�'
+//   },
+//   '2': {
+//     id: '2',
+//     name: '鏁板瓧鍖栦骇鍝丅',
+//     submitUnit: '涓氦浜岃埅灞�',
+//     submitter: '鏉庡洓',
+//     industry: '甯傛斂宸ョ▼',
+//     projectUnit: '鏅烘収绠″粖椤圭洰',
+//     industryStage: '鐮斿彂闃舵',
+//     productType: '纭欢/浼犳劅',
+//     description: '闈㈠悜鍩庡競绠″粖鐩戞祴鐨勪紶鎰熻澶囦笌閲囬泦缃戝叧锛屾敮鎸佽竟缂樿绠椾笌杩滅▼杩愮淮銆�',
+//     shelfStatus: '宸蹭笂鏋�'
+//   }
+// }
 
 const loading = ref(false)
 const priceList = ref<any[]>([])
@@ -343,13 +335,13 @@
   productSuite: '',
   salesForm: 'BUYOUT',
   customerObject: 'ENTERPRISE',
-  accountQuantity: '',
+  accountQuantity: 1,
   accountQuantityUnlimited: false,
-  concurrentNodeQuantity: '',
+  concurrentNodeQuantity: 1,
   concurrentNodeQuantityUnlimited: false,
   priceSettings: [],
-  pointsAmount: '',
-  currencyAmount: '',
+  pointsPrice: '',
+  currencyPrice: '',
   priceUnit: '',
   enableStatus: 'ENABLED',
   authorizationStartTime: undefined,
@@ -359,15 +351,15 @@
 
 // 閫夐」
 const productSuiteOptions = [
-  { label: '浼佷笟绉佹湁SaaS鐗堣鍙�', value: 'ENTERPRISE_PRIVATE_SAAS_LICENSE' },
-  { label: '浼佷笟绉佹湁SaaS鐗圤TA鏈嶅姟', value: 'ENTERPRISE_PRIVATE_SAAS_OTA' },
-  { label: '浼佷笟绉佹湁SaaS鐗堢敤鎴峰閲忓寘', value: 'ENTERPRISE_PRIVATE_SAAS_USER_INCREMENT' },
-  { label: '浼佷笟鍏湁SaaS鐗堣鍙�', value: 'ENTERPRISE_PUBLIC_SAAS_LICENSE' },
-  { label: '浼佷笟鍏湁SaaS鐗圤TA鏈嶅姟', value: 'ENTERPRISE_PUBLIC_SAAS_OTA' },
-  { label: '浼佷笟鍏湁SaaS鐗堢敤鎴峰閲忓寘', value: 'ENTERPRISE_PUBLIC_SAAS_USER_INCREMENT' },
-  { label: '涓汉鍏湁SaaS鍖栬鍙�', value: 'PERSONAL_PUBLIC_SAAS_LICENSE' },
-  { label: 'web杞欢', value: 'WEB_SOFTWARE' },
-  { label: '妗岄潰杞欢', value: 'DESKTOP_SOFTWARE' }
+  { label: '浼佷笟绉佹湁SaaS鐗堣鍙�', value: '浼佷笟绉佹湁SaaS鐗堣鍙�' },
+  { label: '浼佷笟绉佹湁SaaS鐗圤TA鏈嶅姟', value: '浼佷笟绉佹湁SaaS鐗圤TA鏈嶅姟' },
+  { label: '浼佷笟绉佹湁SaaS鐗堢敤鎴峰閲忓寘', value: '浼佷笟绉佹湁SaaS鐗堢敤鎴峰閲忓寘' },
+  { label: '浼佷笟鍏湁SaaS鐗堣鍙�', value: '浼佷笟鍏湁SaaS鐗堣鍙�' },
+  { label: '浼佷笟鍏湁SaaS鐗圤TA鏈嶅姟', value: '浼佷笟鍏湁SaaS鐗圤TA鏈嶅姟' },
+  { label: '浼佷笟鍏湁SaaS鐗堢敤鎴峰閲忓寘', value: '浼佷笟鍏湁SaaS鐗堢敤鎴峰閲忓寘' },
+  { label: '涓汉鍏湁SaaS鍖栬鍙�', value: '涓汉鍏湁SaaS鍖栬鍙�' },
+  { label: 'web杞欢', value: 'web杞欢' },
+  { label: '妗岄潰杞欢', value: '妗岄潰杞欢' }
 ]
 const salesFormOptions = [
   { label: '涔版柇', value: 'BUYOUT' },
@@ -418,8 +410,8 @@
     // 鑻ラ�夋嫨 FREE锛屾竻绌哄叾浠�
     if (key === 'FREE') {
       formData.priceSettings = ['FREE']
-      formData.pointsAmount = ''
-      formData.currencyAmount = ''
+      formData.pointsPrice = ''
+      formData.currencyPrice = ''
       return
     }
     // 鑻ユ鍓嶆湁 FREE锛屽幓鎺� FREE
@@ -456,8 +448,8 @@
     validator: (_: any, value: any[], cb: any) => {
       if (!value || value.length === 0) return cb(new Error('璇疯嚦灏戦�夋嫨涓�绉嶄环鏍艰缃�'))
       if (value.includes('FREE') && value.length > 1) return cb(new Error('鍏嶈垂閫夐」涓嶈兘涓庡叾浠栭�夐」鍚屾椂閫夋嫨'))
-      if (value.includes('POINTS') && (formData.pointsAmount === '' || formData.pointsAmount === undefined)) return cb(new Error('璇疯緭鍏ョН鍒嗛噾棰�'))
-      if (value.includes('CURRENCY') && (formData.currencyAmount === '' || formData.currencyAmount === undefined)) return cb(new Error('璇疯緭鍏ヨ揣甯侀噾棰�'))
+      if (value.includes('POINTS') && (formData.pointsPrice === '' || formData.pointsPrice === undefined)) return cb(new Error('璇疯緭鍏ョН鍒嗛噾棰�'))
+      if (value.includes('CURRENCY') && (formData.currencyPrice === '' || formData.currencyPrice === undefined)) return cb(new Error('璇疯緭鍏ヨ揣甯侀噾棰�'))
       cb()
     },
     trigger: 'change'
@@ -499,61 +491,167 @@
   return map[unit || ''] || unit || ''
 }
 
-function fetchProductDetail(productId?: string) {
+async function fetchProductDetail(productId?: string) {
   if (!productId) {
     productDetail.value = null
     ElMessage.warning('鏈彁渚涗骇鍝両D锛屾棤娉曞姞杞戒骇鍝佽鎯�')
     return
   }
-  // 妯℃嫙寮傛
   loading.value = true
-  setTimeout(() => {
-    productDetail.value = mockProductMap[productId] || null
-    // 鏋勯�犲崱鐗囨墍闇�鐨勬紨绀哄畾浠锋暟鎹�
-    priceList.value = productDetail.value
-      ? [
-          {
-            id: 1,
-            productId: productId,
-            productSuite: 'STANDARD',
-            salesForm: 'BUYOUT',
-            customerObject: 'ENTERPRISE',
-            accountQuantity: 50,
-            accountQuantityUnlimited: false,
-            concurrentNodeQuantity: 50,
-            concurrentNodeQuantityUnlimited: false,
-            priceSettings: ['POINTS'],
-            pointsAmount: 50000,
-            currencyAmount: 0,
-            priceUnit: 'SET_PER_YEAR',
-            enableStatus: 'ENABLED',
-            authorizationStartTime: '2025-01-01',
-            authorizationEndTime: '2025-12-31',
-            remark: '婕旂ず鏁版嵁'
-          },
-          {
-            id: 2,
-            productId: productId,
-            productSuite: 'PRO',
-            salesForm: 'PRIVATE_INCREMENT',
-            customerObject: 'ENTERPRISE',
-            accountQuantity: 100,
-            accountQuantityUnlimited: false,
-            concurrentNodeQuantity: 100,
-            concurrentNodeQuantityUnlimited: false,
-            priceSettings: ['CURRENCY'],
-            pointsAmount: 0,
-            currencyAmount: 7500,
-            priceUnit: 'SET',
-            enableStatus: 'DISABLED',
-            authorizationStartTime: '2025-01-01',
-            authorizationEndTime: '2025-06-30',
-            remark: '婕旂ず鏁版嵁'
-          }
-        ]
-      : []
+  try {
+    // productDetail.value = mockProductMap[productId] || null
+    const data = {
+      id: productId
+    }
+    const detailRes: any = await productApi.getProductById(data)
+    if (detailRes?.code === 200) {
+      productDetail.value = detailRes.data || null
+    } else {
+      productDetail.value = null
+      ElMessage.error(detailRes?.msg || '鑾峰彇浜у搧璇︽儏澶辫触')
+    }
+    await loadPricingList(productId)
+  } catch (e) {
+    productDetail.value = null
+    ElMessage.error('鑾峰彇浜у搧璇︽儏澶辫触')
+  } finally {
     loading.value = false
-  }, 300)
+  }
+}
+
+function mapSalesFormToCN(val: string) {
+  const map: Record<string, string> = {
+    BUYOUT: '涔版柇',
+    LEASE: '绉熻祦',
+    PRIVATE_INCREMENT: '绉佹湁澧炲寘閲�',
+    PUBLIC_INCREMENT: '鍏湁澧炲寘閲�',
+    OTA: 'OTA鏈嶅姟',
+    CLOUD: '浜戞湇鍔�',
+    RESOURCE_PACKAGE: '璧勬簮鍖�',
+    PERSONAL: '涓汉',
+  }
+  return map[val] || val
+}
+
+function mapSalesFormFromCN(val: string) {
+  const map: Record<string, string> = {
+    '涔版柇': 'BUYOUT',
+    '绉熻祦': 'LEASE',
+    '绉佹湁澧炲寘閲�': 'PRIVATE_INCREMENT',
+    '鍏湁澧炲寘閲�': 'PUBLIC_INCREMENT',
+    'OTA鏈嶅姟': 'OTA',
+    '浜戞湇鍔�': 'CLOUD',
+    '璧勬簮鍖�': 'RESOURCE_PACKAGE',
+    '涓汉': 'PERSONAL',
+  }
+  return (map[val] as any) || val
+}
+
+function mapCustomerToCN(val: string) {
+  const map: Record<string, string> = { ENTERPRISE: '浼佷笟', PERSONAL: '涓汉', PROJECT_DEPARTMENT: '椤圭洰閮�' }
+  return map[val] || val
+}
+
+function mapCustomerFromCN(val: string) {
+  const map: Record<string, string> = { '浼佷笟': 'ENTERPRISE', '涓汉': 'PERSONAL', '椤圭洰閮�': 'PROJECT_DEPARTMENT' }
+  return (map[val] as any) || val
+}
+
+function mapUnitToCN(val: string) {
+  const map: Record<string, string> = { SET: '濂�', SET_PER_YEAR: '濂�/骞�', YEAR: '骞�' }
+  return map[val] || val
+}
+
+function mapUnitFromCN(val: string) {
+  const map: Record<string, string> = { '濂�': 'SET', '濂�/骞�': 'SET_PER_YEAR', '骞�': 'YEAR' }
+  return (map[val] as any) || val
+}
+
+function mapPriceTypeToCN(key: 'POINTS' | 'CURRENCY' | 'AGREEMENT' | 'FREE') {
+  const map: Record<string, string> = { POINTS: '绉垎', CURRENCY: '璐у竵', AGREEMENT: '鍗忚', FREE: '鍏嶈垂' }
+  return map[key]
+}
+
+function mapPriceTypeFromCN(val: string): 'POINTS' | 'CURRENCY' | 'AGREEMENT' | 'FREE' | undefined {
+  const map: Record<string, any> = { '绉垎': 'POINTS', '璐у竵': 'CURRENCY', '鍗忚': 'AGREEMENT', '鍏嶈垂': 'FREE' }
+  return map[val]
+}
+
+async function loadPricingList(productId: string) {
+  try {
+    const res: any = await productPricingApi.listByProductId(productId)
+    if (res?.code === 200) {
+      const list = Array.isArray(res.data) ? res.data : []
+      const newList = list.map((it: any) => {
+        const priceSettings =  it.priceType.split(',').map((t:string) => mapPriceTypeFromCN(t))
+        const pointsPrice = priceSettings.includes('POINTS') ? Number(it.pointsPrice || 0) : 0
+        const currencyPrice = priceSettings.includes('CURRENCY') ? Number(it.currencyPrice || 0) : 0
+        return {
+          id: it.id,
+          productId: String(it.productId || productId),
+          productSuite: it.suiteName || '',
+          salesForm: mapSalesFormFromCN(it.salesForm) as any,
+          customerObject: mapCustomerFromCN(it.customerType) as any,
+          accountQuantityUnlimited: (it.accountLimit === '涓嶉檺'),
+          accountQuantity: it.accountLimit === '涓嶉檺' ? '' : Number(it.accountLimit || ''),
+          concurrentNodeQuantityUnlimited: (it.concurrentNodes === '涓嶉檺'),
+          concurrentNodeQuantity: it.concurrentNodes === '涓嶉檺' ? '' : Number(it.concurrentNodes || ''),
+          priceSettings: priceSettings,
+          pointsPrice,
+          currencyPrice,
+          priceUnit: mapUnitFromCN(it.priceUnit) as any,
+          enableStatus: it.isActive ? 'ENABLED' : 'DISABLED',
+          authorizationStartTime: undefined,
+          authorizationEndTime: undefined,
+          remark: it.description || '',
+        }
+      })
+      const groupedList = newList.reduce((acc: any[], it: any) => {
+        // 鎸塸roductSuite鍒嗙粍
+        const productSuite = it.productSuite
+        if (!acc[productSuite]) {
+          acc[productSuite] = []
+        }
+        acc[productSuite].push(it)
+        return acc  
+      }, {})
+      const newGroupedList:any  = []
+      Object.entries(groupedList).forEach(([k,v]) =>{
+        newGroupedList.push({
+          suiteName: k,
+          items: v
+        })
+      })
+      priceList.value = newGroupedList
+      console.log(priceList.value)
+      console.log(groupedList)
+    } else {
+      priceList.value = []
+    }
+  } catch (e) {
+    priceList.value = []
+  }
+}
+
+function buildPayloadFromRow(row: any, overrides: Partial<any> = {}) {const priceTypeCN = row.priceSettings?.[0] ? mapPriceTypeToCN(row.priceSettings[0]) : undefined
+  
+  return {
+    id: row.id,
+    productId: row.productId,
+    productName: productDetail.value?.name,
+    suiteName: row.productSuite,
+    salesForm: mapSalesFormToCN(row.salesForm),
+    customerType: mapCustomerToCN(row.customerObject),
+    accountLimit: row.accountQuantityUnlimited ? '涓嶉檺' : String(row.accountQuantity || ''),
+    concurrentNodes: row.concurrentNodeQuantityUnlimited ? '涓嶉檺' : String(row.concurrentNodeQuantity || ''),
+    priceType: row.priceSettings.map((t:string)=>mapPriceTypeToCN(t as any)).join(','),
+    priceUnit: mapUnitToCN(row.priceUnit || ''),
+    pointsPrice:  row.priceSettings.includes('POINTS') ? row.pointsPrice : '',
+    currencyPrice:  row.priceSettings.includes('CURRENCY') ? row.currencyPrice : '',
+    isActive: row.enableStatus === 'ENABLED',
+    description: row.remark || '',
+    ...overrides,
+  }
 }
 
 // 鏌ョ湅浠锋牸
@@ -570,7 +668,6 @@
   isEditMode.value = false
   resetForm()
   formData.productId = currentProductId.value
-  formData.id = generateId()
   dialogVisible.value = true
 }
 
@@ -579,7 +676,7 @@
   isEditMode.value = true
   resetForm()
   Object.assign(formData, {
-    id: row.id ?? generateId(),
+    id: row.id,
     productId: currentProductId.value,
     productSuite: row.productSuite || '',
     salesForm: row.salesForm || 'BUYOUT',
@@ -589,8 +686,8 @@
     concurrentNodeQuantity: row.concurrentNodeQuantity ?? '',
     concurrentNodeQuantityUnlimited: !!row.concurrentNodeQuantityUnlimited,
     priceSettings: Array.isArray(row.priceSettings) ? row.priceSettings : [],
-    pointsAmount: row.pointsAmount ?? '',
-    currencyAmount: row.currencyAmount ?? '',
+    pointsPrice: row.pointsPrice ?? '',
+    currencyPrice: row.currencyPrice ?? '',
     priceUnit: row.priceUnit || '',
     enableStatus: row.enableStatus || 'ENABLED',
     authorizationStartTime: row.authorizationStartTime,
@@ -611,10 +708,10 @@
       type: 'warning'
     }
   )
-    .then(() => {
-      const idx = priceList.value.findIndex((p: any) => p.id === row.id)
-      if (idx !== -1) priceList.value.splice(idx, 1)
+    .then(async () => {
+      await productPricingApi.remove(row.id)
       ElMessage.success('鍒犻櫎鎴愬姛')
+      if (currentProductId.value) await loadPricingList(currentProductId.value)
     })
     .catch(() => {
       ElMessage.info('宸插彇娑堝垹闄�')
@@ -637,13 +734,13 @@
     productSuite: '',
     salesForm: 'BUYOUT',
     customerObject: 'ENTERPRISE',
-    accountQuantity: '',
+    accountQuantity: 1,
     accountQuantityUnlimited: false,
-    concurrentNodeQuantity: '',
+    concurrentNodeQuantity: 1,
     concurrentNodeQuantityUnlimited: false,
     priceSettings: [],
-    pointsAmount: '',
-    currencyAmount: '',
+    pointsPrice: '',
+    currencyPrice: '',
     priceUnit: '',
     enableStatus: 'ENABLED',
     authorizationStartTime: undefined,
@@ -653,10 +750,6 @@
   if (formRef.value) formRef.value.clearValidate()
 }
 
-function generateId() {
-  const maxId = priceList.value.reduce((m: number, it: any) => Math.max(m, Number(it.id || 0)), 0)
-  return maxId + 1
-}
 
 async function handleSave() {
   try {
@@ -665,17 +758,89 @@
     return
   }
 
+  if (!currentProductId.value) {
+    ElMessage.warning('鏈彁渚涗骇鍝両D锛屾棤娉曚繚瀛樺畾浠�')
+    return
+  }
+
+  const selectedTypes = formData.priceSettings
+  if (!selectedTypes || selectedTypes.length === 0) {
+    ElMessage.warning('璇疯嚦灏戦�夋嫨涓�绉嶄环鏍艰缃�')
+    return
+  }
+
+  const mapSalesFormToCN = (val: string) => ({
+    BUYOUT: '涔版柇',
+    LEASE: '绉熻祦',
+    PRIVATE_INCREMENT: '绉佹湁澧炲寘閲�',
+    PUBLIC_INCREMENT: '鍏湁澧炲寘閲�',
+    OTA: 'OTA鏈嶅姟',
+    CLOUD: '浜戞湇鍔�',
+    RESOURCE_PACKAGE: '璧勬簮鍖�',
+    PERSONAL: '涓汉',
+  } as any)[val] || val
+
+  const mapCustomerToCN = (val: string) => ({ ENTERPRISE: '浼佷笟', PERSONAL: '涓汉', PROJECT_DEPARTMENT: '椤圭洰閮�' } as any)[val] || val
+  const mapUnitToCN = (val: string) => ({ SET: '濂�', SET_PER_YEAR: '濂�/骞�', YEAR: '骞�' } as any)[val] || val
+  const mapPriceTypeToCN = (key: 'POINTS' | 'CURRENCY' | 'AGREEMENT' | 'FREE') => ({ POINTS: '绉垎', CURRENCY: '璐у竵', AGREEMENT: '鍗忚', FREE: '鍏嶈垂' } as any)[key]
+
+  const buildPayload = () => {
+   
+    return {
+      id: isEditMode.value && formData.id  ? formData.id : undefined,
+      productId: currentProductId.value,
+      productName: productDetail.value?.name,
+      suiteName: formData.productSuite,
+      salesForm: mapSalesFormToCN(formData.salesForm),
+      customerType: mapCustomerToCN(formData.customerObject),
+      accountLimit: formData.accountQuantityUnlimited ? '涓嶉檺' : String(formData.accountQuantity || ''),
+      concurrentNodes: formData.concurrentNodeQuantityUnlimited ? '涓嶉檺' : String(formData.concurrentNodeQuantity || ''),
+      priceType: formData.priceSettings.map(t=>mapPriceTypeToCN(t)).join(','),
+      priceUnit: mapUnitToCN(formData.priceUnit || ''),
+      pointsPrice: formData.pointsPrice,
+      currencyPrice: formData.currencyPrice,
+      isActive: formData.enableStatus === 'ENABLED',
+      description: formData.remark || '',
+    }
+  }
+
   saving.value = true
   try {
-    const record: PriceItem = JSON.parse(JSON.stringify(formData))
-    const idx = priceList.value.findIndex((p: any) => p.id === record.id)
-    if (idx === -1) {
-      priceList.value.push(record)
+    if (isEditMode.value && formData.id) {
+      const payload = buildPayload()
+      const res: any = await productPricingApi.update(payload)
+      if (res?.code === 200) {
+        ElMessage.success('淇敼鎴愬姛')
     } else {
-      priceList.value.splice(idx, 1, record)
+        ElMessage.error(res?.msg || '淇敼澶辫触')
+        return
+      }
+    } else {
+      // const tasks = selectedTypes.map(t => productPricingApi.add(buildPayload(t)))
+      // const results: any[] = await Promise.all(tasks)
+      // const ok = results.every(r => r && r.code === 200)
+      const results: any = await productPricingApi.add(buildPayload())
+      if (results?.code !== 200) {
+        ElMessage.error('閮ㄥ垎瀹氫环淇濆瓨澶辫触')
+        return
+      }
+      ElMessage.success('鏂板缓鎴愬姛')
+      // 淇敼浜у搧鐘舵�佷负宸茶浠�
+      // 鍒ゆ柇 浜у搧瀹氫环鍒楄〃鏄惁涓虹┖锛屼负绌哄垯鏇存柊鐘舵�侊紝涓嶄负绌哄垯璇存槑鏇存柊杩囦簡锛屼笉闇�瑕佸湪姝ゆ洿鏂�
+      if (priceList.value.length === 0) {
+        const updateParams = {
+          id: currentProductId.value,
+          listingStatus: 'PRICED'
+        }
+        const res: any = await productApi.updateProductStatus(updateParams)
+        if (res?.code !== 200) {
+          console.log('浜у搧鐘舵�佹洿鏂板け璐ワ紒锛�')
+        }
+      }
     }
-    ElMessage.success(isEditMode.value ? '淇敼鎴愬姛' : '鏂板缓鎴愬姛')
+
     dialogVisible.value = false
+    await loadPricingList(currentProductId.value)
   } finally {
     saving.value = false
   }
@@ -695,11 +860,10 @@
     '鐘舵�佸彉鏇�',
     { confirmButtonText: '纭畾', cancelButtonText: '鍙栨秷', type: 'warning' }
   )
-    .then(() => {
-      const idx = priceList.value.findIndex((p: any) => p.id === row.id)
-      if (idx !== -1) {
-        priceList.value[idx] = { ...priceList.value[idx], enableStatus: newStatus }
-      }
+    .then(async () => {
+      const payload = buildPayloadFromRow(row, { isActive: newStatus === 'ENABLED' })
+      await productPricingApi.update(payload)
+      await loadPricingList(currentProductId.value as string)
       ElMessage.success(newStatus === 'ENABLED' ? '鍚敤鎴愬姛' : '鍋滅敤鎴愬姛')
     })
     .catch(() => {})
@@ -741,6 +905,11 @@
 
   .content-area {
     .price-card {
+      /* 璁╀环鏍煎垪琛ㄥ彲婊氬姩 */
+      :deep(.el-card__body) {
+        max-height: 600px;
+        overflow-y: auto;
+      }
       .card-header {
         display: flex;
         justify-content: space-between;
@@ -801,7 +970,7 @@
 .quantity-input-group { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
 .sales-form-item :deep(.el-form-item__content) { white-space: nowrap; }
 .sales-form-group { display: inline-flex; gap: 12px; flex-wrap: nowrap; }
-.price-form :deep(.el-form-item) { margin-bottom: 12px; }
+.price-form :deep(.el-form-item) { margin-bottom: 20px; }
 /* 涓婃灦鐘舵�侀鑹� */
 .status-online { color: #67C23A; }
 .status-pending { color: #E6A23C; }

--
Gitblit v1.8.0