From bfbb1ea3c6bb2dd7db064fb189290a1bfcf6c9cd Mon Sep 17 00:00:00 2001 From: seatonwan9 Date: 星期四, 28 八月 2025 02:14:48 +0800 Subject: [PATCH] 提交源码 --- src/views/productManage/productPriceViewer/index.vue | 308 ++++++++++++++++++++++++++++++-------------------- 1 files changed, 184 insertions(+), 124 deletions(-) diff --git a/src/views/productManage/productPriceViewer/index.vue b/src/views/productManage/productPriceViewer/index.vue index a559117..71022ee 100644 --- a/src/views/productManage/productPriceViewer/index.vue +++ b/src/views/productManage/productPriceViewer/index.vue @@ -1,12 +1,5 @@ <template> - <el-dialog - v-model="visible" - :title="dialogTitle" - :before-close="handleClose" - destroy-on-close - class="product-price-dialog" - :width="dialogWidth" - > + <div> <div class="price-viewer-container" v-loading="loading"> <!-- 浠锋牸瀵规瘮琛ㄦ牸 --> <div class="pricing-table-container" v-if="showPricePanel && priceList.length > 0"> @@ -19,7 +12,7 @@ > <div class="pricing-table-wrapper"> <table class="pricing-table"> - <thead> + <thead> <tr> <th class="feature-column">鍔熻兘瀵规瘮</th> <th @@ -174,19 +167,19 @@ <span class="label">浜у搧鍚嶇О锛�</span><span class="value strong">{{ productHeader.name }}</span> </div> <div class="grid-item"> - <span class="label">琛屼笟鏉垮潡锛�</span><span class="value">{{ productHeader.industry }}</span> + <span class="label">琛屼笟鏉垮潡锛�</span><span class="value">{{ productHeader.industrialChainName }}</span> </div> <div class="grid-item"> - <span class="label">鎻愪緵鑰咃細</span><span class="value">{{ productHeader.provider }}</span> + <span class="label">鎻愪緵鑰咃細</span><span class="value">{{ productHeader.submissionUnit }}</span> </div> <div class="grid-item"> <span class="label">鐢ㄦ埛濮撳悕锛�</span><span class="value">{{ userInfo.name }}</span> </div> <div class="grid-item"> - <span class="label">鍗曚綅锛�</span><span class="value">{{ userInfo.unit }}</span> + <span class="label">鍗曚綅锛�</span><span class="value">{{ userInfo.unitName }}</span> </div> <div class="grid-item"> - <span class="label">閮ㄩ棬锛�</span><span class="value">{{ userInfo.department }}</span> + <span class="label">閮ㄩ棬锛�</span><span class="value">{{ userInfo.departmentName }}</span> </div> </div> </el-card> @@ -338,32 +331,29 @@ <el-empty description="鏆傛棤浠锋牸淇℃伅" /> </div> </div> - - <template #footer v-if="!showOrderStatus"> - <span class="dialog-footer"> - <template v-if="showPricePanel"> - <el-button @click="handleClose">鍏抽棴</el-button> - <el-button type="primary" @click="handleOrder">绔嬪嵆璁㈣喘</el-button> - </template> - <template v-else> - <el-button @click="returnPricePanel">杩斿洖浠锋牸瀵规瘮</el-button> - <el-button type="primary" @click="submitOrder">鎻愪氦鐢宠</el-button> - </template> - </span> - </template> - </el-dialog> + <div class="footer" v-if="showPricePanel"> + <el-button type="primary" @click="handleOrder">绔嬪嵆璁㈣喘</el-button> + </div> + <div class="footer" v-else> + <el-button @click="returnPricePanel">杩斿洖浠锋牸瀵规瘮</el-button> + <el-button type="primary" @click="submitOrder">鎻愪氦鐢宠</el-button> + </div> + </div> <!-- 浜у搧璁㈣喘瀵硅瘽妗嗙Щ闄わ紝鏀逛负鍐呭祵灞曠ず --> </template> <script setup lang="ts"> -import { ref, watch, computed } from 'vue' +import { ref, watch, computed, onMounted } from 'vue' 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' +import { useUserInfo } from '@/stores/modules/userInfo' +import { queryUserDetail } from '@/api/userInfo' +import productApi from '@/api/productApi' const route = useRoute() @@ -384,36 +374,11 @@ enableStatus: 'ENABLED' | 'DISABLED' } -interface Props { - modelValue: boolean - productId?: string - width?: string -} - -interface Emits { - (e: 'update:modelValue', value: boolean): void - (e: 'order', selectedItems: PriceItem[]): void -} - // 鍏煎 path 鍙傛暟 productId 涓� query 鍙傛暟 id/productId const currentProductId = computed<string | undefined>(() => { return (route.params.productId as string) || (route.query.productId as string) || (route.query.id as string) }) - -const props = withDefaults(defineProps<Props>(), { - modelValue: false, - productId: '', - width: '90%' -}) - - -const emit = defineEmits<Emits>() - -const visible = computed({ - get: () => props.modelValue, - set: (value) => emit('update:modelValue', value) -}) const loading = ref(false) const activeTab = ref('enterprise') @@ -424,8 +389,32 @@ const showPricePanel = ref(true) const showOrderStatus = ref(false) // 妯℃嫙鐢ㄦ埛淇℃伅锛堝疄闄呭簲浠庣敤鎴风姸鎬佽幏鍙栵級 -const currentUserId = ref(1) -const currentUnitId = ref(1) +const userStore = useUserInfo() +let currentUserId = computed(() => userStore.getUserId || userStore.getUserInfo?.userId) +const currentUnitId = computed(() => userStore.getUnitId || userStore.getUserInfo?.unitId || '') + +onMounted(async () => { + if (!currentUserId.value) { + try { + const res: any = await queryUserDetail() + if (res?.code === 200 && res.data) { + userStore.updateUserDetail(res.data) + currentUserId = res.data.userId || res.data.id + userInfo.value = res.data + } else { + ElMessage.error(res?.msg || '鏃犳硶鑾峰彇鐢ㄦ埛淇℃伅锛岃鍏堢櫥褰�') + return + } + } catch (e) { + console.error('鑾峰彇鐢ㄦ埛璇︽儏澶辫触:', e) + ElMessage.error('鑾峰彇鐢ㄦ埛淇℃伅澶辫触锛岃绋嶅悗閲嶈瘯') + return + } + }else{ + userInfo.value = userStore.getUserInfos + } + +}) type PriceTypeKey = 'POINTS' | 'CURRENCY' | 'AGREEMENT' | 'FREE' interface OrderSuite extends PriceItem { selected: boolean @@ -513,14 +502,15 @@ // 浜у搧淇℃伅/鐢ㄦ埛淇℃伅锛堥潤鎬侊級 const productHeader = ref({ - name: '涓氦鏂硅繙鏅鸿兘瀹炴祴瀹為噺绠$悊绯荤粺', - industry: '鍏矾,甯傛斂,寤虹瓚', - provider: '涓氦寤虹瓚闆嗗洟绗竴宸ョ▼鏈夐檺鍏徃' + name: '', + industrialChainName: '', + submissionUnit: '', + createUserId: '' }) const userInfo = ref({ - name: '寮犻潤', - unit: '淇$闆嗗洟', - department: '闂ㄦ埛绯荤粺涓存椂缁�' + name: '', + departmentName: '', + unitName: '' }) // 鍏ㄩ�� @@ -551,7 +541,7 @@ const suite = orderSuites.value[index] if (!suite) return try { - await removeFromCart(suite.id) + await removeFromCart(String(suite.id)) orderSuites.value.splice(index, 1) } catch (e) { } @@ -563,8 +553,6 @@ ElMessage.success('璁㈣喘鐢宠鎻愪氦鎴愬姛锛�') // 娓呯┖閫夋嫨鐘舵�� selectedSuiteIds.value.clear() - // 鍏抽棴浠锋牸鏌ョ湅鍣� - visible.value = false } // 寮圭獥鏍囬 @@ -572,10 +560,6 @@ return `銆�${productName.value}銆戜骇鍝佸畾浠穈 }) -// 寮圭獥瀹藉害 -const dialogWidth = computed(() => { - return props.width -}) // 鎸夊鎴峰璞″垎缁勭殑浠锋牸鏁版嵁 const groupedPriceData = computed(() => { @@ -701,31 +685,33 @@ } finally { loading.value = false } + //鑾峰彇浜у搧璇︽儏淇℃伅 + try { + // productDetail.value = mockProductMap[productId] || null + const data = { + id: productId + } + const detailRes: any = await productApi.getProductById(data) + if (detailRes?.code === 200) { + productHeader.value = detailRes.data || { name: '', industrialChainName: '', submissionUnit: '', createUserId: '' } + } else { + productHeader.value = { name: '', industrialChainName: '', submissionUnit: '', createUserId: '' } + ElMessage.error(detailRes?.msg || '鑾峰彇浜у搧璇︽儏澶辫触') + } + } catch (e) { + productHeader.value = { name: '', industrialChainName: '', submissionUnit: '', createUserId: '' } + ElMessage.error('鑾峰彇浜у搧璇︽儏澶辫触') + } finally { + loading.value = false + } } // 鐩戝惉浜у搧ID鍙樺寲 -watch(() => props.productId, (newProductId) => { - if (newProductId && visible.value) { +watch(currentProductId, (newProductId) => { + if (newProductId) { fetchProductData(newProductId) } -}) - -// 鐩戝惉寮圭獥鏄剧ず鐘舵�� -watch(() => visible.value, (newVisible) => { - if (newVisible && props.productId) { - fetchProductData(props.productId) - } -}) - -// 鍏抽棴寮圭獥 -const handleClose = () => { - visible.value = false - showOrderPanel.value = false - showOrderStatus.value = false - showPricePanel.value = true - orderSuites.value = [] - selectedSuiteIds.value.clear() -} +},{ immediate: true }) // 濂椾欢閫夋嫨澶勭悊 const handleSuiteSelect = (suiteId: number, checked: any) => { @@ -740,7 +726,7 @@ } else { selectedSuiteIds.value.delete(suiteId) // 浠庤喘鐗╄溅绉婚櫎 - removeFromCart(suiteId) + removeFromCart(String(suiteId)) } } @@ -784,24 +770,31 @@ ElMessage.error('鏆備笉鏀寔璐у竵浜ゆ槗锛岃閫夋嫨绉垎鎴栧崗璁敮浠樻柟寮�') return } - + if (!idempotencyToken.value) { ElMessage.error('涓嬪崟Token鑾峰彇澶辫触锛岃杩斿洖閲嶈瘯') return } - + const hasPoints = items.some(item => item.priceType === 'POINTS') + const hasAGREEMENT = items.some(item => item.priceType === 'AGREEMENT') + let paymentType = '' + if(hasPoints){ + paymentType = '绉垎' + }else{ + paymentType = '鍗忚' + } // 缁勮鍒涘缓璁㈠崟鍙傛暟锛圕reateOrderDTO锛� const payload = { userId: currentUserId.value, unitId: currentUnitId.value, productName: productHeader.value.name, - providerName: productHeader.value.provider, - providerId: 3, - paymentType: '绉垎', + providerName: productHeader.value.submissionUnit, + providerId: productHeader.value.createUserId, + paymentType: paymentType, buyerRemarks: '', items: items.map(it => ({ pricingId: it.id, - productId: Number(it.productId), + productId: it.productId, suiteName: getProductSuiteText(it.productSuite), salesForm: getSalesFormText(it.salesForm), customerType: getCustomerObjectText(it.customerObject), @@ -813,8 +806,8 @@ quantity: it.quantity, duration: it.duration, totalPrice: undefined, - providerId: 3, - providerName: productHeader.value.provider, + providerId: productHeader.value.createUserId, + providerName: productHeader.value.submissionUnit, remarks: '' })) } @@ -827,11 +820,28 @@ orderStatus.value = { id: data.orderId || '鈥�', productName: data.productName || productHeader.value.name, - provider: data.providerName || productHeader.value.provider, + provider: data.providerName || productHeader.value.submissionUnit, status: 'SUBMITTED', submitTime: data.applyTime ? String(data.applyTime) : new Date().toLocaleString(), applyTime: data.applyTime ? String(data.applyTime) : new Date().toLocaleString() } + // 璋冪敤宸ヤ綔娴佹帴鍙e彂璧峰鎵规祦绋嬶紝鎷垮埌娴佺▼瀹炰緥ID鍚庡洖鍐欒鍗晈orkflow_id + try { + // 鏍规嵁鏄惁鍖呭惈鍗忚鏄庣粏锛岄厤缃笉鍚屾祦绋嬪畾涔変笌涓氬姟Key锛堝厛鐢ㄩ潤鎬佸�煎崰浣嶏級 + const processdefId = hasAGREEMENT ? 'Process_Agreement_Static' : 'Process_Points_Static' + const businessKey = hasAGREEMENT ? 'agreement_biz_key' : 'points_biz_key' + const wfRes: any = await orderApi.startWorkflowAndComplete({ + processdefId, + userid: String(currentUserId.value || ''), + businessKey + }) + if (wfRes?.code === 200 && wfRes.data?.processinstId) { + await orderApi.updateWorkflowId(data.orderId, wfRes.data.processinstId) + } + } catch (e) { + console.warn('鍚姩宸ヤ綔娴佸け璐ユ垨鏇存柊workflow_id澶辫触', e) + } + // 娓呯┖璐墿杞︼紙鍚庣 + 鏈湴鐘舵�侊級 try { const clearRes: any = await cartApi.clearCart(currentUserId.value, currentUnitId.value) @@ -859,7 +869,7 @@ try { const cartData = { pricingId: priceItem.id, - productId: Number(priceItem.productId), + productId: priceItem.productId, productName: productName.value, suiteName: getProductSuiteText(priceItem.productSuite), salesForm: getSalesFormText(priceItem.salesForm), @@ -885,7 +895,7 @@ } } -const removeFromCart = async (pricingId: number) => { +const removeFromCart = async (pricingId: string) => { try { const res: any = await cartApi.removeFromCart(currentUserId.value, currentUnitId.value, pricingId) if (res?.code === 200) { @@ -1084,29 +1094,65 @@ .pricing-table-container { .pricing-tabs { :deep(.el-tabs__header) { - margin-bottom: 5px; + margin-bottom: 12px; } - + /* 灞呬腑 tabs 瀵艰埅 */ + :deep(.el-tabs__nav-wrap) { + display: flex; + justify-content: center; + } + :deep(.el-tabs__nav) { + margin: 0 auto; + border: none !important; + } + /* 鍗$墖鍨� tabs 缇庡寲涓哄渾瑙掕兌鍥婃晥鏋� */ + :deep(.el-tabs--card > .el-tabs__header .el-tabs__nav) { + border: none; + } + :deep(.el-tabs--card > .el-tabs__header .el-tabs__item) { + border: none; + } + :deep(.el-tabs__item) { + border-radius: 999px; + padding: 8px 18px; + margin: 0 6px; + color: #606266; + background: #f6f8fb; + transition: all .2s ease; + } + :deep(.el-tabs__item:hover) { + color: #3a7afe; + background: #eff4ff; + } :deep(.el-tabs__item.is-active) { - font-weight: bold; + font-weight: 600; + color: #fff; + background: #3a7afe; + box-shadow: 0 6px 16px rgba(58, 122, 254, 0.25); } } .pricing-table-wrapper { overflow-x: auto; + background: #fff; + border-radius: 12px; + box-shadow: 0 6px 24px rgba(0, 0, 0, 0.06); + padding: 8px; .pricing-table { width: 100%; - border-collapse: collapse; - border: 1px solid #e4e7ed; + border-collapse: separate; + border-spacing: 0; background: #fff; + border-radius: 10px; th, td { - border: 1px solid #e4e7ed; - padding: 6px 8px; + border-bottom: 1px solid #eef2f7; + border-right: 1px solid #f3f5f7; + padding: 12px 14px; text-align: center; vertical-align: middle; - font-size: 16px; + font-size: 14px; } tr th:first-child, td:first-child{ font-weight: 700; @@ -1114,7 +1160,7 @@ } th { - background-color: #f5f7fa; + background: linear-gradient(180deg, #f7f9fc 0%, #eef2f7 100%); font-weight: 600; color: #303133; } @@ -1126,9 +1172,9 @@ .sub-header { th { - background-color: #fafafa; + background-color: #f8fafc; font-weight: 500; - font-size: 16px; + font-size: 13px; color: #606266; } } @@ -1141,26 +1187,34 @@ } .feature-value { - color: #606266; - background: #fafafa; /* 琛屼负鐏拌壊 */ + color: #303133; + background: #fff; + } + + tbody tr:hover td { + background: #fafcff; } .order-methods { display: flex; flex-direction: column; - gap: 4px; + gap: 6px; align-items: center; .method-item { - font-size: 16px; - color: #409eff; + font-size: 12px; + color: #3a7afe; + background: #f4f7ff; + border: 1px solid #e3ebff; + border-radius: 999px; + padding: 2px 10px; } } .price-info { display: flex; flex-direction: column; /* 绔栨帓 */ - gap: 8px; + gap: 10px; align-items: center; .price-item { @@ -1168,24 +1222,29 @@ align-items: flex-start; flex-direction: column; gap: 6px; + padding: 10px 12px; + border: 1px solid #f0f2f5; + border-radius: 10px; + background: #fff; + box-shadow: inset 0 -1px 0 rgba(0,0,0,0.02); .price-lable-icon{ display: flex; gap: 6px; } .price-label { - font-size: 16px; - color: #606266; + font-size: 12px; + color: #909399; } .price-value { - font-weight: 500; - font-size: 20px; + font-weight: 600; + font-size: 18px; &.points { color: #e7900d; } &.currency { - color: #e7900d; + color: #10b981; } &.free { @@ -1193,7 +1252,7 @@ } } .price-icon.points { color: #e6a23c; } - .price-icon.currency { color: #e7900d; } + .price-icon.currency { color: #16a34a; } } .add-checkbox { @@ -1206,7 +1265,7 @@ justify-content: center; align-items: center; padding: 8px 0; - .add-cart-icon { color: #409eff; font-size:22px} + .add-cart-icon { color: #3a7afe; font-size:22px} } } } @@ -1348,4 +1407,5 @@ .order-summary .summary-value.highlight{ color:#409eff; } .order-summary .summary-value.total{ color:#e6a23c; } .order-summary .summary-value.currency{ color:#f56c6c; } +.footer { display: flex; flex-direction: row-reverse; margin-right: 50px; gap: 50px; margin-top: 20px;} </style> -- Gitblit v1.8.0