gaoluyang
2026-04-21 207c564c2b8d46fd86160c4f6583c2fc9d4a4e5c
src/pages/cooperativeOffice/collaborativeApproval/approve.vue
@@ -9,6 +9,11 @@
        <text class="info-title">申请信息</text>
      </view>
      <view class="info-content">
        <!-- 审批标题(仅 approveType=9 或 10 显示) -->
        <view v-if="approvalData.approveType === 9 || approvalData.approveType === 10" class="info-row">
          <text class="info-label">审批标题</text>
          <text class="info-value">{{ approvalData.approveTitle || '-' }}</text>
        </view>
        <view class="info-row">
          <text class="info-label">申请人</text>
          <text class="info-value">{{ approvalData.approveUserName }}</text>
@@ -18,14 +23,14 @@
          <text class="info-value">{{ approvalData.approveDeptName }}</text>
        </view>
        <view class="info-row">
          <text class="info-label">申请事由</text>
          <text class="info-label">{{ getApproveReasonLabel() }}</text>
          <text class="info-value">{{ approvalData.approveReason }}</text>
        </view>
        <view class="info-row">
          <text class="info-label">申请日期</text>
          <text class="info-value">{{ approvalData.approveTime }}</text>
        </view>
        <!-- approveType=2 请假相关字段 -->
        <template v-if="approvalData.approveType === 2">
          <view class="info-row">
@@ -37,19 +42,89 @@
            <text class="info-value">{{ approvalData.endDate || '-' }}</text>
          </view>
        </template>
        <!-- approveType=3 出差相关字段 -->
        <view v-if="approvalData.approveType === 3" class="info-row">
          <text class="info-label">出差地点</text>
          <text class="info-value">{{ approvalData.location || '-' }}</text>
        </view>
        <!-- approveType=4 报销相关字段 -->
        <view v-if="approvalData.approveType === 4" class="info-row">
          <text class="info-label">报销金额</text>
          <text class="info-value">{{ approvalData.price ? `¥${approvalData.price}` : '-' }}</text>
        </view>
      </view>
    </view>
    <!-- 销售详情(approveType=9) -->
    <view v-if="isSalesApproval && currentSales.salesContractNo" class="sales-detail">
      <view class="detail-header">
        <text class="detail-title">销售详情</text>
      </view>
      <view class="detail-content">
        <view class="detail-row">
          <text class="detail-label">销售合同号</text>
          <text class="detail-value">{{ currentSales.salesContractNo }}</text>
        </view>
        <view class="detail-row">
          <text class="detail-label">客户名称</text>
          <text class="detail-value">{{ currentSales.customerName }}</text>
        </view>
        <view class="detail-row">
          <text class="detail-label">业务员</text>
          <text class="detail-value">{{ currentSales.salesman }}</text>
        </view>
        <view class="detail-row">
          <text class="detail-label">录入人</text>
          <text class="detail-value">{{ currentSales.entryPersonName }}</text>
        </view>
        <view class="detail-row">
          <text class="detail-label">签订日期</text>
          <text class="detail-value">{{ currentSales.executionDate }}</text>
        </view>
        <view class="detail-row">
          <text class="detail-label">付款方式</text>
          <text class="detail-value">{{ currentSales.paymentMethod }}</text>
        </view>
        <view class="detail-row total-row">
          <text class="detail-label">合同金额</text>
          <text class="detail-value highlight">¥{{ calculateSalesTotalAmount() }}</text>
        </view>
        <!-- 产品明细 -->
        <view v-if="currentSales.productData && currentSales.productData.length > 0" class="product-list">
          <view class="product-header">
            <text class="product-title">产品明细</text>
          </view>
          <view v-for="(product, pIndex) in currentSales.productData" :key="pIndex" class="product-item">
            <view class="product-row">
              <text class="product-label">产品名称</text>
              <text class="product-value">{{ product.productCategory }}</text>
            </view>
            <view class="product-row">
              <text class="product-label">规格型号</text>
              <text class="product-value">{{ product.specificationModel }}</text>
            </view>
            <view class="product-row">
              <text class="product-label">数量</text>
              <text class="product-value">{{ product.quantity }}</text>
            </view>
            <view class="product-row">
              <text class="product-label">含税单价</text>
              <text class="product-value">¥{{ Number(product.taxInclusiveUnitPrice || 0).toFixed(2) }}</text>
            </view>
            <view class="product-row">
              <text class="product-label">含税总价</text>
              <text class="product-value">¥{{ Number(product.taxInclusiveTotalPrice || 0).toFixed(2) }}</text>
            </view>
          </view>
        </view>
      </view>
    </view>
    <!-- 加载状态 -->
    <view v-if="salesLoading" class="loading-state">
      <text>加载销售详情中...</text>
    </view>
    <!-- 审批流程 -->
@@ -128,7 +203,9 @@
<script setup>
import { ref, onMounted, computed } from 'vue'
import { approveProcessGetInfo, approveProcessDetails, updateApproveNode } from '@/api/collaborativeApproval/approvalProcess'
import { getSalesByCode } from '@/api/procurementManagement/procurementLedger.js'
import useUserStore from '@/store/modules/user'
const showToast = (message) => {
   uni.showToast({
      title: message,
@@ -142,14 +219,44 @@
const approvalSteps = ref([])
const approvalOpinion = ref('')
const approveId = ref('')
const approveType = ref(0)
const isSalesApproval = computed(() => Number(approveType.value) === 9)
const currentSales = ref({})
const salesLoading = ref(false)
// 从详情接口字段对齐 canApprove:仅当有 isShen 的节点时可审批
const canApprove = computed(() => {
  return approvalSteps.value.some(step => step.isShen === true)
})
// 获取审批事由标签
const getApproveReasonLabel = () => {
  const type = Number(approveType.value)
  if (type === 5) {
    return '采购合同号'
  } else if (type === 9) {
    return '销售合同号'
  } else if (type === 10) {
    return '审批事由'
  }
  return '申请事由'
}
// 计算销售合同金额(产品明细含税总价之和)
const calculateSalesTotalAmount = () => {
  const products = currentSales.value?.productData || []
  const total = products.reduce((sum, item) => {
    return sum + Number(item.taxInclusiveTotalPrice || 0)
  }, 0)
  return total.toFixed(2)
}
onMounted(() => {
  approveId.value = uni.getStorageSync('approveId')
  const storedApproveType = uni.getStorageSync('approveType')
  if (storedApproveType) {
    approveType.value = Number(storedApproveType)
  }
  if (approveId.value) {
    loadApprovalData()
  }
@@ -159,6 +266,24 @@
  // 基本申请信息
  approveProcessGetInfo({ id: approveId.value }).then(res => {
    approvalData.value = res.data || {}
    // 设置审批类型
    if (res.data && res.data.approveType) {
      approveType.value = Number(res.data.approveType)
    }
    // 销售审批:用审批事由字段承载的"销售合同号"去查销售详情
    if (isSalesApproval.value) {
      const salesContractNo = res.data?.approveReason
      if (salesContractNo) {
        salesLoading.value = true
        getSalesByCode({ salesContractNo }).then(salesRes => {
          currentSales.value = salesRes || {}
        }).catch((err) => {
          console.error('查询销售详情失败:', err)
        }).finally(() => {
          salesLoading.value = false
        })
      }
    }
  })
  // 审批节点详情
  approveProcessDetails(approveId.value).then(res => {
@@ -505,9 +630,117 @@
  }
  
  /* 适配u-button样式 */
  :deep(.u-button) {
    border-radius: 6px;
  }
:deep(.u-button) {
  border-radius: 6px;
}
/* 销售详情样式 */
.sales-detail {
  background: #fff;
  margin: 16px;
  border-radius: 12px;
  overflow: hidden;
}
.detail-header {
  padding: 16px;
  border-bottom: 1px solid #f0f0f0;
  background: #f8f9fa;
}
.detail-title {
  font-size: 16px;
  font-weight: 600;
  color: #333;
}
.detail-content {
  padding: 16px;
}
.detail-row {
  display: flex;
  align-items: center;
  margin-bottom: 12px;
}
.detail-label {
  font-size: 14px;
  color: #666;
  width: 80px;
  flex-shrink: 0;
}
.detail-value {
  font-size: 14px;
  color: #333;
  flex: 1;
}
.detail-value.highlight {
  font-size: 18px;
  color: #e6a23c;
  font-weight: bold;
}
.total-row {
  padding-top: 8px;
  border-top: 1px solid #f0f0f0;
  margin-top: 8px;
}
.product-list {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid #f0f0f0;
}
.product-header {
  margin-bottom: 12px;
}
.product-title {
  font-size: 15px;
  font-weight: 600;
  color: #333;
}
.product-item {
  background: #f8f9fa;
  border-radius: 8px;
  padding: 12px;
  margin-bottom: 8px;
}
.product-row {
  display: flex;
  align-items: center;
  margin-bottom: 6px;
}
.product-row:last-child {
  margin-bottom: 0;
}
.product-label {
  font-size: 13px;
  color: #666;
  width: 70px;
  flex-shrink: 0;
}
.product-value {
  font-size: 13px;
  color: #333;
  flex: 1;
}
.loading-state {
  text-align: center;
  padding: 16px;
  color: #999;
  font-size: 14px;
}
@keyframes pulse {
  0% {