Bang Hu
昨天 8a709ba6db50831048f9c3e2452ea6dc6c3de36f
src/views/tradeManage/detail/index.vue
@@ -2,78 +2,103 @@
  <div class="default-main">
    <!-- 订单信息 + 申请人信息 + 交易内容(合并为同一卡片) -->
    <el-card shadow="never">
      <el-descriptions
        :column="2"
        border
        class="mt10 order-desc fixed-label"
        label-width="180px"
        :label-style="labelStyle"
        :content-style="contentStyle"
      >
        <el-descriptions-item :span="2" class="section-header">
          <template #label>
            <el-icon class="section-icon"><Document /></el-icon>
            <span>订单信息</span>
          </template>
          <template #default></template>
        </el-descriptions-item>
        <el-descriptions-item label="订单编号">{{ detail.orderNo }}</el-descriptions-item>
        <el-descriptions-item label="交易资源类型">{{ detail.resourceTypeName }}</el-descriptions-item>
        <el-descriptions-item label="申请时间">{{ detail.applyTime }}</el-descriptions-item>
        <el-descriptions-item label="交易状态">
          <el-tag :type="getStatusType(detail.status)" size="small">{{ detail.statusName }}</el-tag>
        </el-descriptions-item>
      </el-descriptions>
      <!-- 订单信息 - 使用自定义表格布局 -->
      <div class="order-info-section">
        <div class="section-header">
          <el-icon class="section-icon"><Document /></el-icon>
          <span>订单信息</span>
        </div>
        <div class="order-info-grid">
          <div class="order-info-item">
            <div class="order-label">订单编号</div>
            <div class="order-content">{{ detail.orderNo }}</div>
          </div>
          <div class="order-info-item">
            <div class="order-label">交易资源类型</div>
            <div class="order-content">{{ detail.resourceTypeName }}</div>
          </div>
          <div class="order-info-item">
            <div class="order-label">申请时间</div>
            <div class="order-content">{{ detail.applyTime }}</div>
          </div>
          <div class="order-info-item">
            <div class="order-label">交易状态</div>
            <div class="order-content">
              <el-tag :type="getStatusType(detail.status)" size="small">{{ detail.statusName }}</el-tag>
            </div>
          </div>
        </div>
      </div>
      <!-- 申请人信息(与订单信息同卡片,复用分隔标题样式) -->
      <el-descriptions
        :column="2"
        border
        class="mt15 order-desc fixed-label"
        label-width="180px"
        :label-style="labelStyle"
        :content-style="contentStyle"
      >
        <el-descriptions-item :span="2" class="section-header">
          <template #label>
            <el-icon class="section-icon"><User /></el-icon>
            <span>申请人信息</span>
          </template>
          <template #default></template>
        </el-descriptions-item>
        <el-descriptions-item label="姓名">{{ detail.userName || '-' }}</el-descriptions-item>
        <el-descriptions-item label="单位">{{ detail.unitName || '-' }}</el-descriptions-item>
        <el-descriptions-item label="部门">{{ detail.userDept || '-' }}</el-descriptions-item>
        <el-descriptions-item label="用户名">{{ detail.userAccount || '-' }}</el-descriptions-item>
      </el-descriptions>
      <!-- 申请人信息 - 使用自定义表格布局 -->
      <div class="applicant-info-section">
        <div class="section-header">
          <el-icon class="section-icon"><User /></el-icon>
          <span>申请人信息</span>
        </div>
        <div class="applicant-info-grid">
          <div class="applicant-info-item">
            <div class="applicant-label">姓名</div>
            <div class="applicant-content">{{ detail.userName || '-' }}</div>
          </div>
          <div class="applicant-info-item">
            <div class="applicant-label">单位</div>
            <div class="applicant-content">{{ detail.unitName || '-' }}</div>
          </div>
          <div class="applicant-info-item">
            <div class="applicant-label">部门</div>
            <div class="applicant-content">{{ detail.userDept || '-' }}</div>
          </div>
          <div class="applicant-info-item">
            <div class="applicant-label">用户名</div>
            <div class="applicant-content">{{ detail.userAccount || '-' }}</div>
          </div>
        </div>
      </div>
      <!-- 交易内容(紧随申请人信息,同卡片,复用分隔标题样式) -->
      <el-descriptions
        :column="2"
        border
        class="mt15 order-desc fixed-label"
        label-width="180px"
        :label-style="labelStyle"
        :content-style="contentStyle"
      >
        <el-descriptions-item :span="2" class="section-header">
          <template #label>
            <el-icon class="section-icon"><Goods /></el-icon>
            <span>交易内容</span>
          </template>
          <template #default></template>
        </el-descriptions-item>
        <el-descriptions-item label="产品名称">
          <el-link type="primary" :underline="false">{{ detail.productName }}</el-link>
        </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="产品类型">{{ detail.productType || '-' }}</el-descriptions-item>
        <el-descriptions-item label="产品简介">
          <div class="desc-wrap">{{ detail.productDesc }}</div>
        </el-descriptions-item>
      </el-descriptions>
      <!-- 交易内容 - 使用自定义表格布局 -->
      <div class="transaction-content-section">
        <div class="section-header">
          <el-icon class="section-icon"><Goods /></el-icon>
          <span>交易内容</span>
        </div>
        <div class="transaction-content-grid">
          <div class="transaction-content-item">
            <div class="transaction-label">产品名称</div>
            <div class="transaction-content">
              <el-link type="primary" :underline="false">{{ detail.productName }}</el-link>
            </div>
          </div>
          <div class="transaction-content-item">
            <div class="transaction-label">提供者</div>
            <div class="transaction-content">{{ detail.supplier }}</div>
          </div>
          <div class="transaction-content-item">
            <div class="transaction-label">行业领域</div>
            <div class="transaction-content">{{ detail.industry }}</div>
          </div>
          <div class="transaction-content-item">
            <div class="transaction-label">单位工程</div>
            <div class="transaction-content">
              <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>
            </div>
          </div>
          <div class="transaction-content-item">
            <div class="transaction-label">产品类型</div>
            <div class="transaction-content">{{ detail.productType || '-' }}</div>
          </div>
          <div class="transaction-content-item">
            <div class="transaction-label">产品简介</div>
            <div class="transaction-content">
              <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>
            </div>
          </div>
        </div>
      </div>
      <!-- 订单详情(移动到交易内容下面,同一卡片内) -->
      <div ref="orderTableWrapRef">
@@ -287,6 +312,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 +381,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()
@@ -320,6 +401,7 @@
})
const labelStyle = { width: '180px', maxWidth: '180px' }
const contentStyle = { width: 'calc(50% - 180px)' }
// 文件相关
const fileList = ref<any[]>([])
@@ -334,6 +416,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 +533,7 @@
      projectUnit: data.projectUnit || '-',
      productType: data.productType || '-',
      productDesc: data.productDesc || '-',
      isEvaluate: data.isEvaluate || '未评价'
    }
    // 明细项映射
@@ -481,6 +569,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) => {
@@ -693,7 +793,8 @@
      // 检查响应格式
      const responseData = previewResponse as any
      if (responseData && responseData.code === 200 && responseData.data) {
        previewUrl = responseData.data
        previewUrl = responseData.data.replaceAll("http://192.168.20.52:9000", import.meta.env.VITE_FILE_PREVIEW_URL)
        // previewUrl = responseData.data
        console.log('使用预览URL:', previewUrl)
      } else {
        console.log('预览URL获取失败,使用下载方式')
@@ -1005,11 +1106,184 @@
  width: calc(50% - 180px) !important;
}
/* 订单信息自定义布局样式 */
.order-info-section {
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  margin-top: 10px;
  overflow: hidden;
}
.order-info-section .section-header {
  background: #f3f6fb;
  padding: 12px 16px;
  border-bottom: 1px solid #e4e7ed;
  font-weight: 600;
  display: flex;
  align-items: center;
}
.order-info-section .section-icon {
  margin-right: 6px;
  color: #409eff;
}
.order-info-grid {
  display: grid;
  grid-template-columns: 15% 30% 15% 40%;
  width: 100%;
}
.order-info-item {
  display: contents;
}
.order-info-item .order-label {
  padding: 12px 16px;
  background: #fafafa;
  border: 1px solid #e4e7ed;
  font-size: 14px;
  color: #606266;
  display: flex;
  align-items: center;
}
.order-info-item .order-content {
  padding: 12px 16px;
  border: 1px solid #e4e7ed;
  font-size: 14px;
  color: #303133;
  display: flex;
  align-items: center;
}
/* 申请人信息自定义布局样式 */
.applicant-info-section {
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  margin-top: 15px;
  overflow: hidden;
}
.applicant-info-section .section-header {
  background: #f3f6fb;
  padding: 12px 16px;
  border-bottom: 1px solid #e4e7ed;
  font-weight: 600;
  display: flex;
  align-items: center;
}
.applicant-info-section .section-icon {
  margin-right: 6px;
  color: #409eff;
}
.applicant-info-grid {
  display: grid;
  grid-template-columns: 15% 30% 15% 40%;
  width: 100%;
}
.applicant-info-item {
  display: contents;
}
.applicant-info-item .applicant-label {
  padding: 12px 16px;
  background: #fafafa;
  border: 1px solid #e4e7ed;
  font-size: 14px;
  color: #606266;
  display: flex;
  align-items: center;
}
.applicant-info-item .applicant-content {
  padding: 12px 16px;
  border: 1px solid #e4e7ed;
  font-size: 14px;
  color: #303133;
  display: flex;
  align-items: center;
}
/* 交易内容自定义布局样式 */
.transaction-content-section {
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  margin-top: 15px;
  overflow: hidden;
}
.transaction-content-section .section-header {
  background: #f3f6fb;
  padding: 12px 16px;
  border-bottom: 1px solid #e4e7ed;
  font-weight: 600;
  display: flex;
  align-items: center;
}
.transaction-content-section .section-icon {
  margin-right: 6px;
  color: #409eff;
}
.transaction-content-grid {
  display: grid;
  grid-template-columns: 15% 30% 15% 40%;
  width: 100%;
}
.transaction-content-item {
  display: contents;
}
.transaction-content-item .transaction-label {
  padding: 12px 16px;
  background: #fafafa;
  border: 1px solid #e4e7ed;
  font-size: 14px;
  color: #606266;
  display: flex;
  align-items: center;
}
.transaction-content-item .transaction-content {
  padding: 12px 16px;
  border: 1px solid #e4e7ed;
  font-size: 14px;
  color: #303133;
  display: flex;
  align-items: center;
}
.desc-wrap {
  white-space: pre-wrap;
  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;