Commit 7cf20db674aa70e82a7a1d43982621a51de797d4
1 parent
18300670
完成工作单详情
Showing
13 changed files
with
1863 additions
and
9 deletions
src/api/oa/workDetailApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | + | |
| 3 | +// 获取工作单详情 | |
| 4 | +export function getWorkPoolDetail(params) { | |
| 5 | + return new Promise((resolve, reject) => { | |
| 6 | + request({ | |
| 7 | + url: '/work.listWorkPool', | |
| 8 | + method: 'get', | |
| 9 | + params | |
| 10 | + }).then(response => { | |
| 11 | + const res = response.data | |
| 12 | + resolve(res) | |
| 13 | + }).catch(error => { | |
| 14 | + reject(error) | |
| 15 | + }) | |
| 16 | + }) | |
| 17 | +} | |
| 18 | + | |
| 19 | +// 获取工作单任务列表 | |
| 20 | +export function listWorkTask(params) { | |
| 21 | + return new Promise((resolve, reject) => { | |
| 22 | + request({ | |
| 23 | + url: '/work.listWorkTask', | |
| 24 | + method: 'get', | |
| 25 | + params | |
| 26 | + }).then(response => { | |
| 27 | + const res = response.data | |
| 28 | + resolve(res) | |
| 29 | + }).catch(error => { | |
| 30 | + reject(error) | |
| 31 | + }) | |
| 32 | + }) | |
| 33 | +} | |
| 34 | + | |
| 35 | +// 获取工作单任务项列表 | |
| 36 | +export function listWorkTaskItem(params) { | |
| 37 | + return new Promise((resolve, reject) => { | |
| 38 | + request({ | |
| 39 | + url: '/task.listWorkTaskItem', | |
| 40 | + method: 'get', | |
| 41 | + params | |
| 42 | + }).then(response => { | |
| 43 | + const res = response.data | |
| 44 | + resolve(res) | |
| 45 | + }).catch(error => { | |
| 46 | + reject(error) | |
| 47 | + }) | |
| 48 | + }) | |
| 49 | +} | |
| 50 | + | |
| 51 | +// 获取工作单抄送人列表 | |
| 52 | +export function listWorkCopy(params) { | |
| 53 | + return new Promise((resolve, reject) => { | |
| 54 | + request({ | |
| 55 | + url: '/work.listWorkCopy', | |
| 56 | + method: 'get', | |
| 57 | + params | |
| 58 | + }).then(response => { | |
| 59 | + const res = response.data | |
| 60 | + resolve(res) | |
| 61 | + }).catch(error => { | |
| 62 | + reject(error) | |
| 63 | + }) | |
| 64 | + }) | |
| 65 | +} | |
| 66 | + | |
| 67 | +// 获取工作单流转事件列表 | |
| 68 | +export function listWorkEvent(params) { | |
| 69 | + return new Promise((resolve, reject) => { | |
| 70 | + request({ | |
| 71 | + url: '/workEvent.listWorkEvent', | |
| 72 | + method: 'get', | |
| 73 | + params | |
| 74 | + }).then(response => { | |
| 75 | + const res = response.data | |
| 76 | + resolve(res) | |
| 77 | + }).catch(error => { | |
| 78 | + reject(error) | |
| 79 | + }) | |
| 80 | + }) | |
| 81 | +} | |
| 82 | + | |
| 83 | +// 获取工作单流转附件列表 | |
| 84 | +export function listWorkPoolFile(params) { | |
| 85 | + return new Promise((resolve, reject) => { | |
| 86 | + request({ | |
| 87 | + url: '/work.listWorkPoolFile', | |
| 88 | + method: 'get', | |
| 89 | + params | |
| 90 | + }).then(response => { | |
| 91 | + const res = response.data | |
| 92 | + resolve(res) | |
| 93 | + }).catch(error => { | |
| 94 | + reject(error) | |
| 95 | + }) | |
| 96 | + }) | |
| 97 | +} | |
| 98 | + | |
| 99 | +// 获取工作单类型列表 | |
| 100 | +export function listWorkType(params) { | |
| 101 | + return new Promise((resolve, reject) => { | |
| 102 | + request({ | |
| 103 | + url: '/workType.listWorkType', | |
| 104 | + method: 'get', | |
| 105 | + params | |
| 106 | + }).then(response => { | |
| 107 | + const res = response.data | |
| 108 | + resolve(res) | |
| 109 | + }).catch(error => { | |
| 110 | + reject(error) | |
| 111 | + }) | |
| 112 | + }) | |
| 113 | +} | |
| 114 | + | |
| 115 | +// 获取工作单周期列表 | |
| 116 | +export function listWorkCycle(params) { | |
| 117 | + return new Promise((resolve, reject) => { | |
| 118 | + request({ | |
| 119 | + url: '/workCycle.listWorkCycle', | |
| 120 | + method: 'get', | |
| 121 | + params | |
| 122 | + }).then(response => { | |
| 123 | + const res = response.data | |
| 124 | + resolve(res) | |
| 125 | + }).catch(error => { | |
| 126 | + reject(error) | |
| 127 | + }) | |
| 128 | + }) | |
| 129 | +} | |
| 0 | 130 | \ No newline at end of file | ... | ... |
src/components/oa/WorkDetailCopy.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="work-detail-copy"> | |
| 3 | + <el-row :gutter="20" class="margin-top-lg"> | |
| 4 | + <el-col :span="6"> | |
| 5 | + <el-input | |
| 6 | + v-model.trim="workDetailCopyInfo.staffNameLike" | |
| 7 | + :placeholder="$t('workDetailCopy.staffNamePlaceholder')" | |
| 8 | + clearable | |
| 9 | + /> | |
| 10 | + </el-col> | |
| 11 | + <el-col :span="6"> | |
| 12 | + <el-button type="primary" @click="queryWorkDetailCopy"> | |
| 13 | + <i class="el-icon-search"></i>{{ $t('common.search') }} | |
| 14 | + </el-button> | |
| 15 | + <el-button @click="resetWorkDetailCopy"> | |
| 16 | + <i class="el-icon-refresh"></i>{{ $t('common.reset') }} | |
| 17 | + </el-button> | |
| 18 | + </el-col> | |
| 19 | + </el-row> | |
| 20 | + | |
| 21 | + <div class="margin-top"> | |
| 22 | + <el-table | |
| 23 | + :data="workDetailCopyInfo.copys" | |
| 24 | + border | |
| 25 | + style="width: 100%" | |
| 26 | + v-loading="loading" | |
| 27 | + > | |
| 28 | + <el-table-column | |
| 29 | + prop="copyId" | |
| 30 | + :label="$t('workDetailCopy.copyId')" | |
| 31 | + align="center" | |
| 32 | + /> | |
| 33 | + <el-table-column | |
| 34 | + prop="staffName" | |
| 35 | + :label="$t('workDetailCopy.staffName')" | |
| 36 | + align="center" | |
| 37 | + /> | |
| 38 | + <el-table-column | |
| 39 | + prop="createTime" | |
| 40 | + :label="$t('workDetailCopy.createTime')" | |
| 41 | + align="center" | |
| 42 | + /> | |
| 43 | + <el-table-column | |
| 44 | + prop="stateName" | |
| 45 | + :label="$t('workDetailCopy.stateName')" | |
| 46 | + align="center" | |
| 47 | + /> | |
| 48 | + <el-table-column | |
| 49 | + prop="remark" | |
| 50 | + :label="$t('workDetailCopy.remark')" | |
| 51 | + align="center" | |
| 52 | + /> | |
| 53 | + </el-table> | |
| 54 | + | |
| 55 | + <el-pagination | |
| 56 | + :current-page.sync="page.current" | |
| 57 | + :page-sizes="[10, 20, 30, 50]" | |
| 58 | + :page-size="page.size" | |
| 59 | + :total="page.total" | |
| 60 | + layout="total, sizes, prev, pager, next, jumper" | |
| 61 | + @size-change="handleSizeChange" | |
| 62 | + @current-change="handleCurrentChange" | |
| 63 | + /> | |
| 64 | + </div> | |
| 65 | + </div> | |
| 66 | +</template> | |
| 67 | + | |
| 68 | +<script> | |
| 69 | +import { listWorkCopy } from '@/api/oa/workDetailApi' | |
| 70 | + | |
| 71 | +export default { | |
| 72 | + name: 'WorkDetailCopy', | |
| 73 | + data() { | |
| 74 | + return { | |
| 75 | + workDetailCopyInfo: { | |
| 76 | + copys: [], | |
| 77 | + workId: '', | |
| 78 | + staffNameLike: '' | |
| 79 | + }, | |
| 80 | + loading: false, | |
| 81 | + page: { | |
| 82 | + current: 1, | |
| 83 | + size: 10, | |
| 84 | + total: 0 | |
| 85 | + } | |
| 86 | + } | |
| 87 | + }, | |
| 88 | + methods: { | |
| 89 | + open(params) { | |
| 90 | + this.workDetailCopyInfo.workId = params.workId | |
| 91 | + this.loadWorkDetailCopyData(this.page.current, this.page.size) | |
| 92 | + }, | |
| 93 | + async loadWorkDetailCopyData(page, size) { | |
| 94 | + try { | |
| 95 | + this.loading = true | |
| 96 | + const params = { | |
| 97 | + workId: this.workDetailCopyInfo.workId, | |
| 98 | + staffNameLike: this.workDetailCopyInfo.staffNameLike, | |
| 99 | + page, | |
| 100 | + row: size | |
| 101 | + } | |
| 102 | + const { data, total } = await listWorkCopy(params) | |
| 103 | + this.workDetailCopyInfo.copys = data | |
| 104 | + this.page.total = total | |
| 105 | + } catch (error) { | |
| 106 | + console.error('获取抄送人列表失败:', error) | |
| 107 | + } finally { | |
| 108 | + this.loading = false | |
| 109 | + } | |
| 110 | + }, | |
| 111 | + queryWorkDetailCopy() { | |
| 112 | + this.page.current = 1 | |
| 113 | + this.loadWorkDetailCopyData(this.page.current, this.page.size) | |
| 114 | + }, | |
| 115 | + resetWorkDetailCopy() { | |
| 116 | + this.workDetailCopyInfo.staffNameLike = '' | |
| 117 | + this.queryWorkDetailCopy() | |
| 118 | + }, | |
| 119 | + handleSizeChange(val) { | |
| 120 | + this.page.size = val | |
| 121 | + this.loadWorkDetailCopyData(this.page.current, this.page.size) | |
| 122 | + }, | |
| 123 | + handleCurrentChange(val) { | |
| 124 | + this.page.current = val | |
| 125 | + this.loadWorkDetailCopyData(this.page.current, this.page.size) | |
| 126 | + } | |
| 127 | + } | |
| 128 | +} | |
| 129 | +</script> | |
| 130 | + | |
| 131 | +<style scoped> | |
| 132 | +.margin-top-lg { | |
| 133 | + margin-top: 20px; | |
| 134 | +} | |
| 135 | +.margin-top { | |
| 136 | + margin-top: 20px; | |
| 137 | +} | |
| 138 | +</style> | |
| 0 | 139 | \ No newline at end of file | ... | ... |
src/components/oa/WorkDetailCycle.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="work-detail-cycle"> | |
| 3 | + <div class="margin-top"> | |
| 4 | + <el-table | |
| 5 | + :data="workDetailCycleInfo.cycles" | |
| 6 | + border | |
| 7 | + style="width: 100%" | |
| 8 | + v-loading="loading" | |
| 9 | + > | |
| 10 | + <el-table-column | |
| 11 | + prop="staffName" | |
| 12 | + :label="$t('workDetailCycle.staffName')" | |
| 13 | + align="center" | |
| 14 | + /> | |
| 15 | + <el-table-column | |
| 16 | + :label="$t('workDetailCycle.workCycle')" | |
| 17 | + align="center" | |
| 18 | + > | |
| 19 | + <template slot-scope="scope"> | |
| 20 | + {{ scope.row.workCycle === '1001' ? $t('workDetailCycle.once') : $t('workDetailCycle.periodic') }} | |
| 21 | + </template> | |
| 22 | + </el-table-column> | |
| 23 | + <el-table-column | |
| 24 | + prop="hours" | |
| 25 | + :label="$t('workDetailCycle.hours')" | |
| 26 | + align="center" | |
| 27 | + /> | |
| 28 | + <el-table-column | |
| 29 | + :label="$t('workDetailCycle.period')" | |
| 30 | + align="center" | |
| 31 | + > | |
| 32 | + <template slot-scope="scope"> | |
| 33 | + {{ scope.row.period === '2020022' ? $t('workDetailCycle.monthDay') : $t('workDetailCycle.weekly') }} | |
| 34 | + </template> | |
| 35 | + </el-table-column> | |
| 36 | + <el-table-column | |
| 37 | + prop="periodMonth" | |
| 38 | + :label="$t('workDetailCycle.month')" | |
| 39 | + align="center" | |
| 40 | + > | |
| 41 | + <template slot-scope="scope"> | |
| 42 | + {{ scope.row.periodMonth || '-' }} | |
| 43 | + </template> | |
| 44 | + </el-table-column> | |
| 45 | + <el-table-column | |
| 46 | + prop="periodDay" | |
| 47 | + :label="$t('workDetailCycle.day')" | |
| 48 | + align="center" | |
| 49 | + > | |
| 50 | + <template slot-scope="scope"> | |
| 51 | + {{ scope.row.periodDay || '-' }} | |
| 52 | + </template> | |
| 53 | + </el-table-column> | |
| 54 | + <el-table-column | |
| 55 | + prop="periodWorkday" | |
| 56 | + :label="$t('workDetailCycle.week')" | |
| 57 | + align="center" | |
| 58 | + > | |
| 59 | + <template slot-scope="scope"> | |
| 60 | + {{ scope.row.periodWorkday || '-' }} | |
| 61 | + </template> | |
| 62 | + </el-table-column> | |
| 63 | + </el-table> | |
| 64 | + | |
| 65 | + <el-pagination | |
| 66 | + :current-page.sync="page.current" | |
| 67 | + :page-sizes="[10, 20, 30, 50]" | |
| 68 | + :page-size="page.size" | |
| 69 | + :total="page.total" | |
| 70 | + layout="total, sizes, prev, pager, next, jumper" | |
| 71 | + @size-change="handleSizeChange" | |
| 72 | + @current-change="handleCurrentChange" | |
| 73 | + /> | |
| 74 | + </div> | |
| 75 | + </div> | |
| 76 | +</template> | |
| 77 | + | |
| 78 | +<script> | |
| 79 | +import { listWorkCycle } from '@/api/oa/workDetailApi' | |
| 80 | + | |
| 81 | +export default { | |
| 82 | + name: 'WorkDetailCycle', | |
| 83 | + data() { | |
| 84 | + return { | |
| 85 | + workDetailCycleInfo: { | |
| 86 | + cycles: [], | |
| 87 | + workId: '' | |
| 88 | + }, | |
| 89 | + loading: false, | |
| 90 | + page: { | |
| 91 | + current: 1, | |
| 92 | + size: 10, | |
| 93 | + total: 0 | |
| 94 | + } | |
| 95 | + } | |
| 96 | + }, | |
| 97 | + methods: { | |
| 98 | + open(params) { | |
| 99 | + this.workDetailCycleInfo.workId = params.workId | |
| 100 | + this.loadWorkDetailCycleData(this.page.current, this.page.size) | |
| 101 | + }, | |
| 102 | + async loadWorkDetailCycleData(page, size) { | |
| 103 | + try { | |
| 104 | + this.loading = true | |
| 105 | + const params = { | |
| 106 | + workId: this.workDetailCycleInfo.workId, | |
| 107 | + page, | |
| 108 | + row: size | |
| 109 | + } | |
| 110 | + const { data, total } = await listWorkCycle(params) | |
| 111 | + this.workDetailCycleInfo.cycles = data | |
| 112 | + this.page.total = total | |
| 113 | + } catch (error) { | |
| 114 | + console.error('获取工作单周期列表失败:', error) | |
| 115 | + } finally { | |
| 116 | + this.loading = false | |
| 117 | + } | |
| 118 | + }, | |
| 119 | + handleSizeChange(val) { | |
| 120 | + this.page.size = val | |
| 121 | + this.loadWorkDetailCycleData(this.page.current, this.page.size) | |
| 122 | + }, | |
| 123 | + handleCurrentChange(val) { | |
| 124 | + this.page.current = val | |
| 125 | + this.loadWorkDetailCycleData(this.page.current, this.page.size) | |
| 126 | + } | |
| 127 | + } | |
| 128 | +} | |
| 129 | +</script> | |
| 130 | + | |
| 131 | +<style scoped> | |
| 132 | +.margin-top { | |
| 133 | + margin-top: 20px; | |
| 134 | +} | |
| 135 | +</style> | |
| 0 | 136 | \ No newline at end of file | ... | ... |
src/components/oa/WorkDetailEvent.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="work-detail-event"> | |
| 3 | + <el-row :gutter="20"> | |
| 4 | + <el-col :span="4"> | |
| 5 | + <div class="tree-container"> | |
| 6 | + <el-scrollbar> | |
| 7 | + <ul class="content-list"> | |
| 8 | + <li | |
| 9 | + v-for="(item,index) in workDetailEventInfo.contents" | |
| 10 | + :key="index" | |
| 11 | + @click="swatchEventContentId(item)" | |
| 12 | + :class="{'active-content': workDetailEventInfo.contentId === item.contentId}" | |
| 13 | + > | |
| 14 | + 问题{{ item.seqNum }} | |
| 15 | + </li> | |
| 16 | + </ul> | |
| 17 | + </el-scrollbar> | |
| 18 | + </div> | |
| 19 | + </el-col> | |
| 20 | + <el-col :span="20"> | |
| 21 | + <el-row :gutter="20" class="margin-top-lg"> | |
| 22 | + <el-col :span="6"> | |
| 23 | + <el-input | |
| 24 | + v-model.trim="workDetailEventInfo.staffNameLike" | |
| 25 | + :placeholder="$t('workDetailEvent.staffNamePlaceholder')" | |
| 26 | + clearable | |
| 27 | + /> | |
| 28 | + </el-col> | |
| 29 | + <el-col :span="6"> | |
| 30 | + <el-date-picker | |
| 31 | + v-model="workDetailEventInfo.queryStartTime" | |
| 32 | + type="datetime" | |
| 33 | + :placeholder="$t('workDetailEvent.startTimePlaceholder')" | |
| 34 | + value-format="yyyy-MM-dd HH:mm:ss" | |
| 35 | + style="width: 100%" | |
| 36 | + /> | |
| 37 | + </el-col> | |
| 38 | + <el-col :span="6"> | |
| 39 | + <el-date-picker | |
| 40 | + v-model="workDetailEventInfo.queryEndTime" | |
| 41 | + type="datetime" | |
| 42 | + :placeholder="$t('workDetailEvent.endTimePlaceholder')" | |
| 43 | + value-format="yyyy-MM-dd HH:mm:ss" | |
| 44 | + style="width: 100%" | |
| 45 | + /> | |
| 46 | + </el-col> | |
| 47 | + <el-col :span="6"> | |
| 48 | + <el-button type="primary" @click="queryWorkDetailEvent"> | |
| 49 | + <i class="el-icon-search"></i>{{ $t('common.search') }} | |
| 50 | + </el-button> | |
| 51 | + <el-button @click="resetWorkDetailEvent"> | |
| 52 | + <i class="el-icon-refresh"></i>{{ $t('common.reset') }} | |
| 53 | + </el-button> | |
| 54 | + </el-col> | |
| 55 | + </el-row> | |
| 56 | + | |
| 57 | + <div class="margin-top"> | |
| 58 | + <el-table | |
| 59 | + :data="workDetailEventInfo.events" | |
| 60 | + border | |
| 61 | + style="width: 100%" | |
| 62 | + v-loading="loading" | |
| 63 | + > | |
| 64 | + <el-table-column | |
| 65 | + prop="preStaffName" | |
| 66 | + :label="$t('workDetailEvent.preStaffName')" | |
| 67 | + align="center" | |
| 68 | + /> | |
| 69 | + <el-table-column | |
| 70 | + prop="staffName" | |
| 71 | + :label="$t('workDetailEvent.staffName')" | |
| 72 | + align="center" | |
| 73 | + /> | |
| 74 | + <el-table-column | |
| 75 | + :label="$t('workDetailEvent.taskValidPeriod')" | |
| 76 | + align="center" | |
| 77 | + > | |
| 78 | + <template slot-scope="scope"> | |
| 79 | + {{ scope.row.startTime }}<br>~{{ scope.row.endTime }} | |
| 80 | + </template> | |
| 81 | + </el-table-column> | |
| 82 | + <el-table-column | |
| 83 | + prop="remark" | |
| 84 | + :label="$t('workDetailEvent.remark')" | |
| 85 | + align="center" | |
| 86 | + /> | |
| 87 | + <el-table-column | |
| 88 | + prop="createTime" | |
| 89 | + :label="$t('workDetailEvent.createTime')" | |
| 90 | + align="center" | |
| 91 | + /> | |
| 92 | + </el-table> | |
| 93 | + | |
| 94 | + <el-pagination | |
| 95 | + :current-page.sync="page.current" | |
| 96 | + :page-sizes="[10, 20, 30, 50]" | |
| 97 | + :page-size="page.size" | |
| 98 | + :total="page.total" | |
| 99 | + layout="total, sizes, prev, pager, next, jumper" | |
| 100 | + @size-change="handleSizeChange" | |
| 101 | + @current-change="handleCurrentChange" | |
| 102 | + /> | |
| 103 | + </div> | |
| 104 | + </el-col> | |
| 105 | + </el-row> | |
| 106 | + </div> | |
| 107 | +</template> | |
| 108 | + | |
| 109 | +<script> | |
| 110 | +import { listWorkEvent } from '@/api/oa/workDetailApi' | |
| 111 | + | |
| 112 | +export default { | |
| 113 | + name: 'WorkDetailEvent', | |
| 114 | + data() { | |
| 115 | + return { | |
| 116 | + workDetailEventInfo: { | |
| 117 | + events: [], | |
| 118 | + contents: [], | |
| 119 | + workId: '', | |
| 120 | + contentId: '', | |
| 121 | + staffNameLike: '', | |
| 122 | + queryStartTime: '', | |
| 123 | + queryEndTime: '' | |
| 124 | + }, | |
| 125 | + loading: false, | |
| 126 | + page: { | |
| 127 | + current: 1, | |
| 128 | + size: 10, | |
| 129 | + total: 0 | |
| 130 | + } | |
| 131 | + } | |
| 132 | + }, | |
| 133 | + methods: { | |
| 134 | + open(params) { | |
| 135 | + this.workDetailEventInfo.workId = params.workId | |
| 136 | + this.workDetailEventInfo.contents = params.contents | |
| 137 | + if (params.contents.length > 0) { | |
| 138 | + this.swatchEventContentId(params.contents[0]) | |
| 139 | + } | |
| 140 | + }, | |
| 141 | + async loadWorkDetailEventData(page, size) { | |
| 142 | + try { | |
| 143 | + this.loading = true | |
| 144 | + const params = { | |
| 145 | + workId: this.workDetailEventInfo.workId, | |
| 146 | + contentId: this.workDetailEventInfo.contentId, | |
| 147 | + staffNameLike: this.workDetailEventInfo.staffNameLike, | |
| 148 | + queryStartTime: this.workDetailEventInfo.queryStartTime, | |
| 149 | + queryEndTime: this.workDetailEventInfo.queryEndTime, | |
| 150 | + page, | |
| 151 | + row: size | |
| 152 | + } | |
| 153 | + const { data, total } = await listWorkEvent(params) | |
| 154 | + this.workDetailEventInfo.events = data | |
| 155 | + this.page.total = total | |
| 156 | + } catch (error) { | |
| 157 | + console.error('获取工作单流转列表失败:', error) | |
| 158 | + } finally { | |
| 159 | + this.loading = false | |
| 160 | + } | |
| 161 | + }, | |
| 162 | + queryWorkDetailEvent() { | |
| 163 | + this.page.current = 1 | |
| 164 | + this.loadWorkDetailEventData(this.page.current, this.page.size) | |
| 165 | + }, | |
| 166 | + swatchEventContentId(content) { | |
| 167 | + this.workDetailEventInfo.contentId = content.contentId | |
| 168 | + this.loadWorkDetailEventData(this.page.current, this.page.size) | |
| 169 | + }, | |
| 170 | + resetWorkDetailEvent() { | |
| 171 | + this.workDetailEventInfo.staffNameLike = '' | |
| 172 | + this.workDetailEventInfo.queryStartTime = '' | |
| 173 | + this.workDetailEventInfo.queryEndTime = '' | |
| 174 | + this.queryWorkDetailEvent() | |
| 175 | + }, | |
| 176 | + handleSizeChange(val) { | |
| 177 | + this.page.size = val | |
| 178 | + this.loadWorkDetailEventData(this.page.current, this.page.size) | |
| 179 | + }, | |
| 180 | + handleCurrentChange(val) { | |
| 181 | + this.page.current = val | |
| 182 | + this.loadWorkDetailEventData(this.page.current, this.page.size) | |
| 183 | + } | |
| 184 | + } | |
| 185 | +} | |
| 186 | +</script> | |
| 187 | + | |
| 188 | +<style scoped> | |
| 189 | +.tree-container { | |
| 190 | + height: 500px; | |
| 191 | + border: 1px solid #ebeef5; | |
| 192 | + border-radius: 4px; | |
| 193 | + padding: 10px; | |
| 194 | +} | |
| 195 | + | |
| 196 | +.content-list { | |
| 197 | + list-style: none; | |
| 198 | + padding: 0; | |
| 199 | + margin: 0; | |
| 200 | +} | |
| 201 | + | |
| 202 | +.content-list li { | |
| 203 | + padding: 10px; | |
| 204 | + margin-bottom: 5px; | |
| 205 | + border-radius: 4px; | |
| 206 | + cursor: pointer; | |
| 207 | + text-align: center; | |
| 208 | +} | |
| 209 | + | |
| 210 | +.content-list li:hover { | |
| 211 | + background-color: #f5f7fa; | |
| 212 | +} | |
| 213 | + | |
| 214 | +.active-content { | |
| 215 | + background-color: #ecf5ff; | |
| 216 | + color: #409eff; | |
| 217 | + border: 1px solid #d9ecff; | |
| 218 | +} | |
| 219 | + | |
| 220 | +.margin-top-lg { | |
| 221 | + margin-top: 20px; | |
| 222 | +} | |
| 223 | +.margin-top { | |
| 224 | + margin-top: 20px; | |
| 225 | +} | |
| 226 | +</style> | |
| 0 | 227 | \ No newline at end of file | ... | ... |
src/components/oa/WorkDetailFile.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="work-detail-file"> | |
| 3 | + <el-row :gutter="20"> | |
| 4 | + <el-col :span="4"> | |
| 5 | + <div class="tree-container"> | |
| 6 | + <el-scrollbar> | |
| 7 | + <ul class="content-list"> | |
| 8 | + <li | |
| 9 | + v-for="(item,index) in workDetailFileInfo.contents" | |
| 10 | + :key="index" | |
| 11 | + @click="swatchFileContentId(item)" | |
| 12 | + :class="{'active-content': workDetailFileInfo.contentId === item.contentId}" | |
| 13 | + > | |
| 14 | + 问题{{ item.seqNum }} | |
| 15 | + </li> | |
| 16 | + </ul> | |
| 17 | + </el-scrollbar> | |
| 18 | + </div> | |
| 19 | + </el-col> | |
| 20 | + <el-col :span="20"> | |
| 21 | + <el-row :gutter="20" class="margin-top-lg"> | |
| 22 | + <el-col :span="6"> | |
| 23 | + <el-input | |
| 24 | + v-model.trim="workDetailFileInfo.staffNameLike" | |
| 25 | + :placeholder="$t('workDetailFile.staffNamePlaceholder')" | |
| 26 | + clearable | |
| 27 | + /> | |
| 28 | + </el-col> | |
| 29 | + <el-col :span="6"> | |
| 30 | + <el-date-picker | |
| 31 | + v-model="workDetailFileInfo.queryStartTime" | |
| 32 | + type="datetime" | |
| 33 | + :placeholder="$t('workDetailFile.startTimePlaceholder')" | |
| 34 | + value-format="yyyy-MM-dd HH:mm:ss" | |
| 35 | + style="width: 100%" | |
| 36 | + /> | |
| 37 | + </el-col> | |
| 38 | + <el-col :span="6"> | |
| 39 | + <el-date-picker | |
| 40 | + v-model="workDetailFileInfo.queryEndTime" | |
| 41 | + type="datetime" | |
| 42 | + :placeholder="$t('workDetailFile.endTimePlaceholder')" | |
| 43 | + value-format="yyyy-MM-dd HH:mm:ss" | |
| 44 | + style="width: 100%" | |
| 45 | + /> | |
| 46 | + </el-col> | |
| 47 | + <el-col :span="6"> | |
| 48 | + <el-button type="primary" @click="queryWorkDetailFile"> | |
| 49 | + <i class="el-icon-search"></i>{{ $t('common.search') }} | |
| 50 | + </el-button> | |
| 51 | + <el-button @click="resetWorkDetailFile"> | |
| 52 | + <i class="el-icon-refresh"></i>{{ $t('common.reset') }} | |
| 53 | + </el-button> | |
| 54 | + </el-col> | |
| 55 | + </el-row> | |
| 56 | + | |
| 57 | + <div class="margin-top"> | |
| 58 | + <el-table | |
| 59 | + :data="workDetailFileInfo.files" | |
| 60 | + border | |
| 61 | + style="width: 100%" | |
| 62 | + v-loading="loading" | |
| 63 | + > | |
| 64 | + <el-table-column | |
| 65 | + prop="staffName" | |
| 66 | + :label="$t('workDetailFile.staffName')" | |
| 67 | + align="center" | |
| 68 | + /> | |
| 69 | + <el-table-column | |
| 70 | + :label="$t('workDetailFile.attachment')" | |
| 71 | + align="center" | |
| 72 | + > | |
| 73 | + <template slot-scope="scope"> | |
| 74 | + <div v-if="scope.row.fileType !== 'S'"> | |
| 75 | + <el-image | |
| 76 | + v-if="scope.row.pathUrl.endsWith('jpg') || scope.row.pathUrl.endsWith('png')" | |
| 77 | + style="width: 60px; height: 60px;" | |
| 78 | + :src="scope.row.pathUrl" | |
| 79 | + :preview-src-list="[scope.row.pathUrl]" | |
| 80 | + fit="cover" | |
| 81 | + /> | |
| 82 | + <el-link v-else :href="scope.row.pathUrl" target="_blank"> | |
| 83 | + {{ $t('common.download') }} | |
| 84 | + </el-link> | |
| 85 | + </div> | |
| 86 | + <span v-else>--</span> | |
| 87 | + </template> | |
| 88 | + </el-table-column> | |
| 89 | + </el-table> | |
| 90 | + | |
| 91 | + <el-pagination | |
| 92 | + :current-page.sync="page.current" | |
| 93 | + :page-sizes="[10, 20, 30, 50]" | |
| 94 | + :page-size="page.size" | |
| 95 | + :total="page.total" | |
| 96 | + layout="total, sizes, prev, pager, next, jumper" | |
| 97 | + @size-change="handleSizeChange" | |
| 98 | + @current-change="handleCurrentChange" | |
| 99 | + /> | |
| 100 | + </div> | |
| 101 | + </el-col> | |
| 102 | + </el-row> | |
| 103 | + </div> | |
| 104 | +</template> | |
| 105 | + | |
| 106 | +<script> | |
| 107 | +import { listWorkPoolFile } from '@/api/oa/workDetailApi' | |
| 108 | + | |
| 109 | +export default { | |
| 110 | + name: 'WorkDetailFile', | |
| 111 | + data() { | |
| 112 | + return { | |
| 113 | + workDetailFileInfo: { | |
| 114 | + files: [], | |
| 115 | + contents: [], | |
| 116 | + workId: '', | |
| 117 | + contentId: '', | |
| 118 | + staffNameLike: '', | |
| 119 | + queryStartTime: '', | |
| 120 | + queryEndTime: '' | |
| 121 | + }, | |
| 122 | + loading: false, | |
| 123 | + page: { | |
| 124 | + current: 1, | |
| 125 | + size: 10, | |
| 126 | + total: 0 | |
| 127 | + } | |
| 128 | + } | |
| 129 | + }, | |
| 130 | + methods: { | |
| 131 | + open(params) { | |
| 132 | + this.workDetailFileInfo.workId = params.workId | |
| 133 | + this.workDetailFileInfo.contents = params.contents | |
| 134 | + if (params.contents.length > 0) { | |
| 135 | + this.swatchFileContentId(params.contents[0]) | |
| 136 | + } | |
| 137 | + }, | |
| 138 | + async loadWorkDetailFileData(page, size) { | |
| 139 | + try { | |
| 140 | + this.loading = true | |
| 141 | + const params = { | |
| 142 | + workId: this.workDetailFileInfo.workId, | |
| 143 | + contentId: this.workDetailFileInfo.contentId, | |
| 144 | + staffNameLike: this.workDetailFileInfo.staffNameLike, | |
| 145 | + queryStartTime: this.workDetailFileInfo.queryStartTime, | |
| 146 | + queryEndTime: this.workDetailFileInfo.queryEndTime, | |
| 147 | + page, | |
| 148 | + row: size | |
| 149 | + } | |
| 150 | + const { data, total } = await listWorkPoolFile(params) | |
| 151 | + this.workDetailFileInfo.files = data | |
| 152 | + this.page.total = total | |
| 153 | + } catch (error) { | |
| 154 | + console.error('获取流转附件列表失败:', error) | |
| 155 | + } finally { | |
| 156 | + this.loading = false | |
| 157 | + } | |
| 158 | + }, | |
| 159 | + queryWorkDetailFile() { | |
| 160 | + this.page.current = 1 | |
| 161 | + this.loadWorkDetailFileData(this.page.current, this.page.size) | |
| 162 | + }, | |
| 163 | + swatchFileContentId(content) { | |
| 164 | + this.workDetailFileInfo.contentId = content.contentId | |
| 165 | + this.loadWorkDetailFileData(this.page.current, this.page.size) | |
| 166 | + }, | |
| 167 | + resetWorkDetailFile() { | |
| 168 | + this.workDetailFileInfo.staffNameLike = '' | |
| 169 | + this.workDetailFileInfo.queryStartTime = '' | |
| 170 | + this.workDetailFileInfo.queryEndTime = '' | |
| 171 | + this.queryWorkDetailFile() | |
| 172 | + }, | |
| 173 | + handleSizeChange(val) { | |
| 174 | + this.page.size = val | |
| 175 | + this.loadWorkDetailFileData(this.page.current, this.page.size) | |
| 176 | + }, | |
| 177 | + handleCurrentChange(val) { | |
| 178 | + this.page.current = val | |
| 179 | + this.loadWorkDetailFileData(this.page.current, this.page.size) | |
| 180 | + } | |
| 181 | + } | |
| 182 | +} | |
| 183 | +</script> | |
| 184 | + | |
| 185 | +<style scoped> | |
| 186 | +.tree-container { | |
| 187 | + height: 500px; | |
| 188 | + border: 1px solid #ebeef5; | |
| 189 | + border-radius: 4px; | |
| 190 | + padding: 10px; | |
| 191 | +} | |
| 192 | + | |
| 193 | +.content-list { | |
| 194 | + list-style: none; | |
| 195 | + padding: 0; | |
| 196 | + margin: 0; | |
| 197 | +} | |
| 198 | + | |
| 199 | +.content-list li { | |
| 200 | + padding: 10px; | |
| 201 | + margin-bottom: 5px; | |
| 202 | + border-radius: 4px; | |
| 203 | + cursor: pointer; | |
| 204 | + text-align: center; | |
| 205 | +} | |
| 206 | + | |
| 207 | +.content-list li:hover { | |
| 208 | + background-color: #f5f7fa; | |
| 209 | +} | |
| 210 | + | |
| 211 | +.active-content { | |
| 212 | + background-color: #ecf5ff; | |
| 213 | + color: #409eff; | |
| 214 | + border: 1px solid #d9ecff; | |
| 215 | +} | |
| 216 | + | |
| 217 | +.margin-top-lg { | |
| 218 | + margin-top: 20px; | |
| 219 | +} | |
| 220 | +.margin-top { | |
| 221 | + margin-top: 20px; | |
| 222 | +} | |
| 223 | +</style> | |
| 0 | 224 | \ No newline at end of file | ... | ... |
src/components/oa/WorkDetailTask.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="work-detail-task"> | |
| 3 | + <el-row :gutter="20" class="margin-top-lg"> | |
| 4 | + <el-col :span="6"> | |
| 5 | + <el-input | |
| 6 | + v-model.trim="workDetailTaskInfo.staffNameLike" | |
| 7 | + :placeholder="$t('workDetailTask.staffNamePlaceholder')" | |
| 8 | + clearable | |
| 9 | + /> | |
| 10 | + </el-col> | |
| 11 | + <el-col :span="6"> | |
| 12 | + <el-date-picker | |
| 13 | + v-model="workDetailTaskInfo.queryStartTime" | |
| 14 | + type="datetime" | |
| 15 | + :placeholder="$t('workDetailTask.startTimePlaceholder')" | |
| 16 | + value-format="yyyy-MM-dd HH:mm:ss" | |
| 17 | + style="width: 100%" | |
| 18 | + /> | |
| 19 | + </el-col> | |
| 20 | + <el-col :span="6"> | |
| 21 | + <el-date-picker | |
| 22 | + v-model="workDetailTaskInfo.queryEndTime" | |
| 23 | + type="datetime" | |
| 24 | + :placeholder="$t('workDetailTask.endTimePlaceholder')" | |
| 25 | + value-format="yyyy-MM-dd HH:mm:ss" | |
| 26 | + style="width: 100%" | |
| 27 | + /> | |
| 28 | + </el-col> | |
| 29 | + <el-col :span="6"> | |
| 30 | + <el-button type="primary" @click="queryWorkDetailTask"> | |
| 31 | + <i class="el-icon-search"></i>{{ $t('common.search') }} | |
| 32 | + </el-button> | |
| 33 | + <el-button @click="resetWorkDetailTask"> | |
| 34 | + <i class="el-icon-refresh"></i>{{ $t('common.reset') }} | |
| 35 | + </el-button> | |
| 36 | + </el-col> | |
| 37 | + </el-row> | |
| 38 | + | |
| 39 | + <div class="margin-top"> | |
| 40 | + <el-table | |
| 41 | + :data="workDetailTaskInfo.tasks" | |
| 42 | + border | |
| 43 | + style="width: 100%" | |
| 44 | + v-loading="loading" | |
| 45 | + > | |
| 46 | + <el-table-column | |
| 47 | + prop="taskId" | |
| 48 | + :label="$t('workDetailTask.taskId')" | |
| 49 | + align="center" | |
| 50 | + /> | |
| 51 | + <el-table-column | |
| 52 | + prop="staffName" | |
| 53 | + :label="$t('workDetailTask.staffName')" | |
| 54 | + align="center" | |
| 55 | + /> | |
| 56 | + <el-table-column | |
| 57 | + prop="startTime" | |
| 58 | + :label="$t('workDetailTask.startTime')" | |
| 59 | + align="center" | |
| 60 | + /> | |
| 61 | + <el-table-column | |
| 62 | + prop="endTime" | |
| 63 | + :label="$t('workDetailTask.endTime')" | |
| 64 | + align="center" | |
| 65 | + /> | |
| 66 | + <el-table-column | |
| 67 | + prop="createTime" | |
| 68 | + :label="$t('workDetailTask.createTime')" | |
| 69 | + align="center" | |
| 70 | + /> | |
| 71 | + <el-table-column | |
| 72 | + prop="stateName" | |
| 73 | + :label="$t('workDetailTask.stateName')" | |
| 74 | + align="center" | |
| 75 | + /> | |
| 76 | + <el-table-column | |
| 77 | + :label="$t('common.operation')" | |
| 78 | + align="center" | |
| 79 | + width="120" | |
| 80 | + > | |
| 81 | + <template slot-scope="scope"> | |
| 82 | + <el-button | |
| 83 | + size="mini" | |
| 84 | + @click="openWorkTaskDetail(scope.row)" | |
| 85 | + > | |
| 86 | + {{ $t('workDetailTask.progress') }} | |
| 87 | + </el-button> | |
| 88 | + </template> | |
| 89 | + </el-table-column> | |
| 90 | + </el-table> | |
| 91 | + | |
| 92 | + <el-pagination | |
| 93 | + :current-page.sync="page.current" | |
| 94 | + :page-sizes="[10, 20, 30, 50]" | |
| 95 | + :page-size="page.size" | |
| 96 | + :total="page.total" | |
| 97 | + layout="total, sizes, prev, pager, next, jumper" | |
| 98 | + @size-change="handleSizeChange" | |
| 99 | + @current-change="handleCurrentChange" | |
| 100 | + /> | |
| 101 | + </div> | |
| 102 | + </div> | |
| 103 | +</template> | |
| 104 | + | |
| 105 | +<script> | |
| 106 | +import { listWorkTask } from '@/api/oa/workDetailApi' | |
| 107 | + | |
| 108 | +export default { | |
| 109 | + name: 'WorkDetailTask', | |
| 110 | + data() { | |
| 111 | + return { | |
| 112 | + workDetailTaskInfo: { | |
| 113 | + tasks: [], | |
| 114 | + workId: '', | |
| 115 | + staffNameLike: '', | |
| 116 | + queryStartTime: '', | |
| 117 | + queryEndTime: '' | |
| 118 | + }, | |
| 119 | + loading: false, | |
| 120 | + page: { | |
| 121 | + current: 1, | |
| 122 | + size: 10, | |
| 123 | + total: 0 | |
| 124 | + } | |
| 125 | + } | |
| 126 | + }, | |
| 127 | + methods: { | |
| 128 | + open(params) { | |
| 129 | + this.workDetailTaskInfo.workId = params.workId | |
| 130 | + this.loadWorkDetailTaskData(this.page.current, this.page.size) | |
| 131 | + }, | |
| 132 | + async loadWorkDetailTaskData(page, size) { | |
| 133 | + try { | |
| 134 | + this.loading = true | |
| 135 | + const params = { | |
| 136 | + workId: this.workDetailTaskInfo.workId, | |
| 137 | + staffNameLike: this.workDetailTaskInfo.staffNameLike, | |
| 138 | + queryStartTime: this.workDetailTaskInfo.queryStartTime, | |
| 139 | + queryEndTime: this.workDetailTaskInfo.queryEndTime, | |
| 140 | + page, | |
| 141 | + row: size | |
| 142 | + } | |
| 143 | + const { data, total } = await listWorkTask(params) | |
| 144 | + this.workDetailTaskInfo.tasks = data | |
| 145 | + this.page.total = total | |
| 146 | + } catch (error) { | |
| 147 | + console.error('获取任务列表失败:', error) | |
| 148 | + } finally { | |
| 149 | + this.loading = false | |
| 150 | + } | |
| 151 | + }, | |
| 152 | + queryWorkDetailTask() { | |
| 153 | + this.page.current = 1 | |
| 154 | + this.loadWorkDetailTaskData(this.page.current, this.page.size) | |
| 155 | + }, | |
| 156 | + resetWorkDetailTask() { | |
| 157 | + this.workDetailTaskInfo.staffNameLike = '' | |
| 158 | + this.workDetailTaskInfo.queryStartTime = '' | |
| 159 | + this.workDetailTaskInfo.queryEndTime = '' | |
| 160 | + this.queryWorkDetailTask() | |
| 161 | + }, | |
| 162 | + openWorkTaskDetail(work) { | |
| 163 | + this.$router.push({ | |
| 164 | + path: '/oa/workTaskDetail', | |
| 165 | + query: { | |
| 166 | + workId: work.workId, | |
| 167 | + taskId: work.taskId | |
| 168 | + } | |
| 169 | + }) | |
| 170 | + }, | |
| 171 | + handleSizeChange(val) { | |
| 172 | + this.page.size = val | |
| 173 | + this.loadWorkDetailTaskData(this.page.current, this.page.size) | |
| 174 | + }, | |
| 175 | + handleCurrentChange(val) { | |
| 176 | + this.page.current = val | |
| 177 | + this.loadWorkDetailTaskData(this.page.current, this.page.size) | |
| 178 | + } | |
| 179 | + } | |
| 180 | +} | |
| 181 | +</script> | |
| 182 | + | |
| 183 | +<style scoped> | |
| 184 | +.margin-top-lg { | |
| 185 | + margin-top: 20px; | |
| 186 | +} | |
| 187 | +.margin-top { | |
| 188 | + margin-top: 20px; | |
| 189 | +} | |
| 190 | +</style> | |
| 0 | 191 | \ No newline at end of file | ... | ... |
src/components/oa/WorkDetailTaskItem.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="work-detail-task-item"> | |
| 3 | + <el-row :gutter="20"> | |
| 4 | + <el-col :span="4"> | |
| 5 | + <div class="tree-container"> | |
| 6 | + <el-scrollbar> | |
| 7 | + <ul class="task-list"> | |
| 8 | + <li v-for="(item, index) in workDetailTaskItemInfo.tasks" :key="index" @click="swatchTaskItemTaskId(item)" | |
| 9 | + :class="{ 'active-task': workDetailTaskItemInfo.taskId === item.taskId }"> | |
| 10 | + <div>{{ item.staffName }}</div> | |
| 11 | + <div>({{ formatDate(item.startTime) }} ~ {{ formatDate(item.endTime) }})</div> | |
| 12 | + </li> | |
| 13 | + </ul> | |
| 14 | + </el-scrollbar> | |
| 15 | + </div> | |
| 16 | + </el-col> | |
| 17 | + <el-col :span="20"> | |
| 18 | + <el-table :data="workDetailTaskItemInfo.items" border style="width: 100%" v-loading="loading"> | |
| 19 | + <el-table-column prop="content" :label="$t('workDetailTaskItem.content')" width="400" /> | |
| 20 | + <el-table-column prop="finishTime" :label="$t('workDetailTaskItem.finishTime')" align="center" /> | |
| 21 | + <el-table-column :label="$t('workDetailTaskItem.state')" align="center"> | |
| 22 | + <template slot-scope="scope"> | |
| 23 | + <span v-if="scope.row.state === 'CC'">{{ $t('workDetailTaskItem.copyProcessed') }}</span> | |
| 24 | + <span v-else-if="scope.row.state === 'C'">{{ $t('workDetailTaskItem.handlerProcessed') }}</span> | |
| 25 | + <span v-else>{{ $t('workDetailTaskItem.pending') }}</span> | |
| 26 | + </template> | |
| 27 | + </el-table-column> | |
| 28 | + <el-table-column prop="remark" :label="$t('workDetailTaskItem.remark')" align="center" /> | |
| 29 | + <el-table-column :label="$t('workDetailTaskItem.attachment')" align="center"> | |
| 30 | + <template slot-scope="scope"> | |
| 31 | + <div v-if="scope.row.pathUrls"> | |
| 32 | + <div v-for="(url, index) in scope.row.pathUrls" :key="index"> | |
| 33 | + <div v-if="url.endsWith('jpg') || url.endsWith('png')"> | |
| 34 | + <el-image style="width: 60px; height: 60px;" :src="url" :preview-src-list="[url]" fit="cover" /> | |
| 35 | + </div> | |
| 36 | + <div v-else> | |
| 37 | + <el-link :href="url" target="_blank">{{ $t('common.download') }}</el-link> | |
| 38 | + </div> | |
| 39 | + </div> | |
| 40 | + </div> | |
| 41 | + <div v-else>-</div> | |
| 42 | + </template> | |
| 43 | + </el-table-column> | |
| 44 | + <el-table-column prop="score" :label="$t('workDetailTaskItem.score')" align="center" /> | |
| 45 | + <el-table-column prop="deductionMoney" :label="$t('workDetailTaskItem.deductionMoney')" align="center" /> | |
| 46 | + <el-table-column prop="deductionReason" :label="$t('workDetailTaskItem.deductionReason')" align="center" /> | |
| 47 | + <el-table-column prop="deductionPersonName" :label="$t('workDetailTaskItem.deductionPerson')" | |
| 48 | + align="center" /> | |
| 49 | + <el-table-column prop="createTime" :label="$t('workDetailTaskItem.createTime')" align="center" /> | |
| 50 | + </el-table> | |
| 51 | + </el-col> | |
| 52 | + </el-row> | |
| 53 | + </div> | |
| 54 | +</template> | |
| 55 | + | |
| 56 | +<script> | |
| 57 | +import { listWorkTask, listWorkTaskItem } from '@/api/oa/workDetailApi' | |
| 58 | +import { dateFormat } from '@/utils/dateUtil' | |
| 59 | + | |
| 60 | +export default { | |
| 61 | + name: 'WorkDetailTaskItem', | |
| 62 | + data() { | |
| 63 | + return { | |
| 64 | + workDetailTaskItemInfo: { | |
| 65 | + tasks: [], | |
| 66 | + workId: '', | |
| 67 | + taskId: '', | |
| 68 | + items: [] | |
| 69 | + }, | |
| 70 | + loading: false | |
| 71 | + } | |
| 72 | + }, | |
| 73 | + methods: { | |
| 74 | + open(params) { | |
| 75 | + this.workDetailTaskItemInfo.workId = params.workId | |
| 76 | + this.queryWorkDetailTaskData() | |
| 77 | + }, | |
| 78 | + async queryWorkDetailTaskData() { | |
| 79 | + try { | |
| 80 | + this.loading = true | |
| 81 | + const params = { | |
| 82 | + workId: this.workDetailTaskItemInfo.workId, | |
| 83 | + page: 1, | |
| 84 | + row: 100 | |
| 85 | + } | |
| 86 | + const { data } = await listWorkTask(params) | |
| 87 | + this.workDetailTaskItemInfo.tasks = data | |
| 88 | + if (data.length > 0) { | |
| 89 | + this.swatchTaskItemTaskId(data[0]) | |
| 90 | + } | |
| 91 | + } catch (error) { | |
| 92 | + console.error('获取任务列表失败:', error) | |
| 93 | + } finally { | |
| 94 | + this.loading = false | |
| 95 | + } | |
| 96 | + }, | |
| 97 | + async loadWorkDetailTaskItemData() { | |
| 98 | + try { | |
| 99 | + this.loading = true | |
| 100 | + const params = { | |
| 101 | + workId: this.workDetailTaskItemInfo.workId, | |
| 102 | + taskId: this.workDetailTaskItemInfo.taskId, | |
| 103 | + page: 1, | |
| 104 | + row: 100 | |
| 105 | + } | |
| 106 | + const { data } = await listWorkTaskItem(params) | |
| 107 | + this.workDetailTaskItemInfo.items = data | |
| 108 | + } catch (error) { | |
| 109 | + console.error('获取任务项列表失败:', error) | |
| 110 | + } finally { | |
| 111 | + this.loading = false | |
| 112 | + } | |
| 113 | + }, | |
| 114 | + swatchTaskItemTaskId(task) { | |
| 115 | + this.workDetailTaskItemInfo.taskId = task.taskId | |
| 116 | + this.loadWorkDetailTaskItemData() | |
| 117 | + }, | |
| 118 | + formatDate(date) { | |
| 119 | + return dateFormat(date) | |
| 120 | + } | |
| 121 | + } | |
| 122 | +} | |
| 123 | +</script> | |
| 124 | + | |
| 125 | +<style scoped> | |
| 126 | +.tree-container { | |
| 127 | + height: 500px; | |
| 128 | + border: 1px solid #ebeef5; | |
| 129 | + border-radius: 4px; | |
| 130 | + padding: 10px; | |
| 131 | +} | |
| 132 | + | |
| 133 | +.task-list { | |
| 134 | + list-style: none; | |
| 135 | + padding: 0; | |
| 136 | + margin: 0; | |
| 137 | +} | |
| 138 | + | |
| 139 | +.task-list li { | |
| 140 | + padding: 10px; | |
| 141 | + margin-bottom: 5px; | |
| 142 | + border-radius: 4px; | |
| 143 | + cursor: pointer; | |
| 144 | + text-align: center; | |
| 145 | +} | |
| 146 | + | |
| 147 | +.task-list li:hover { | |
| 148 | + background-color: #f5f7fa; | |
| 149 | +} | |
| 150 | + | |
| 151 | +.active-task { | |
| 152 | + background-color: #ecf5ff; | |
| 153 | + color: #409eff; | |
| 154 | + border: 1px solid #d9ecff; | |
| 155 | +} | |
| 156 | +</style> | |
| 0 | 157 | \ No newline at end of file | ... | ... |
src/components/oa/WorkDetailType.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="work-detail-type"> | |
| 3 | + <div class="margin-top"> | |
| 4 | + <el-table | |
| 5 | + :data="workDetailTypeInfo.types" | |
| 6 | + border | |
| 7 | + style="width: 100%" | |
| 8 | + v-loading="loading" | |
| 9 | + > | |
| 10 | + <el-table-column | |
| 11 | + prop="typeName" | |
| 12 | + :label="$t('workDetailType.typeName')" | |
| 13 | + align="center" | |
| 14 | + /> | |
| 15 | + <el-table-column | |
| 16 | + :label="$t('workDetailType.notifyWay')" | |
| 17 | + align="center" | |
| 18 | + > | |
| 19 | + <template slot-scope="scope"> | |
| 20 | + <span v-if="scope.row.smsWay === 'WECHAT'">{{ $t('workDetailType.wechat') }}</span> | |
| 21 | + <span v-else-if="scope.row.smsWay === 'ALI_SMS'">{{ $t('workDetailType.aliSms') }}</span> | |
| 22 | + <span v-else>{{ $t('workDetailType.unknown') }}</span> | |
| 23 | + </template> | |
| 24 | + </el-table-column> | |
| 25 | + <el-table-column | |
| 26 | + prop="createTime" | |
| 27 | + :label="$t('workDetailType.createTime')" | |
| 28 | + align="center" | |
| 29 | + /> | |
| 30 | + <el-table-column | |
| 31 | + prop="remark" | |
| 32 | + :label="$t('workDetailType.remark')" | |
| 33 | + align="center" | |
| 34 | + > | |
| 35 | + <template slot-scope="scope"> | |
| 36 | + {{ scope.row.remark || '-' }} | |
| 37 | + </template> | |
| 38 | + </el-table-column> | |
| 39 | + </el-table> | |
| 40 | + | |
| 41 | + <el-pagination | |
| 42 | + :current-page.sync="page.current" | |
| 43 | + :page-sizes="[10, 20, 30, 50]" | |
| 44 | + :page-size="page.size" | |
| 45 | + :total="page.total" | |
| 46 | + layout="total, sizes, prev, pager, next, jumper" | |
| 47 | + @size-change="handleSizeChange" | |
| 48 | + @current-change="handleCurrentChange" | |
| 49 | + /> | |
| 50 | + </div> | |
| 51 | + </div> | |
| 52 | +</template> | |
| 53 | + | |
| 54 | +<script> | |
| 55 | +import { listWorkType } from '@/api/oa/workDetailApi' | |
| 56 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 57 | + | |
| 58 | +export default { | |
| 59 | + name: 'WorkDetailType', | |
| 60 | + data() { | |
| 61 | + return { | |
| 62 | + workDetailTypeInfo: { | |
| 63 | + types: [], | |
| 64 | + wtId: '' | |
| 65 | + }, | |
| 66 | + loading: false, | |
| 67 | + page: { | |
| 68 | + current: 1, | |
| 69 | + size: 10, | |
| 70 | + total: 0 | |
| 71 | + }, | |
| 72 | + communityId: '' | |
| 73 | + } | |
| 74 | + }, | |
| 75 | + created() { | |
| 76 | + this.communityId = getCommunityId() | |
| 77 | + }, | |
| 78 | + methods: { | |
| 79 | + open(params) { | |
| 80 | + this.workDetailTypeInfo.wtId = params.wtId | |
| 81 | + this.loadWorkDetailTypeData(this.page.current, this.page.size) | |
| 82 | + }, | |
| 83 | + async loadWorkDetailTypeData(page, size) { | |
| 84 | + try { | |
| 85 | + this.loading = true | |
| 86 | + const params = { | |
| 87 | + wtId: this.workDetailTypeInfo.wtId, | |
| 88 | + communityId: this.communityId, | |
| 89 | + page, | |
| 90 | + row: size | |
| 91 | + } | |
| 92 | + const { data, total } = await listWorkType(params) | |
| 93 | + this.workDetailTypeInfo.types = data | |
| 94 | + this.page.total = total | |
| 95 | + } catch (error) { | |
| 96 | + console.error('获取工作单类型列表失败:', error) | |
| 97 | + } finally { | |
| 98 | + this.loading = false | |
| 99 | + } | |
| 100 | + }, | |
| 101 | + handleSizeChange(val) { | |
| 102 | + this.page.size = val | |
| 103 | + this.loadWorkDetailTypeData(this.page.current, this.page.size) | |
| 104 | + }, | |
| 105 | + handleCurrentChange(val) { | |
| 106 | + this.page.current = val | |
| 107 | + this.loadWorkDetailTypeData(this.page.current, this.page.size) | |
| 108 | + } | |
| 109 | + } | |
| 110 | +} | |
| 111 | +</script> | |
| 112 | + | |
| 113 | +<style scoped> | |
| 114 | +.margin-top { | |
| 115 | + margin-top: 20px; | |
| 116 | +} | |
| 117 | +</style> | |
| 0 | 118 | \ No newline at end of file | ... | ... |
src/i18n/oaI18n.js
| ... | ... | @@ -41,6 +41,7 @@ import { messages as workTypeMessages } from '../views/oa/workTypeLang' |
| 41 | 41 | import { messages as startWorkMessages } from '../views/oa/startWorkLang' |
| 42 | 42 | import { messages as addWorkMessages } from '../views/oa/addWorkLang' |
| 43 | 43 | import { messages as editWorkMessages } from '../views/oa/editWorkLang' |
| 44 | +import { messages as workDetailMessages } from '../views/oa/workDetailLang' | |
| 44 | 45 | export const messages ={ |
| 45 | 46 | en:{ |
| 46 | 47 | ...activitiesTypeManageMessages.en, |
| ... | ... | @@ -85,6 +86,7 @@ export const messages ={ |
| 85 | 86 | ...startWorkMessages.en, |
| 86 | 87 | ...addWorkMessages.en, |
| 87 | 88 | ...editWorkMessages.en, |
| 89 | + ...workDetailMessages.en, | |
| 88 | 90 | }, |
| 89 | 91 | zh:{ |
| 90 | 92 | ...activitiesTypeManageMessages.zh, |
| ... | ... | @@ -129,5 +131,6 @@ export const messages ={ |
| 129 | 131 | ...startWorkMessages.zh, |
| 130 | 132 | ...addWorkMessages.zh, |
| 131 | 133 | ...editWorkMessages.zh, |
| 134 | + ...workDetailMessages.zh, | |
| 132 | 135 | } |
| 133 | 136 | } |
| 134 | 137 | \ No newline at end of file | ... | ... |
src/router/oaRouter.js
| ... | ... | @@ -185,13 +185,18 @@ export default [ |
| 185 | 185 | component: () => import('@/views/oa/startWorkList.vue') |
| 186 | 186 | }, |
| 187 | 187 | { |
| 188 | - path:'/views/oa/addWork', | |
| 189 | - name:'/views/oa/addWork', | |
| 188 | + path: '/views/oa/addWork', | |
| 189 | + name: '/views/oa/addWork', | |
| 190 | 190 | component: () => import('@/views/oa/addWorkList.vue') |
| 191 | - }, | |
| 192 | - { | |
| 193 | - path:'/views/oa/editWork', | |
| 194 | - name:'/views/oa/editWork', | |
| 195 | - component: () => import('@/views/oa/editWorkList.vue') | |
| 196 | - }, | |
| 191 | + }, | |
| 192 | + { | |
| 193 | + path: '/views/oa/editWork', | |
| 194 | + name: '/views/oa/editWork', | |
| 195 | + component: () => import('@/views/oa/editWorkList.vue') | |
| 196 | + }, | |
| 197 | + { | |
| 198 | + path: '/views/oa/workDetail', | |
| 199 | + name: '/views/oa/workDetail', | |
| 200 | + component: () => import('@/views/oa/workDetailList.vue') | |
| 201 | + }, | |
| 197 | 202 | ] |
| 198 | 203 | \ No newline at end of file | ... | ... |
src/views/oa/startWorkList.vue
| ... | ... | @@ -201,7 +201,7 @@ export default { |
| 201 | 201 | this.$router.push(`/views/oa/editWork?workId=${row.workId}`) |
| 202 | 202 | }, |
| 203 | 203 | handleDetail(row) { |
| 204 | - this.$router.push(`/oa/workDetail?workId=${row.workId}`) | |
| 204 | + this.$router.push(`/views/oa/workDetail?workId=${row.workId}`) | |
| 205 | 205 | }, |
| 206 | 206 | handleDelete(row) { |
| 207 | 207 | this.$refs.deleteWork.open(row) | ... | ... |
src/views/oa/workDetailLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + workDetail: { | |
| 4 | + title: 'Work Order Details', | |
| 5 | + workId: 'Work Order ID', | |
| 6 | + workName: 'Work Order Name', | |
| 7 | + typeName: 'Type Name', | |
| 8 | + workCycle: 'Mark', | |
| 9 | + once: 'One-time Work Order', | |
| 10 | + periodic: 'Periodic Work Order', | |
| 11 | + startTime: 'Start Time', | |
| 12 | + endTime: 'End Time', | |
| 13 | + createUserName: 'Initiator', | |
| 14 | + curStaffName: 'Handler', | |
| 15 | + curCopyName: 'Copy Person', | |
| 16 | + stateName: 'Status', | |
| 17 | + createTime: 'Create Time', | |
| 18 | + attachment: 'Attachment', | |
| 19 | + content: 'Content', | |
| 20 | + handler: 'Handler', | |
| 21 | + handlerContent: 'Handler Content', | |
| 22 | + copyPerson: 'Copy Person', | |
| 23 | + workFlow: 'Work Order Flow', | |
| 24 | + flowAttachment: 'Flow Attachment', | |
| 25 | + workType: 'Work Order Type', | |
| 26 | + workCycleTab: 'Work Order Cycle' | |
| 27 | + }, | |
| 28 | + workDetailTask: { | |
| 29 | + taskId: 'Task ID', | |
| 30 | + staffName: 'Handler', | |
| 31 | + startTime: 'Start Time', | |
| 32 | + endTime: 'End Time', | |
| 33 | + createTime: 'Create Time', | |
| 34 | + stateName: 'Status', | |
| 35 | + operation: 'Operation', | |
| 36 | + progress: 'Progress', | |
| 37 | + staffNamePlaceholder: 'Please enter handler', | |
| 38 | + startTimePlaceholder: 'Start time', | |
| 39 | + endTimePlaceholder: 'End time' | |
| 40 | + }, | |
| 41 | + workDetailTaskItem: { | |
| 42 | + content: 'Work Content', | |
| 43 | + finishTime: 'Finish Time', | |
| 44 | + state: 'Status', | |
| 45 | + remark: 'Remark', | |
| 46 | + attachment: 'Attachment', | |
| 47 | + score: 'Score', | |
| 48 | + deductionMoney: 'Deduction Amount', | |
| 49 | + deductionReason: 'Deduction Reason', | |
| 50 | + deductionPerson: 'Deduction Person', | |
| 51 | + createTime: 'Create Time', | |
| 52 | + copyProcessed: 'Copy Person Processed', | |
| 53 | + handlerProcessed: 'Handler Processed', | |
| 54 | + pending: 'Pending' | |
| 55 | + }, | |
| 56 | + workDetailCopy: { | |
| 57 | + copyId: 'Task ID', | |
| 58 | + staffName: 'Copy Person', | |
| 59 | + createTime: 'Create Time', | |
| 60 | + stateName: 'Status', | |
| 61 | + remark: 'Remark', | |
| 62 | + staffNamePlaceholder: 'Please enter copy person' | |
| 63 | + }, | |
| 64 | + workDetailEvent: { | |
| 65 | + preStaffName: 'Previous Handler', | |
| 66 | + staffName: 'Handler', | |
| 67 | + taskValidPeriod: 'Task Valid Period', | |
| 68 | + remark: 'Remark', | |
| 69 | + createTime: 'Time', | |
| 70 | + staffNamePlaceholder: 'Please enter handler', | |
| 71 | + startTimePlaceholder: 'Start time', | |
| 72 | + endTimePlaceholder: 'End time' | |
| 73 | + }, | |
| 74 | + workDetailFile: { | |
| 75 | + staffName: 'Handler', | |
| 76 | + attachment: 'Attachment', | |
| 77 | + staffNamePlaceholder: 'Please enter handler', | |
| 78 | + startTimePlaceholder: 'Start time', | |
| 79 | + endTimePlaceholder: 'End time' | |
| 80 | + }, | |
| 81 | + workDetailType: { | |
| 82 | + typeName: 'Type Name', | |
| 83 | + notifyWay: 'Notification Method', | |
| 84 | + createTime: 'Create Time', | |
| 85 | + remark: 'Remark', | |
| 86 | + wechat: 'WeChat', | |
| 87 | + aliSms: 'Ali SMS', | |
| 88 | + unknown: 'Unknown' | |
| 89 | + }, | |
| 90 | + workDetailCycle: { | |
| 91 | + staffName: 'Handler', | |
| 92 | + workCycle: 'Mark', | |
| 93 | + hours: 'Completion Hours', | |
| 94 | + period: 'Cycle', | |
| 95 | + month: 'Month', | |
| 96 | + day: 'Day', | |
| 97 | + week: 'Week', | |
| 98 | + once: 'One-time Work Order', | |
| 99 | + periodic: 'Periodic Work Order', | |
| 100 | + monthDay: 'Month/Day', | |
| 101 | + weekly: 'Weekly' | |
| 102 | + } | |
| 103 | + }, | |
| 104 | + zh: { | |
| 105 | + workDetail: { | |
| 106 | + title: '工作单详情', | |
| 107 | + workId: '工单编号', | |
| 108 | + workName: '工单名称', | |
| 109 | + typeName: '类型名称', | |
| 110 | + workCycle: '标识', | |
| 111 | + once: '一次性工单', | |
| 112 | + periodic: '周期性工单', | |
| 113 | + startTime: '开始时间', | |
| 114 | + endTime: '结束时间', | |
| 115 | + createUserName: '发起人', | |
| 116 | + curStaffName: '处理人', | |
| 117 | + curCopyName: '抄送人', | |
| 118 | + stateName: '状态', | |
| 119 | + createTime: '创建时间', | |
| 120 | + attachment: '附件', | |
| 121 | + content: '内容', | |
| 122 | + handler: '处理人', | |
| 123 | + handlerContent: '处理内容', | |
| 124 | + copyPerson: '抄送人', | |
| 125 | + workFlow: '工作单流转', | |
| 126 | + flowAttachment: '流转附件', | |
| 127 | + workType: '工作单类型', | |
| 128 | + workCycleTab: '工作单周期' | |
| 129 | + }, | |
| 130 | + workDetailTask: { | |
| 131 | + taskId: '任务编号', | |
| 132 | + staffName: '处理人', | |
| 133 | + startTime: '开始时间', | |
| 134 | + endTime: '结束时间', | |
| 135 | + createTime: '创建时间', | |
| 136 | + stateName: '状态', | |
| 137 | + operation: '操作', | |
| 138 | + progress: '进度', | |
| 139 | + staffNamePlaceholder: '请填写处理人', | |
| 140 | + startTimePlaceholder: '开始时间', | |
| 141 | + endTimePlaceholder: '结束时间' | |
| 142 | + }, | |
| 143 | + workDetailTaskItem: { | |
| 144 | + content: '工作内容', | |
| 145 | + finishTime: '完成时间', | |
| 146 | + state: '状态', | |
| 147 | + remark: '说明', | |
| 148 | + attachment: '附件', | |
| 149 | + score: '评分', | |
| 150 | + deductionMoney: '扣款金额', | |
| 151 | + deductionReason: '扣款原因', | |
| 152 | + deductionPerson: '扣款人', | |
| 153 | + createTime: '创建时间', | |
| 154 | + copyProcessed: '抄送人已办理', | |
| 155 | + handlerProcessed: '处理人已办理', | |
| 156 | + pending: '待处理' | |
| 157 | + }, | |
| 158 | + workDetailCopy: { | |
| 159 | + copyId: '任务编号', | |
| 160 | + staffName: '抄送人', | |
| 161 | + createTime: '创建时间', | |
| 162 | + stateName: '状态', | |
| 163 | + remark: '说明', | |
| 164 | + staffNamePlaceholder: '请填写抄送人' | |
| 165 | + }, | |
| 166 | + workDetailEvent: { | |
| 167 | + preStaffName: '前处理人', | |
| 168 | + staffName: '处理人', | |
| 169 | + taskValidPeriod: '任务有效期', | |
| 170 | + remark: '说明', | |
| 171 | + createTime: '时间', | |
| 172 | + staffNamePlaceholder: '请填写处理人', | |
| 173 | + startTimePlaceholder: '开始时间', | |
| 174 | + endTimePlaceholder: '结束时间' | |
| 175 | + }, | |
| 176 | + workDetailFile: { | |
| 177 | + staffName: '处理人', | |
| 178 | + attachment: '附件', | |
| 179 | + staffNamePlaceholder: '请填写处理人', | |
| 180 | + startTimePlaceholder: '开始时间', | |
| 181 | + endTimePlaceholder: '结束时间' | |
| 182 | + }, | |
| 183 | + workDetailType: { | |
| 184 | + typeName: '类型名称', | |
| 185 | + notifyWay: '通知方式', | |
| 186 | + createTime: '创建时间', | |
| 187 | + remark: '备注', | |
| 188 | + wechat: '微信', | |
| 189 | + aliSms: '阿里短信', | |
| 190 | + unknown: '未知' | |
| 191 | + }, | |
| 192 | + workDetailCycle: { | |
| 193 | + staffName: '处理人', | |
| 194 | + workCycle: '标识', | |
| 195 | + hours: '完成小时', | |
| 196 | + period: '周期', | |
| 197 | + month: '月', | |
| 198 | + day: '日', | |
| 199 | + week: '周', | |
| 200 | + once: '一次性工单', | |
| 201 | + periodic: '周期性工单', | |
| 202 | + monthDay: '月/天', | |
| 203 | + weekly: '按周' | |
| 204 | + } | |
| 205 | + } | |
| 206 | +} | |
| 0 | 207 | \ No newline at end of file | ... | ... |
src/views/oa/workDetailList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="work-detail-container"> | |
| 3 | + <el-card class="box-card"> | |
| 4 | + <div slot="header" class="clearfix"> | |
| 5 | + <div class="flex justify-between"> | |
| 6 | + <div class="text-title">{{ $t('workDetail.title') }}</div> | |
| 7 | + <div> | |
| 8 | + <el-button type="primary" size="small" @click="goBack"> | |
| 9 | + <i class="el-icon-close"></i>{{ $t('common.back') }} | |
| 10 | + </el-button> | |
| 11 | + </div> | |
| 12 | + </div> | |
| 13 | + </div> | |
| 14 | + | |
| 15 | + <!-- 业主信息 --> | |
| 16 | + <div class="margin-top"> | |
| 17 | + <el-row :gutter="20" > | |
| 18 | + <el-col :span="24" class="text-left"> | |
| 19 | + <el-row :gutter="20"> | |
| 20 | + <el-col :span="6"> | |
| 21 | + <div class="form-group"> | |
| 22 | + <label class="col-form-label"> | |
| 23 | + {{ $t('workDetail.workId') }}: | |
| 24 | + </label> | |
| 25 | + <label>{{ workDetailInfo.workId }}</label> | |
| 26 | + </div> | |
| 27 | + </el-col> | |
| 28 | + <el-col :span="6"> | |
| 29 | + <div class="form-group"> | |
| 30 | + <label class="col-form-label"> | |
| 31 | + {{ $t('workDetail.workName') }}: | |
| 32 | + </label> | |
| 33 | + <label>{{ workDetailInfo.workName }}</label> | |
| 34 | + </div> | |
| 35 | + </el-col> | |
| 36 | + <el-col :span="6"> | |
| 37 | + <div class="form-group"> | |
| 38 | + <label class="col-form-label"> | |
| 39 | + {{ $t('workDetail.typeName') }}: | |
| 40 | + </label> | |
| 41 | + <label>{{ workDetailInfo.typeName }}</label> | |
| 42 | + </div> | |
| 43 | + </el-col> | |
| 44 | + <el-col :span="6"> | |
| 45 | + <div class="form-group"> | |
| 46 | + <label class="col-form-label"> | |
| 47 | + {{ $t('workDetail.workCycle') }}: | |
| 48 | + </label> | |
| 49 | + <label>{{ workDetailInfo.workCycle == '1001' ? $t('workDetail.once') : $t('workDetail.periodic') | |
| 50 | + }}</label> | |
| 51 | + </div> | |
| 52 | + </el-col> | |
| 53 | + </el-row> | |
| 54 | + <el-row :gutter="20"> | |
| 55 | + <el-col :span="6"> | |
| 56 | + <div class="form-group"> | |
| 57 | + <label class="col-form-label"> | |
| 58 | + {{ $t('workDetail.startTime') }}: | |
| 59 | + </label> | |
| 60 | + <label>{{ workDetailInfo.startTime }}</label> | |
| 61 | + </div> | |
| 62 | + </el-col> | |
| 63 | + <el-col :span="6"> | |
| 64 | + <div class="form-group"> | |
| 65 | + <label class="col-form-label"> | |
| 66 | + {{ $t('workDetail.endTime') }}: | |
| 67 | + </label> | |
| 68 | + <label>{{ workDetailInfo.endTime }}</label> | |
| 69 | + </div> | |
| 70 | + </el-col> | |
| 71 | + <el-col :span="6"> | |
| 72 | + <div class="form-group"> | |
| 73 | + <label class="col-form-label"> | |
| 74 | + {{ $t('workDetail.createUserName') }}: | |
| 75 | + </label> | |
| 76 | + <label>{{ workDetailInfo.createUserName }}</label> | |
| 77 | + </div> | |
| 78 | + </el-col> | |
| 79 | + <el-col :span="6"> | |
| 80 | + <div class="form-group"> | |
| 81 | + <label class="col-form-label"> | |
| 82 | + {{ $t('workDetail.curStaffName') }}: | |
| 83 | + </label> | |
| 84 | + <label>{{ workDetailInfo.curStaffName }}</label> | |
| 85 | + </div> | |
| 86 | + </el-col> | |
| 87 | + <el-col :span="6"> | |
| 88 | + <div class="form-group"> | |
| 89 | + <label class="col-form-label"> | |
| 90 | + {{ $t('workDetail.curCopyName') }}: | |
| 91 | + </label> | |
| 92 | + <label>{{ workDetailInfo.curCopyName }}</label> | |
| 93 | + </div> | |
| 94 | + </el-col> | |
| 95 | + <el-col :span="6"> | |
| 96 | + <div class="form-group"> | |
| 97 | + <label class="col-form-label"> | |
| 98 | + {{ $t('workDetail.stateName') }}: | |
| 99 | + </label> | |
| 100 | + <label>{{ workDetailInfo.stateName }}</label> | |
| 101 | + </div> | |
| 102 | + </el-col> | |
| 103 | + <el-col :span="6"> | |
| 104 | + <div class="form-group"> | |
| 105 | + <label class="col-form-label"> | |
| 106 | + {{ $t('workDetail.createTime') }}: | |
| 107 | + </label> | |
| 108 | + <label>{{ workDetailInfo.createTime }}</label> | |
| 109 | + </div> | |
| 110 | + </el-col> | |
| 111 | + <el-col :span="6"> | |
| 112 | + <div class="form-group flex justify-start"> | |
| 113 | + <label class="col-form-label"> | |
| 114 | + {{ $t('workDetail.attachment') }}: | |
| 115 | + </label> | |
| 116 | + <div class="flex justify-start" v-if="workDetailInfo.pathUrls"> | |
| 117 | + <div v-for="(url, index) in workDetailInfo.pathUrls" :key="index"> | |
| 118 | + <div v-if="url.endsWith('jpg') || url.endsWith('png')"> | |
| 119 | + <img style="width: 60px; height: 60px;" class="border-radius" :src="url" | |
| 120 | + @click="viewTaskFileImg(url)" /> | |
| 121 | + </div> | |
| 122 | + <div v-else> | |
| 123 | + <a :href="url" target="_blank">{{ $t('common.download') }}</a> | |
| 124 | + </div> | |
| 125 | + </div> | |
| 126 | + </div> | |
| 127 | + </div> | |
| 128 | + </el-col> | |
| 129 | + </el-row> | |
| 130 | + </el-col> | |
| 131 | + </el-row> | |
| 132 | + </div> | |
| 133 | + | |
| 134 | + <divider></divider> | |
| 135 | + | |
| 136 | + <div class="margin-top-sm"> | |
| 137 | + <el-tabs v-model="workDetailInfo._currentTab" @tab-click="changeTab(workDetailInfo._currentTab)"> | |
| 138 | + <el-tab-pane :label="$t('workDetail.content')" name="workDetailContent"></el-tab-pane> | |
| 139 | + <el-tab-pane :label="$t('workDetail.handler')" name="workDetailTask"></el-tab-pane> | |
| 140 | + <el-tab-pane :label="$t('workDetail.handlerContent')" name="workDetailTaskItem"></el-tab-pane> | |
| 141 | + <el-tab-pane :label="$t('workDetail.copyPerson')" name="workDetailCopy"></el-tab-pane> | |
| 142 | + <el-tab-pane :label="$t('workDetail.workFlow')" name="workDetailEvent"></el-tab-pane> | |
| 143 | + <el-tab-pane :label="$t('workDetail.flowAttachment')" name="workDetailFile"></el-tab-pane> | |
| 144 | + <el-tab-pane :label="$t('workDetail.workType')" name="workDetailType"></el-tab-pane> | |
| 145 | + <el-tab-pane v-if="workDetailInfo.workCycle == '2002'" :label="$t('workDetail.workCycle')" | |
| 146 | + name="workDetailCycle"></el-tab-pane> | |
| 147 | + </el-tabs> | |
| 148 | + </div> | |
| 149 | + | |
| 150 | + <div v-if="workDetailInfo._currentTab == 'workDetailContent'"> | |
| 151 | + <div class="padding flex justify-start" v-for="(item, index) in workDetailInfo.contents" :key="index"> | |
| 152 | + <div>{{ item.seqNum }}、</div> | |
| 153 | + <div v-html="item.content" style="width: 80%;"></div> | |
| 154 | + </div> | |
| 155 | + </div> | |
| 156 | + <div v-if="workDetailInfo._currentTab == 'workDetailTask'"> | |
| 157 | + <work-detail-task ref="workDetailTask"></work-detail-task> | |
| 158 | + </div> | |
| 159 | + <div v-if="workDetailInfo._currentTab == 'workDetailTaskItem'"> | |
| 160 | + <work-detail-task-item ref="workDetailTaskItem"></work-detail-task-item> | |
| 161 | + </div> | |
| 162 | + <div v-if="workDetailInfo._currentTab == 'workDetailCopy'"> | |
| 163 | + <work-detail-copy ref="workDetailCopy"></work-detail-copy> | |
| 164 | + </div> | |
| 165 | + <div v-if="workDetailInfo._currentTab == 'workDetailEvent'"> | |
| 166 | + <work-detail-event ref="workDetailEvent"></work-detail-event> | |
| 167 | + </div> | |
| 168 | + <div v-if="workDetailInfo._currentTab == 'workDetailFile'"> | |
| 169 | + <work-detail-file ref="workDetailFile"></work-detail-file> | |
| 170 | + </div> | |
| 171 | + <div v-if="workDetailInfo._currentTab == 'workDetailType'"> | |
| 172 | + <work-detail-type ref="workDetailType"></work-detail-type> | |
| 173 | + </div> | |
| 174 | + <div v-if="workDetailInfo._currentTab == 'workDetailCycle'"> | |
| 175 | + <work-detail-cycle ref="workDetailCycle"></work-detail-cycle> | |
| 176 | + </div> | |
| 177 | + </el-card> | |
| 178 | + </div> | |
| 179 | +</template> | |
| 180 | + | |
| 181 | +<script> | |
| 182 | +import { getWorkPoolDetail } from '@/api/oa/workDetailApi' | |
| 183 | +import WorkDetailTask from '@/components/oa/WorkDetailTask' | |
| 184 | +import WorkDetailTaskItem from '@/components/oa/WorkDetailTaskItem' | |
| 185 | +import WorkDetailCopy from '@/components/oa/WorkDetailCopy' | |
| 186 | +import WorkDetailEvent from '@/components/oa/WorkDetailEvent' | |
| 187 | +import WorkDetailFile from '@/components/oa/WorkDetailFile' | |
| 188 | +import WorkDetailType from '@/components/oa/WorkDetailType' | |
| 189 | +import WorkDetailCycle from '@/components/oa/WorkDetailCycle' | |
| 190 | +import Divider from '@/components/system/divider' | |
| 191 | + | |
| 192 | +export default { | |
| 193 | + name: 'WorkDetailList', | |
| 194 | + components: { | |
| 195 | + WorkDetailTask, | |
| 196 | + WorkDetailTaskItem, | |
| 197 | + WorkDetailCopy, | |
| 198 | + WorkDetailEvent, | |
| 199 | + WorkDetailFile, | |
| 200 | + WorkDetailType, | |
| 201 | + WorkDetailCycle, | |
| 202 | + Divider | |
| 203 | + }, | |
| 204 | + data() { | |
| 205 | + return { | |
| 206 | + workDetailInfo: { | |
| 207 | + viewWorkFlag: '', | |
| 208 | + workId: "", | |
| 209 | + wtId: '', | |
| 210 | + workName: '', | |
| 211 | + typeName: "", | |
| 212 | + workCycle: "", | |
| 213 | + startTime: "", | |
| 214 | + endTime: "", | |
| 215 | + createUserName: "", | |
| 216 | + curStaffName: "", | |
| 217 | + curCopyName: "", | |
| 218 | + stateName: "", | |
| 219 | + createTime: '', | |
| 220 | + content: '', | |
| 221 | + pathUrls: [], | |
| 222 | + _currentTab: 'workDetailContent', | |
| 223 | + contents: [] | |
| 224 | + } | |
| 225 | + } | |
| 226 | + }, | |
| 227 | + created() { | |
| 228 | + this.workDetailInfo.workId = this.$route.query.workId | |
| 229 | + if (!this.workDetailInfo.workId) { | |
| 230 | + return | |
| 231 | + } | |
| 232 | + const currentTab = this.$route.query.currentTab | |
| 233 | + if (currentTab) { | |
| 234 | + this.workDetailInfo._currentTab = currentTab | |
| 235 | + } | |
| 236 | + this.loadWorkInfo() | |
| 237 | + this.changeTab(this.workDetailInfo._currentTab) | |
| 238 | + }, | |
| 239 | + methods: { | |
| 240 | + async loadWorkInfo() { | |
| 241 | + try { | |
| 242 | + const params = { | |
| 243 | + workId: this.workDetailInfo.workId, | |
| 244 | + page: 1, | |
| 245 | + row: 1, | |
| 246 | + } | |
| 247 | + const { data } = await getWorkPoolDetail(params) | |
| 248 | + this.workDetailInfo = { ...this.workDetailInfo, ...data[0] } | |
| 249 | + } catch (error) { | |
| 250 | + console.error('获取工作单详情失败:', error) | |
| 251 | + } | |
| 252 | + }, | |
| 253 | + changeTab(tab) { | |
| 254 | + this.workDetailInfo._currentTab = tab | |
| 255 | + setTimeout(() => { | |
| 256 | + if (this.$refs[tab]) { | |
| 257 | + this.$refs[tab].open({ | |
| 258 | + taskId: this.workDetailInfo.taskId, | |
| 259 | + workId: this.workDetailInfo.workId, | |
| 260 | + wtId: this.workDetailInfo.wtId, | |
| 261 | + contents: this.workDetailInfo.contents | |
| 262 | + }) | |
| 263 | + } | |
| 264 | + }, 500) | |
| 265 | + }, | |
| 266 | + viewTaskFileImg(url) { | |
| 267 | + this.$emit('viewImage', { url }) | |
| 268 | + }, | |
| 269 | + goBack() { | |
| 270 | + this.$router.go(-1) | |
| 271 | + } | |
| 272 | + } | |
| 273 | +} | |
| 274 | +</script> | |
| 275 | + | |
| 276 | +<style lang="scss" scoped> | |
| 277 | +.work-detail-container { | |
| 278 | + padding: 20px; | |
| 279 | + | |
| 280 | + .box-card { | |
| 281 | + margin-bottom: 20px; | |
| 282 | + } | |
| 283 | + | |
| 284 | + .text-title { | |
| 285 | + font-size: 18px; | |
| 286 | + font-weight: bold; | |
| 287 | + } | |
| 288 | + | |
| 289 | + .margin-top { | |
| 290 | + margin-top: 20px; | |
| 291 | + } | |
| 292 | + | |
| 293 | + .margin-top-sm { | |
| 294 | + margin-top: 10px; | |
| 295 | + } | |
| 296 | + | |
| 297 | + .padding { | |
| 298 | + padding: 10px; | |
| 299 | + } | |
| 300 | + | |
| 301 | + .border-radius { | |
| 302 | + border-radius: 4px; | |
| 303 | + } | |
| 304 | + | |
| 305 | + .flex { | |
| 306 | + display: flex; | |
| 307 | + } | |
| 308 | + | |
| 309 | + .justify-between { | |
| 310 | + justify-content: space-between; | |
| 311 | + } | |
| 312 | + | |
| 313 | + .justify-start { | |
| 314 | + justify-content: flex-start; | |
| 315 | + } | |
| 316 | + | |
| 317 | + .form-group { | |
| 318 | + margin-bottom: 15px; | |
| 319 | + | |
| 320 | + .col-form-label { | |
| 321 | + display: inline-block; | |
| 322 | + margin-right: 10px; | |
| 323 | + } | |
| 324 | + } | |
| 325 | +} | |
| 326 | +</style> | |
| 0 | 327 | \ No newline at end of file | ... | ... |