gaoluyang
3 天以前 76ebf70b38016446c18af3d9b1d153ed7901d146
1.协同审批流程联调
已修改3个文件
218 ■■■■ 文件已修改
src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue 212 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/approvalProcess/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
@@ -6,36 +6,113 @@
        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>
                    <el-col :span="24">
                        <el-form-item label="审批事由:" 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>
      <el-form :model="{ activities }" ref="formRef" label-position="top">
        <el-timeline style="max-width: 600px">
          <el-timeline-item
        <el-steps :active="getActiveStep()" finish-status="success" process-status="process" align-center direction="vertical">
          <el-step
              v-for="(activity, index) in activities"
              :key="index"
              :type="activity.current ? 'primary' : ''"
              :hollow="activity.current"
              :timestamp="activity.approveNodeTime"
                        finish-status="success"
            :title="getNodeTitle(index, activities.length)"
            :description="activity.approveNodeUser"
            :icon="getNodeIcon(activity, index)"
          >
            <el-card>
              <span style="font-size: 18px;font-weight: 700">节点{{activity.approveNodeOrder}}</span>
              <div style="margin: 10px 0">
                <span style="font-size: 16px;font-weight: 600">审批人:{{activity.approveNodeUser}}</span>
                        <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>
              <div>
                <span style="margin-bottom: 8px;display: inline-block;font-size: 16px;font-weight: 600">审批意见:</span>
                <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
                  v-if="activity.approveNodeRemark == 1"
                  :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>
                <el-form-item v-else>
                  <el-input v-model="activity.approveNodeReason" clearable type="textarea" disabled></el-input>
                </el-form-item>
              </div>
            </el-card>
          </el-timeline-item>
        </el-timeline>
            </template>
          </el-step>
        </el-steps>
      </el-form>
      <template #footer v-if="operationType === 'approval'">
        <div class="dialog-footer">
@@ -49,8 +126,15 @@
</template>
<script setup>
import {getCurrentInstance, ref} from "vue";
import {approveProcessDetails, updateApproveNode} from "../../../../api/collaborativeApproval/approvalProcess.js";
import {getCurrentInstance, 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'
const emit = defineEmits(['close'])
const { proxy } = getCurrentInstance()
@@ -58,21 +142,77 @@
const operationType = ref('')
const activities = ref([])
const formRef = ref(null);
const userStore = useUserStore()
const productOptions = ref([]);
const userList = ref([])
const data = reactive({
    form: {
        approveTime: "",
        approveId: "",
        approveUser: "",
        approveDeptId: "",
        approveReason: "",
        checkResult: "",
    },
});
const { form } = toRefs(data);
// 节点标题
const getNodeTitle = (index, len) => {
  if (index === 0) return '发起';
  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;
    userListNoPageByTenantId().then((res) => {
        userList.value = res.data;
    });
    form.value = {...row}
    getProductOptions()
    approveProcessDetails(row.approveId).then((res) => {
        console.log(res)
        activities.value = res.data
    // 增加isApproval字段
    activities.value.forEach(item => {
      if (item.approveNodeStatus === 2) {
        item.isApproval = '已驳回';
      } else if (item.approveNodeStatus === 1) {
        item.isApproval = '已同意';
      } else {
        item.isApproval = '未审批';
      }
    })
    })
}
const getProductOptions = () => {
    getDept().then((res) => {
        productOptions.value = res.data;
    });
};
// 提交审批
const submitForm = (status) => {
    const filteredActivities = activities.value.filter(activity => activity.approveNodeRemark == 1);
  const filteredActivities = activities.value.filter(activity => activity.isShen);
    filteredActivities[0].approveNodeStatus = status
    updateApproveNode(filteredActivities[0]).then(() => {
  // 判断是否为最后一步
  const isLast = activities.value.findIndex(a => a.isShen) === activities.value.length-1;
  updateApproveNode({ ...filteredActivities[0], isLast }).then(() => {
        proxy.$modal.msgSuccess("提交成功");
        closeDia();
    })
@@ -89,7 +229,29 @@
</script>
<style scoped>
.el-timeline {
  padding-left: 10px;
.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;
}
</style>
src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue
@@ -160,6 +160,7 @@
});
const { form, rules } = toRefs(data);
const productOptions = ref([]);
const currentApproveStatus = ref(0)
// 审批人节点相关
const approverNodes = ref([
@@ -178,6 +179,7 @@
const openDialog = (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
    currentApproveStatus.value = row.approveStatus
    userListNoPageByTenantId().then((res) => {
    userList.value = res.data;
  });
@@ -240,7 +242,7 @@
  }
  proxy.$refs.formRef.validate(valid => {
    if (valid) {
      if (operationType.value === "add") {
      if (operationType.value === "add" || currentApproveStatus.value == 3) {
        approveProcessAdd(form.value).then(res => {
          proxy.$modal.msgSuccess("提交成功");
          closeDia();
src/views/collaborativeApproval/approvalProcess/index.vue
@@ -140,7 +140,7 @@
        clickFun: (row) => {
          openApprovalDia("approval", row);
        },
                disabled: (row) => row.approveUserCurrentId == null || row.approveStatus == 2 || row.approveUserCurrentId !== userStore.id
                disabled: (row) => row.approveUserCurrentId == null || row.approveStatus == 2 || row.approveStatus == 3 || row.approveUserCurrentId !== userStore.id
      },
      {
        name: "详情",