Bang Hu
2 天以前 b3fedd4221b807a07058be9d5d5d8ba8998adbcb
src/views/productManage/productPriceViewer/index.vue
@@ -77,15 +77,7 @@
                      :colspan="getColspan(priceItem)"
                      class="feature-value"
                    >
                      <div class="order-methods">
                        <span
                          v-for="method in priceItem.priceSettings"
                          :key="method"
                          class="method-item"
                        >
                          ✓ {{ getPriceSettingText(method) }}
                        </span>
                      </div>
                      {{ priceItem.priceSettings.map((m:any) => getPriceSettingText(m)).join('、') }}
                    </td>
                  </tr>
                  <tr>
@@ -96,42 +88,7 @@
                      :colspan="getColspan(priceItem)"
                      class="feature-value"
                    >
                      <div class="price-info">
                        <div
                          v-if="priceItem.priceSettings.includes('POINTS') && priceItem.pointsAmount > 0"
                          class="price-item"
                        >
                         <div class="price-lable-icon">
                          <el-icon class="price-icon points"><Coin /></el-icon>
                          <span class="price-label">积分</span>
                         </div>
                          <span class="price-value points">{{ formatNumber(priceItem.pointsAmount) }} / {{ getPriceUnitText(priceItem.priceUnit) }}</span>
                        </div>
                                                 <div
                           v-if="priceItem.priceSettings.includes('CURRENCY') && priceItem.currencyAmount > 0"
                           class="price-item"
                         >
                          <div class="price-lable-icon">
                           <span class="price-icon currency">¥</span>
                           <span class="price-label">货币</span>
                           </div>
                           <span class="price-value currency">{{ formatNumber(priceItem.currencyAmount) }} / {{ getPriceUnitText(priceItem.priceUnit) }}</span>
                         </div>
                        <div
                          v-if="priceItem.priceSettings.includes('FREE')"
                          class="price-item"
                        >
                          <span class="price-label">费用</span>
                          <span class="price-value free">免费</span>
                        </div>
                                                 <div
                           v-if="priceItem.priceSettings.includes('AGREEMENT')"
                           class="price-item"
                         >
                           <span class="price-label">协议:</span>
                           <span class="price-value agreement">每{{ getPriceUnitText(priceItem.priceUnit) }}</span>
                         </div>
                       </div>
                      {{ renderPrice(priceItem) }}
                     </td>
                   </tr>
                   <tr>
@@ -250,7 +207,7 @@
                      :controls="true" 
                      size="large"
                      class="quantity-input"
                      @change="(value) => handleQuantityChange(suite.id, value?value:1)"
                      @change="(value) => handleQuantityChange(suite.id,value?value:1)"
                    />
                  </td>
                  <td class="th-center">
@@ -305,23 +262,26 @@
          <table class="order-info-table">
            <tbody>
              <tr>
                <td class="label">订单编号:</td>
                <td class="value">{{ orderStatus.id }}</td>
                <td class="label">申请时间:</td>
                <td class="label">订单编号</td>
                <td class="value">
                  {{ orderStatus.id }}
                  <el-link type="primary" @click="goBuyerCenter" style="margin-left: 8px">点击查看</el-link>
                </td>
                <td class="label">申请时间</td>
                <td class="value">{{ orderStatus.applyTime }}</td>
              </tr>
              <tr>
                <td class="label">产品名称:</td>
                <td class="label">产品名称</td>
                <td class="value">{{ orderStatus.productName }}</td>
                <td class="label">提供者:</td>
                <td class="label">提供者</td>
                <td class="value">{{ orderStatus.provider }}</td>
              </tr>
              <tr>
                <td class="label">订单状态:</td>
                <td class="label">订单状态</td>
                <td class="value">{{ statusText(orderStatus.status) }}</td>
                <td></td>
                <td class="value link">
                  <el-link type="primary" @click="viewOrder">查看订单信息</el-link>
<!--                  <el-link type="primary" @click="viewOrder">查看订单信息</el-link>-->
                </td>
              </tr>
            </tbody>
@@ -337,7 +297,7 @@
    <div class="footer" v-if="showPricePanel">
     <el-button type="primary" @click="handleOrder">立即订购</el-button>
    </div>
    <div class="footer" v-else>
    <div class="footer" v-if="showOrderPanel">
      <el-button @click="returnPricePanel">返回价格对比</el-button>
      <el-button type="primary" @click="submitOrder">提交申请</el-button>
    </div>
@@ -348,17 +308,19 @@
<script setup lang="ts">
import { ref, watch, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
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'
import workFlowApi from '@/api/workFlowApi'
const route = useRoute()
const router = useRouter()
interface PriceItem {
  id: number
@@ -393,7 +355,7 @@
const showOrderStatus = ref(false)
// 模拟用户信息(实际应从用户状态获取)
const userStore = useUserInfo()
let currentUserId = computed(() => userStore.getUserId || userStore.getUserInfo?.userId)
const currentUserId = computed(() => userStore.getUserId || userStore.getUserInfo?.userId)
const currentUnitId = computed(() => userStore.getUnitId || userStore.getUserInfo?.unitId || '')
onMounted(async () => {
@@ -402,7 +364,8 @@
      const res: any = await queryUserDetail()
      if (res?.code === 200 && res.data) {
        userStore.updateUserDetail(res.data)
        currentUserId = res.data.userId || res.data.id
        // currentUserId.value = res.data.id || res.data.userId
        console.log(currentUserId.value)
        userInfo.value = res.data
      } else {
        ElMessage.error(res?.msg || '无法获取用户信息,请先登录')
@@ -416,7 +379,8 @@
  }else{
    userInfo.value = userStore.getUserInfos
  }
  // 获取订购信息
  fetchProductData(currentProductId.value ? currentProductId.value : '')
})
type PriceTypeKey = 'POINTS' | 'CURRENCY' | 'AGREEMENT' | 'FREE'
interface OrderSuite extends PriceItem {
@@ -473,6 +437,10 @@
const viewOrder = () => {
  window.alert('这里可跳转到订单详情页(示例)')
}
const goBuyerCenter = () => {
  router.push({ name: 'tradeBuyerCenter', query: { t: String(Date.now()) } })
}
 
const selectedCount = computed(() => orderSuites.value.filter(s => s.selected).length)
@@ -546,6 +514,7 @@
  try {
    await removeFromCart(String(suite.id))
    orderSuites.value.splice(index, 1)
    selectedSuiteIds.value.delete(suite.id)
  } catch (e) {
  }
}
@@ -637,7 +606,8 @@
  loading.value = true
  try {
    const res: any = await productPricingApi.listByProductId(productId)
    // 只查询已启用的定价
    const res: any = await productPricingApi.listBycondition({ productId: productId,isActive: true })
    if (res?.code === 200) {
      const list = Array.isArray(res.data) ? res.data : []
      const mapped: PriceItem[] = list.map((it: any) => {
@@ -707,6 +677,13 @@
  } finally {
    loading.value = false
  }
  // 修改activeTab  默认值
  if(priceList.value.length > 0){
    activeTab.value =  groupedPriceData.value.hasOwnProperty('enterprise')  ? 'enterprise'
        :  groupedPriceData.value.hasOwnProperty('project') ? 'project' : 'personal'
  }
}
// 监听产品ID变化
@@ -714,7 +691,7 @@
  if (newProductId) {
    fetchProductData(newProductId)
  }
},{ immediate: true })
})
// 套件选择处理
const handleSuiteSelect = (suiteId: number, checked: any) => {
@@ -786,6 +763,21 @@
  }else{
     paymentType = '协议'
  }
     let processdefId: string = ''
     const type = hasAGREEMENT ? 'trade_agreement' : 'trade_point';
     // 获取工作流参数
     const  wkParamsRes: any = await workFlowApi.getWorkFlowParams({
      type: type,
      // unitId: '1',
      businessKey: type
    })
  if(wkParamsRes?.code === 200 && wkParamsRes.data?.processTemplateId){
    processdefId = wkParamsRes.data.processTemplateId
  }else {
    ElMessage.error('获取工作流参数失败!')
    return
  }
  // 组装创建订单参数(CreateOrderDTO)
  const payload = {
    userId: currentUserId.value,
@@ -795,6 +787,7 @@
    providerId: productHeader.value.createUserId,
    paymentType: paymentType,
    buyerRemarks: '',
    processdefId: processdefId,
    items: items.map(it => ({
      pricingId: it.id,
      productId: it.productId,
@@ -829,25 +822,35 @@
        applyTime: data.applyTime ? String(data.applyTime) : new Date().toLocaleString()
      }
      // 调用工作流接口发起审批流程,拿到流程实例ID后回写订单workflow_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 {
      //   // 根据是否包含协议明细,配置不同流程定义与业务Key(先用静态值占位)
      //   // const processdefId = hasAGREEMENT ? 'Process_Agreement_Static' : 'Process_Points_Static'
      //   const businessKey = hasAGREEMENT ? 'agreement_biz_key' : 'points_biz_key'
      //   const type = hasAGREEMENT ? 'trade_agreement' : 'trade_point';
      //   // 获取工作流参数
      //   const  wkParamsRes: any = await workFlowApi.getWorkFlowParams({
      //     type: type,
      //     unitId: '1'
      //   })
      //   if(wkParamsRes?.code === 200 && wkParamsRes.data?.processTemplateId){
      //     const wfRes: any = await workFlowApi.startWorkflowAndComplete({
      //       processdefId: wkParamsRes.data.processTemplateId,
      //       userid: String(currentUserId.value || ''),
      //       businessKey: 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)
        const clearRes: any = await cartApi.clearCart(currentUserId.value, currentUnitId.value,currentProductId.value ? currentProductId.value : '')
        if (clearRes?.code === 200) {
          cartItems.value = []
          orderSuites.value = []
@@ -900,7 +903,7 @@
const removeFromCart = async (pricingId: string) => {
  try {
    const res: any = await cartApi.removeFromCart(currentUserId.value, currentUnitId.value, pricingId)
    const res: any = await cartApi.removeFromCart(currentUserId.value, currentUnitId.value, currentProductId.value? currentProductId.value : '',pricingId)
    if (res?.code === 200) {
      ElMessage.success('已从购物车移除')
    } else {
@@ -912,10 +915,16 @@
  }
}
const updateCartItem = async (pricingId: number, quantity: number, duration: number) => {
const updateCartItem = async (pricingId: number, quantity: number | null, duration: number | null) => {
  try {
    // 这里需要根据实际接口调整,可能需要传递更多参数
    const res: any = await cartApi.updateCartItem(currentUserId.value, currentUnitId.value, pricingId, quantity)
    let res: any = {}
    if(quantity){
      res = await cartApi.updateCartItem(currentUserId.value, currentUnitId.value, currentProductId.value? currentProductId.value : '', pricingId, quantity)
    }
    if(duration){
      res = await cartApi.updateCartItemDuration(currentUserId.value, currentUnitId.value, currentProductId.value? currentProductId.value : '', pricingId, duration)
    }
    if (res?.code === 200) {
      ElMessage.success('购物车已更新')
    } else {
@@ -930,7 +939,7 @@
const fetchCartItems = async () => {
  cartLoading.value = true
  try {
    const res: any = await cartApi.getCartItems(currentUserId.value, currentUnitId.value)
    const res: any = await cartApi.getCartItems(currentUserId.value, currentUnitId.value, currentProductId.value? currentProductId.value : '')
    if (res?.code === 200) {
      cartItems.value = res.data || []
      // 将购物车数据转换为订单套件格式
@@ -972,7 +981,7 @@
// 处理数量变化
const handleQuantityChange = async (pricingId: number, quantity: number) => {
  try {
    await updateCartItem(pricingId, quantity, 1) // 暂时传递默认duration为1
    await updateCartItem(pricingId, quantity, null) // 暂时传递默认duration为1
  } catch (error) {
    console.error('更新数量失败:', error)
  }
@@ -982,7 +991,7 @@
const handleDurationChange = async (pricingId: number, duration: number) => {
  try {
    // 这里可能需要根据实际接口调整,传递duration参数
    await updateCartItem(pricingId, 1, duration) // 暂时传递默认quantity为1
    await updateCartItem(pricingId, null, duration) // 暂时传递默认quantity为1
  } catch (error) {
    console.error('更新年限失败:', error)
  }
@@ -996,7 +1005,9 @@
    PRIVATE_INCREMENT: '私有增量包',
    PUBLIC_INCREMENT: '公有增量包',
    OTA: 'OTA服务',
    CLOUD: '云服务'
    CLOUD: '云服务',
    RESOURCE_PACKAGE: '资源包',
    PERSONAL: '个人'
  }
  return map[salesForm] || salesForm
}
@@ -1070,6 +1081,24 @@
    YEAR: '年'
  }
  return map[unit] || unit
}
// 统一渲染价格:去除“积分/货币/费用/协议”等类型前缀,仅输出纯价格文本
const renderPrice = (priceItem: PriceItem) => {
  const segments: string[] = []
  if (priceItem.priceSettings.includes('POINTS') && priceItem.pointsAmount > 0) {
    segments.push(`${formatNumber(priceItem.pointsAmount)} / ${getPriceUnitText(priceItem.priceUnit)}`)
  }
  if (priceItem.priceSettings.includes('CURRENCY') && priceItem.currencyAmount > 0) {
    segments.push(`${formatNumber(priceItem.currencyAmount)} / ${getPriceUnitText(priceItem.priceUnit)}`)
  }
  if (priceItem.priceSettings.includes('FREE')) {
    segments.push('免费')
  }
  if (priceItem.priceSettings.includes('AGREEMENT')) {
    segments.push(`每${getPriceUnitText(priceItem.priceUnit)}`)
  }
  return segments.join(';')
}
// 获取分组后的表头数据
@@ -1453,7 +1482,7 @@
    white-space: nowrap; 
    overflow: hidden; 
    text-overflow: ellipsis;
    line-height: 1;
    line-height: 2;
  }
  .label { color:#606266; font-weight: 500; }
  .value { color:#303133; }