zhangwencui
2026-05-15 429b6e4d00594183bbcf02aba24d2df2d3f4c95b
src/pages/cooperativeOffice/collaborativeApproval/approve.vue
@@ -1,8 +1,7 @@
<template>
  <view class="approve-page">
    <PageHeader title="审核" @back="goBack" />
    <PageHeader title="审核"
                @back="goBack" />
    <!-- 申请信息 -->
    <view class="application-info">
      <view class="info-header">
@@ -25,7 +24,6 @@
          <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,30 +35,27 @@
            <text class="info-value">{{ approvalData.endDate || '-' }}</text>
          </view>
        </template>
        <!-- approveType=3 出差相关字段 -->
        <view v-if="approvalData.approveType === 3" class="info-row">
        <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">
        <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>
    <!-- 审批流程 -->
    <view class="approval-process">
      <view class="process-header">
        <text class="process-title">审批流程</text>
      </view>
      <view class="process-steps">
        <view
          v-for="(step, index) in approvalSteps"
        <view v-for="(step, index) in approvalSteps"
          :key="index" 
          class="process-step"
          :class="{
@@ -68,177 +63,190 @@
            'current': step.status === 'current',
            'pending': step.status === 'pending',
            'rejected': step.status === 'rejected'
          }"
        >
          }">
          <view class="step-indicator">
            <view class="step-dot">
              <text v-if="step.status === 'completed'" class="step-icon">✓</text>
              <text v-else-if="step.status === 'rejected'" class="step-icon">✗</text>
              <text v-else class="step-number">{{ index + 1 }}</text>
              <text v-if="step.status === 'completed'"
                    class="step-icon">✓</text>
              <text v-else-if="step.status === 'rejected'"
                    class="step-icon">✗</text>
              <text v-else
                    class="step-number">{{ index + 1 }}</text>
            </view>
            <view v-if="index < approvalSteps.length - 1" class="step-line"></view>
            <view v-if="index < approvalSteps.length - 1"
                  class="step-line"></view>
          </view>
          <view class="step-content">
            <view class="step-info">
              <text class="step-title">{{ step.title }}</text>
              <text class="step-approver">{{ step.approverName }}</text>
              <text v-if="step.approveTime" class="step-time">{{ step.approveTime }}</text>
              <text v-if="step.approveTime"
                    class="step-time">{{ step.approveTime }}</text>
            </view>
            <view v-if="step.opinion" class="step-opinion">
            <view v-if="step.opinion"
                  class="step-opinion">
              <text class="opinion-label">审批意见:</text>
              <text class="opinion-content">{{ step.opinion }}</text>
            </view>
            <!-- 签名展示 -->
            <view v-if="step.urlTem" class="step-opinion" style="margin-top:8px;">
            <view v-if="step.urlTem"
                  class="step-opinion"
                  style="margin-top:8px;">
              <text class="opinion-label">签名:</text>
              <image :src="step.urlTem" mode="widthFix" style="width:180px;border-radius:6px;border:1px solid #eee;" />
              <image :src="step.urlTem"
                     mode="widthFix"
                     style="width:180px;border-radius:6px;border:1px solid #eee;" />
            </view>
          </view>
        </view>
      </view>
    </view>
    <!-- 审核意见输入 -->
    <view v-if="canApprove" class="approval-input">
    <view v-if="canApprove"
          class="approval-input">
      <view class="input-header">
        <text class="input-title">审核意见</text>
      </view>
      <view class="input-content">
        <u-textarea
          v-model="approvalOpinion"
        <u-textarea v-model="approvalOpinion"
          rows="4"
          placeholder="请输入审核意见"
          maxlength="200"
          count
        />
                    count />
      </view>
    </view>
    <!-- 底部操作按钮 -->
    <view v-if="canApprove" class="footer-actions">
      <u-button class="reject-btn" @click="handleReject">驳回</u-button>
      <u-button class="approve-btn" @click="handleApprove">通过</u-button>
    <view v-if="canApprove"
          class="footer-actions">
      <u-button class="reject-btn"
                @click="handleReject">驳回</u-button>
      <u-button class="approve-btn"
                @click="handleApprove">通过</u-button>
    </view>
  </view>
</template>
<script setup>
import { ref, onMounted, computed } from 'vue'
import { approveProcessGetInfo, approveProcessDetails, updateApproveNode } from '@/api/collaborativeApproval/approvalProcess'
import useUserStore from '@/store/modules/user'
const showToast = (message) => {
  import { ref, onMounted, computed } from "vue";
  import {
    approveProcessGetInfo,
    approveProcessDetails,
    updateApproveNode,
  } from "@/api/collaborativeApproval/approvalProcess";
  import useUserStore from "@/store/modules/user";
  const showToast = message => {
   uni.showToast({
      title: message,
      icon: 'none'
   })
}
      icon: "none",
    });
  };
import PageHeader from "@/components/PageHeader.vue";
const userStore = useUserStore()
const approvalData = ref({})
const approvalSteps = ref([])
const approvalOpinion = ref('')
const approveId = ref('')
  const userStore = useUserStore();
  const approvalData = ref({});
  const approvalSteps = ref([]);
  const approvalOpinion = ref("");
  const approveId = ref("");
// 从详情接口字段对齐 canApprove:仅当有 isShen 的节点时可审批
const canApprove = computed(() => {
  return approvalSteps.value.some(step => step.isShen === true)
})
    return approvalSteps.value.some(step => step.isShen === true);
  });
onMounted(() => {
  approveId.value = uni.getStorageSync('approveId')
    approveId.value = uni.getStorageSync("approveId");
  if (approveId.value) {
    loadApprovalData()
      loadApprovalData();
  }
})
  });
const loadApprovalData = () => {
  // 基本申请信息
  approveProcessGetInfo({ id: approveId.value }).then(res => {
    approvalData.value = res.data || {}
  })
      approvalData.value = res.data || {};
    });
  // 审批节点详情
  approveProcessDetails(approveId.value).then(res => {
    const list = Array.isArray(res.data) ? res.data : []
      const list = Array.isArray(res.data) ? res.data : [];
    // 保存原始节点数据供提交使用
    activities.value = list
      activities.value = list;
    approvalSteps.value = list.map((it, idx) => {
      // 节点状态映射:1=通过,2=不通过,否则看是否当前(isShen),再默认为待处理
      let status = 'pending'
      if (it.approveNodeStatus === 1) status = 'completed'
      else if (it.approveNodeStatus === 2) status = 'rejected'
      else if (it.isShen) status = 'current'
        let status = "pending";
        if (it.approveNodeStatus === 1) status = "completed";
        else if (it.approveNodeStatus === 2) status = "rejected";
        else if (it.isShen) status = "current";
      return {
        title: `第${idx + 1}步审批`,
        approverName: it.approveNodeUser || '未知用户',
          approverName: it.approveNodeUser || "未知用户",
        status,
        approveTime: it.approveTime || null,
        opinion: it.approveNodeReason || '',
        urlTem: it.urlTem || '',
        isShen: !!it.isShen
      }
    })
  })
}
          opinion: it.approveNodeReason || "",
          urlTem: it.urlTem || "",
          isShen: !!it.isShen,
        };
      });
    });
  };
const goBack = () => {
  uni.removeStorageSync('approveId');
  uni.navigateBack()
}
    uni.removeStorageSync("approveId");
    uni.navigateBack();
  };
const submitForm = (status) => {
  const submitForm = status => {
  // 可选:校验审核意见
  if (!approvalOpinion.value?.trim()) {
    showToast('请输入审核意见')
    return
      showToast("请输入审核意见");
      return;
  }
  // 找到当前可审批节点
  const filteredActivities = activities.value.filter(activity => activity.isShen)
    const filteredActivities = activities.value.filter(
      activity => activity.isShen
    );
  if (!filteredActivities.length) {
    showToast('当前无可审批节点')
    return
      showToast("当前无可审批节点");
      return;
  }
  // 写入状态和意见
  filteredActivities[0].approveNodeStatus = status
  filteredActivities[0].approveNodeReason = approvalOpinion.value || ''
    filteredActivities[0].approveNodeStatus = status;
    filteredActivities[0].approveNodeReason = approvalOpinion.value || "";
  // 计算是否为最后一步
  const isLast = activities.value.findIndex(a => a.isShen) === activities.value.length - 1
    const isLast =
      activities.value.findIndex(a => a.isShen) === activities.value.length - 1;
  // 调用后端
  updateApproveNode({ ...filteredActivities[0], isLast }).then(() => {
    const msg = status === 1 ? '审批通过' : '审批已驳回'
    showToast(msg)
      const msg = status === 1 ? "审批通过" : "审批已驳回";
      showToast(msg);
    // 提示后返回上一个页面
    setTimeout(() => {
      goBack() // 内部是 uni.navigateBack()
    }, 800)
  })
}
        goBack(); // 内部是 uni.navigateBack()
      }, 800);
    });
  };
const handleApprove = () => {
  uni.showModal({
    title: '确认操作',
    content: '确定要通过此审批吗?',
    success: (res) => {
      if (res.confirm) submitForm(1)
    }
  })
}
      title: "确认操作",
      content: "确定要通过此审批吗?",
      success: res => {
        if (res.confirm) submitForm(1);
      },
    });
  };
const handleReject = () => {
  uni.showModal({
    title: '确认操作',
    content: '确定要驳回此审批吗?',
    success: (res) => {
      if (res.confirm) submitForm(2)
    }
  })
}
      title: "确认操作",
      content: "确定要驳回此审批吗?",
      success: res => {
        if (res.confirm) submitForm(2);
      },
    });
  };
// 原始节点数据(用于提交逻辑)
const activities = ref([])
  const activities = ref([]);
</script>
<style scoped lang="scss">