From 95cb69b9f79893d7cd1319d754064c93e3fa4e2f Mon Sep 17 00:00:00 2001 From: seatonwan9 Date: 星期二, 19 八月 2025 18:15:56 +0800 Subject: [PATCH] 提交源码 --- src/views/productManage/productPriceViewer/index.vue | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 256 insertions(+), 44 deletions(-) diff --git a/src/views/productManage/productPriceViewer/index.vue b/src/views/productManage/productPriceViewer/index.vue index fb0bd06..a559117 100644 --- a/src/views/productManage/productPriceViewer/index.vue +++ b/src/views/productManage/productPriceViewer/index.vue @@ -249,10 +249,25 @@ </div> </td> <td class="th-center"> - <el-input-number v-model="suite.quantity" :min="1" :max="999" :controls="false" size="small" /> + <el-input-number + v-model="suite.quantity" + :min="1" + :max="999" + :controls="true" + size="large" + @change="(value) => handleQuantityChange(suite.id, value?value:1)" + /> </td> <td class="th-center"> - <el-input-number v-model="suite.duration" :min="1" :max="10" :controls="false" size="small" /> + <el-input-number + v-model="suite.duration" + :min="1" + :max="100" + :controls="true" + size="large" + :disabled="suite.priceType === 'FREE'" + @change="(value) => handleDurationChange(suite.id, value?value:1)" + /> </td> <td class="th-center"> <el-button type="danger" link @click="removeSuite(idx)">鍒犻櫎</el-button> @@ -331,7 +346,7 @@ <el-button type="primary" @click="handleOrder">绔嬪嵆璁㈣喘</el-button> </template> <template v-else> - <el-button @click="showOrderPanel = false">杩斿洖浠锋牸瀵规瘮</el-button> + <el-button @click="returnPricePanel">杩斿洖浠锋牸瀵规瘮</el-button> <el-button type="primary" @click="submitOrder">鎻愪氦鐢宠</el-button> </template> </span> @@ -346,6 +361,8 @@ import { ElMessage } from 'element-plus' import { useRoute } from 'vue-router' import productPricingApi from '@/api/productPricingApi' +import cartApi from '@/api/cartApi' +import orderApi from '@/api/orderApi' import { ShoppingCart, Coin, Money } from '@element-plus/icons-vue' const route = useRoute() @@ -406,6 +423,9 @@ const showOrderPanel = ref(false) const showPricePanel = ref(true) const showOrderStatus = ref(false) +// 妯℃嫙鐢ㄦ埛淇℃伅锛堝疄闄呭簲浠庣敤鎴风姸鎬佽幏鍙栵級 +const currentUserId = ref(1) +const currentUnitId = ref(1) type PriceTypeKey = 'POINTS' | 'CURRENCY' | 'AGREEMENT' | 'FREE' interface OrderSuite extends PriceItem { selected: boolean @@ -414,6 +434,11 @@ priceType?: PriceTypeKey } const orderSuites = ref<OrderSuite[]>([]) + +// 璐墿杞︾浉鍏崇姸鎬� +const cartItems = ref<any[]>([]) +const cartLoading = ref(false) +const idempotencyToken = ref<string>('') // 璁㈠崟鐘舵�佺浉鍏� type OrderStatus = 'SUBMITTED' | 'AUTHORIZED' | 'CONFIRMED' | 'EVALUATED' @@ -522,7 +547,25 @@ const map: Record<string, string> = { SET: '/濂�', SET_PER_YEAR: '/濂�/骞�', YEAR: '/骞�' } return map[unit || ''] || '' } -const removeSuite = (index: number) => { orderSuites.value.splice(index, 1) } +const removeSuite = async (index: number) => { + const suite = orderSuites.value[index] + if (!suite) return + try { + await removeFromCart(suite.id) + orderSuites.value.splice(index, 1) + } catch (e) { + } +} + +// 璁㈣喘鎴愬姛鍥炶皟 +const handleOrderSuccess = (orderData: any) => { + console.log('璁㈣喘鎴愬姛:', orderData) + ElMessage.success('璁㈣喘鐢宠鎻愪氦鎴愬姛锛�') + // 娓呯┖閫夋嫨鐘舵�� + selectedSuiteIds.value.clear() + // 鍏抽棴浠锋牸鏌ョ湅鍣� + visible.value = false +} // 寮圭獥鏍囬 const dialogTitle = computed(() => { @@ -689,26 +732,28 @@ const isChecked = Boolean(checked) if (isChecked) { selectedSuiteIds.value.add(suiteId) + // 娣诲姞鍒拌喘鐗╄溅 + const priceItem = priceList.value.find(item => item.id === suiteId) + if (priceItem) { + addToCart(priceItem) + } } else { selectedSuiteIds.value.delete(suiteId) + // 浠庤喘鐗╄溅绉婚櫎 + removeFromCart(suiteId) } } // 绔嬪嵆璁㈣喘 const handleOrder = () => { - if (selectedSuiteIds.value.size === 0) { - ElMessage.warning('璇烽�夋嫨瑕佽璐殑杞欢濂椾欢') - return - } - const selectedItems = priceList.value.filter(item => selectedSuiteIds.value.has(item.id)) - // 鏋勫缓鍐呭祵璁㈣喘鍒楄〃 - orderSuites.value = selectedItems.map(it => ({ - ...it, - selected: true, - quantity: 1, - duration: 1, - priceType: getDefaultPriceType(it as any) - })) as any + // 鏌ヨ璐墿杞︿俊鎭繘琛屽睍绀� + fetchCartItems() + // 鑾峰彇涓�娆℃�ч槻閲嶅鎻愪氦token + orderApi.getIdempotencyToken(currentUserId.value).then((res: any) => { + if (res?.code === 200) { + idempotencyToken.value = res.data as string + } + }).catch(() => {}) showOrderPanel.value = true showPricePanel.value = false } @@ -719,6 +764,12 @@ // 鍚敤/鍋滅敤鎸夐挳 function handleToggleEnableStatus(row: any) { // ... existing code ... +} + +function returnPricePanel() { + showOrderPanel.value = false + showOrderStatus.value = false + showPricePanel.value = true } async function submitOrder() { @@ -733,34 +784,195 @@ ElMessage.error('鏆備笉鏀寔璐у竵浜ゆ槗锛岃閫夋嫨绉垎鎴栧崗璁敮浠樻柟寮�') return } - - // 杩欓噷鍙鎺ュ疄闄呬笅鍗曟帴鍙o紱鍏堝仛鍓嶇鎻愮ず - // emit('order', items as any) - - // 妯℃嫙璁㈠崟鐘舵�佹暟鎹� - orderStatus.value = { - id: '4348442557619205545', - productName: productHeader.value.name, - provider: productHeader.value.provider, - status: 'SUBMITTED', - submitTime: new Date().toLocaleString(), - applyTime: new Date().toLocaleString() + + if (!idempotencyToken.value) { + ElMessage.error('涓嬪崟Token鑾峰彇澶辫触锛岃杩斿洖閲嶈瘯') + return } - - // 鏄剧ず璁㈠崟鐘舵�侀潰鏉� - showOrderPanel.value = false - showPricePanel.value = false - showOrderStatus.value = true + + // 缁勮鍒涘缓璁㈠崟鍙傛暟锛圕reateOrderDTO锛� + const payload = { + userId: currentUserId.value, + unitId: currentUnitId.value, + productName: productHeader.value.name, + providerName: productHeader.value.provider, + providerId: 3, + paymentType: '绉垎', + buyerRemarks: '', + items: items.map(it => ({ + pricingId: it.id, + productId: Number(it.productId), + suiteName: getProductSuiteText(it.productSuite), + salesForm: getSalesFormText(it.salesForm), + customerType: getCustomerObjectText(it.customerObject), + accountLimit: it.accountQuantityUnlimited ? '涓嶉檺' : String(it.accountQuantity), + concurrentNodes: it.concurrentNodeQuantityUnlimited ? '涓嶉檺' : String(it.concurrentNodeQuantity), + priceType: (it.priceType === 'POINTS' ? '绉垎' : it.priceType === 'CURRENCY' ? '璐у竵' : it.priceType === 'AGREEMENT' ? '鍗忚' : '鍏嶈垂'), + priceUnit: getPriceUnitText(it.priceUnit), + unitPrice: (it.priceType === 'POINTS' ? it.pointsAmount : it.currencyAmount) || 0, + quantity: it.quantity, + duration: it.duration, + totalPrice: undefined, + providerId: 3, + providerName: productHeader.value.provider, + remarks: '' + })) + } + + try { + const res: any = await orderApi.createOrder(payload, idempotencyToken.value) + if (res?.code === 200) { + ElMessage.success('璁㈠崟鍒涘缓鎴愬姛') + const data = res.data || {} + orderStatus.value = { + id: data.orderId || '鈥�', + productName: data.productName || productHeader.value.name, + provider: data.providerName || productHeader.value.provider, + status: 'SUBMITTED', + submitTime: data.applyTime ? String(data.applyTime) : new Date().toLocaleString(), + applyTime: data.applyTime ? String(data.applyTime) : new Date().toLocaleString() + } + // 娓呯┖璐墿杞︼紙鍚庣 + 鏈湴鐘舵�侊級 + try { + const clearRes: any = await cartApi.clearCart(currentUserId.value, currentUnitId.value) + if (clearRes?.code === 200) { + cartItems.value = [] + orderSuites.value = [] + selectedSuiteIds.value.clear() + selectAllChecked.value = false + } + } catch (e) { /* ignore */ } + // 鏄剧ず璁㈠崟鐘舵�侀潰鏉� + showOrderPanel.value = false + showPricePanel.value = false + showOrderStatus.value = true + } else { + ElMessage.error(res?.msg || '鍒涘缓璁㈠崟澶辫触') + } + } catch (e) { + ElMessage.error('鍒涘缓璁㈠崟澶辫触') + } } -// 璁㈣喘鎴愬姛鍥炶皟 -const handleOrderSuccess = (orderData: any) => { - console.log('璁㈣喘鎴愬姛:', orderData) - ElMessage.success('璁㈣喘鐢宠鎻愪氦鎴愬姛锛�') - // 娓呯┖閫夋嫨鐘舵�� - selectedSuiteIds.value.clear() - // 鍏抽棴浠锋牸鏌ョ湅鍣� - visible.value = false +// 璐墿杞︾浉鍏虫柟娉� +const addToCart = async (priceItem: PriceItem) => { + try { + const cartData = { + pricingId: priceItem.id, + productId: Number(priceItem.productId), + productName: productName.value, + suiteName: getProductSuiteText(priceItem.productSuite), + salesForm: getSalesFormText(priceItem.salesForm), + customerType: getCustomerObjectText(priceItem.customerObject), + accountLimit: priceItem.accountQuantityUnlimited ? '涓嶉檺' : String(priceItem.accountQuantity), + concurrentNodes: priceItem.concurrentNodeQuantityUnlimited ? '涓嶉檺' : String(priceItem.concurrentNodeQuantity), + priceType: priceItem.priceSettings.map(item => getPriceSettingText(item)).join(','), + priceUnit: getPriceUnitText(priceItem.priceUnit), + unitPrice: priceItem.pointsAmount || priceItem.currencyAmount || 0, + quantity: 1, + duration: 1 + } + + const res: any = await cartApi.addToCart(cartData, currentUserId.value, currentUnitId.value) + if (res?.code === 200) { + ElMessage.success('宸叉坊鍔犲埌璐墿杞�') + } else { + ElMessage.error(res?.msg || '娣诲姞鍒拌喘鐗╄溅澶辫触') + } + } catch (error) { + console.error('娣诲姞鍒拌喘鐗╄溅澶辫触:', error) + ElMessage.error('娣诲姞鍒拌喘鐗╄溅澶辫触') + } +} + +const removeFromCart = async (pricingId: number) => { + try { + const res: any = await cartApi.removeFromCart(currentUserId.value, currentUnitId.value, pricingId) + if (res?.code === 200) { + ElMessage.success('宸蹭粠璐墿杞︾Щ闄�') + } else { + ElMessage.error(res?.msg || '浠庤喘鐗╄溅绉婚櫎澶辫触') + } + } catch (error) { + console.error('浠庤喘鐗╄溅绉婚櫎澶辫触:', error) + ElMessage.error('浠庤喘鐗╄溅绉婚櫎澶辫触') + } +} + +const updateCartItem = async (pricingId: number, quantity: number, duration: number) => { + try { + // 杩欓噷闇�瑕佹牴鎹疄闄呮帴鍙h皟鏁达紝鍙兘闇�瑕佷紶閫掓洿澶氬弬鏁� + const res: any = await cartApi.updateCartItem(currentUserId.value, currentUnitId.value, pricingId, quantity) + if (res?.code === 200) { + ElMessage.success('璐墿杞﹀凡鏇存柊') + } else { + ElMessage.error(res?.msg || '鏇存柊璐墿杞﹀け璐�') + } + } catch (error) { + console.error('鏇存柊璐墿杞﹀け璐�:', error) + ElMessage.error('鏇存柊璐墿杞﹀け璐�') + } +} + +const fetchCartItems = async () => { + cartLoading.value = true + try { + const res: any = await cartApi.getCartItems(currentUserId.value, currentUnitId.value) + if (res?.code === 200) { + cartItems.value = res.data || [] + // 灏嗚喘鐗╄溅鏁版嵁杞崲涓鸿鍗曞浠舵牸寮� + orderSuites.value = cartItems.value.map((item: any) => ({ + id: item.pricingId, + productId: String(item.productId), + productSuite: item.suiteName, + salesForm: mapSalesFormFromCN(item.salesForm), + customerObject: mapCustomerFromCN(item.customerType), + accountQuantity: item.accountLimit === '涓嶉檺' ? 0 : Number(item.accountLimit), + accountQuantityUnlimited: item.accountLimit === '涓嶉檺', + concurrentNodeQuantity: item.concurrentNodes === '涓嶉檺' ? 0 : Number(item.concurrentNodes), + concurrentNodeQuantityUnlimited: item.concurrentNodes === '涓嶉檺', + priceSettings: item.priceType.split(',').map((t: string) => mapPriceTypeFromCN(t)).filter(Boolean), + pointsAmount: item.priceType.includes('绉垎') ? item.unitPrice : 0, + currencyAmount: item.priceType.includes('璐у竵') ? item.unitPrice : 0, + priceUnit: mapUnitFromCN(item.priceUnit), + enableStatus: 'ENABLED', + selected: true, + quantity: item.quantity || 1, + duration: item.duration || 1, + priceType: getDefaultPriceType({ + priceSettings: item.priceType.split(',').map((t: string) => mapPriceTypeFromCN(t)).filter(Boolean) + } as any) + })) as any + } else { + orderSuites.value = [] + ElMessage.error(res?.msg || '鑾峰彇璐墿杞︿俊鎭け璐�') + } + } catch (error) { + console.error('鑾峰彇璐墿杞︿俊鎭け璐�:', error) + orderSuites.value = [] + ElMessage.error('鑾峰彇璐墿杞︿俊鎭け璐�') + } finally { + cartLoading.value = false + } +} + +// 澶勭悊鏁伴噺鍙樺寲 +const handleQuantityChange = async (pricingId: number, quantity: number) => { + try { + await updateCartItem(pricingId, quantity, 1) // 鏆傛椂浼犻�掗粯璁uration涓�1 + } catch (error) { + console.error('鏇存柊鏁伴噺澶辫触:', error) + } +} + +// 澶勭悊骞撮檺鍙樺寲 +const handleDurationChange = async (pricingId: number, duration: number) => { + try { + // 杩欓噷鍙兘闇�瑕佹牴鎹疄闄呮帴鍙h皟鏁达紝浼犻�抎uration鍙傛暟 + await updateCartItem(pricingId, 1, duration) // 鏆傛椂浼犻�掗粯璁uantity涓�1 + } catch (error) { + console.error('鏇存柊骞撮檺澶辫触:', error) + } } // 鑾峰彇閿�鍞舰寮忔枃鏈� @@ -973,7 +1185,7 @@ } &.currency { - color: #f56c6c; + color: #e7900d; } &.free { @@ -981,7 +1193,7 @@ } } .price-icon.points { color: #e6a23c; } - .price-icon.currency { color: #f56c6c; } + .price-icon.currency { color: #e7900d; } } .add-checkbox { -- Gitblit v1.8.0