YZProjectCloud/yanzhu-ui-vue3/src/views/flowable/task/todo/detail/indexDrawer.vue

1029 lines
41 KiB
Vue
Raw Normal View History

2024-12-22 19:55:21 +08:00
<template>
<div class="app-detailDrawer">
<el-drawer v-model="onOpen" :show-close="true" size="80%">
<template #header>
<h4>流程详情 {{ title }} - 当前进度{{ jdtitle }}<span v-if="showjd">
- 当前节点{{ dataOptions.taskName }}</span
></h4>
</template>
<div class="drawer" v-loading="loading">
<div class="drawerLeft">
<div class="block containers">
<div class="canvas" ref="flowCanvas"></div>
<div class="maskLayer" />
</div>
<el-timeline style="padding: 5px;">
<el-timeline-item
v-for="(item, index) in flowRecordList"
:key="index"
:icon="setIcon(item)"
:color="setColor(item)"
>
<p style="font-weight: 700">
{{ getSort(index) }}{{ item.taskName }}{{ item.commentResult }}
</p>
<el-card style="margin-top: 5px;">
<el-descriptions class="margin-top" :column="1" size="small" border>
<el-descriptions-item
v-if="item.assigneeName"
label-class-name="d-it-label"
>
<template #label>
<div class="my-label"><el-icon><User /></el-icon></div>
</template>
{{ item.assigneeName }}
<el-tag type="info" size="small">{{ item.deptName }}</el-tag>
</el-descriptions-item>
<el-descriptions-item
v-if="item.candidate"
label-class-name="d-it-label"
>
<template #label>
<div class="my-label"><el-icon><UserFilled /></el-icon></div>
</template>
{{ item.candidate }}
</el-descriptions-item>
<el-descriptions-item
v-if="item.deleteReason"
label-class-name="d-it-label"
>
<template #label>
<div class="my-label"><el-icon><Operation /></el-icon></div>
</template>
{{ getDeleteReason(item.deleteReason) }}
</el-descriptions-item>
<el-descriptions-item
label-class-name="d-it-label"
>
<template #label>
<div class="my-label"><el-icon><Clock /></el-icon></div>
</template>
{{ item.startTime }}
</el-descriptions-item>
<el-descriptions-item
v-if="item.endTime"
label-class-name="d-it-label"
>
<template #label>
<div class="my-label"><el-icon><Clock /></el-icon></div>
</template>
{{ item.endTime }}
</el-descriptions-item>
<el-descriptions-item
v-if="item.duration"
label-class-name="d-it-label"
>
<template #label>
<div class="my-label"><el-icon><Timer /></el-icon></div>
</template>
{{ formatDuraTime(item.duration) }}
</el-descriptions-item>
<el-descriptions-item
v-if="item.message"
label-class-name="d-it-label"
>
<template #label>
<div class="my-label"><el-icon><Warning /></el-icon></div>
</template>
{{ item.message }}
</el-descriptions-item>
</el-descriptions>
</el-card>
</el-timeline-item>
</el-timeline>
</div>
<div class="drawerRight">
<el-tabs v-model="activeName" type="card" class="demo-tabs">
<el-tab-pane label="单位信息" name="base" v-if="dataOptions.category=='1'">
<el-form label-width="100px" size="small" >
<el-form-item label="单位类型">
<el-tag effect="dark">{{ initData.subDeptTypeName }}</el-tag>
</el-form-item>
<el-form-item label="单位名称">
{{ initData.subDeptName }} <el-tag type="info">{{ parData.subDeptCode }}</el-tag>
</el-form-item>
<el-form-item label="进入场地时间" v-if="dataOptions.category=='1'">
{{ parseTime(parData.useDates, '{y}-{m}-{d}') }}
</el-form-item>
<el-row v-if="dataOptions.category=='1'">
<el-col :span="12">
<el-form-item label="计划开工时间">
{{ parseTime(parData.startWorkDates, '{y}-{m}-{d}') }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="计划完工时间">
{{ parseTime(parData.endWorkDates, '{y}-{m}-{d}') }}
</el-form-item>
</el-col>
</el-row>
<el-form-item label="营业执照">
<ImagePreview :src="parData.businessLicensePath" :width="120" :height="70"/>
</el-form-item>
<el-form-item label="合同约定范围">
{{ parData.contractInfos }}
</el-form-item>
<el-form-item label="法人身份证">
<ImagePreview :src="parData.subDeptInfos.legalPersonCardImgPos" :width="120" :height="70"/>
<ImagePreview :src="parData.subDeptInfos.legalPersonCardImgInv" :width="120" :height="70" style="margin-left: 20px;"/>
</el-form-item>
<el-form-item label="法人姓名">
{{ parData.subDeptInfos.legalPerson }}
</el-form-item>
<el-form-item label="法人身份证号">
{{ parData.subDeptInfos.legalPersonCard }}
</el-form-item>
</el-form>
</el-tab-pane>
2025-02-09 23:21:26 +08:00
<el-tab-pane label="人员信息" name="users" v-if="dataOptions.category=='1' || dataOptions.category=='2' || dataOptions.category=='3' || dataOptions.category=='4' || dataOptions.category=='5' || dataOptions.category=='6' || dataOptions.category=='8'">
2024-12-22 19:55:21 +08:00
<el-form label-width="100px" size="small" >
<el-form-item label="代理人身份证" v-if="dataOptions.category=='1'">
2025-01-15 00:49:31 +08:00
<ImagePreview :src="initData.userInfos.cardImgPos" :width="120" :height="70"/>
<ImagePreview :src="initData.userInfos.cardImgInv" :width="120" :height="70" style="margin-left: 20px;"/>
2024-12-22 19:55:21 +08:00
</el-form-item>
<el-form-item label="入场肖像近照" v-if="dataOptions.category=='1'">
2025-01-15 00:49:31 +08:00
<ImagePreview :src="initData.userPicture" :width="120" :height="70"/>
2024-12-22 19:55:21 +08:00
</el-form-item>
2025-02-09 23:21:26 +08:00
<el-form-item label="单位委托证明" v-if="dataOptions.category!='3' && dataOptions.category!='4' && dataOptions.category!='5' && dataOptions.category!='8'">
2024-12-22 19:55:21 +08:00
<ImagePreview :src="initData.subDeptPowerPath" :width="120" :height="70"/>
</el-form-item>
<el-form-item label="委托人姓名" v-if="dataOptions.category=='1'">
2025-01-15 00:49:31 +08:00
{{ initData.userName }} <el-tag type="info">{{ initData.cardCode }}</el-tag>
2024-12-22 19:55:21 +08:00
</el-form-item>
2024-12-30 00:30:39 +08:00
<el-form-item label="人员姓名" v-if="dataOptions.category!='1'">
2025-01-15 00:49:31 +08:00
{{ initData.userName }} <el-tag type="info">{{ initData.cardCode }}</el-tag>
2024-12-30 00:30:39 +08:00
</el-form-item>
<el-form-item label="工种岗位" v-if="dataOptions.category!='1'">
{{ initData.craftPostName }}
</el-form-item>
<el-form-item label="工种班组" v-if="dataOptions.category!='1' && dataOptions.category!='2'">
{{ initData.subDeptGroupName }}
</el-form-item>
2025-02-16 17:19:52 +08:00
<el-form-item label="民族" v-if="dataOptions.category!='1'">
{{ initData.userInfos.nation }}
</el-form-item>
<el-form-item label="籍贯" v-if="dataOptions.category!='1'">
2025-01-15 00:49:31 +08:00
{{ initData.userInfos.nativePlace }}
2024-12-30 00:30:39 +08:00
</el-form-item>
<el-form-item label="详细地址" v-if="dataOptions.category!='1'">
2025-01-15 00:49:31 +08:00
{{ initData.userInfos.address }}
2024-12-30 00:30:39 +08:00
</el-form-item>
<el-form-item label="身份证照片" v-if="dataOptions.category!='1'">
2025-01-15 00:49:31 +08:00
<ImagePreview :src="initData.userInfos.cardImgPos" :width="120" :height="70"/>
<ImagePreview :src="initData.userInfos.cardImgInv" :width="120" :height="70" style="margin-left: 20px;"/>
2024-12-30 00:30:39 +08:00
</el-form-item>
<el-form-item label="入场肖像近照" v-if="dataOptions.category!='1'">
2025-01-15 00:49:31 +08:00
<ImagePreview :src="initData.userPicture" :width="120" :height="70"/>
2024-12-30 00:30:39 +08:00
</el-form-item>
<el-form-item label="紧急联系人" v-if="dataOptions.category!='1'">
2025-01-15 00:49:31 +08:00
{{ initData.userInfos.emergencyContact }} <el-tag type="info">{{ initData.userInfos.contactPhone }}</el-tag>
2024-12-30 00:30:39 +08:00
</el-form-item>
<el-form-item label="开户行名称" v-if="dataOptions.category=='4'">
2025-01-15 00:49:31 +08:00
{{ initData.userInfos.bankName }}
2024-12-30 00:30:39 +08:00
</el-form-item>
<el-form-item label="开户行网点" v-if="dataOptions.category=='4'">
2025-01-15 00:49:31 +08:00
{{ initData.userInfos.bankName }}
2024-12-30 00:30:39 +08:00
</el-form-item>
<el-form-item label="工资银行卡号" v-if="dataOptions.category=='4'">
2025-01-15 00:49:31 +08:00
{{ initData.userInfos.bankName }}
2024-12-30 00:30:39 +08:00
</el-form-item>
2024-12-22 19:55:21 +08:00
<el-form-item label="联系电话">
2025-01-15 00:49:31 +08:00
{{ initData.userPhone }}
2024-12-22 19:55:21 +08:00
</el-form-item>
<el-form-item label="文化程度">
<el-tag effect="dark">{{ initData.degreeGradeName }}</el-tag>
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item label="身体健康问题">
<el-tag effect="dark" :type="initData.illnessStatus==0?'success':'danger'">{{ initData.illnessStatus==0?'无':'有' }}</el-tag>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="严重疾病情况">
<el-tag effect="dark" :type="initData.supIllnessStatus==0?'success':'danger'">{{ initData.supIllnessStatus==0?'无':'有' }}</el-tag>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="安全培训承诺书">
<el-button link type="primary" icon="Link" @click="handleDownloadEduFile(initData.eduFilePath)"></el-button>
</el-form-item>
</el-form>
</el-tab-pane>
2025-02-09 23:21:26 +08:00
<el-tab-pane label="视频培训" name="video" v-if="dataOptions.category=='1' || dataOptions.category=='2' || dataOptions.category=='3' || dataOptions.category=='4' || dataOptions.category=='5' || dataOptions.category=='46' || dataOptions.category=='8'">
2024-12-22 19:55:21 +08:00
<el-table :data="userEduVideoList">
<el-table-column label="播放时间" align="center" prop="playDates" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.playDates, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="播放时长" align="center" prop="playTimes" width="100">
<template #default="scope">
<span>{{ (scope.row.playTimes/1000).toFixed(2)+' 秒' }}</span>
</template>
</el-table-column>
<el-table-column label="培训名称" align="center" prop="trainTitle" :show-overflow-tooltip="true"/>
<el-table-column label="培训类型" align="center" prop="trainTypeName"/>
<el-table-column label="培训级别" align="center" prop="trainLevelName"/>
</el-table>
</el-tab-pane>
2025-02-09 23:21:26 +08:00
<el-tab-pane label="考试情况" name="exams" v-if="dataOptions.category=='1' || dataOptions.category=='2' || dataOptions.category=='3' || dataOptions.category=='4' || dataOptions.category=='5' || dataOptions.category=='6' || dataOptions.category=='8'">
2024-12-22 19:55:21 +08:00
<el-row class="task_panel">
<el-col :span="6">
<el-statistic class="statistic_div">
<template #title>
<div style="display: inline-flex; align-items: center">
<el-icon style="margin-right: 4px; color: #409eff" :size="12">
<InfoFilled />
</el-icon>
<strong>考试结果</strong>
</div>
</template>
</el-statistic>
<div v-if="userEduExamInfos.resStatus == '0'" class="countdown-footer">
<strong style="font-size: 16px; color: #909399; font-weight: 800;">未提交</strong>
</div>
<div v-if="userEduExamInfos.resStatus == '1'" class="countdown-footer">
<strong style="font-size: 16px; color: #67c23a; font-weight: 800;">已通过</strong>
</div>
<div v-if="userEduExamInfos.resStatus == '2'" class="countdown-footer">
<strong style="font-size: 16px; color: #f56c6c; font-weight: 800;">不通过</strong>
</div>
</el-col>
<el-col :span="6">
<el-statistic class="statistic_div">
<template #title>
<div style="display: inline-flex; align-items: center">
<el-icon style="margin-right: 4px; color: #67c23a" :size="12">
<TrendCharts />
</el-icon>
<strong>考试分数</strong>
</div>
</template>
</el-statistic>
<div class="countdown-footer">
<strong style="font-size: 16px; color: #909399">{{userEduExamInfos.userMark!=null?userEduExamInfos.userMark:'-'}}</strong>
</div>
</el-col>
<el-col :span="6">
<el-statistic class="statistic_div">
<template #title>
<div style="display: inline-flex; align-items: center">
<el-icon style="margin-right: 4px; color: #409eff" :size="12">
<InfoFilled />
</el-icon>
<strong>答题耗时</strong>
</div>
</template>
</el-statistic>
<div class="countdown-footer">
<strong style="font-size: 16px; color: #909399" v-if="userEduExamInfos.useTimes">{{formatDuraTime(userEduExamInfos.useTimes)}}</strong>
<strong style="font-size: 16px; color: #909399" v-if="!userEduExamInfos.useTimes"> - </strong>
</div>
</el-col>
<el-col :span="6">
<el-statistic class="statistic_div">
<template #title>
<div style="display: inline-flex; align-items: center">
<el-icon style="margin-right: 4px" :size="12">
<Calendar />
</el-icon>
答题时间
</div>
</template>
</el-statistic>
<div class="countdown-footer">
<strong>{{ parseTime(userEduExamInfos.createTime, "{y}-{m}-{d} {h}:{i}") }}</strong>
</div>
</el-col>
</el-row>
<div class="startExamination">
<ul>
<li v-for="(item,idx) in userEduQuestionList" :key="item.id">
<div class="topicTilte" style="font-weight: bold" ref="topicTilte">
{{ idx + 1 }}<span class="score">[{{ item.questionType==1?'单选题':(item.questionType==2?'多选题':'判断题')}}]</span>{{ item.questionTitle }}
</div>
<template v-if="item.questionType === 1">
<el-radio-group v-model="item.userAnswer" class="ml-4 Selected_item_radio" style="width: 100%">
<div v-for="(option,ox) in item.questionOption" class="Selected_item">
<el-radio :label="option.opt" disabled> {{ option.result }} </el-radio>
</div>
</el-radio-group>
<div :class="item.answer == item.userAnswer?'answer':'error'">
<div class="correctAnswer">正确答案{{ item.answer }}</div>
<div class="testAnswers">试卷答案{{ item.userAnswer }}</div>
</div>
</template>
<template v-if="item.questionType === 2">
<el-checkbox-group v-model="item.userAnswerValues" class="ml-4 Selected_item_radio" style="width: 100%">
<div v-for="option in item.questionOption" class="Selected_item">
<el-checkbox :label="option.opt" disabled> {{ option.result }} </el-checkbox>
</div>
</el-checkbox-group>
<div :class="item.answer == item.userAnswer?'answer':'error'">
<div class="correctAnswer">正确答案{{ item.answer }}</div>
<div class="testAnswers">试卷答案{{ item.userAnswer }}</div>
</div>
</template>
<template v-if="item.questionType === 3">
<el-checkbox-group v-model="item.userAnswerValues" class="ml-4 Selected_item_radio" style="width: 100%">
<div v-for="option in item.questionOption" class="Selected_item">
<el-checkbox :label="option.opt" disabled> {{ option.result }} </el-checkbox>
</div>
</el-checkbox-group>
<div :class="item.answer == item.userAnswer?'answer':'error'">
<div class="correctAnswer">正确答案{{ item.answer }}</div>
<div class="testAnswers">试卷答案{{ item.userAnswer }}</div>
</div>
</template>
</li>
</ul>
</div>
</el-tab-pane>
</el-tabs>
<el-form ref="approveProcessRef" :model="form" :rules="rules" label-width="100px" size="small" >
<el-form-item label="审批意见" prop="comment">
<el-input
type="textarea"
v-model="form.comment"
placeholder="请输入审批意见最多500字"
:rows="5"
/>
</el-form-item>
<div style="text-align: center">
<el-button
v-if="returnTaskBtn"
icon="CircleCloseFilled"
type="danger"
size="small"
@click="handleReturn"
>驳回申请</el-button
>
<el-button
2025-03-14 00:14:41 +08:00
v-if="false"
2024-12-22 19:55:21 +08:00
icon="WarningFilled"
type="warning"
size="small"
@click="handleReject"
>驳回上级</el-button
>
<el-button
icon="Finished"
type="success"
size="small"
@click="handlePass"
>审批通过</el-button
>
</div>
</el-form>
<div class="page-warning">
<p v-if="returnTaskBtn">
<strong style="color: #f56c6c">驳回申请</strong>
操作后代表您对当前任务不满意任务退回给申请人处理
</p>
2025-03-14 00:14:41 +08:00
<p v-if="false">
2024-12-22 19:55:21 +08:00
<strong style="color: #e6a23c">驳回上级</strong>
操作后代表您对当前任务不满意任务退回到上一阶段继续处理
</p>
<p>
<strong style="color: #67c23a">审批通过</strong>
操作后代表您对当前任务满意任务进入下一阶段
</p>
</div>
</div>
</div>
</el-drawer>
</div>
</template>
<script setup name="approveProcessDrawer">
import { flowXmlAndNode } from "@/api/flowable/definition";
import { CustomViewer as BpmnViewer } from "@/components/Process/common";
import { Clock, Select, CloseBold } from '@element-plus/icons-vue';
import { complete, rejectTask, returnTask, returnList } from "@/api/flowable/todo";
import {
findCommentByProcInsId,
} from "@/api/flowable/businessKey";
import { getProProjectInfoSubdepts } from "@/api/manage/proProjectInfoSubdepts";
2025-03-14 00:14:41 +08:00
import { getProProjectInfoSubdeptsUsers, editApproveStatus } from "@/api/manage/proProjectInfoSubdeptsUsers";
2024-12-22 19:55:21 +08:00
import { getBusExamUserLast } from "@/api/manage/busExamUser";
import { getBusTrainingVideoUserLast } from "@/api/manage/busTrainingVideoUser";
import useUserStore from '@/store/modules/user'
const { proxy } = getCurrentInstance();
const userStore = useUserStore()
const onOpen = ref(false);
const loading = ref(false);
const bpmnViewer = ref(null);
const title = ref("");
const jdtitle = ref("");
const showjd = ref(false);
const dataOptions = ref({});
const activeName = ref("");
const returnTaskBtn = ref(false);
const flowRecordList = ref([]);
const userEduVideoList = ref([]);
const userEduExamInfos = ref({});
const userEduQuestionList = ref([]);
const data = reactive({
parData: {
subDeptInfos:{}
},
initData: {
2025-02-16 17:19:52 +08:00
userInfos: {}
2024-12-22 19:55:21 +08:00
},
form: {
},
rules: {
comment: [{ required: true, message: "审批意见不能为空", trigger: "blur" },
{
max: 500,
message: "审批意见最多输入500字",
trigger: "blur",
}
]
}
});
const { parData, initData, form, rules } = toRefs(data);
const emit = defineEmits(["handle"]);
/** 获取节点图标 */
const setIcon = (row) => {
if (row.endTime) {
if (row.commentResult == "驳回") {
return CloseBold;
} else {
return Select;
}
} else {
return Clock;
}
};
/** 获取节点颜色 */
const setColor = (row) => {
if (row.endTime) {
if (row.commentResult == "驳回") {
return "#f56c6c";
} else {
return "#2bc418";
}
} else {
return "#409eff";
}
};
/** 获取节点排序 */
const getSort = (i) => {
let num = flowRecordList.value.length - i;
if (num < 10) {
num = "0" + num;
}
return num + ". ";
};
const doCanel = () => {
onOpen.value = false;
};
/** 审批通过 */
function handlePass() {
proxy.$refs["approveProcessRef"].validate((valid) => {
if (valid) {
loading.value = true;
proxy.$modal.confirm('是否确认审批通过流程编号为"' + dataOptions.value.taskId + '"的数据项?').then(function() {
return complete(form.value);
}).then(() => {
doCanel();
emit('handle');
proxy.$modal.msgSuccess("审批成功");
}).catch(() => {});
}
});
}
/** 驳回上级 */
function handleReject() {
proxy.$refs["approveProcessRef"].validate((valid) => {
if (valid) {
loading.value = true;
proxy.$modal.confirm('是否确认审批驳回流程编号为"' + dataOptions.value.taskId + '"的数据项?').then(function() {
return rejectTask(form.value);
}).then(() => {
doCanel();
emit('handle');
proxy.$modal.msgSuccess("审批成功");
}).catch(() => {});
}
});
}
/** 驳回申请 */
function handleReturn() {
proxy.$refs["approveProcessRef"].validate((valid) => {
if (valid) {
loading.value = true;
proxy.$modal.confirm('是否确认审批驳回流程编号为"' + dataOptions.value.taskId + '"的数据项至申请人?').then(function() {
return returnTask(form.value);
}).then(() => {
2025-03-14 00:14:41 +08:00
editApproveStatus(dataOptions.value.businessKey);
2024-12-22 19:55:21 +08:00
doCanel();
emit('handle');
proxy.$modal.msgSuccess("审批成功");
}).catch(() => {});
}
});
}
/** 显示流程详情 */
const show = (options) => {
dataOptions.value = options;
title.value = options.procDefName;
onOpen.value = true;
showjd.value = false;
if (options.finishTime == null) {
jdtitle.value = "进行中";
showjd.value = true;
} else if (options.finishTime!= null && options.assigneeId == null) {
jdtitle.value = "已终止";
} else {
jdtitle.value = "已完成";
}
2025-02-16 17:19:52 +08:00
activeName.value = "users";
2024-12-22 19:55:21 +08:00
initFormDate();
initFormValues();
getFlowRecordList(options.procInsId, options.deployId);
flowXmlAndNode({ procInsId: options.procInsId, deployId: options.deployId }).then(
(res) => {
initFlowImage(res.data);
}
);
};
/** 初始化表单数据 */
const initFormDate = () => {
form.value.taskId = dataOptions.value.taskId;
form.value.taskName = dataOptions.value.taskName;
form.value.userId = userStore.uid;
form.value.deployId = dataOptions.value.deployId;
form.value.procInsId = dataOptions.value.procInsId;
form.value.instanceId = dataOptions.value.procInsId;
form.value.executionId = dataOptions.value.procInsId;
form.value.comment = "";
returnTaskBtn.value = true;
loading.value = false;
initReturnList();
}
/** 初始化流程节点 */
const initReturnList = () => {
returnList(form.value).then((res) => {
//退回节点>1时可显示退回按钮
if (res.data.length == 0) {
returnTaskBtn.value = false;
}else{
form.value.targetKey = res.data[0].id;
}
});
}
/** 初始化工作流 */
const initFlowImage = async (data) => {
try {
bpmnViewer.value && bpmnViewer.value.destroy();
bpmnViewer.value = new BpmnViewer({
container: proxy.$refs.flowCanvas,
height: '90px',
});
await bpmnViewer.value.importXML(data.xmlData);
// 自适应
bpmnViewer.value.get("canvas").zoom("fit-viewport", "auto");
// 流程线高亮设置
if (data.nodeData !== undefined && data.nodeData.length > 0) {
await fillColor(data.nodeData);
}
} catch (err) {
console.error(err.message, err.warnings);
}
};
/** 获取流程节点 */
const getFlowRecordList = (procInsId, deployId) => {
const params = { procInsId: procInsId };
findCommentByProcInsId(params)
.then((res) => {
flowRecordList.value = res.data;
})
.catch((res) => {
console.error("数据异常,请联系管理员...");
});
};
/** 获取表单数据 */
const initFormValues = () => {
let category = parseInt(dataOptions.value.category);
2025-02-09 23:21:26 +08:00
if(category==1 || category==2 || category==3 || category==4 || category==5 || category==6 || category==8){
2024-12-22 19:55:21 +08:00
getProProjectInfoSubdeptsUsers(dataOptions.value.businessKey).then(res =>{
2025-01-15 00:49:31 +08:00
if(res.data.userInfos){
res.data.userInfos = JSON.parse(res.data.userInfos);
2024-12-22 19:55:21 +08:00
}
initData.value = res.data ;
getProProjectInfoSubdepts(res.data.subDeptId).then(parRes =>{
if(parRes.data.subDeptInfos){
parRes.data.subDeptInfos = JSON.parse(parRes.data.subDeptInfos);
}
parData.value = parRes.data;
});
});
findEduVideos();
findEduExams();
}
};
/** 用户视频培训 */
function findEduVideos(){
2025-02-16 17:19:52 +08:00
getBusTrainingVideoUserLast(dataOptions.value.startProId, dataOptions.value.startUserId).then(res =>{
2024-12-22 19:55:21 +08:00
userEduVideoList.value = res.data||[]
});
}
/** 用户考试情况 */
function findEduExams(){
2025-02-16 17:19:52 +08:00
getBusExamUserLast(dataOptions.value.startProId, dataOptions.value.startUserId).then(res =>{
2024-12-22 19:55:21 +08:00
if(res.code==200 && res.data){
userEduExamInfos.value = res.data;
let list = res.data.busExamUserResultList;
list.forEach(item => {
if(item.questionType===2){
if(item.userAnswer==null){
item.userAnswer = "";
}
item.userAnswerValues = item.userAnswer.split(',');
}
item.questionOption = JSON.parse(item.questionOption);
});
userEduQuestionList.value = list;
}
});
}
/** 下载培训承诺书 */
function handleDownloadEduFile(filePath){
proxy.$download.resource(filePath);
};
/** 设置高亮颜色的 */
function fillColor(nodeData) {
const canvas = bpmnViewer.value.get('canvas')
bpmnViewer.value.getDefinitions().rootElements[0].flowElements.forEach(n => {
const completeTask = nodeData.find(m => m.key === n.id)
const todoTask = nodeData.find(m => !m.completed)
const endTask = nodeData[nodeData.length - 1]
if (n.$type === 'bpmn:UserTask') {
if (completeTask) {
canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo')
n.outgoing?.forEach(nn => {
const targetTask = nodeData.find(m => m.key === nn.targetRef.id)
if (targetTask) {
if (todoTask && completeTask.key === todoTask.key && !todoTask.completed){
canvas.addMarker(nn.id, todoTask.completed ? 'highlight' : 'highlight-todo')
canvas.addMarker(nn.targetRef.id, todoTask.completed ? 'highlight' : 'highlight-todo')
}else {
canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo')
canvas.addMarker(nn.targetRef.id, targetTask.completed ? 'highlight' : 'highlight-todo')
}
}
})
}
}
// 排他网关
else if (n.$type === 'bpmn:ExclusiveGateway') {
if (completeTask) {
canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo')
n.outgoing?.forEach(nn => {
const targetTask = nodeData.find(m => m.key === nn.targetRef.id)
if (targetTask) {
canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo')
canvas.addMarker(nn.targetRef.id, targetTask.completed ? 'highlight' : 'highlight-todo')
}
})
}
}
// 并行网关
else if (n.$type === 'bpmn:ParallelGateway') {
if (completeTask) {
canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo')
n.outgoing?.forEach(nn => {
const targetTask = nodeData.find(m => m.key === nn.targetRef.id)
if (targetTask) {
canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo')
canvas.addMarker(nn.targetRef.id, targetTask.completed ? 'highlight' : 'highlight-todo')
}
})
}
}
else if (n.$type === 'bpmn:StartEvent') {
n.outgoing.forEach(nn => {
const completeTask = nodeData.find(m => m.key === nn.targetRef.id)
if (completeTask) {
canvas.addMarker(nn.id, 'highlight')
canvas.addMarker(n.id, 'highlight')
return;
}
})
}
else if (n.$type === 'bpmn:EndEvent') {
if (endTask.key === n.id && endTask.completed) {
canvas.addMarker(n.id, 'highlight')
return;
}
}
})
}
/** 获取审批节点 */
const getDeleteReason = (val) => {
val = val.replace("Change activity to ", "");
let flowRecordList = this.flowRecordList;
for (let i = 0; i < flowRecordList.length; i++) {
if (flowRecordList[i].taskDefKey == val) {
return "驳回至" + flowRecordList[i].taskName;
}
}
};
/** 暴露组件 */
defineExpose({
show
});
</script>
<style lang="scss">
.app-detailDrawer {
.el-drawer__header{
margin-bottom: 0 !important;
}
.drawer {
width: 100%;
height: 100%;
padding-left: 20px;
padding-right: 20px;
padding-bottom: 20px;
.drawerLeft {
width: 50%;
min-width: 280px;
height: 100%;
float: left;
border-right: 1px solid #dcdfe6;
overflow-y: scroll;
padding-right: 20px;
.bjs-powered-by {
display: none !important;
}
.maskLayer {
width: 50%;
height: 90px;
position: absolute;
z-index: 9999;
top: 77px;
}
.el-timeline-item{
.el-timeline-item__node{
width: 20px;
height: 20px;
margin-top: -4px;
.el-timeline-item__icon{
font-size: 16px !important;
}
}
}
}
.drawerRight {
width: 50%;
min-width: 400px;
height: 100%;
float: left;
padding-left: 20px;
.el-link_div {
width: 100%;
overflow: hidden;
}
.el-form-item__content{
.el-tag--info{
margin-left: 5px;
}
}
}
}
.containers {
width: 100%;
height: 90px;
.canvas {
width: 100%;
height: 100px;
}
.panel {
position: absolute;
right: 0;
top: 50px;
width: 300px;
}
.load {
margin-right: 10px;
}
.el-form-item__label {
font-size: 13px;
}
.djs-palette {
left: 0px !important;
top: 0px;
border-top: none;
}
.djs-container svg {
min-height: 90px;
}
.highlight.djs-shape .djs-visual > :nth-child(1) {
fill: green !important;
stroke: green !important;
fill-opacity: 0.2 !important;
}
.highlight.djs-shape .djs-visual > :nth-child(2) {
fill: green !important;
}
.highlight.djs-shape .djs-visual > path {
fill: green !important;
fill-opacity: 0.2 !important;
stroke: green !important;
}
.highlight.djs-connection > .djs-visual > path {
stroke: green !important;
}
.highlight-todo.djs-connection > .djs-visual > path {
stroke: orange !important;
stroke-dasharray: 4px !important;
fill-opacity: 0.2 !important;
}
.highlight-todo.djs-shape .djs-visual > :nth-child(1) {
fill: orange !important;
stroke: orange !important;
stroke-dasharray: 4px !important;
fill-opacity: 0.2 !important;
}
.overlays-div {
font-size: 10px;
color: red;
width: 100px;
top: -20px !important;
}
}
}
.mytags{
float:left;
margin-right: 6px;
}
.d-it-label{
width: 150px;
.my-label{
display: flex;
align-items: center;
.el-icon{
margin-right: 5px;
}
}
}
.el-divider__text{
color: #409eff;
font-weight: 800;
}
.task_panel {
text-align: center;
margin-bottom: 20px;
margin-top: 10px;
}
.statistic_div {
.el-statistic__content {
display: none;
}
}
.startExamination {
padding: 0px 20px;
ul {
margin: 30px 0;
li {
list-style: none;
margin-top: 10px;
.Selected_item_radio {
display: block;
flex: none;
}
.topicTilte {
.score {
display: inline-block;
margin-right: 10px;
}
}
.Selected_item_fill {
height: 45px;
display: flex;
align-items: center;
}
.answer {
height: 30px;
display: flex;
align-items: center;
border: 1px solid #e1f3d8;
color: #67c23a;
padding: 0 15px;
//margin: 10px 20px 10px 0;
background-color: #f0f9eb;
.correctAnswer {
margin-right: 40px;
}
}
.error {
height: 30px;
display: flex;
align-items: center;
padding: 0 15px;
//margin: 10px 20px 10px 0;
background: #fdf6ec;
border: 1px solid #faecd8;
color: #f56c6c;
.correctAnswer {
margin-right: 40px;
}
}
.CompletionAnswer {
height: 80px;
display: flex;
align-items: center;
border: 1px solid #e1f3d8;
color: #67c23a;
padding: 0 15px;
margin: 10px 20px 10px 0;
background-color: #f0f9eb;
.CompletionAnswerIndex {
width: 50px;
height: 100%;
display: flex;
align-items: center;
border-right: 1px solid #e1f3d8;
margin-right: 20px;
}
.correctAnswer {
margin-right: 40px;
}
}
.CompletionError {
height: 80px;
display: flex;
align-items: center;
padding: 0 15px;
margin: 10px 20px 10px 0;
background: #fdf6ec;
border: 1px solid #faecd8;
color: #f56c6c;
.CompletionAnswerIndex {
width: 25px;
height: 100%;
display: flex;
align-items: center;
border-right: 1px solid #faecd8;
margin-right: 20px;
}
.correctAnswer {
height: 40px;
margin-right: 40px;
}
}
}
}
}
.el-alert {
margin: 20px 0 0;
}
.el-alert:first-child {
margin: 0;
}
.page-warning {
padding: 8px 16px;
background-color: #f0f9eb;
border-radius: 4px;
border-left: 5px solid #67c23a;
margin: 20px 0;
font-size: 13px;
margin-top: 30px;
color: darkkhaki;
p{
margin-bottom: 5px;
}
}
</style>