gaoluyang
2026-04-21 207c564c2b8d46fd86160c4f6583c2fc9d4a4e5c
湟水峡app
1.协同审批功能删减
已添加3个文件
已修改9个文件
2015 ■■■■■ 文件已修改
src/api/procurementManagement/procurementLedger.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/config.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages.json 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cooperativeOffice/collaborativeApproval/approve.vue 247 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cooperativeOffice/collaborativeApproval/components/approvalDia.vue 535 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cooperativeOffice/collaborativeApproval/components/infoFormDia.vue 504 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cooperativeOffice/collaborativeApproval/detail.vue 214 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cooperativeOffice/collaborativeApproval/index.vue 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cooperativeOffice/collaborativeApproval/indexNew.vue 382 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/index.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/indexItem.vue 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/works.vue 52 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/procurementManagement/procurementLedger.js
@@ -78,4 +78,12 @@
        method: 'get',
        params: query,
    })
}
// æŸ¥è¯¢é”€å”®è¯¦æƒ…(用于销售审批)
export function getSalesByCode(query) {
  return request({
    url: "/purchase/ledger/getSalesByCode",
    method: "get",
    params: query,
  });
}
src/config.js
@@ -1,6 +1,6 @@
// åº”用全局配置
const config = {
  baseUrl: "http://1.15.17.182:9003",
  baseUrl: "http://192.168.0.244:7003",
  fileUrl: "http://1.15.17.182:9002",
  // åº”用信息
  appInfo: {
src/pages.json
@@ -423,6 +423,13 @@
      }
    },
    {
      "path": "pages/cooperativeOffice/collaborativeApproval/index",
      "style": {
        "navigationBarTitleText": "协同审批",
        "navigationStyle": "custom"
      }
    },
    {
      "path": "pages/managementMeetings/meetingSettings/index",
      "style": {
        "navigationBarTitleText": "会议设置",
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% {
src/pages/cooperativeOffice/collaborativeApproval/components/approvalDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,535 @@
<template>
  <div>
    <el-dialog
      v-model="dialogFormVisible"
      :title="operationType === 'add' ? '新增审批流程' : '编辑审批流程'"
      width="700px"
      @close="closeDia"
    >
            <el-form :model="form" label-width="140px" label-position="top" ref="formRef">
                <el-row>
                    <el-col :span="24">
                        <el-form-item label="流程编号:" prop="approveId">
                            <el-input v-model="form.approveId" placeholder="自动编号" clearable disabled/>
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row>
                    <el-col :span="24">
                        <el-form-item label="申请部门:" prop="approveDeptId">
                            <el-select
                                disabled
                                v-model="form.approveDeptId"
                                placeholder="选择部门"
                            >
                                <el-option
                                    v-for="user in productOptions"
                                    :key="user.deptId"
                                    :label="user.deptName"
                                    :value="user.deptId"
                                />
                            </el-select>
                        </el-form-item>
                    </el-col>
                </el-row>
                <!-- å®¡æ‰¹æ ‡é¢˜ï¼ˆä»…自由协同审批显示) -->
                <el-row v-if="isFreeApproval">
                    <el-col :span="24">
                        <el-form-item label="审批标题:" prop="approveTitle">
                            <el-input v-model="form.approveTitle" placeholder="请输入" clearable disabled/>
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row v-if="!isQuotationApproval && !isPurchaseApproval">
                    <el-col :span="24">
                        <el-form-item :label="props.approveType == 5 ? '采购合同号:' : '审批事由:'" prop="approveReason">
                            <el-input v-model="form.approveReason" placeholder="请输入" clearable type="textarea" disabled/>
                        </el-form-item>
                    </el-col>
                </el-row>
                <!-- å®¡æ‰¹äººé€‰æ‹©ï¼ˆåŠ¨æ€èŠ‚ç‚¹ï¼‰ -->
                <el-row :gutter="30">
                    <el-col :span="12">
                        <el-form-item label="申请人:" prop="approveUser">
                            <el-select
                                v-model="form.approveUser"
                                placeholder="选择人员"
                                disabled
                            >
                                <el-option
                                    v-for="user in userList"
                                    :key="user.userId"
                                    :label="user.nickName"
                                    :value="user.userId"
                                />
                            </el-select>
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="申请日期:" prop="approveTime">
                            <el-date-picker
                                v-model="form.approveTime"
                                type="date"
                                placeholder="请选择日期"
                                value-format="YYYY-MM-DD"
                                format="YYYY-MM-DD"
                                clearable
                                style="width: 100%"
                                disabled
                            />
                        </el-form-item>
                    </el-col>
                </el-row>
            </el-form>
      <!-- æŠ¥ä»·å®¡æ‰¹ï¼šå±•示报价详情(复用销售报价"查看详情对话框"内容结构) -->
      <div v-if="isQuotationApproval" style="margin: 10px 0 18px;">
        <el-divider content-position="left">报价详情</el-divider>
        <el-skeleton :loading="quotationLoading" animated>
          <template #template>
            <el-skeleton-item variant="h3" style="width: 30%" />
            <el-skeleton-item variant="text" style="width: 100%" />
            <el-skeleton-item variant="text" style="width: 100%" />
          </template>
          <template #default>
            <el-empty v-if="!currentQuotation || !currentQuotation.quotationNo" description="未查询到对应报价详情" />
            <template v-else>
              <el-descriptions :column="2" border>
                <el-descriptions-item label="报价单号">{{ currentQuotation.quotationNo }}</el-descriptions-item>
                <el-descriptions-item label="客户名称">{{ currentQuotation.customer }}</el-descriptions-item>
                <el-descriptions-item label="业务员">{{ currentQuotation.salesperson }}</el-descriptions-item>
                <el-descriptions-item label="报价日期">{{ currentQuotation.quotationDate }}</el-descriptions-item>
                <el-descriptions-item label="有效期至">{{ currentQuotation.validDate }}</el-descriptions-item>
                <el-descriptions-item label="付款方式">{{ currentQuotation.paymentMethod }}</el-descriptions-item>
                <el-descriptions-item label="报价总额" :span="2">
                  <span style="font-size: 18px; color: #e6a23c; font-weight: bold;">
                    Â¥{{ Number(currentQuotation.totalAmount ?? 0).toFixed(2) }}
                  </span>
                </el-descriptions-item>
              </el-descriptions>
              <div style="margin-top: 20px;">
                <h4>产品明细</h4>
                <el-table :data="currentQuotation.products || []" border style="width: 100%">
                  <el-table-column prop="product" label="产品名称" />
                  <el-table-column prop="specification" label="规格型号" />
                  <el-table-column prop="unit" label="单位" />
                  <el-table-column prop="unitPrice" label="单价">
                    <template #default="scope">Â¥{{ Number(scope.row.unitPrice ?? 0).toFixed(2) }}</template>
                  </el-table-column>
                </el-table>
              </div>
              <div v-if="currentQuotation.remark" style="margin-top: 20px;">
                <h4>备注</h4>
                <p>{{ currentQuotation.remark }}</p>
              </div>
            </template>
          </template>
        </el-skeleton>
      </div>
      <!-- é‡‡è´­å®¡æ‰¹ï¼šå±•示采购详情 -->
      <div v-if="isPurchaseApproval" style="margin: 10px 0 18px;">
        <el-divider content-position="left">采购详情</el-divider>
        <el-skeleton :loading="purchaseLoading" animated>
          <template #template>
            <el-skeleton-item variant="h3" style="width: 30%" />
            <el-skeleton-item variant="text" style="width: 100%" />
            <el-skeleton-item variant="text" style="width: 100%" />
          </template>
          <template #default>
            <el-empty v-if="!currentPurchase || !currentPurchase.purchaseContractNumber" description="未查询到对应采购详情" />
            <template v-else>
              <el-descriptions :column="2" border>
                <el-descriptions-item label="采购合同号">{{ currentPurchase.purchaseContractNumber }}</el-descriptions-item>
                <el-descriptions-item label="供应商名称">{{ currentPurchase.supplierName }}</el-descriptions-item>
                <el-descriptions-item label="项目名称">{{ currentPurchase.projectName }}</el-descriptions-item>
                <el-descriptions-item label="销售合同号">{{ currentPurchase.salesContractNo }}</el-descriptions-item>
                <el-descriptions-item label="签订日期">{{ currentPurchase.executionDate }}</el-descriptions-item>
                <el-descriptions-item label="录入日期">{{ currentPurchase.entryDate }}</el-descriptions-item>
                <el-descriptions-item label="付款方式">{{ currentPurchase.paymentMethod }}</el-descriptions-item>
                <el-descriptions-item label="合同金额" :span="2">
                  <span style="font-size: 18px; color: #e6a23c; font-weight: bold;">
                    Â¥{{ Number(currentPurchase.contractAmount ?? 0).toFixed(2) }}
                  </span>
                </el-descriptions-item>
              </el-descriptions>
              <div style="margin-top: 20px;">
                <h4>产品明细</h4>
                <el-table :data="currentPurchase.productData || []" border style="width: 100%">
                  <el-table-column prop="productCategory" label="产品名称" />
                  <el-table-column prop="specificationModel" label="规格型号" />
                  <el-table-column prop="unit" label="单位" />
                  <el-table-column prop="quantity" label="数量" />
                  <el-table-column prop="taxInclusiveUnitPrice" label="含税单价">
                    <template #default="scope">Â¥{{ Number(scope.row.taxInclusiveUnitPrice ?? 0).toFixed(2) }}</template>
                  </el-table-column>
                  <el-table-column prop="taxInclusiveTotalPrice" label="含税总价">
                    <template #default="scope">Â¥{{ Number(scope.row.taxInclusiveTotalPrice ?? 0).toFixed(2) }}</template>
                  </el-table-column>
                </el-table>
              </div>
            </template>
          </template>
        </el-skeleton>
      </div>
      <!-- é”€å”®å®¡æ‰¹ï¼šå±•示销售详情 -->
      <div v-if="isSalesApproval" style="margin: 10px 0 18px;">
        <el-divider content-position="left">销售详情</el-divider>
        <el-skeleton :loading="salesLoading" animated>
          <template #template>
            <el-skeleton-item variant="h3" style="width: 30%" />
            <el-skeleton-item variant="text" style="width: 100%" />
            <el-skeleton-item variant="text" style="width: 100%" />
          </template>
          <template #default>
            <el-empty v-if="!currentSales || !currentSales.salesContractNo" description="未查询到对应销售详情" />
            <template v-else>
              <el-descriptions :column="2" border>
                <el-descriptions-item label="销售合同号">{{ currentSales.salesContractNo }}</el-descriptions-item>
                <el-descriptions-item label="客户名称">{{ currentSales.customerName }}</el-descriptions-item>
                <el-descriptions-item label="业务员">{{ currentSales.salesman }}</el-descriptions-item>
                <el-descriptions-item label="录入人">{{ currentSales.entryPersonName }}</el-descriptions-item>
                <el-descriptions-item label="签订日期">{{ currentSales.executionDate }}</el-descriptions-item>
                <el-descriptions-item label="录入日期">{{ currentSales.entryDate }}</el-descriptions-item>
                <el-descriptions-item label="付款方式">{{ currentSales.paymentMethod }}</el-descriptions-item>
                <el-descriptions-item label="合同金额" :span="2">
                  <span style="font-size: 18px; color: #e6a23c; font-weight: bold;">
                    Â¥{{ calculateSalesTotalAmount() }}
                  </span>
                </el-descriptions-item>
              </el-descriptions>
              <div style="margin-top: 20px;">
                <h4>产品明细</h4>
                <el-table :data="currentSales.productData || []" border style="width: 100%">
                  <el-table-column prop="productCategory" label="产品名称" />
                  <el-table-column prop="specificationModel" label="规格型号" />
                  <el-table-column prop="unit" label="单位" />
                  <el-table-column prop="quantity" label="数量" />
                  <el-table-column prop="taxInclusiveUnitPrice" label="含税单价">
                    <template #default="scope">Â¥{{ Number(scope.row.taxInclusiveUnitPrice ?? 0).toFixed(2) }}</template>
                  </el-table-column>
                  <el-table-column prop="taxInclusiveTotalPrice" label="含税总价">
                    <template #default="scope">Â¥{{ Number(scope.row.taxInclusiveTotalPrice ?? 0).toFixed(2) }}</template>
                  </el-table-column>
                </el-table>
              </div>
            </template>
          </template>
        </el-skeleton>
      </div>
      <el-form :model="{ activities }" ref="formRef" label-position="top">
        <el-steps :active="getActiveStep()" finish-status="success" process-status="process" align-center direction="vertical">
          <el-step
            v-for="(activity, index) in activities"
            :key="index"
                        finish-status="success"
            :title="getNodeTitle(index, activities.length)"
            :description="activity.approveNodeUser"
            :icon="getNodeIcon(activity, index)"
          >
                        <template #icon>
                            <el-icon v-if="activity.approveNodeStatus === 2" color="red" :size="22"><WarningFilled /></el-icon>
                            <el-icon v-else-if="activity.isShen" color="#1890ff" :size="22"><Edit /></el-icon>
                            <el-icon v-else-if="activity.approveNodeStatus === 1" color="#67C23A" :size="26"><Check /></el-icon>
                            <el-icon v-else color="#C0C4CC" :size="22"><MoreFilled /></el-icon>
                        </template>
            <template #title>
              <span style="color: #000000">{{ getNodeTitle(index, activities.length) }}</span>
            </template>
            <template #description>
              <div class="node-user">
                <div class="avatar-wrapper">
                  <img :src="userStore.avatar" class="user-avatar" alt=""/>
                </div>
                <span style="color: #000000">{{ activity.approveNodeUser }}-{{activity.isApproval}}</span>
              </div>
              <div v-if="!activity.isShen" class="node-reason">
                <span>审批意见:</span>{{ activity.approveNodeReason }}
              </div>
              <div v-else-if="activity.isShen">
                <el-form-item
                  :prop="'activities.' + index + '.approveNodeReason'"
                  :rules="[{ required: true, message: '审批意见不能为空', trigger: 'blur' }]"
                >
                  <el-input v-model="activity.approveNodeReason" clearable type="textarea" :disabled="operationType === 'view'"></el-input>
                </el-form-item>
              </div>
            </template>
          </el-step>
        </el-steps>
      </el-form>
      <template #footer v-if="operationType === 'approval'">
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm(2)">不通过</el-button>
          <el-button type="primary" @click="submitForm(1)">通过</el-button>
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import { computed, getCurrentInstance, nextTick, reactive, ref, toRefs } from "vue";
import {
    approveProcessDetails,
    getDept,
    updateApproveNode
} from "@/api/collaborativeApproval/approvalProcess.js";
import useUserStore from "@/store/modules/user.js";
import {userListNoPageByTenantId} from "@/api/system/user.js";
import { WarningFilled, Edit, Check, MoreFilled } from '@element-plus/icons-vue'
import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
import { getPurchaseByCode, getSalesByCode } from "@/api/procurementManagement/procurementLedger.js";
const emit = defineEmits(['close'])
const { proxy } = getCurrentInstance()
const props = defineProps({
  approveType: {
    type: [Number, String],
    default: 0
  }
})
const dialogFormVisible = ref(false);
const operationType = ref('')
const activities = ref([])
const formRef = ref(null);
const userStore = useUserStore()
const productOptions = ref([]);
const userList = ref([])
const quotationLoading = ref(false)
const currentQuotation = ref({})
const purchaseLoading = ref(false)
const currentPurchase = ref({})
const salesLoading = ref(false)
const currentSales = ref({})
const isQuotationApproval = computed(() => Number(props.approveType) === 6)
const isPurchaseApproval = computed(() => Number(props.approveType) === 5)
const isSalesApproval = computed(() => Number(props.approveType) === 9)
const isFreeApproval = computed(() => Number(props.approveType) === 10)
const data = reactive({
    form: {
        approveTime: "",
        approveId: "",
        approveUser: "",
        approveDeptId: "",
        approveReason: "",
        checkResult: "",
    },
});
const { form } = toRefs(data);
// èŠ‚ç‚¹æ ‡é¢˜
const getNodeTitle = (index, len) => {
  if (index === len - 1) return '结束';
  return '审批';
};
// èŽ·å–å½“å‰æ¿€æ´»æ­¥éª¤
const getActiveStep = () => {
  // å¦‚果所有 isShen éƒ½ä¸º false,返回最后一个步骤(全部完成)
  const hasActive = activities.value.some(a => a.isShen === true);
  if (!hasActive) return activities.value.length;
  // å½“前节点索引
  return activities.value.findIndex(a => a.isShen  == true);
};
// æ­¥éª¤icon
const getNodeIcon = (activity, index) => {
  if (activity.approveNodeStatus === 2) return 'el-icon-warning'; // ä¸é€šè¿‡
  if (activity.isShen) return 'Edit';
  return '';
};
// æ‰“开弹框
const openDialog = (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
  currentQuotation.value = {}
  currentPurchase.value = {}
    userListNoPageByTenantId().then((res) => {
        userList.value = res.data;
    });
    form.value = {...row}
    // ç«‹å³æ¸…除表单验证状态(因为字段是disabled的,不需要验证)
    nextTick(() => {
        if (formRef.value) {
            formRef.value.clearValidate();
        }
    });
    // ç¡®ä¿é€‰é¡¹åŠ è½½å®ŒæˆåŽå†åŒ¹é…å€¼ç±»åž‹
    getProductOptions().then(() => {
        // ç¡®ä¿å€¼ç±»åž‹åŒ¹é…ï¼ˆå¦‚果选项已加载)
        if (productOptions.value.length > 0 && form.value.approveDeptId) {
            const matchedOption = productOptions.value.find(opt =>
                opt.deptId == form.value.approveDeptId ||
                String(opt.deptId) === String(form.value.approveDeptId)
            );
            if (matchedOption) {
                form.value.approveDeptId = matchedOption.deptId;
            }
        }
        // å†æ¬¡æ¸…除验证,确保选项加载后值匹配正确
        nextTick(() => {
            if (formRef.value) {
                formRef.value.clearValidate();
            }
        });
    });
  // æŠ¥ä»·å®¡æ‰¹ï¼šç”¨å®¡æ‰¹äº‹ç”±å­—段承载的"报价单号"去查报价列表
  if (isQuotationApproval.value) {
    const quotationNo = row?.approveReason;
    if (quotationNo) {
      quotationLoading.value = true
      getQuotationList({ quotationNo }).then((res) => {
        const records = res?.data?.records || []
        currentQuotation.value = records[0] || {}
      }).finally(() => {
        quotationLoading.value = false
      })
    }
  }
  // é‡‡è´­å®¡æ‰¹ï¼šç”¨å®¡æ‰¹äº‹ç”±å­—段承载的"采购合同号"去查采购详情
  if (isPurchaseApproval.value) {
    const purchaseContractNumber = row?.approveReason;
    if (purchaseContractNumber) {
      purchaseLoading.value = true
      getPurchaseByCode({ purchaseContractNumber }).then((res) => {
        currentPurchase.value = res
      }).catch((err) => {
        console.error('查询采购详情失败:', err)
        proxy.$modal.msgError('查询采购详情失败')
      }).finally(() => {
        purchaseLoading.value = false
      })
    }
  }
  // é”€å”®å®¡æ‰¹ï¼šç”¨å®¡æ‰¹äº‹ç”±å­—段承载的"销售合同号"去查销售详情
  if (isSalesApproval.value) {
    const salesContractNo = row?.approveReason;
    if (salesContractNo) {
      salesLoading.value = true
      getSalesByCode({ salesContractNo }).then((res) => {
        currentSales.value = res
      }).catch((err) => {
        console.error('查询销售详情失败:', err)
        proxy.$modal.msgError('查询销售详情失败')
      }).finally(() => {
        salesLoading.value = false
      })
    }
  }
  approveProcessDetails(row.approveId).then((res) => {
    activities.value = res.data
    // å¢žåŠ isApproval字段
    activities.value.forEach(item => {
            if (item.url && item.url.includes('word')) {
                item.urlTem = item.url.replaceAll('word', 'img')
            } else {
                item.urlTem = item.url
            }
      if (item.approveNodeStatus === 2) {
        item.isApproval = '已驳回';
      } else if (item.approveNodeStatus === 1) {
        item.isApproval = '已同意';
      } else {
        item.isApproval = '未审批';
      }
    })
  })
}
const getProductOptions = () => {
    return getDept().then((res) => {
        productOptions.value = res.data;
    });
};
// æäº¤å®¡æ‰¹
const submitForm = (status) => {
  const filteredActivities = activities.value.filter(activity => activity.isShen);
  if (!filteredActivities || filteredActivities.length === 0) {
    proxy.$modal.msgError("未找到待审批的节点");
    return;
  }
  const currentActivity = filteredActivities[0];
  if (!currentActivity) {
    proxy.$modal.msgError("未找到待审批的节点");
    return;
  }
  currentActivity.approveNodeStatus = status;
  // åˆ¤æ–­æ˜¯å¦ä¸ºæœ€åŽä¸€æ­¥
  const isLast = activities.value.findIndex(a => a.isShen) === activities.value.length-1;
  updateApproveNode({ ...currentActivity, isLast }).then(() => {
    proxy.$modal.msgSuccess("提交成功");
    closeDia();
  });
};
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  proxy.resetForm("formRef");
  dialogFormVisible.value = false;
  quotationLoading.value = false
  currentQuotation.value = {}
  purchaseLoading.value = false
  currentPurchase.value = {}
  salesLoading.value = false
  currentSales.value = {}
  emit('close')
};
// è®¡ç®—销售合同金额(产品明细含税总价之和)
const calculateSalesTotalAmount = () => {
  const products = currentSales.value?.productData || []
  const total = products.reduce((sum, item) => {
    return sum + Number(item.taxInclusiveTotalPrice || 0)
  }, 0)
  return total.toFixed(2)
}
defineExpose({
  openDialog,
});
</script>
<style scoped>
.node-user {
  margin: 10px 0;
  font-size: 16px;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 8px;
}
.node-status {
  color: #1890ff;
  margin-left: 8px;
  font-size: 14px;
}
.node-reason {
  font-size: 15px;
  color: #333;
  margin: 10px 0;
}
.user-avatar {
    cursor: pointer;
    width: 30px;
    height: 30px;
    border-radius: 50px;
}
.signImg {
    cursor: pointer;
    width: 200px;
    height: 60px;
}
</style>
src/pages/cooperativeOffice/collaborativeApproval/components/infoFormDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,504 @@
<template>
  <div>
    <el-dialog
        v-model="dialogFormVisible"
        :title="operationType === 'add' ? '新增审批流程' : '编辑审批流程'"
        width="50%"
        @close="closeDia"
    >
      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
        <el-row>
          <el-col :span="24">
            <el-form-item label="流程编号:" prop="approveId">
              <el-input v-model="form.approveId" placeholder="自动编号" clearable disabled/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="申请部门:" prop="approveDeptName">
<!--              <el-input v-model="form.approveDeptName" placeholder="请输入" clearable/>-->
                            <el-select
                                v-model="form.approveDeptIdArray"
                                placeholder="选择部门"
                multiple
                collapse-tags
                @change="handleDeptChange"
                style="width: 100%"
                            >
                                <el-option
                                    v-for="user in productOptions"
                                    :key="user.deptId"
                                    :label="user.deptName"
                                    :value="user.deptId"
                                />
                            </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <!-- å®¡æ‰¹æ ‡é¢˜ï¼ˆä»…当 approveType ä¸º 9 æ—¶æ˜¾ç¤ºï¼‰ -->
        <el-row v-if="props.approveType == 9">
          <el-col :span="24">
            <el-form-item label="审批标题:" prop="approveTitle">
              <el-input v-model="form.approveTitle" placeholder="请输入审批标题" clearable />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item :label="getApproveReasonLabel()" prop="approveReason">
              <el-input v-model="form.approveReason" placeholder="请输入" clearable type="textarea" />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- è¯·å‡æ—¶é—´ï¼ˆä»…当 approveType ä¸º 2 æ—¶æ˜¾ç¤ºï¼‰ -->
        <el-row :gutter="30" v-if="props.approveType == 2">
          <el-col :span="12">
            <el-form-item label="请假开始时间:" prop="startDate">
              <el-date-picker
                  v-model="form.startDate"
                  type="date"
                  placeholder="请选择开始日期"
                  value-format="YYYY-MM-DD"
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="请假结束时间:" prop="endDate">
              <el-date-picker
                  v-model="form.endDate"
                  type="date"
                  placeholder="请选择结束日期"
                  value-format="YYYY-MM-DD"
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- æŠ¥é”€é‡‘额(仅当 approveType ä¸º 4 æ—¶æ˜¾ç¤ºï¼‰ -->
        <el-row v-if="props.approveType == 4">
          <el-col :span="24">
            <el-form-item label="报销金额:" prop="price">
              <el-input-number
                  v-model="form.price"
                  placeholder="请输入报销金额"
                  :min="0"
                  :precision="2"
                  :step="0.01"
                  style="width: 100%"
                  clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- å‡ºå·®åœ°ç‚¹ï¼ˆä»…当 approveType ä¸º 3 æ—¶æ˜¾ç¤ºï¼‰ -->
        <el-row v-if="props.approveType == 3">
          <el-col :span="24">
            <el-form-item label="出差地点:" prop="location">
              <el-input
                  v-model="form.location"
                  placeholder="请输入出差地点"
                  clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- å®¡æ‰¹äººé€‰æ‹©ï¼ˆåŠ¨æ€èŠ‚ç‚¹ï¼‰ -->
        <el-row>
          <el-col :span="24">
            <el-form-item>
              <template #label>
                <span>审批人选择:</span>
                <el-button type="primary" @click="addApproverNode" style="margin-left: 8px;">新增节点</el-button>
              </template>
              <div style="display: flex; align-items: flex-end; flex-wrap: wrap;">
                <div
                  v-for="(node, index) in approverNodes"
                  :key="node.id"
                  style="margin-right: 30px; text-align: center; margin-bottom: 10px;"
                >
                  <div>
                    <span>审批人</span>
                    â†’
                  </div>
                  <el-select
                    v-model="node.userId"
                    placeholder="选择人员"
                    style="width: 120px; margin-bottom: 8px;"
                  >
                    <el-option
                      v-for="user in userList"
                      :key="user.userId"
                      :label="user.nickName"
                      :value="user.userId"
                    />
                  </el-select>
                  <div>
                    <el-button
                      type="danger"
                      size="small"
                      @click="removeApproverNode(index)"
                      v-if="approverNodes.length > 1"
                    >删除</el-button>
                  </div>
                </div>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="申请人:" prop="approveUser">
                            <el-select
                                v-model="form.approveUser"
                                placeholder="选择人员"
                filterable
                default-first-option
                :reserve-keyword="false"
                            >
                                <el-option
                                    v-for="user in userList"
                                    :key="user.userId"
                                    :label="user.nickName"
                                    :value="user.userId"
                                />
                            </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="申请日期:" prop="approveTime">
              <el-date-picker
                  v-model="form.approveTime"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="附件材料:" prop="remark">
              <el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload
                         :headers="upload.headers" :before-upload="handleBeforeUpload" :on-error="handleUploadError"
                         :on-success="handleUploadSuccess" :on-remove="handleRemove">
                <el-button type="primary" v-if="operationType !== 'view'">上传</el-button>
                <template #tip v-if="operationType !== 'view'">
                  <div class="el-upload__tip">
                    æ–‡ä»¶æ ¼å¼æ”¯æŒ
                    doc,docx,xls,xlsx,ppt,pptx,pdf,txt,xml,jpg,jpeg,png,gif,bmp,rar,zip,7z
                  </div>
                </template>
              </el-upload>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确认</el-button>
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {ref, reactive, toRefs, getCurrentInstance} from "vue";
import {
  approveProcessAdd, approveProcessGetInfo,
  approveProcessUpdate,
  getDept
} from "@/api/collaborativeApproval/approvalProcess.js";
import {
  delLedgerFile,
} from "@/api/salesManagement/salesLedger.js";
import {userListNoPageByTenantId} from "@/api/system/user.js";
import { getToken } from "@/utils/auth";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
import useUserStore from "@/store/modules/user";
import { getCurrentDate } from "@/utils/index.js";
import log from "@/views/monitor/job/log.vue";
const userStore = useUserStore();
const dialogFormVisible = ref(false);
const operationType = ref('')
const fileList = ref([]);
const upload = reactive({
  // ä¸Šä¼ çš„地址
  url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
  // è®¾ç½®ä¸Šä¼ çš„请求头部
  headers: { Authorization: "Bearer " + getToken() },
});
const data = reactive({
  form: {
    approveTime: "",
    approveId: "",
    approveUser: "",
        approveDeptIdArray: [],
    approveDeptName: "",
    approveTitle: "", // å®¡æ‰¹æ ‡é¢˜ï¼ˆè‡ªç”±ååŒå®¡æ‰¹ä½¿ç”¨ï¼‰
    approveReason: "",
    checkResult: "",
    tempFileIds: [],
    approverList: [], // æ–°å¢žå­—段,存储所有节点的审批人id
    startDate: "", // è¯·å‡å¼€å§‹æ—¶é—´
    endDate: "", // è¯·å‡ç»“束时间
    price: null, // æŠ¥é”€é‡‘额
    location: "" // å‡ºå·®åœ°ç‚¹
  },
  rules: {
    approveTime: [{ required: false, message: "请输入", trigger: "change" },],
    approveId: [{ required: false, message: "请输入", trigger: "blur" }],
    approveUser: [{ required: false, message: "请输入", trigger: "blur" }],
    approveDeptName: [{ required: true, message: "请选择申请部门", trigger: "change" }],
    approveTitle: [{ required: true, message: "请输入审批标题", trigger: "blur" }],
    approveReason: [{ required: true, message: "请输入", trigger: "blur" }],
    checkResult: [{ required: false, message: "请输入", trigger: "blur" }],
    startDate: [{ required: true, message: "请选择请假开始时间", trigger: "change" }],
    endDate: [{ required: true, message: "请选择请假结束时间", trigger: "change" }],
    price: [{ required: true, message: "请输入报销金额", trigger: "blur" }],
    location: [{ required: true, message: "请输入出差地点", trigger: "blur" }],
  },
});
const { form, rules } = toRefs(data);
const productOptions = ref([]);
const currentApproveStatus = ref(0)
const props = defineProps({
  approveType: {
    type: [Number, String],
    default: 0
  }
})
// èŽ·å–å®¡æ‰¹äº‹ç”±æ ‡ç­¾
const getApproveReasonLabel = () => {
  const type = Number(props.approveType)
  if (type === 5) {
    return '采购计划说明:'
  } else if (type === 9) {
    return '销售合同号:'
  } else if (type === 10) {
    return '审批事由:'
  }
  return '审批事由:'
}
// å®¡æ‰¹äººèŠ‚ç‚¹ç›¸å…³
const approverNodes = ref([
  { id: 1, userId: null }
])
let nextApproverId = 2
const userList = ref([])
function addApproverNode() {
  approverNodes.value.push({ id: nextApproverId++, userId: null })
}
function removeApproverNode(index) {
  approverNodes.value.splice(index, 1)
}
// å¤„理部门选择变化
const handleDeptChange = (deptIds) => {
  if (deptIds && deptIds.length > 0) {
    const selectedNames = productOptions.value
      .filter(dept => deptIds.includes(dept.deptId))
      .map(dept => dept.deptName);
    form.value.approveDeptName = selectedNames.join(',');
  } else {
    form.value.approveDeptName = '';
  }
};
// æ‰“开弹框
const openDialog = (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
    userListNoPageByTenantId().then((res) => {
    userList.value = res.data;
  });
  getProductOptions();
    form.value = {}
    approverNodes.value = [
        { id: 1, userId: null }
    ]
  form.value.approveUser = userStore.id;
  form.value.approveTime = getCurrentDate();
  // èŽ·å–å½“å‰ç”¨æˆ·ä¿¡æ¯å¹¶è®¾ç½®éƒ¨é—¨ID
  form.value.approveDeptIdArray = []
  if (operationType.value === 'edit') {
    fileList.value = row.commonFileList
    form.value.tempFileIds = fileList.value.map(file => file.id)
        currentApproveStatus.value = row.approveStatus
    approveProcessGetInfo({id: row.approveId,approveReason: '1'}).then(res => {
            form.value = {...res.data}
      // å¤„理部门反显(根据后端返回的 approveDeptId å¤„理为数组)
      const deptId = res.data.approveDeptId;
      if (deptId !== undefined && deptId !== null) {
        if (Array.isArray(deptId)) {
          form.value.approveDeptIdArray = deptId;
        } else if (typeof deptId === 'string' && deptId.includes(',')) {
          form.value.approveDeptIdArray = deptId.split(',').map(id => parseInt(id.trim())).filter(id => !isNaN(id));
        } else if (typeof deptId === 'string' || typeof deptId === 'number') {
          form.value.approveDeptIdArray = [parseInt(deptId)];
        }
      } else {
        form.value.approveDeptIdArray = [];
      }
      // åæ˜¾å®¡æ‰¹äºº
      if (res.data && res.data.approveUserIds) {
        const userIds = res.data.approveUserIds.split(',')
        approverNodes.value = userIds.map((userId, idx) => ({
          id: idx + 1,
          userId: parseInt(userId.trim())
        }))
        nextApproverId = userIds.length + 1
      } else {
        approverNodes.value = [{ id: 1, userId: null }]
        nextApproverId = 2
      }
    })
  }
}
const getProductOptions = () => {
  getDept().then((res) => {
    productOptions.value = res.data;
  });
};
function convertIdToValue(data) {
  return data.map((item) => {
    const { id, children, ...rest } = item;
    const newItem = {
      ...rest,
      value: id, // å°† id æ”¹ä¸º value
    };
    if (children && children.length > 0) {
      newItem.children = convertIdToValue(children);
    }
    return newItem;
  });
}
// æäº¤äº§å“è¡¨å•
const submitForm = () => {
  // æ”¶é›†æ‰€æœ‰èŠ‚ç‚¹çš„å®¡æ‰¹äººid
  form.value.approveUserIds = approverNodes.value.map(node => node.userId).join(',')
  form.value.approveType = props.approveType
  // å®¡æ‰¹äººå¿…填校验
  const hasEmptyApprover = approverNodes.value.some(node => !node.userId)
  if (hasEmptyApprover) {
    proxy.$modal.msgError("请为所有审批节点选择审批人!")
    return
  }
  // å½“ approveType ä¸º 2 æ—¶ï¼Œæ ¡éªŒè¯·å‡æ—¶é—´
  if (props.approveType == 2) {
    if (!form.value.startDate) {
      proxy.$modal.msgError("请选择请假开始时间!")
      return
    }
    if (!form.value.endDate) {
      proxy.$modal.msgError("请选择请假结束时间!")
      return
    }
    // æ ¡éªŒç»“束时间不能早于开始时间
    if (new Date(form.value.endDate) < new Date(form.value.startDate)) {
      proxy.$modal.msgError("请假结束时间不能早于开始时间!")
      return
    }
  }
  // å½“ approveType ä¸º 3 æ—¶ï¼Œæ ¡éªŒå‡ºå·®åœ°ç‚¹
  if (props.approveType == 3) {
    if (!form.value.location || form.value.location.trim() === '') {
      proxy.$modal.msgError("请输入出差地点!")
      return
    }
  }
  // å½“ approveType ä¸º 4 æ—¶ï¼Œæ ¡éªŒæŠ¥é”€é‡‘额
  if (props.approveType == 4) {
    if (!form.value.price || form.value.price <= 0) {
      proxy.$modal.msgError("请输入有效的报销金额!")
      return
    }
  }
  proxy.$refs.formRef.validate(valid => {
    if (valid) {
      const submitData = { ...form.value };
      if (operationType.value === "add" || currentApproveStatus.value == 3) {
        approveProcessAdd(submitData).then(res => {
          proxy.$modal.msgSuccess("提交成功");
          closeDia();
        })
      } else {
        approveProcessUpdate(submitData).then(res => {
          proxy.$modal.msgSuccess("提交成功");
          closeDia();
        })
      }
    }
  })
}
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  fileList.value = []
  proxy.resetForm("formRef");
  dialogFormVisible.value = false;
  emit('close')
};
// ä¸Šä¼ å‰æ ¡æ£€
function handleBeforeUpload(file) {
  // æ ¡æ£€æ–‡ä»¶å¤§å°
  // if (file.size > 1024 * 1024 * 10) {
  //   proxy.$modal.msgError("上传文件大小不能超过10MB!");
  //   return false;
  // }
  proxy.$modal.loading("正在上传文件,请稍候...");
  return true;
}
// ä¸Šä¼ å¤±è´¥
function handleUploadError(err) {
  proxy.$modal.msgError("上传文件失败");
  proxy.$modal.closeLoading();
}
// ä¸Šä¼ æˆåŠŸå›žè°ƒ
function handleUploadSuccess(res, file, uploadFiles) {
  proxy.$modal.closeLoading();
  if (res.code === 200) {
    // ç¡®ä¿ tempFileIds å­˜åœ¨ä¸”为数组
    if (!form.value.tempFileIds) {
      form.value.tempFileIds = [];
    }
    form.value.tempFileIds.push(res.data.tempId);
    proxy.$modal.msgSuccess("上传成功");
  } else {
    proxy.$modal.msgError(res.msg);
    proxy.$refs.fileUpload.handleRemove(file);
  }
}
// ç§»é™¤æ–‡ä»¶
function handleRemove(file) {
  if (operationType.value === "edit") {
    let ids = [];
    ids.push(file.id);
    delLedgerFile(ids).then((res) => {
      proxy.$modal.msgSuccess("删除成功");
    });
  }
}
defineExpose({
  openDialog,
});
</script>
<style scoped>
</style>
src/pages/cooperativeOffice/collaborativeApproval/detail.vue
@@ -14,22 +14,29 @@
                 disabled
                 placeholder="自动编号" />
      </u-form-item>
      <!-- å®¡æ‰¹æ ‡é¢˜ï¼ˆä»…当 approveType ä¸º 9 æˆ– 10 æ—¶æ˜¾ç¤ºï¼‰ -->
      <u-form-item v-if="approveType === 9 || approveType === 10"
                   prop="approveTitle"
                   label="审批标题"
                   required>
        <u-input v-model="form.approveTitle"
                 placeholder="请输入审批标题"
                 clearable />
      </u-form-item>
      <u-form-item prop="approveReason"
                   :label="approveType === 5 ? '采购事由' : '申请事由'"
                   :label="getApproveReasonLabel()"
                   required>
        <u-input v-model="form.approveReason"
                 type="textarea"
                 rows="2"
                 auto-height
                 maxlength="200"
                 :placeholder="approveType === 5 ? '请输入采购事由' : '请输入申请事由'"
                 :placeholder="getApproveReasonPlaceholder()"
                 show-word-limit />
      </u-form-item>
      <u-form-item prop="approveDeptName"
                   label="申请部门"
                   required>
        <!-- <u-input v-model="form.approveDeptName"
                 placeholder="请选择申请部门" /> -->
        <u-input v-model="form.approveDeptName"
                 readonly
                 placeholder="请选择申请部门"
@@ -103,6 +110,19 @@
                 type="number"
                 placeholder="请输入报销金额"
                 clearable />
      </u-form-item>
      <!-- é™„件上传 -->
      <u-form-item label="附件材料">
        <view class="file-upload-area">
          <view v-for="(file, index) in fileList" :key="file.id || index" class="file-item">
            <text class="file-name">{{ file.name || file.fileName }}</text>
            <text class="file-delete" @click="removeFile(index)">×</text>
          </view>
          <view class="upload-btn" @click="chooseFile" v-if="operationType !== 'view'">
            <up-icon name="plus" size="20" color="#006cfb"></up-icon>
            <text class="upload-text">上传附件</text>
          </view>
        </view>
      </u-form-item>
    </u-form>
    <!-- é€‰æ‹©å™¨å¼¹çª— -->
@@ -227,6 +247,7 @@
      approveUserName: "",
      approveDeptName: "",
      approveDeptId: "",
      approveTitle: "", // å®¡æ‰¹æ ‡é¢˜ï¼ˆè‡ªç”±ååŒå®¡æ‰¹ä½¿ç”¨ï¼‰
      approveReason: "",
      checkResult: "",
      tempFileIds: [],
@@ -239,8 +260,9 @@
    rules: {
      approveTime: [{ required: false, message: "请输入", trigger: "change" }],
      approveId: [{ required: false, message: "请输入", trigger: "blur" }],
      approveDeptId: [{ required: true, message: "请输入", trigger: "blur" }],
      approveDeptId: [{ required: true, message: "请选择", trigger: "change" }],
      approveReason: [{ required: true, message: "请输入", trigger: "blur" }],
      approveTitle: [{ required: true, message: "请输入审批标题", trigger: "blur" }],
      checkResult: [{ required: false, message: "请输入", trigger: "blur" }],
      startDate: [
        { required: false, message: "请选择开始时间", trigger: "change" },
@@ -271,6 +293,32 @@
  const userStore = useUserStore();
  const approveType = ref(0);
  // èŽ·å–å®¡æ‰¹äº‹ç”±æ ‡ç­¾
  const getApproveReasonLabel = () => {
    const type = Number(approveType.value);
    if (type === 5) {
      return '采购计划说明';
    } else if (type === 9) {
      return '销售合同号';
    } else if (type === 10) {
      return '审批事由';
    }
    return '审批事由';
  };
  // èŽ·å–å®¡æ‰¹äº‹ç”±å ä½ç¬¦
  const getApproveReasonPlaceholder = () => {
    const type = Number(approveType.value);
    if (type === 5) {
      return '请输入采购计划说明';
    } else if (type === 9) {
      return '请输入销售合同号';
    } else if (type === 10) {
      return '请输入审批事由';
    }
    return '请输入申请事由';
  };
  const getProductOptions = () => {
    getDept().then(res => {
      productOptions.value = res.data.map(item => ({
@@ -281,6 +329,76 @@
  };
  const fileList = ref([]);
  let nextApproverId = 2;
  // å¤„理部门选择变化
  const handleDeptChange = (deptIds) => {
    if (deptIds && deptIds.length > 0) {
      const selectedNames = productOptions.value
        .filter(dept => deptIds.includes(dept.value))
        .map(dept => dept.name);
      form.value.approveDeptName = selectedNames.join(',');
    } else {
      form.value.approveDeptName = '';
    }
  };
  // é€‰æ‹©å®¡æ‰¹äºº
  const addApprover = (stepIndex) => {
    uni.setStorageSync("stepIndex", stepIndex);
    uni.navigateTo({
      url: "/pages/cooperativeOffice/collaborativeApproval/contactSelect",
    });
  };
  // æ·»åŠ å®¡æ‰¹èŠ‚ç‚¹
  const addApprovalStep = () => {
    approverNodes.value.push({ id: nextApproverId++, userId: null, nickName: null });
  };
  // ç§»é™¤å®¡æ‰¹äºº
  const removeApprover = (stepIndex) => {
    approverNodes.value[stepIndex].userId = null;
    approverNodes.value[stepIndex].nickName = null;
  };
  // ç§»é™¤å®¡æ‰¹èŠ‚ç‚¹
  const removeApprovalStep = (stepIndex) => {
    if (approverNodes.value.length > 1) {
      approverNodes.value.splice(stepIndex, 1);
    } else {
      showToast("至少需要一个审批步骤");
    }
  };
  // å¤„理联系人选择结果
  const handleSelectContact = (data) => {
    const { stepIndex, contact } = data;
    approverNodes.value[stepIndex].userId = contact.userId;
    approverNodes.value[stepIndex].nickName = contact.nickName;
  };
  // é€‰æ‹©æ–‡ä»¶ä¸Šä¼ 
  const chooseFile = () => {
    uni.chooseMessageFile({
      count: 10,
      success: (res) => {
        const tempFilePaths = res.tempFiles;
        // è¿™é‡Œå¯ä»¥æ·»åŠ ä¸Šä¼ é€»è¾‘
        tempFilePaths.forEach(file => {
          fileList.value.push({
            name: file.name,
            path: file.path,
            size: file.size,
          });
        });
      }
    });
  };
  // ç§»é™¤æ–‡ä»¶
  const removeFile = (index) => {
    fileList.value.splice(index, 1);
  };
  const getCurrentinfo = () => {
    userStore.getInfo().then(res => {
      form.value.approveDeptId = res.user.tenantId;
@@ -461,44 +579,6 @@
      });
  };
  // å¤„理联系人选择结果
  const handleSelectContact = data => {
    const { stepIndex, contact } = data;
    // å°†é€‰ä¸­çš„联系人设置为对应审批步骤的审批人
    approverNodes.value[stepIndex].userId = contact.userId;
    approverNodes.value[stepIndex].nickName = contact.nickName;
  };
  const addApprover = stepIndex => {
    // è·³è½¬åˆ°è”系人选择页面
    uni.setStorageSync("stepIndex", stepIndex);
    uni.navigateTo({
      url: "/pages/cooperativeOffice/collaborativeApproval/contactSelect",
    });
  };
  const addApprovalStep = () => {
    // æ·»åŠ æ–°çš„å®¡æ‰¹æ­¥éª¤
    approverNodes.value.push({ userId: null, nickName: null });
  };
  const removeApprover = stepIndex => {
    // ç§»é™¤å®¡æ‰¹äºº
    approverNodes.value[stepIndex].userId = null;
    approverNodes.value[stepIndex].nickName = null;
  };
  const removeApprovalStep = stepIndex => {
    // ç¡®ä¿è‡³å°‘保留一个审批步骤
    if (approverNodes.value.length > 1) {
      approverNodes.value.splice(stepIndex, 1);
    } else {
      uni.showToast({
        title: "至少需要一个审批步骤",
        icon: "none",
      });
    }
  };
  // æ˜¾ç¤ºæ—¥æœŸé€‰æ‹©å™¨
  const showDatePicker = () => {
    showDate.value = true;
@@ -926,4 +1006,52 @@
    color: #3b82f6;
    font-size: 14px;
  }
  // æ–‡ä»¶ä¸Šä¼ åŒºåŸŸæ ·å¼
  .file-upload-area {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }
  .file-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: #f8f9fa;
    padding: 10px 12px;
    border-radius: 8px;
  }
  .file-name {
    font-size: 14px;
    color: #333;
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .file-delete {
    font-size: 18px;
    color: #ff4d4f;
    margin-left: 8px;
    padding: 0 4px;
  }
  .upload-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    border: 2px dashed #d9d9d9;
    border-radius: 8px;
    padding: 16px;
    background: #fafafa;
  }
  .upload-text {
    font-size: 14px;
    color: #666;
  }
</style>
src/pages/cooperativeOffice/collaborativeApproval/index.vue
@@ -140,13 +140,16 @@
  import { onLoad, onShow } from "@dcloudio/uni-app";
  import useUserStore from "@/store/modules/user";
  // æŽ¥æ”¶çˆ¶ç»„件传递的 approveType å‚æ•°
  // æŽ¥æ”¶çˆ¶ç»„件传递的 approveType å‚数(用于 index1.vue, index2.vue ç­‰ç»„件方式调用)
  const props = defineProps({
    approveType: {
      type: Number,
      default: 0,
    },
  });
  // å®¡æ‰¹ç±»åž‹
  const approveType = ref(0);
  // æ˜ å°„ approveType åˆ°å¯¹åº”的页面标题
  const getPageTitle = type => {
@@ -159,11 +162,13 @@
      6: "报价管理",
      7: "发货审批",
      8: "危险作业审批",
      9: "销售审批",
      10: "自由协同审批",
    };
    return titleMap[type] || "审批管理";
    return titleMap[type] || "协同审批";
  };
  const pageTitle = getPageTitle(props.approveType);
  const pageTitle = ref("协同审批");
  const userStore = useUserStore();
  // æ•°æ®
@@ -188,7 +193,7 @@
    };
    approveProcessListPage({
      ...page,
      approveType: props.approveType,
      approveType: approveType.value,
      ...searchForm.value,
    })
      .then(res => {
@@ -256,7 +261,7 @@
    uni.setStorageSync("invoiceLedgerEditRow", JSON.stringify(item));
    uni.setStorageSync("operationType", "edit");
    uni.setStorageSync("approveId", item.approveId);
    uni.setStorageSync("approveType", props.approveType);
    uni.setStorageSync("approveType", approveType.value);
    uni.navigateTo({
      url: "/pages/cooperativeOffice/collaborativeApproval/detail",
    });
@@ -265,31 +270,50 @@
  // æ·»åŠ æ–°è®°å½•
  const handleAdd = () => {
    uni.setStorageSync("operationType", "add");
    uni.setStorageSync("approveType", props.approveType);
    uni.setStorageSync("approveType", approveType.value);
    uni.navigateTo({
      url: `/pages/cooperativeOffice/collaborativeApproval/detail?approveType=${props.approveType}`,
      url: `/pages/cooperativeOffice/collaborativeApproval/detail?approveType=${approveType.value}`,
    });
  };
  // ç‚¹å‡»å®¡æ ¸
  const approve = item => {
    uni.setStorageSync("approveId", item.approveId);
    uni.setStorageSync("approveType", props.approveType);
    uni.setStorageSync("approveType", approveType.value);
    uni.navigateTo({
      url:
        "/pages/cooperativeOffice/collaborativeApproval/approve?approveType=" +
        props.approveType,
        approveType.value,
    });
  };
  onLoad(options => {
    console.log('onLoad options:', options, 'props.approveType:', props.approveType);
    // ä¼˜å…ˆä½¿ç”¨ props çš„ approveType(组件方式调用,如 index1.vue)
    // å¦‚果没有 props,则使用 URL å‚数(如 index?approveType=9)
    if (props.approveType && props.approveType > 0) {
      approveType.value = props.approveType;
      console.log('从 props è®¾ç½® approveType:', approveType.value);
    } else if (options.approveType) {
      approveType.value = Number(options.approveType);
      console.log('从 URL å‚数设置 approveType:', approveType.value);
    } else {
      console.log('未获取到 approveType å‚æ•°');
    }
    // è®¾ç½®é¡µé¢æ ‡é¢˜
    pageTitle.value = getPageTitle(approveType.value);
    // è§£æžapproveId
    if (options.approveId) {
      searchForm.value.approveId = options.approveId;
    }
    // é¡µé¢åŠ è½½æ—¶ç«‹å³èŽ·å–åˆ—è¡¨
    getList();
  });
  onShow(() => {
    // é¡µé¢åŠ è½½å®ŒæˆåŽçš„åˆå§‹åŒ–é€»è¾‘
    // é¡µé¢æ˜¾ç¤ºæ—¶åˆ·æ–°åˆ—表
    getList();
  });
</script>
src/pages/cooperativeOffice/collaborativeApproval/indexNew.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,382 @@
<template>
    <div class="app-container">
        <!-- æ ‡ç­¾é¡µåˆ‡æ¢ä¸åŒçš„审批类型 -->
        <el-tabs v-model="activeTab" @tab-change="handleTabChange" class="approval-tabs">
            <el-tab-pane label="公出管理" name="1"></el-tab-pane>
            <el-tab-pane label="请假管理" name="2"></el-tab-pane>
            <el-tab-pane label="出差管理" name="3"></el-tab-pane>
            <el-tab-pane label="报销管理" name="4"></el-tab-pane>
            <el-tab-pane label="采购计划审批" name="5"></el-tab-pane>
            <!--      <el-tab-pane label="报价审批" name="6"></el-tab-pane>-->
            <el-tab-pane label="出库审批" name="7"></el-tab-pane>
            <el-tab-pane label="销售审批" name="9"></el-tab-pane>
            <el-tab-pane label="自由协同审批" name="10"></el-tab-pane>
        </el-tabs>
        <div class="search_form">
            <div>
                <span class="search_title">流程编号:</span>
                <el-input
                    v-model="searchForm.approveId"
                    style="width: 240px"
                    placeholder="请输入流程编号搜索"
                    @change="handleQuery"
                    clearable
                    :prefix-icon="Search"
                />
                <span class="search_title ml10">审批状态:</span>
                <el-select v-model="searchForm.approveStatus" clearable @change="handleQuery" style="width: 240px">
                    <el-option label="待审核" :value="0" />
                    <el-option label="审核中" :value="1" />
                    <el-option label="审核完成" :value="2" />
                    <el-option label="审核未通过" :value="3" />
                    <el-option label="已重新提交" :value="4" />
                </el-select>
                <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
                >搜索</el-button
                >
            </div>
            <div>
                <el-button type="primary" @click="openForm('add')" v-if="currentApproveType !== 6 && currentApproveType !== 5 && currentApproveType !== 9">新增</el-button>
                <el-button @click="handleOut">导出</el-button>
                <el-button type="danger" plain @click="handleDelete">删除</el-button>
            </div>
        </div>
        <div class="table_list">
            <PIMTable
                rowKey="id"
                :column="tableColumnCopy"
                :tableData="tableData"
                :page="page"
                :isSelection="true"
                @selection-change="handleSelectionChange"
                :tableLoading="tableLoading"
                @pagination="pagination"
                :total="page.total"
            ></PIMTable>
        </div>
        <info-form-dia ref="infoFormDia" @close="handleQuery" :approveType="currentApproveType"></info-form-dia>
        <approval-dia ref="approvalDia" @close="handleQuery" :approveType="currentApproveType"></approval-dia>
        <FileList ref="fileListRef" />
    </div>
</template>
<script setup>
import FileList from "./fileList.vue";
import { Search } from "@element-plus/icons-vue";
import {onMounted, ref, computed, reactive, toRefs, nextTick, getCurrentInstance} from "vue";
import {ElMessageBox} from "element-plus";
import { useRoute } from 'vue-router';
import InfoFormDia from "@/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue";
import ApprovalDia from "@/views/collaborativeApproval/approvalProcess/components/approvalDia.vue";
import {approveProcessDelete, approveProcessListPage} from "@/api/collaborativeApproval/approvalProcess.js";
import useUserStore from "@/store/modules/user";
const userStore = useUserStore();
const route = useRoute();
// å½“前选中的标签页,默认为公出管理
const activeTab = ref('1');
// å½“前审批类型,根据选中的标签页计算
const currentApproveType = computed(() => {
    return Number(activeTab.value);
});
// æ ‡ç­¾é¡µåˆ‡æ¢å¤„理
const handleTabChange = (tabName) => {
    // åˆ‡æ¢æ ‡ç­¾é¡µæ—¶é‡ç½®æœç´¢æ¡ä»¶å’Œåˆ†é¡µï¼Œå¹¶é‡æ–°åŠ è½½æ•°æ®
    searchForm.value.approveId = '';
    searchForm.value.approveStatus = '';
    page.current = 1;
    getList();
};
const data = reactive({
    searchForm: {
        approveId: "",
        approveStatus: "",
    },
});
const { searchForm } = toRefs(data);
// åŠ¨æ€è¡¨æ ¼åˆ—é…ç½®ï¼Œæ ¹æ®å®¡æ‰¹ç±»åž‹ç”Ÿæˆåˆ—
const tableColumnCopy = computed(() => {
    const isLeaveType = currentApproveType.value === 2; // è¯·å‡ç®¡ç†
    const isReimburseType = currentApproveType.value === 4; // æŠ¥é”€ç®¡ç†
    const isQuotationType = currentApproveType.value === 6; // æŠ¥ä»·å®¡æ‰¹
    const isSalesType = currentApproveType.value === 9; // é”€å”®å®¡æ‰¹
    const isFreeType = currentApproveType.value === 10; // è‡ªç”±ååŒå®¡æ‰¹
    // åŸºç¡€åˆ—配置
    const baseColumns = [
        {
            label: "审批状态",
            prop: "approveStatus",
            dataType: "tag",
            width: 100,
            formatData: (params) => {
                if (params == 0) {
                    return "待审核";
                } else if (params == 1) {
                    return "审核中";
                } else if (params == 2) {
                    return "审核完成";
                } else if (params == 4) {
                    return "已重新提交";
                } else {
                    return '不通过';
                }
            },
            formatType: (params) => {
                if (params == 0) {
                    return "warning";
                } else if (params == 1) {
                    return "primary";
                } else if (params == 2) {
                    return "success";
                } else if (params == 4) {
                    return "info";
                } else {
                    return 'danger';
                }
            },
        },
        {
            label: "流程编号",
            prop: "approveId",
            width: 170
        },
        {
            label: "申请部门",
            prop: "approveDeptName",
            width: 220
        },
        // å®¡æ‰¹æ ‡é¢˜ï¼ˆä»…自由协同审批显示)
        ...(isFreeType ? [{
            label: "审批标题",
            prop: "approveTitle",
            width: 200
        }] : []),
        {
            label: isQuotationType ? "报价单号" : (isSalesType ? "销售合同号" : "审批事由"),
            prop: "approveReason",
            width: 200
        },
        {
            label: "申请人",
            prop: "approveUserName",
            width: 120
        }
    ];
    // é‡‘额列(仅报销管理显示)
    if (isReimburseType) {
        baseColumns.push({
            label: "金额(元)",
            prop: "price",
            width: 120
        });
    }
    // æ—¥æœŸåˆ—(根据类型动态配置)
    baseColumns.push(
        {
            label: isLeaveType ? "开始日期" : "申请日期",
            prop: isLeaveType ? "startDate" : "approveTime",
            width: 200
        },
        {
            label: "结束日期",
            prop: isLeaveType ? "endDate" : "approveOverTime",
            width: 120
        }
    );
    // å½“前审批人列
    baseColumns.push({
        label: "当前审批人",
        prop: "approveUserCurrentName",
        width: 120
    });
    // æ“ä½œåˆ—
    baseColumns.push({
        dataType: "action",
        label: "操作",
        align: "center",
        fixed: "right",
        width: 230,
        operation: [
            {
                name: "编辑",
                type: "text",
                clickFun: (row) => {
                    openForm("edit", row);
                },
                disabled: (row) => currentApproveType.value === 6 || row.approveStatus == 2 || row.approveStatus == 1 || row.approveStatus == 4
            },
            {
                name: "审核",
                type: "text",
                clickFun: (row) => {
                    openApprovalDia("approval", row);
                },
                disabled: (row) => row.approveUserCurrentId == null || row.approveStatus == 2 || row.approveStatus == 3 || row.approveStatus == 4 || row.approveUserCurrentId !== userStore.id
            },
            {
                name: "详情",
                type: "text",
                clickFun: (row) => {
                    openApprovalDia('view', row);
                },
            },
            {
                name: "附件",
                type: "text",
                clickFun: (row) => {
                    downLoadFile(row);
                },
            },
        ],
    });
    return baseColumns;
});
const tableData = ref([]);
const selectedRows = ref([]);
const tableLoading = ref(false);
const page = reactive({
    current: 1,
    size: 100,
    total: 0
});
const infoFormDia = ref()
const approvalDia = ref()
const { proxy } = getCurrentInstance()
// æŸ¥è¯¢åˆ—表
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
    page.current = 1;
    getList();
};
const fileListRef = ref(null)
const downLoadFile = (row) => {
    fileListRef.value.open(row.commonFileList)
}
const pagination = (obj) => {
    page.current = obj.page;
    page.size = obj.limit;
    getList();
};
const getList = () => {
    tableLoading.value = true;
    approveProcessListPage({...page, ...searchForm.value, approveType: currentApproveType.value}).then(res => {
        tableLoading.value = false;
        tableData.value = res.data.records
        page.total = res.data.total;
    }).catch(err => {
        tableLoading.value = false;
    })
};
// å¯¼å‡º
const handleOut = () => {
    const type = currentApproveType.value
    const urlMap = {
        0: "/approveProcess/exportZero",
        1: "/approveProcess/exportOne",
        2: "/approveProcess/exportTwo",
        3: "/approveProcess/exportThree",
        4: "/approveProcess/exportFour",
        5: "/approveProcess/exportFive",
        6: "/approveProcess/exportSix",
        7: "/approveProcess/exportSeven",
        9: "/approveProcess/exportEight",
        10: "/approveProcess/exportNine",
    }
    const url = urlMap[type] || urlMap[0]
    const nameMap = {
        0: "协同审批管理表",
        1: "公出管理审批表",
        2: "请假管理审批表",
        3: "出差管理审批表",
        4: "报销管理审批表",
        5: "采购申请审批表",
        6: "报价审批表",
        7: "出库审批表",
        9: "销售审批表",
        10: "自由协同审批表",
    }
    const fileName = nameMap[type] || nameMap[0]
    proxy.download(url, {}, `${fileName}.xlsx`)
}
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
    selectedRows.value = selection;
};
// æ‰“开新增、编辑弹框
const openForm = (type, row) => {
    nextTick(() => {
        infoFormDia.value?.openDialog(type, row)
    })
};
// æ‰“开新增检验弹框
const openApprovalDia = (type, row) => {
    nextTick(() => {
        approvalDia.value?.openDialog(type, row)
    })
};
// åˆ é™¤
const handleDelete = () => {
    let ids = [];
    if (selectedRows.value.length > 0) {
        ids = selectedRows.value.map((item) => item.approveId);
    } else {
        proxy.$modal.msgWarning("请选择数据");
        return;
    }
    ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "导出", {
        confirmButtonText: "确认",
        cancelButtonText: "取消",
        type: "warning",
    })
        .then(() => {
            approveProcessDelete(ids).then((res) => {
                proxy.$modal.msgSuccess("删除成功");
                getList();
            });
        })
        .catch(() => {
            proxy.$modal.msg("已取消");
        });
};
onMounted(() => {
    // æ ¹æ®URL参数设置标签页和查询条件
    const approveType = route.query.approveType;
    const approveId = route.query.approveId;
    if (approveType) {
        // è®¾ç½®æ ‡ç­¾é¡µï¼ˆapproveType å¯¹åº” activeTab çš„ name)
        activeTab.value = String(approveType);
    }
    if (approveId) {
        // è®¾ç½®æµç¨‹ç¼–号查询条件
        searchForm.value.approveId = String(approveId);
    }
    // æŸ¥è¯¢åˆ—表
    getList();
});
</script>
<style scoped>
.approval-tabs {
    margin-bottom: 10px;
}
</style>
src/pages/index.vue
@@ -235,7 +235,7 @@
// å®¢æˆ·åˆåŒé‡‘额分析:无需筛选项(按接口默认返回展示)
const { triggerVersionCheck } = createVersionUpgradeChecker({ logPrefix: "[version-index]" });
// const { triggerVersionCheck } = createVersionUpgradeChecker({ logPrefix: "[version-index]" });
function toggleOverview() {
  overviewExpanded.value = !overviewExpanded.value;
@@ -447,12 +447,12 @@
  } catch (e) {
    isCanvas2d.value = false;
  }
  triggerVersionCheck("onMounted");
  // triggerVersionCheck("onMounted");
  loadHome();
});
onShow(() => {
  triggerVersionCheck("onShow");
  // triggerVersionCheck("onShow");
});
</script>
src/pages/indexItem.vue
@@ -55,9 +55,11 @@
    "请假管理": "/pages/cooperativeOffice/collaborativeApproval/index2",
    "出差管理": "/pages/cooperativeOffice/collaborativeApproval/index3",
    "报销管理": "/pages/cooperativeOffice/collaborativeApproval/index4",
    "采购审批": "/pages/cooperativeOffice/collaborativeApproval/index5",
    "采购计划审批": "/pages/cooperativeOffice/collaborativeApproval/index5",
    "报价审批": "/pages/cooperativeOffice/collaborativeApproval/index6",
    "发货审批": "/pages/cooperativeOffice/collaborativeApproval/index7",
    "出库审批": "/pages/cooperativeOffice/collaborativeApproval/index7",
    "销售审批": "/pages/cooperativeOffice/collaborativeApproval/index?approveType=9",
    "自由协同审批": "/pages/cooperativeOffice/collaborativeApproval/index?approveType=10",
    "协同审批": "/pages/cooperativeOffice/collaborativeApproval/index",
    "会议设置": "/pages/managementMeetings/meetingSettings/index",
    "会议列表": "/pages/managementMeetings/meetingList/index",
@@ -106,9 +108,11 @@
      { icon: "/static/images/icon/qingjiaguanli.svg", label: "请假管理" },
      { icon: "/static/images/icon/chuchaiguanli.svg", label: "出差管理" },
      { icon: "/static/images/icon/baoxiaoguanli.svg", label: "报销管理" },
      { icon: "/static/images/icon/caigouguanli.svg", label: "采购审批" },
      { icon: "/static/images/icon/baojiaguanli.svg", label: "报价审批" },
      { icon: "/static/images/icon/fahuoguanli.svg", label: "发货审批" },
      { icon: "/static/images/icon/caigouguanli.svg", label: "采购计划审批" },
      // { icon: "/static/images/icon/baojiaguanli.svg", label: "报价审批" },
      { icon: "/static/images/icon/fahuoguanli.svg", label: "出库审批" },
      { icon: "/static/images/icon/fahuoguanli.svg", label: "销售审批" },
      { icon: "/static/images/icon/fahuoguanli.svg", label: "自由协同审批" },
    ],
  };
src/pages/works.vue
@@ -280,7 +280,7 @@
  import useUserStore from "@/store/modules/user";
  const userStore = useUserStore();
  const { triggerVersionCheck } = createVersionUpgradeChecker({ logPrefix: "[version-works]" });
  // const { triggerVersionCheck } = createVersionUpgradeChecker({ logPrefix: "[version-works]" });
  const show = ref(false);
  const factoryList = ref([]);
  const factoryListTem = ref([]);
@@ -483,30 +483,30 @@
      icon: "/static/images/icon/xietongshenpi.svg",
      label: "协同审批",
    },
    {
      icon: "/static/images/icon/huiyiguanli.svg",
      label: "会议管理",
    },
    {
      icon: "/static/images/icon/tongzhigonggao.svg",
      label: "通知公告",
    },
    {
      icon: "/static/images/icon/zhishiku.svg",
      label: "知识库",
    },
    {
      icon: "/static/images/icon/yongyinguanli.svg",
      label: "用印管理",
    },
    {
      icon: "/static/images/icon/guizhangzhidu.svg",
      label: "规章制度",
    },
    {
      icon: "/static/images/icon/kehubaifang.svg",
      label: "客户拜访",
    },
    // {
    //   icon: "/static/images/icon/huiyiguanli.svg",
    //   label: "会议管理",
    // },
    // {
    //   icon: "/static/images/icon/tongzhigonggao.svg",
    //   label: "通知公告",
    // },
    // {
    //   icon: "/static/images/icon/zhishiku.svg",
    //   label: "知识库",
    // },
    // {
    //   icon: "/static/images/icon/yongyinguanli.svg",
    //   label: "用印管理",
    // },
    // {
    //   icon: "/static/images/icon/guizhangzhidu.svg",
    //   label: "规章制度",
    // },
    // {
    //   icon: "/static/images/icon/kehubaifang.svg",
    //   label: "客户拜访",
    // },
  ]);
  // ç”Ÿäº§ç®¡æŽ§åŠŸèƒ½æ•°æ®
@@ -1155,7 +1155,7 @@
  const hasEquipmentItems = computed(() => equipmentItems.length > 0);
  onMounted(() => {
    triggerVersionCheck("onMounted");
    // triggerVersionCheck("onMounted");
    // æ¯æ¬¡è¿›å…¥é¦–页都强制刷新用户信息和路由权限,不做本地缓存判断
    userStore.getInfo().then(() => {
      userStore