|
@@ -0,0 +1,405 @@
|
|
|
|
|
+<!--
|
|
|
|
|
+ * @Author: wanglj 471442253@qq.com
|
|
|
|
|
+ * @Date: 2023-01-10 13:41:07
|
|
|
|
|
+ * @LastEditors: wanglj
|
|
|
|
|
+ * @LastEditTime: 2023-01-10 18:00:55
|
|
|
|
|
+ * @Description: file content
|
|
|
|
|
+ * @FilePath: \opms_frontend\src\views\plat\task\detail.vue
|
|
|
|
|
+-->
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="detail">
|
|
|
|
|
+ <el-row :gutter="10">
|
|
|
|
|
+ <el-col :span="16">
|
|
|
|
|
+ <div class="title">
|
|
|
|
|
+ <p>督办详情</p>
|
|
|
|
|
+ <h3>
|
|
|
|
|
+ {{ theTask.taskTitle }}
|
|
|
|
|
+ <span></span>
|
|
|
|
|
+ </h3>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <header>
|
|
|
|
|
+ <el-descriptions :colon="false" :column="6" direction="vertical">
|
|
|
|
|
+ <el-descriptions-item content-class-name="my-content" label="督办类型" label-class-name="my-label">
|
|
|
|
|
+ {{ typeMap[theTask.taskType] }}
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item content-class-name="my-content" label="状态" label-class-name="my-label">
|
|
|
|
|
+ <span v-if="theTask.taskStatus === '10'">发起</span>
|
|
|
|
|
+ <span v-else-if="theTask.taskStatus === '20'">进行中</span>
|
|
|
|
|
+ <span v-else-if="theTask.taskStatus === '30'">流程完成</span>
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item content-class-name="my-content" label="超期" label-class-name="my-label">
|
|
|
|
|
+ {{ theTask.isOverdue === '10' ? '否' : '是' }}
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item content-class-name="my-content" label="开始时间" label-class-name="my-label">
|
|
|
|
|
+ {{ parseTime(theTask.taskStartDate) }}
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item content-class-name="my-content" label="结束时间" label-class-name="my-label">
|
|
|
|
|
+ {{ parseTime(theTask.taskEndDate) }}
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item content-class-name="my-content" label="说明" label-class-name="my-label">
|
|
|
|
|
+ {{ theTask.taskDesc }}
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ </el-descriptions>
|
|
|
|
|
+ <el-descriptions :colon="false" :column="6" direction="vertical">
|
|
|
|
|
+ <el-descriptions-item content-class-name="my-content" label="督办人" label-class-name="my-label">
|
|
|
|
|
+ {{ userMap[theTask.supervisorUserId] }}
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item content-class-name="my-content" label="监办人" label-class-name="my-label">
|
|
|
|
|
+ {{ userMap[theTask.watchUserId] }}
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item content-class-name="my-content" label="负责人" label-class-name="my-label">
|
|
|
|
|
+ {{ userMap[theTask.mainUserId] }}
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item content-class-name="my-content" label="团队成员" label-class-name="my-label">
|
|
|
|
|
+ {{ teamNames }}
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item content-class-name="my-content" label="关联类型" label-class-name="my-label">
|
|
|
|
|
+ <span v-show="theTask.targetType == '10'">客户</span>
|
|
|
|
|
+ <span v-show="theTask.targetType == '20'">项目</span>
|
|
|
|
|
+ <span v-show="theTask.targetType == '30'">合同</span>
|
|
|
|
|
+ <span v-show="theTask.targetType == '40'">回款</span>
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item content-class-name="my-content" label="关联对象" label-class-name="my-label">
|
|
|
|
|
+ {{ theTask.targetName }}
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ </el-descriptions>
|
|
|
|
|
+ </header>
|
|
|
|
|
+ <el-form label-width="80px" :model="form" style="margin-top: 10px">
|
|
|
|
|
+ <el-form-item label="进展情况">
|
|
|
|
|
+ <el-button v-show="theTask.step === 20 && type == '1'" circle icon="el-icon-plus" @click="addProgress" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label-width="0">
|
|
|
|
|
+ <el-table border :data="progressList" max-height="300px">
|
|
|
|
|
+ <el-table-column align="center" label="进展说明" prop="progDesc">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <span v-if="row.id">{{ row.progDesc }}</span>
|
|
|
|
|
+ <el-input v-else v-model="row.progDesc" placeholder="进展说明" style="width: 100%" />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column align="center" label="时间" prop="progDate">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <span v-if="row.id">{{ parseTime(row.progDate) }}</span>
|
|
|
|
|
+ <el-date-picker
|
|
|
|
|
+ v-else
|
|
|
|
|
+ v-model="row.progDate"
|
|
|
|
|
+ style="width: 100%"
|
|
|
|
|
+ value-format="yyyy-MM-dd HH:mm:ss" />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column align="center" label="附件" prop="progFile">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <el-link v-show="row.progFile" @click="showFile(row.progFile)">查看附件</el-link>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column align="center" label="备注" prop="remark">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <span v-if="row.id">{{ row.remark }}</span>
|
|
|
|
|
+ <el-input v-else v-model="row.remark" placeholder="备注" style="width: 100%" />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column v-if="theTask.step < 30 && type == 1" align="center" label="操作">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <el-button type="text" @click="handleDel(row.$index)">删除</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item v-if="theTask.approDate || theTask.step === 30" label="审批意见">
|
|
|
|
|
+ <el-input v-if="theTask.step === 30" v-model="form.approDesc" placeholder="审批意见" />
|
|
|
|
|
+ <span v-else>{{ theTask.approDesc }}</span>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item v-if="theTask.approDate || theTask.step === 40" label="督办评价">
|
|
|
|
|
+ <el-input v-if="theTask.step === 40" v-model="form.evaluateDesc" placeholder="督办评价" />
|
|
|
|
|
+ <span v-else>{{ theTask.evaluateDesc }}</span>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ </el-col>
|
|
|
|
|
+ <el-col :span="8">
|
|
|
|
|
+ <div class="buttons">
|
|
|
|
|
+ <el-button v-show="theTask.taskStatus === '10' && type == 1" type="primary" @click="changeStatus(10, '10')">
|
|
|
|
|
+ 接收
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ v-show="theTask.taskStatus === '20' && theTask.step === 20 && type == 1"
|
|
|
|
|
+ type="success"
|
|
|
|
|
+ @click="changeStatus(15)">
|
|
|
|
|
+ 暂存
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ v-show="theTask.taskStatus === '20' && theTask.step === 20 && type == 1"
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ @click="changeStatus(20, '20')">
|
|
|
|
|
+ 提交
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button v-show="theTask.step === 30 && type == 1" type="primary" @click="changeStatus(30, '30')">
|
|
|
|
|
+ 审批通过
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button v-show="theTask.step === 30 && type == 1" type="danger" @click="changeStatus(30, '40')">
|
|
|
|
|
+ 审批退回
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button v-show="theTask.step === 40 && type == 1" type="primary" @click="changeStatus(40, '30')">
|
|
|
|
|
+ 审批通过
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button v-show="theTask.step === 40 && type == 1" type="danger" @click="changeStatus(40, '40')">
|
|
|
|
|
+ 审批退回
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button @click="$router.go(-1)">返回</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <ul class="records">
|
|
|
|
|
+ <li v-for="log in logList" :key="log.id">
|
|
|
|
|
+ <vab-icon icon="record-circle-line" />
|
|
|
|
|
+ <div class="text">
|
|
|
|
|
+ <p class="action">
|
|
|
|
|
+ <span>{{ log.nodeName }}</span>
|
|
|
|
|
+ <span>{{ log.desc }}</span>
|
|
|
|
|
+ </p>
|
|
|
|
|
+ <p>
|
|
|
|
|
+ <span>开始处理</span>
|
|
|
|
|
+ <span>完成处理</span>
|
|
|
|
|
+ </p>
|
|
|
|
|
+ <p>
|
|
|
|
|
+ <span>{{ log.startTime }}</span>
|
|
|
|
|
+ <span>{{ log.endTime }}</span>
|
|
|
|
|
+ </p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </li>
|
|
|
|
|
+ </ul>
|
|
|
|
|
+ </el-col>
|
|
|
|
|
+ </el-row>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+<script>
|
|
|
|
|
+ import to from 'await-to-js'
|
|
|
|
|
+ import taskApi from '@/api/plat/task'
|
|
|
|
|
+ import userApi from '@/api/system/user'
|
|
|
|
|
+ import dictApi from '@/api/system/dict'
|
|
|
|
|
+ export default {
|
|
|
|
|
+ name: 'TaskDetail',
|
|
|
|
|
+ data() {
|
|
|
|
|
+ return {
|
|
|
|
|
+ detail: {},
|
|
|
|
|
+ // 督办进展
|
|
|
|
|
+ progressList: [],
|
|
|
|
|
+ // 日志
|
|
|
|
|
+ logList: [],
|
|
|
|
|
+ theTask: {},
|
|
|
|
|
+ typeMap: {},
|
|
|
|
|
+ userMap: {},
|
|
|
|
|
+ teamNames: '',
|
|
|
|
|
+ form: {
|
|
|
|
|
+ comment: '',
|
|
|
|
|
+ },
|
|
|
|
|
+ type: '',
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ async mounted() {
|
|
|
|
|
+ this.type = this.$route.query.type
|
|
|
|
|
+ await this.initData()
|
|
|
|
|
+ this.theTask = this.$store.state.task.theTask
|
|
|
|
|
+ this.open()
|
|
|
|
|
+ },
|
|
|
|
|
+ methods: {
|
|
|
|
|
+ // 打开弹窗
|
|
|
|
|
+ open() {
|
|
|
|
|
+ // 获取数据信息
|
|
|
|
|
+ this.getProgressList()
|
|
|
|
|
+ this.getLogList()
|
|
|
|
|
+ this.teamNames = ''
|
|
|
|
|
+ if (this.theTask.ownerUserId != '') {
|
|
|
|
|
+ let ids = this.theTask.ownerUserId.split(',')
|
|
|
|
|
+ for (let id of ids) {
|
|
|
|
|
+ if (this.teamNames == '') {
|
|
|
|
|
+ this.teamNames = this.userMap[parseInt(id)]
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.teamNames += ',' + this.userMap[parseInt(id)]
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 初始化数据
|
|
|
|
|
+ async initData() {
|
|
|
|
|
+ const [err, [type, user]] = await to(
|
|
|
|
|
+ Promise.all([dictApi.getDictDataList({ dictType: 'TaskType' }), userApi.getList()])
|
|
|
|
|
+ )
|
|
|
|
|
+ if (err) return
|
|
|
|
|
+ this.types = type.data.list
|
|
|
|
|
+ for (let type of this.types) {
|
|
|
|
|
+ this.typeMap[type.dictValue] = type.dictLabel
|
|
|
|
|
+ }
|
|
|
|
|
+ this.users = user.data.list
|
|
|
|
|
+ for (let user of this.users) {
|
|
|
|
|
+ this.userMap[user.id] = user.userName
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 获取进展信息
|
|
|
|
|
+ getProgressList() {
|
|
|
|
|
+ this.progressList = []
|
|
|
|
|
+ taskApi
|
|
|
|
|
+ .getTaskProgressList({ taskId: this.theTask.id + '' })
|
|
|
|
|
+ .then((res) => {
|
|
|
|
|
+ if (res.data.list) {
|
|
|
|
|
+ this.progressList = res.data.list
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch((err) => {
|
|
|
|
|
+ console.error(err)
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ // 获取日志信息
|
|
|
|
|
+ getLogList() {
|
|
|
|
|
+ this.logList = []
|
|
|
|
|
+ taskApi
|
|
|
|
|
+ .getTaskLogList({ taskId: this.theTask.id + '' })
|
|
|
|
|
+ .then((res) => {
|
|
|
|
|
+ if (res.data.list) {
|
|
|
|
|
+ this.logList = res.data.list
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch((err) => {
|
|
|
|
|
+ console.error(err)
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ // 改变督办状态
|
|
|
|
|
+ changeStatus(step, status) {
|
|
|
|
|
+ if (step == 30 && !this.form.approDesc) return this.$message.warning('请填写审批意见')
|
|
|
|
|
+ else if (step == 40 && !this.form.evaluateDesc) return this.$message.warning('请填写督办意见')
|
|
|
|
|
+ this.$confirm('确定修改督办状态?', '提示', {
|
|
|
|
|
+ confirmButtonText: '确定',
|
|
|
|
|
+ cancelButtonText: '取消',
|
|
|
|
|
+ type: 'warning',
|
|
|
|
|
+ }).then(async () => {
|
|
|
|
|
+ // eslint-disable-next-line vue/no-mutating-props
|
|
|
|
|
+ this.selfVisible = false
|
|
|
|
|
+ let data = {
|
|
|
|
|
+ taskId: this.theTask.id,
|
|
|
|
|
+ step,
|
|
|
|
|
+ handleStatus: status,
|
|
|
|
|
+ handleDesc: '',
|
|
|
|
|
+ progressList: this.progressList,
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.theTask.step == 30) data.handleDesc = this.form.approDesc
|
|
|
|
|
+ else if (this.theTask.step == 40) data.handleDesc = this.form.evaluateDesc
|
|
|
|
|
+ const { msg } = await taskApi.handleTask(data)
|
|
|
|
|
+ this.$baseMessage(msg, 'success', 'vab-hey-message-success')
|
|
|
|
|
+ this.$router.go(-1)
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ // 查看附件
|
|
|
|
|
+ showFile(path) {
|
|
|
|
|
+ const a = document.createElement('a')
|
|
|
|
|
+ a.href = path // 文件链接
|
|
|
|
|
+ a.download = path // 文件名,跨域资源download无效
|
|
|
|
|
+ a.click()
|
|
|
|
|
+ a.remove()
|
|
|
|
|
+ },
|
|
|
|
|
+ // 添加进展
|
|
|
|
|
+ addProgress() {
|
|
|
|
|
+ this.progressList.push({})
|
|
|
|
|
+ },
|
|
|
|
|
+ handleDel(index) {
|
|
|
|
|
+ this.progressList.splice(index, 1)
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ }
|
|
|
|
|
+</script>
|
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
|
+ $base: '.detail';
|
|
|
|
|
+ #{$base} {
|
|
|
|
|
+ height: calc(100vh - 60px - 12px * 2 - 40px);
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ padding: 20px 40px;
|
|
|
|
|
+ > .el-row {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ > .el-col {
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .title {
|
|
|
|
|
+ p,
|
|
|
|
|
+ h3 {
|
|
|
|
|
+ margin: 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ p {
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ font-weight: 400;
|
|
|
|
|
+ line-height: 22px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ h3 {
|
|
|
|
|
+ font-size: 24px;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ line-height: 36px;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ header {
|
|
|
|
|
+ min-height: 134px;
|
|
|
|
|
+ background: rgba(196, 196, 196, 0.5);
|
|
|
|
|
+ border-radius: 4px;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ padding: 7px 20px;
|
|
|
|
|
+ margin-top: 16px;
|
|
|
|
|
+ ::v-deep .el-descriptions__body {
|
|
|
|
|
+ background: transparent;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ ::v-deep .my-label {
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ color: #1d66dc;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ ::v-deep .my-content {
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .buttons {
|
|
|
|
|
+ height: 60px;
|
|
|
|
|
+ padding-top: 28px;
|
|
|
|
|
+ text-align: right;
|
|
|
|
|
+ }
|
|
|
|
|
+ .add-pro {
|
|
|
|
|
+ text-align: right;
|
|
|
|
|
+ margin: 10px 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ .records {
|
|
|
|
|
+ padding: 10px 20px;
|
|
|
|
|
+ height: calc(100% - 60px);
|
|
|
|
|
+ overflow-y: auto;
|
|
|
|
|
+ li {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ i {
|
|
|
|
|
+ font-size: 40px;
|
|
|
|
|
+ margin-right: 10px;
|
|
|
|
|
+ }
|
|
|
|
|
+ .text {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ p {
|
|
|
|
|
+ height: 20px;
|
|
|
|
|
+ line-height: 20px;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ &:first-child {
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ & + li {
|
|
|
|
|
+ margin-top: 10px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+</style>
|