22cc8ce22157a32bfcd4ee14d824769c6e318cec..b3fedd4221b807a07058be9d5d5d8ba8998adbcb
2 天以前 Bang Hu
Bug修改代码提交
b3fedd 对比 | 目录
2 天以前 p-honggang.li
修改买家中心卖家中心产品类型等条件查询问题
349091 对比 | 目录
12个文件已修改
606 ■■■■ 已修改文件
components.d.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/App.vue 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/userInfo.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/workFlowApi.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/approveManage/tradeApproval/list.vue 104 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productManage/price/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productManage/productOrderStatusDialog/index.vue 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productManage/productPriceViewer/index.vue 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/tradeManage/buyer/index.vue 153 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/tradeManage/detail/index.vue 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/tradeManage/seller/index.vue 106 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite.config.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
components.d.ts
@@ -13,6 +13,7 @@
    ElButton: typeof import('element-plus/es')['ElButton']
    ElCard: typeof import('element-plus/es')['ElCard']
    ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
    ElCol: typeof import('element-plus/es')['ElCol']
    ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
    ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
    ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
@@ -36,6 +37,8 @@
    ElRadio: typeof import('element-plus/es')['ElRadio']
    ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
    ElRate: typeof import('element-plus/es')['ElRate']
    ElRow: typeof import('element-plus/es')['ElRow']
    ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
    ElSelect: typeof import('element-plus/es')['ElSelect']
    ElStep: typeof import('element-plus/es')['ElStep']
@@ -46,6 +49,8 @@
    ElTabPane: typeof import('element-plus/es')['ElTabPane']
    ElTabs: typeof import('element-plus/es')['ElTabs']
    ElTag: typeof import('element-plus/es')['ElTag']
    ElTooltip: typeof import('element-plus/es')['ElTooltip']
    ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
    ElUpload: typeof import('element-plus/es')['ElUpload']
    FileInfoPreview: typeof import('./src/components/fileInfoPreview/index.vue')['default']
    FilePreview: typeof import('./src/components/filePreview/index.vue')['default']
src/App.vue
@@ -123,5 +123,14 @@
.rowBtnDiv .normal-btn,.action-btns .normal-btn{
    padding: 8px 4px !important;
  }
/* Tooltip 宽度与换行控制(Element Plus Teleport 到 body,需要 deep 选择器) */
.tooltip-wrap{
  max-width: 340px !important;
}
.tooltip-wrap .el-tooltip__content {
  max-width: 340px !important;
  white-space: normal !important;
  word-break: break-word;
  overflow-wrap: anywhere;
}
</style>
src/api/userInfo.ts
@@ -14,7 +14,7 @@
// 查看个人信息
export function queryUserDetail(data: object = {}): ApiPromise {
    return createAxios({
        baseURL: '/api',
        baseURL: '/api1',
        url: `/admin/common/userDetail`,
        headers: {
            'Content-Type': 'application/json;charset=UTF-8'
src/api/workFlowApi.ts
@@ -4,7 +4,7 @@
const workFlowApi = {
  getWorkFlowParams(data: object = {}) : ApiPromise{
    return createAxios({
        baseURL: '/api',
        baseURL: '/api1',
        url: `/approval/templateRelation/relationByType`,
        headers: {
            'Content-Type': 'application/json;charset=UTF-8'
src/views/approveManage/tradeApproval/list.vue
@@ -14,9 +14,25 @@
            </el-select>
          </el-form-item>
          <el-form-item label="" class="col-17">
            <el-select v-model="query.unitProject" placeholder="请选择单位工程" clearable style="width: 100%">
              <el-option v-for="item in unitProjectOptions" :key="item.value" :label="item.label" :value="item.value" />
            </el-select>
<!--            <el-select v-model="query.unitProject" placeholder="请选择单位工程" clearable style="width: 100%">-->
<!--              <el-option v-for="item in unitProjectOptions" :key="item.value" :label="item.label" :value="item.value" />-->
<!--            </el-select>-->
            <el-tree-select
                ref="areaIdTreeRef"
                v-model="query.unitProject"
                :data="unitProjectOptions"
                placeholder="请选择单位工程"
                multiple
                collapse-tags
                collapse-tags-tooltip
                clearable
                :default-expand-all="true"
                :render-after-expand="false"
                show-checkbox
                style="width: 170px;"
                @change="importantAreaCh"
                @clear="importantAreaClear"
            />
          </el-form-item>
          <el-form-item label="交易状态" class="col-30">
            <el-select v-model="query.status" placeholder="全部" style="width: 100%">
@@ -183,9 +199,9 @@
            </el-table-column>
          </el-table-column>
          
          <!-- 总价 -->
          <el-table-column label="总价" align="center">
            <el-table-column label="单价" prop="unitPrice" width="90">
          <!-- 单价(与“期限(年)”保持相同的父子表头结构) -->
          <el-table-column label="单价" align="center" width="80">
            <el-table-column label="" prop="unitPrice" width="80">
              <template #default="{ row }">
                <div v-if="row.isSpacer" class="spacer-cell"></div>
                <div v-else-if="!row.isMainOrder" class="price-info">
@@ -204,7 +220,11 @@
                </div>
              </template>
            </el-table-column>
            <el-table-column label="数量" prop="quantity" width="50">
          </el-table-column>
          <!-- 数量(与“期限(年)”保持相同的父子表头结构) -->
          <el-table-column label="数量" align="center" width="80">
            <el-table-column label="" prop="quantity" width="80" align="center">
              <template #default="{ row }">
                <div v-if="row.isSpacer" class="spacer-cell"></div>
                <div v-else-if="!row.isMainOrder" class="quantity">{{ row.quantity }}</div>
@@ -214,7 +234,7 @@
          
          <!-- 期限(年) -->
          <el-table-column label="期限(年)" align="center" width="80">
            <el-table-column label="" prop="period" width="80">
            <el-table-column label="" prop="period" width="80" align="center">
              <template #default="{ row }">
                <div v-if="row.isSpacer" class="spacer-cell"></div>
                <div v-else-if="!row.isMainOrder" class="period-info">
@@ -317,6 +337,7 @@
const router = useRouter()
const userStore = useUserInfo()
const areaIdTreeRef=ref<any>()
// 状态选项(更新为新的工作流程状态)
const statusOptions = [
@@ -339,12 +360,13 @@
const query = reactive({
  productName: '',
  industry: '',
  unitProject: '',
  unitProject: [] as string[],
  productType: '',
  productSubType: '',
  importantDistrictIdList: [] as string[],
  orderNo: '',
  status: '',
  dateRange: [],
  dateRange: [] as string[],
})
// 分页信息
@@ -396,6 +418,24 @@
  return 'currency'
}
const importantAreaCh=()=>{
  let checkedKeys = areaIdTreeRef.value!.getCheckedNodes(false, true)
  if(checkedKeys&&checkedKeys.length>0&& query.unitProject.length>0){
    query.importantDistrictIdList=[] as string[]
    checkedKeys.forEach((item:any)=>{
      if(item.children&&item.children.length>0){
        query.importantDistrictIdList.push(item.value)
      }
    })
  }
}
const importantAreaClear=()=>{
  query.unitProject = [] as string[]
  query.importantDistrictIdList = [] as string[]
  areaIdTreeRef.value.setCheckedKeys([])
}
// 获取行业领域选项
const getIndustryOptions = async () => {
  try {
@@ -435,14 +475,40 @@
  try {
    const res = await productApi.getCategoryByParent({ parentId: industryCode })
    if (res?.code === 200 && res.data) {
      unitProjectOptions.value = res.data.map((item: any) => ({
        label: item.name,
        value: item.id
      }))
      unitProjectOptions.value = handleIndustryData(res.data)
    }
  } catch (error) {
    console.error('获取单位工程选项失败:', error)
    unitProjectOptions.value = []
  }
}
const handleIndustryData=(list:any)=>{
  if(list&& list.length>0){
    let data=list.map((item:any)=>{
      return {
        label:item.name,
        value:item.id,
        parentId:item.parentId,
        parentName:item.parentName,
        children:item.childrenList?handleIndustryChildData(item,item.childrenList):[]
      }
    })
    return data
  }
}
const handleIndustryChildData=(parentItem:any,childList:any)=>{
  if(childList&& childList.length>0){
    let data=childList.map((item:any)=>{
      return {
        parentId:parentItem.id,
        parentName:parentItem.name,
        label:item.name,
        value:item.id,
        children:item.childrenList?handleIndustryChildData(item,item.childrenList):[]
      }
    })
    return data
  }
}
@@ -469,7 +535,7 @@
// 处理行业领域变化
const handleIndustryChange = async (value: string) => {
  // 清空单位工程选择
  query.unitProject = ''
  query.unitProject = [] as string[]
  // 获取对应的单位工程选项
  await getUnitProjectOptions(value)
}
@@ -595,12 +661,13 @@
  
  // 添加产品条件查询
  if (query.industry) payload.industryId = query.industry
  if (query.unitProject) payload.unitProjectId = query.unitProject
  if (query.unitProject.length > 0) payload.unitProjectId = query.unitProject
  if (query.importantDistrictIdList.length > 0) payload.importantDistrictId = query.importantDistrictIdList
  if (query.productType) payload.productTypeId = query.productType
  if (query.productSubType) payload.productSubTypeId = query.productSubType
  // 根据是否有产品条件选择不同的API
  const hasProductConditions = query.industry || query.unitProject || query.productType || query.productSubType
  const hasProductConditions = query.industry || query.unitProject.length > 0 || query.productType || query.productSubType
  const apiMethod = hasProductConditions ? fetchApprovalPageWithProductConditions : fetchApprovalPage
  
  const res = (await apiMethod(payload)) as any
@@ -668,7 +735,7 @@
  Object.assign(query, {
    productName: '',
    industry: '',
    unitProject: '',
    unitProject: [],
    productType: '',
    productSubType: '',
    orderNo: '',
@@ -955,6 +1022,7 @@
.period-info {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 12px;
  
src/views/productManage/price/index.vue
@@ -13,7 +13,7 @@
            <el-icon class="section-icon"><Goods /></el-icon>
            <span>产品基本信息</span>
          </div>
          <div class="id-info">产品ID:{{ currentProductId || '未提供' }}</div>
<!--          <div class="id-info">产品ID:{{ currentProductId || '未提供' }}</div>-->
        </div>
      </template>
@@ -856,7 +856,7 @@
function handleToggleEnableStatus(row: any) {
  const newStatus = row.enableStatus === 'ENABLED' ? 'DISABLED' : 'ENABLED'
  ElMessageBox.confirm(
    `确认要${newStatus === 'ENABLED' ? '启用' : '停用'}该价格(ID: ${row.id})吗?`,
    `确认要${newStatus === 'ENABLED' ? '启用' : '停用'}该定价标准吗?`,
    '状态变更',
    { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }
  )
src/views/productManage/productOrderStatusDialog/index.vue
@@ -1,7 +1,7 @@
<template>
  <el-dialog
    v-model="visible"
    title="产品订单"
    title="产品订购"
    width="900px"
    destroy-on-close
    class="order-status-dialog"
@@ -30,19 +30,22 @@
          <table class="order-info-table">
            <tbody>
              <tr>
                <td class="label">订单编号:</td>
                <td class="value">{{ order.id }}</td>
                <td class="label">申请时间:</td>
                <td class="label">订单编号</td>
                <td class="value">
                  {{ order.id }}
                  <el-link type="primary" @click="goBuyerCenter" style="margin-left: 8px">前往买家中心</el-link>
                </td>
                <td class="label">申请时间</td>
                <td class="value">{{ order.applyTime }}</td>
              </tr>
              <tr>
                <td class="label">产品名称:</td>
                <td class="label">产品名称</td>
                <td class="value">{{ order.productName }}</td>
                <td class="label">提供者:</td>
                <td class="label">提供者</td>
                <td class="value">{{ order.provider }}</td>
              </tr>
              <tr>
                <td class="label">订单状态:</td>
                <td class="label">订单状态</td>
                <td class="value">{{ statusText(order.status) }}</td>
                <td></td>
                <td class="value link">
@@ -65,6 +68,7 @@
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { useRouter } from 'vue-router'
interface Props {
  modelValue: boolean
@@ -92,6 +96,7 @@
const loading = ref(false)
const order = ref<OrderDetail | null>(null)
const router = useRouter()
// 模拟订单数据
const mockOrders: Record<string, OrderDetail> = {
@@ -158,6 +163,10 @@
  // 仅演示
  window.alert('这里可跳转到订单详情页(示例)')
}
const goBuyerCenter = () => {
  router.push({ name: 'tradeBuyerCenter', query: { t: String(Date.now()) } })
}
</script>
<style scoped lang="scss">
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>
@@ -305,19 +262,22 @@
          <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">
@@ -348,6 +308,7 @@
<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'
@@ -359,6 +320,7 @@
import workFlowApi from '@/api/workFlowApi'
const route = useRoute()
const router = useRouter()
interface PriceItem {
  id: number
@@ -476,6 +438,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)
const totalByType = computed(() => {
@@ -548,6 +514,7 @@
  try {
    await removeFromCart(String(suite.id))
    orderSuites.value.splice(index, 1)
    selectedSuiteIds.value.delete(suite.id)
  } catch (e) {
  }
}
@@ -1038,7 +1005,9 @@
    PRIVATE_INCREMENT: '私有增量包',
    PUBLIC_INCREMENT: '公有增量包',
    OTA: 'OTA服务',
    CLOUD: '云服务'
    CLOUD: '云服务',
    RESOURCE_PACKAGE: '资源包',
    PERSONAL: '个人'
  }
  return map[salesForm] || salesForm
}
@@ -1114,6 +1083,24 @@
  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(';')
}
// 获取分组后的表头数据
const getGroupedHeaders = (tabData: PriceItem[]) => {
  const groups: Record<string, { count: number; productSuite: string }> = {}
src/views/tradeManage/buyer/index.vue
@@ -14,9 +14,25 @@
            </el-select>
          </el-form-item>
          <el-form-item label="" class="col-17">
            <el-select v-model="query.unitProject" placeholder="请选择单位工程" clearable style="width: 100%">
              <el-option v-for="item in unitProjectOptions" :key="item.value" :label="item.label" :value="item.value" />
            </el-select>
<!--            <el-select v-model="query.unitProject" placeholder="请选择单位工程" clearable style="width: 100%">-->
<!--              <el-option v-for="item in unitProjectOptions" :key="item.value" :label="item.label" :value="item.value" />-->
<!--            </el-select>-->
            <el-tree-select
                ref="areaIdTreeRef"
                v-model="query.unitProject"
                :data="unitProjectOptions"
                placeholder="请选择单位工程"
                multiple
                collapse-tags
                collapse-tags-tooltip
                clearable
                :default-expand-all="true"
                :render-after-expand="false"
                show-checkbox
                style="width: 170px;"
                @change="importantAreaCh"
                @clear="importantAreaClear"
            />
          </el-form-item>
          <el-form-item label="交易状态" class="col-30">
            <el-select v-model="query.status" placeholder="全部" style="width: 100%">
@@ -57,8 +73,8 @@
        <!-- 第三行:操作按钮(右对齐) -->
        <div class="form-row actions">
          <el-form-item class="row-actions">
            <el-button type="primary" @click="handleSearch" :icon="Search">查询</el-button>
            <el-button @click="reset" :icon="Refresh">重置</el-button>
            <el-button type="primary" @click="handleSearch" icon="Search">查询</el-button>
            <el-button @click="reset" icon="Refresh">重置</el-button>
          </el-form-item>
        </div>
      </el-form>
@@ -138,28 +154,9 @@
            </el-table-column>
          </el-table-column>
          <!-- 总价 -->
          <el-table-column label="总价" align="center">
            <el-table-column label="单价" prop="unitPrice" width="90">
              <template #default="{ row }">
                <div v-if="row.isSpacer" class="spacer-cell"></div>
                <div v-else-if="!row.isMainOrder" class="price-info">
                  <span v-if="row.priceType === 'points'" class="price-points">
                    积分 {{ row.unitPrice }}
                  </span>
                  <span v-else-if="row.priceType === 'currency'" class="price-currency">
                    货币 {{ row.unitPrice }}
                  </span>
                  <span v-else-if="row.priceType === 'agreement'" class="price-agreement">
                    协议
                  </span>
                  <span v-else-if="row.priceType === 'free'" class="price-free">
                    免费
                  </span>
                </div>
              </template>
            </el-table-column>
            <el-table-column label="数量" prop="quantity" width="50">
          <!-- 数量 -->
          <el-table-column label="数量" align="center" width="80">
            <el-table-column label="" prop="quantity" width="80" align="center">
              <template #default="{ row }">
                <div v-if="row.isSpacer" class="spacer-cell"></div>
                <div v-else-if="!row.isMainOrder" class="quantity">{{ row.quantity }}</div>
@@ -169,7 +166,7 @@
          <!-- 期限(年) -->
          <el-table-column label="期限(年)" align="center" width="80">
            <el-table-column label="" prop="period" width="80">
            <el-table-column label="" prop="period" width="80" align="center">
              <template #default="{ row }">
                <div v-if="row.isSpacer" class="spacer-cell"></div>
                <div v-else-if="!row.isMainOrder" class="period-info">
@@ -290,6 +287,8 @@
const router = useRouter()
const userStore = useUserInfo()
const areaIdTreeRef=ref()
// 状态选项(更新为新的工作流程状态)
const statusOptions = [
  { label: '全部', value: '' },
@@ -307,12 +306,25 @@
const productSubTypeOptions = ref<any[]>([])
// 查询条件
const query = reactive({
type BuyerQuery = {
  productName: string
  industry: string
  unitProject: string[]
  productType: string
  productSubType: string
  importantDistrictIdList: string[]
  orderNo: string
  status: string
  dateRange: string[]
}
const query = reactive<BuyerQuery>({
  productName: '',
  industry: '',
  unitProject: '',
  unitProject: [],
  productType: '',
  productSubType: '',
  importantDistrictIdList: [],
  orderNo: '',
  status: '',
  dateRange: [],
@@ -360,6 +372,25 @@
  return 'currency'
}
const importantAreaCh=()=>{
  let checkedKeys = areaIdTreeRef.value!.getCheckedNodes(false, true)
  if(checkedKeys&&checkedKeys.length>0&& query.unitProject.length>0){
    query.importantDistrictIdList=[]
    checkedKeys.forEach((item:any)=>{
      if(item.children&&item.children.length>0){
        query.importantDistrictIdList.push(item.value)
      }
    })
  }
}
const importantAreaClear=()=>{
  query.unitProject = []
  query.importantDistrictIdList = []
  areaIdTreeRef.value.setCheckedKeys([])
}
// 获取行业领域选项
const getIndustryOptions = async () => {
  try {
@@ -400,14 +431,40 @@
  try {
    const res = await productApi.getCategoryByParent({ parentId: industryCode })
    if (res?.code === 200 && res.data) {
      unitProjectOptions.value = res.data.map((item: any) => ({
        label: item.name,
        value: item.id
      }))
      unitProjectOptions.value = handleIndustryData(res.data)
    }
  } catch (error) {
    console.error('获取单位工程选项失败:', error)
    unitProjectOptions.value = []
  }
}
const handleIndustryData=(list:any)=>{
  if(list&& list.length>0){
    let data=list.map((item:any)=>{
      return {
        label:item.name,
        value:item.id,
        parentId:item.parentId,
        parentName:item.parentName,
        children:item.childrenList?handleIndustryChildData(item,item.childrenList):[]
      }
    })
    return data
  }
}
const handleIndustryChildData=(parentItem:any,childList:any)=>{
  if(childList&& childList.length>0){
    let data=childList.map((item:any)=>{
      return {
        parentId:parentItem.id,
        parentName:parentItem.name,
        label:item.name,
        value:item.id,
        children:item.childrenList?handleIndustryChildData(item,item.childrenList):[]
      }
    })
    return data
  }
}
@@ -434,7 +491,8 @@
// 处理行业领域变化
const handleIndustryChange = async (value: string) => {
  // 清空单位工程选择
  query.unitProject = ''
  query.unitProject = []
  query.importantDistrictIdList = []
  // 获取对应的单位工程选项
  await getUnitProjectOptions(value)
}
@@ -478,7 +536,7 @@
    // 主订单行,合并所有列显示订单信息
    if (columnIndex === 0) { // 第一列,合并所有列
      return {
        colspan: 8, // 总共8列:订单信息2列 + 购买方式2列 + 总价2列 + 期限1列 + 操作1列
        colspan: 7, // 总共7列:订单信息2列 + 购买方式2列 + 数量1列 + 期限1列 + 操作1列
        rowspan: 1
      }
    } else {
@@ -510,7 +568,7 @@
          }
        }
      }
    } else if (columnIndex === 7) { // 操作列(第8列)
    } else if (columnIndex === 6) { // 操作列(第7列)
      // 找到当前子订单所属的主订单
      const parentOrder = row.parentOrder
      if (parentOrder && parentOrder.subOrders) {
@@ -541,6 +599,7 @@
// 搜索处理(接入真实后端)
const handleSearch = async () => {
  const filterEvaluated = query.status === 'EVALUATED'
  const payload: any = {
    pageNum: page.current,
    pageSize: page.size,
@@ -548,7 +607,9 @@
    orderId: query.orderNo || undefined,
    userId: userStore.getUserId ? userStore.getUserId : undefined,
  }
  if (query.status) payload.orderStatus = statusUiToServer[query.status]
  if (query.status) {
    payload.orderStatus = filterEvaluated ? OrderStatus.COMPLETED : statusUiToServer[query.status]
  }
  if (Array.isArray(query.dateRange) && query.dateRange.length === 2) {
    payload.applyTimeStart = query.dateRange[0]
    payload.applyTimeEnd = query.dateRange[1]
@@ -556,17 +617,22 @@
  // 添加产品条件查询
  if (query.industry) payload.industryId = query.industry
  if (query.unitProject) payload.unitProjectId = query.unitProject
  if (query.unitProject.length > 0) payload.unitProjectId = query.unitProject
  if (query.importantDistrictIdList.length > 0) payload.importantDistrictId = query.importantDistrictIdList
  if (query.productType) payload.productTypeId = query.productType
  if (query.productSubType) payload.productSubTypeId = query.productSubType
  // 根据是否有产品条件选择不同的API
  const hasProductConditions = query.industry || query.unitProject || query.productType || query.productSubType
  const hasProductConditions = query.industry || query.unitProject.length > 0 || query.productType || query.productSubType
  const apiMethod = hasProductConditions ? orderApi.getBuyerOrderPageWithProductConditions : orderApi.getBuyerOrderPage
  const res = (await apiMethod(payload)) as any
  const pageData = res?.data
  const list: any[] = Array.isArray(pageData?.list) ? pageData.list : []
  let list: any[] = Array.isArray(pageData?.list) ? pageData.list : []
  // 若筛选“已评价”,先以已完成查询,再在前端按已评价过滤
  if (filterEvaluated) {
    list = list.filter((order: any) => order?.isEvaluate === '已评价')
  }
  page.total = Number(pageData?.total || 0)
  const flatData: any[] = []
@@ -617,9 +683,10 @@
  Object.assign(query, {
    productName: '',
    industry: '',
    unitProject: '',
    unitProject: [],
    productType: '',
    productSubType: '',
    importantDistrictIdList: [],
    orderNo: '',
    status: '',
    dateRange: [],
@@ -935,6 +1002,7 @@
.period-info {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 12px;
@@ -1065,6 +1133,7 @@
  font-size: 12px;
  color: #303133;
  font-weight: 500;
  text-align: center;
}
.pagination-container {
src/views/tradeManage/detail/index.vue
@@ -68,10 +68,16 @@
        </el-descriptions-item>
        <el-descriptions-item label="提供者">{{ detail.supplier }}</el-descriptions-item>
        <el-descriptions-item label="行业领域">{{ detail.industry }}</el-descriptions-item>
        <el-descriptions-item label="单位工程">{{ detail.projectUnit }}</el-descriptions-item>
        <el-descriptions-item label="单位工程">
          <el-tooltip effect="dark" :content="detail.projectUnit || '-'" placement="top" :disabled="!(detail.projectUnit && String(detail.projectUnit).trim())" popper-class="tooltip-wrap">
            <div class="ellipsis-1">{{ detail.projectUnit || '-' }}</div>
          </el-tooltip>
        </el-descriptions-item>
        <el-descriptions-item label="产品类型">{{ detail.productType || '-' }}</el-descriptions-item>
        <el-descriptions-item label="产品简介">
          <div class="desc-wrap">{{ detail.productDesc }}</div>
          <el-tooltip effect="dark" :content="detail.productDesc || '-'" placement="top" :disabled="!(detail.productDesc && String(detail.productDesc).trim())" popper-class="tooltip-wrap" trigger="click">
            <div class="desc-wrap ellipsis-3">{{ detail.productDesc || '-' }}</div>
          </el-tooltip>
        </el-descriptions-item>
      </el-descriptions>
@@ -287,6 +293,53 @@
      </div>
    </el-card>
    <!-- 交易评价(当已评价时显示) -->
    <el-card class="mt15" shadow="never" v-if="showEvaluation">
      <div class="title">交易评价</div>
      <div class="evaluation-content">
        <div class="evaluation-form">
          <div class="rating-section">
            <div class="rating-items">
              <div class="rating-row">
                <div class="rating-item">
                  <label class="required">综合评分:</label>
                  <el-rate :model-value="evaluation.overallRating" :max="5" disabled :colors="['#99A9BF', '#F7BA2A', '#FF9900']" />
                </div>
                <div class="rating-item">
                  <label class="required">服务评分:</label>
                  <el-rate :model-value="evaluation.serviceRating" :max="5" disabled :colors="['#99A9BF', '#F7BA2A', '#FF9900']" />
                </div>
              </div>
              <div class="rating-row">
                <div class="rating-item">
                  <label class="required">质量评分:</label>
                  <el-rate :model-value="evaluation.qualityRating" :max="5" disabled :colors="['#99A9BF', '#F7BA2A', '#FF9900']" />
                </div>
                <div class="rating-item">
                  <label class="required">速度评分:</label>
                  <el-rate :model-value="evaluation.speedRating" :max="5" disabled :colors="['#99A9BF', '#F7BA2A', '#FF9900']" />
                </div>
              </div>
            </div>
          </div>
          <div class="form-item">
            <label class="required">评价内容:</label>
            <div class="eval-text">{{ evaluation.content || '-' }}</div>
          </div>
          <div class="form-item">
            <label>其他信息:</label>
            <div class="eval-meta">
              <span>是否匿名:{{ evaluation.isAnonymous ? '是' : '否' }}</span>
              <span class="split">|</span>
              <span>评价时间:{{ evaluation.evaluateTime || '-' }}</span>
            </div>
          </div>
        </div>
      </div>
    </el-card>
    <!-- 返回按钮 -->
    <div class="action-buttons">
        <el-button @click="goBack">返回</el-button>
@@ -309,6 +362,15 @@
const route = useRoute()
const router = useRouter()
const detail = reactive<any>({ items: [], records: [], nodes: [] })
const evaluation = reactive<any>({
  content: '',
  overallRating: 0,
  serviceRating: 0,
  qualityRating: 0,
  speedRating: 0,
  isAnonymous: false,
  evaluateTime: ''
})
const orderTableWrapRef = ref<HTMLElement | null>(null)
const activeTab = ref('records')
const userStore = useUserInfo()
@@ -334,6 +396,11 @@
  const statusOrder = ['WAIT_UPLOAD', 'WAIT_AUTHORIZE', 'WAIT_CONFIRM', 'COMPLETED', 'EVALUATED']
  const currentStatus = statusServerToUi[statusName]
  return currentStatus && statusOrder.indexOf(currentStatus) >= statusOrder.indexOf('WAIT_CONFIRM')
})
// 是否显示评价卡片(已评价时显示)
const showEvaluation = computed(() => {
  return (detail.isEvaluate === '已评价')
})
// 计算表格数据,添加汇总行
@@ -446,6 +513,7 @@
      projectUnit: data.projectUnit || '-',
      productType: data.productType || '-',
      productDesc: data.productDesc || '-',
      isEvaluate: data.isEvaluate || '未评价'
    }
    // 明细项映射
@@ -481,6 +549,18 @@
      nodes: [],
      workflowId: data.workflowId || data.processinstId || ''
    })
    // 映射交易评价信息(如果存在)
    if (data.evaluation) {
      evaluation.content = data.evaluation.content || ''
      evaluation.overallRating = Number(data.evaluation.rating || data.evaluation.overallRating || 0)
      evaluation.serviceRating = Number(data.evaluation.serviceRating || 0)
      evaluation.qualityRating = Number(data.evaluation.qualityRating || 0)
      // 后端为 deliveryRating,对齐前端 speedRating 命名
      evaluation.speedRating = Number(data.evaluation.deliveryRating || data.evaluation.speedRating || 0)
      evaluation.isAnonymous = Boolean(data.evaluation.isAnonymous)
      evaluation.evaluateTime = formatDateTime((data.evaluation.replyTime || data.evaluation.createdAt || data.evaluation.createTime) as any)
    }
    // 初始化交易信息备注数据
    remarkItems.value = (detail.items || []).map((item: any, index: number) => {
@@ -1011,6 +1091,25 @@
  line-height: 22px;
}
/* 单行省略(用于“单位工程”) */
.ellipsis-1 {
  max-height: 22px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 多行省略(用于“产品简介”,固定为3行,可按需调整) */
.ellipsis-3 {
  display: -webkit-box;
  line-clamp: 3;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* 审批追踪标签页样式 */
.approval-tabs {
  margin-top: 15px;
src/views/tradeManage/seller/index.vue
@@ -14,9 +14,25 @@
            </el-select>
          </el-form-item>
          <el-form-item label="" class="col-17">
            <el-select v-model="query.unitProject" placeholder="请选择单位工程" clearable style="width: 100%">
              <el-option v-for="item in unitProjectOptions" :key="item.value" :label="item.label" :value="item.value" />
            </el-select>
<!--            <el-select v-model="query.unitProject" placeholder="请选择单位工程" clearable style="width: 100%">-->
<!--              <el-option v-for="item in unitProjectOptions" :key="item.value" :label="item.label" :value="item.value" />-->
<!--            </el-select>-->
            <el-tree-select
                ref="areaIdTreeRef"
                v-model="query.unitProject"
                :data="unitProjectOptions"
                placeholder="请选择单位工程"
                multiple
                collapse-tags
                collapse-tags-tooltip
                clearable
                :default-expand-all="true"
                :render-after-expand="false"
                show-checkbox
                style="width: 170px;"
                @change="importantAreaCh"
                @clear="importantAreaClear"
            />
          </el-form-item>
          <el-form-item label="产品类型" class="col-30">
            <el-select v-model="query.productType" placeholder="请选择产品类型" clearable style="width: 100%" @change="handleProductTypeChange">
@@ -137,9 +153,9 @@
            </el-table-column>
          </el-table-column>
          <!-- 总价 -->
          <el-table-column label="总价" align="center">
            <el-table-column label="单价" prop="unitPrice" width="90">
          <!-- 单价(与“期限(年)”保持相同的父子表头结构) -->
          <el-table-column label="单价" align="center" width="80">
            <el-table-column label="" prop="unitPrice" width="80">
              <template #default="{ row }">
                <div v-if="row.isSpacer" class="spacer-cell"></div>
                <div v-else-if="!row.isMainOrder" class="price-info">
@@ -158,7 +174,11 @@
                </div>
              </template>
            </el-table-column>
            <el-table-column label="数量" prop="quantity" width="50">
          </el-table-column>
          <!-- 数量(与“期限(年)”保持相同的父子表头结构) -->
          <el-table-column label="数量" align="center" width="80">
            <el-table-column label="" prop="quantity" width="80" align="center">
              <template #default="{ row }">
                <div v-if="row.isSpacer" class="spacer-cell"></div>
                <div v-else-if="!row.isMainOrder" class="quantity">{{ row.quantity }}</div>
@@ -168,7 +188,7 @@
          <!-- 期限(年) -->
          <el-table-column label="期限(年)" align="center" width="80">
            <el-table-column label="" prop="period" width="80">
            <el-table-column label="" prop="period" width="80" align="center">
              <template #default="{ row }">
                <div v-if="row.isSpacer" class="spacer-cell"></div>
                <div v-else-if="!row.isMainOrder" class="period-info">
@@ -254,6 +274,7 @@
const router = useRouter()
const userStore = useUserInfo()
const areaIdTreeRef=ref()
// 状态选项(更新为新的工作流程状态)
const statusOptions = [
@@ -275,12 +296,13 @@
const query = reactive({
  productName: '',
  industry: '',
  unitProject: '',
  unitProject: [] as string[],
  productType: '',
  productSubType: '',
  importantDistrictIdList: [] as string[],
  orderNo: '',
  status: '',
  dateRange: [],
  dateRange: [] as string[],
})
// 分页信息
@@ -363,14 +385,40 @@
  try {
    const res = await productApi.getCategoryByParent({ parentId: industryCode })
    if (res?.code === 200 && res.data) {
      unitProjectOptions.value = res.data.map((item: any) => ({
        label: item.name,
        value: item.id
      }))
      unitProjectOptions.value = handleIndustryData(res.data)
    }
  } catch (error) {
    console.error('获取单位工程选项失败:', error)
    unitProjectOptions.value = []
  }
}
const handleIndustryData=(list:any)=>{
  if(list&& list.length>0){
    let data=list.map((item:any)=>{
      return {
        label:item.name,
        value:item.id,
        parentId:item.parentId,
        parentName:item.parentName,
        children:item.childrenList?handleIndustryChildData(item,item.childrenList):[]
      }
    })
    return data
  }
}
const handleIndustryChildData=(parentItem:any,childList:any)=>{
  if(childList&& childList.length>0){
    let data=childList.map((item:any)=>{
      return {
        parentId:parentItem.id,
        parentName:parentItem.name,
        label:item.name,
        value:item.id,
        children:item.childrenList?handleIndustryChildData(item,item.childrenList):[]
      }
    })
    return data
  }
}
@@ -394,10 +442,28 @@
  }
}
const importantAreaCh=()=>{
  let checkedKeys = areaIdTreeRef.value!.getCheckedNodes(false, true)
  if(checkedKeys&&checkedKeys.length>0&& query.unitProject.length>0){
    query.importantDistrictIdList=[]
    checkedKeys.forEach((item:any)=>{
      if(item.children&&item.children.length>0){
        query.importantDistrictIdList.push(String(item.value))
      }
    })
  }
}
const importantAreaClear=()=>{
  query.unitProject = []
  query.importantDistrictIdList = []
  areaIdTreeRef.value.setCheckedKeys([])
}
// 处理行业领域变化
const handleIndustryChange = async (value: string) => {
  // 清空单位工程选择
  query.unitProject = ''
  query.unitProject = []
  // 获取对应的单位工程选项
  await getUnitProjectOptions(value)
}
@@ -409,8 +475,6 @@
  // 获取对应的产品子级选项
 // await getProductSubTypeOptions(value)
}
// 获取状态类型
const getStatusType = (status: string) => {
@@ -442,7 +506,7 @@
    // 主订单行,合并所有列显示订单信息
    if (columnIndex === 0) { // 第一列,合并所有列
      return {
        colspan: 8, // 总共8列:订单信息2列 + 购买方式2列 + 总价2列 + 期限1列 + 操作1列
        colspan: 8, // 总共8列:订单信息2列 + 购买方式2列 + 单价1列 + 数量1列 + 期限1列 + 操作1列
        rowspan: 1
      }
    } else {
@@ -525,12 +589,13 @@
    // 添加产品条件查询
    if (query.industry) payload.industryId = query.industry
    if (query.unitProject) payload.unitProjectId = query.unitProject
    if (query.unitProject.length > 0) payload.unitProjectId = query.unitProject
    if (query.importantDistrictIdList.length > 0) payload.importantDistrictId = query.importantDistrictIdList
    if (query.productType) payload.productTypeId = query.productType
    if (query.productSubType) payload.productSubTypeId = query.productSubType
    // 根据是否有产品条件选择不同的API
    const hasProductConditions = query.industry || query.unitProject || query.productType || query.productSubType
    const hasProductConditions = query.industry || query.unitProject.length > 0 || query.productType || query.productSubType
    const apiMethod = hasProductConditions ? orderApi.getSellerOrderPageWithProductConditions : orderApi.getSellerOrderPage
    const res = (await apiMethod(payload)) as any
@@ -858,6 +923,7 @@
.period-info {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 12px;
vite.config.ts
@@ -33,7 +33,7 @@
      // target:'http://10.209.233.16/admin',//信创正式
      // target: 'http://36.133.126.111:7099/api', //测试
      // target: 'https://zynlpt.ccccltd.cn/admin', // 正式  (要打开changeOrigin和rewrite)
      //   target: 'http://localhost:8089',
      //  target: 'http://localhost:8089',
       target: 'http://36.133.126.111:7099/trade-api',
      changeOrigin: true, // 允许跨域
      rewrite: (path) => path.replace(/^\/api/, '/'), //连测试环境要注释这行,连后端个人则打开