Commit 300e6afff6cda62b4830cdce83cff0b92edc10aa

Authored by wuxw
1 parent e4877374

开发完成admin 工作单 和工作单详情页面

src/api/work/adminWorkDetailApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 获取工作单详情
  4 +export function getWorkDetail(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/work.listAdminWorkPool',
  8 + method: 'get',
  9 + params
  10 + }).then(response => {
  11 + const res = response.data
  12 + if (res.code === 0) {
  13 + resolve(res)
  14 + } else {
  15 + reject(new Error(res.msg || 'Failed to get work detail'))
  16 + }
  17 + }).catch(error => {
  18 + reject(error)
  19 + })
  20 + })
  21 +}
  22 +
  23 +// 获取工作单任务列表
  24 +export function listAdminWorkTask(params) {
  25 + return new Promise((resolve, reject) => {
  26 + request({
  27 + url: '/work.listAdminWorkTask',
  28 + method: 'get',
  29 + params
  30 + }).then(response => {
  31 + const res = response.data
  32 + if (res.code === 0) {
  33 + resolve(res)
  34 + } else {
  35 + reject(new Error(res.msg || 'Failed to get work tasks'))
  36 + }
  37 + }).catch(error => {
  38 + reject(error)
  39 + })
  40 + })
  41 +}
  42 +
  43 +// 获取工作单任务项列表
  44 +export function listAdminWorkTaskItem(params) {
  45 + return new Promise((resolve, reject) => {
  46 + request({
  47 + url: '/task.listAdminWorkTaskItem',
  48 + method: 'get',
  49 + params
  50 + }).then(response => {
  51 + const res = response.data
  52 + if (res.code === 0) {
  53 + resolve(res)
  54 + } else {
  55 + reject(new Error(res.msg || 'Failed to get work task items'))
  56 + }
  57 + }).catch(error => {
  58 + reject(error)
  59 + })
  60 + })
  61 +}
  62 +
  63 +// 获取工作单抄送人列表
  64 +export function listAdminWorkCopy(params) {
  65 + return new Promise((resolve, reject) => {
  66 + request({
  67 + url: '/work.listAdminWorkCopy',
  68 + method: 'get',
  69 + params
  70 + }).then(response => {
  71 + const res = response.data
  72 + if (res.code === 0) {
  73 + resolve(res)
  74 + } else {
  75 + reject(new Error(res.msg || 'Failed to get work copy list'))
  76 + }
  77 + }).catch(error => {
  78 + reject(error)
  79 + })
  80 + })
  81 +}
  82 +
  83 +// 获取工作单事件列表
  84 +export function listAdminWorkEvent(params) {
  85 + return new Promise((resolve, reject) => {
  86 + request({
  87 + url: '/workEvent.listAdminWorkEvent',
  88 + method: 'get',
  89 + params
  90 + }).then(response => {
  91 + const res = response.data
  92 + if (res.code === 0) {
  93 + resolve(res)
  94 + } else {
  95 + reject(new Error(res.msg || 'Failed to get work events'))
  96 + }
  97 + }).catch(error => {
  98 + reject(error)
  99 + })
  100 + })
  101 +}
  102 +
  103 +// 获取工作单文件列表
  104 +export function listAdminWorkPoolFile(params) {
  105 + return new Promise((resolve, reject) => {
  106 + request({
  107 + url: '/work.listAdminWorkPoolFile',
  108 + method: 'get',
  109 + params
  110 + }).then(response => {
  111 + const res = response.data
  112 + if (res.code === 0) {
  113 + resolve(res)
  114 + } else {
  115 + reject(new Error(res.msg || 'Failed to get work files'))
  116 + }
  117 + }).catch(error => {
  118 + reject(error)
  119 + })
  120 + })
  121 +}
  122 +
  123 +// 获取工作单类型列表
  124 +export function listAdminWorkType(params) {
  125 + return new Promise((resolve, reject) => {
  126 + request({
  127 + url: '/workType.listAdminWorkType',
  128 + method: 'get',
  129 + params
  130 + }).then(response => {
  131 + const res = response.data
  132 + if (res.code === 0) {
  133 + resolve(res)
  134 + } else {
  135 + reject(new Error(res.msg || 'Failed to get work types'))
  136 + }
  137 + }).catch(error => {
  138 + reject(error)
  139 + })
  140 + })
  141 +}
  142 +
  143 +// 获取工作单周期列表
  144 +export function listAdminWorkCycle(params) {
  145 + return new Promise((resolve, reject) => {
  146 + request({
  147 + url: '/workCycle.listAdminWorkCycle',
  148 + method: 'get',
  149 + params
  150 + }).then(response => {
  151 + const res = response.data
  152 + if (res.code === 0) {
  153 + resolve(res)
  154 + } else {
  155 + reject(new Error(res.msg || 'Failed to get work cycles'))
  156 + }
  157 + }).catch(error => {
  158 + reject(error)
  159 + })
  160 + })
  161 +}
0 162 \ No newline at end of file
... ...
src/api/work/adminWorkPoolApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 获取工作单池列表
  4 +export function listAdminWorkTask(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/work.listAdminWorkTask',
  8 + method: 'get',
  9 + params
  10 + }).then(response => {
  11 + const res = response.data
  12 + if (res.code === 0) {
  13 + resolve({
  14 + data: res.data,
  15 + total: res.total
  16 + })
  17 + } else {
  18 + reject(new Error(res.msg || '获取工作单池列表失败'))
  19 + }
  20 + }).catch(error => {
  21 + reject(error)
  22 + })
  23 + })
  24 +}
  25 +
  26 +// 获取管理员小区列表
  27 +export function listAdminCommunitys(params) {
  28 + return new Promise((resolve, reject) => {
  29 + request({
  30 + url: '/community.listAdminCommunitys',
  31 + method: 'get',
  32 + params
  33 + }).then(response => {
  34 + const res = response.data
  35 + if (res.code === 0) {
  36 + resolve({
  37 + data: res.data,
  38 + total: res.total
  39 + })
  40 + } else {
  41 + reject(new Error(res.msg || '获取管理员小区列表失败'))
  42 + }
  43 + }).catch(error => {
  44 + reject(error)
  45 + })
  46 + })
  47 +}
0 48 \ No newline at end of file
... ...
src/components/work/aWorkDetailCopy.vue 0 → 100644
  1 +<template>
  2 + <div class="a-work-detail-copy">
  3 + <el-row :gutter="20" class="search-row">
  4 + <el-col :span="6">
  5 + <el-input v-model="searchForm.staffNameLike" :placeholder="$t('adminWorkDetail.copyTo')" clearable />
  6 + </el-col>
  7 + <el-col :span="6">
  8 + <el-button type="primary" @click="handleSearch">{{ $t('common.search') }}</el-button>
  9 + <el-button @click="handleReset">{{ $t('common.reset') }}</el-button>
  10 + </el-col>
  11 + </el-row>
  12 +
  13 + <el-table :data="tableData" border style="width: 100%">
  14 + <el-table-column prop="copyId" :label="$t('adminWorkDetail.taskId')" align="center" />
  15 + <el-table-column prop="staffName" :label="$t('adminWorkDetail.copyTo')" align="center" />
  16 + <el-table-column prop="createTime" :label="$t('adminWorkDetail.createTime')" align="center" />
  17 + <el-table-column prop="stateName" :label="$t('adminWorkDetail.stateName')" align="center" />
  18 + <el-table-column prop="remark" :label="$t('adminWorkDetail.remark')" align="center" />
  19 + </el-table>
  20 +
  21 + <el-pagination
  22 + :current-page="pagination.current"
  23 + :page-sizes="[10, 20, 30, 50]"
  24 + :page-size="pagination.size"
  25 + :total="pagination.total"
  26 + layout="total, sizes, prev, pager, next, jumper"
  27 + @size-change="handleSizeChange"
  28 + @current-change="handleCurrentChange"
  29 + />
  30 + </div>
  31 +</template>
  32 +
  33 +<script>
  34 +import { listAdminWorkCopy } from '@/api/work/adminWorkDetailApi'
  35 +
  36 +export default {
  37 + name: 'AWorkDetailCopy',
  38 + props: {
  39 + workId: {
  40 + type: String,
  41 + required: true
  42 + }
  43 + },
  44 + data() {
  45 + return {
  46 + searchForm: {
  47 + staffNameLike: ''
  48 + },
  49 + tableData: [],
  50 + pagination: {
  51 + current: 1,
  52 + size: 10,
  53 + total: 0
  54 + },
  55 + loading: false
  56 + }
  57 + },
  58 + methods: {
  59 + loadData() {
  60 + this.loading = true
  61 + const params = {
  62 + workId: this.workId,
  63 + staffNameLike: this.searchForm.staffNameLike,
  64 + page: this.pagination.current,
  65 + row: this.pagination.size
  66 + }
  67 +
  68 + listAdminWorkCopy(params)
  69 + .then(response => {
  70 + this.tableData = response.data
  71 + this.pagination.total = response.total
  72 + })
  73 + .catch(error => {
  74 + this.$message.error(this.$t('adminWorkDetail.fetchError'))
  75 + console.error(error)
  76 + })
  77 + .finally(() => {
  78 + this.loading = false
  79 + })
  80 + },
  81 + handleSearch() {
  82 + this.pagination.current = 1
  83 + this.loadData()
  84 + },
  85 + handleReset() {
  86 + this.searchForm = {
  87 + staffNameLike: ''
  88 + }
  89 + this.handleSearch()
  90 + },
  91 + handleSizeChange(val) {
  92 + this.pagination.size = val
  93 + this.loadData()
  94 + },
  95 + handleCurrentChange(val) {
  96 + this.pagination.current = val
  97 + this.loadData()
  98 + }
  99 + },
  100 +}
  101 +</script>
  102 +
  103 +<style lang="scss" scoped>
  104 +.a-work-detail-copy {
  105 + padding: 20px;
  106 +
  107 + .search-row {
  108 + margin-bottom: 20px;
  109 +
  110 + .el-col {
  111 + display: flex;
  112 + align-items: center;
  113 +
  114 + .el-button {
  115 + margin-left: 10px;
  116 + }
  117 + }
  118 + }
  119 +
  120 + .el-pagination {
  121 + margin-top: 20px;
  122 + text-align: right;
  123 + }
  124 +}
  125 +</style>
0 126 \ No newline at end of file
... ...
src/components/work/aWorkDetailCycle.vue 0 → 100644
  1 +<template>
  2 + <div class="a-work-detail-cycle">
  3 + <el-table :data="tableData" border style="width: 100%">
  4 + <el-table-column prop="staffName" :label="$t('adminWorkDetail.processor')" align="center" />
  5 + <el-table-column :label="$t('adminWorkDetail.workCycle')" align="center">
  6 + <template slot-scope="scope">
  7 + <span v-if="scope.row.workCycle === '1001'">{{ $t('adminWorkDetail.once') }}</span>
  8 + <span v-else>{{ $t('adminWorkDetail.periodic') }}</span>
  9 + </template>
  10 + </el-table-column>
  11 + <el-table-column prop="hours" :label="$t('adminWorkDetail.completeHours')" align="center" />
  12 + <el-table-column :label="$t('adminWorkDetail.cycle')" align="center">
  13 + <template slot-scope="scope">
  14 + <span v-if="scope.row.period === '2020022'">{{ $t('adminWorkDetail.monthDay') }}</span>
  15 + <span v-else>{{ $t('adminWorkDetail.weekly') }}</span>
  16 + </template>
  17 + </el-table-column>
  18 + <el-table-column prop="periodMonth" :label="$t('adminWorkDetail.month')" align="center" />
  19 + <el-table-column prop="periodDay" :label="$t('adminWorkDetail.day')" align="center" />
  20 + <el-table-column prop="periodWorkday" :label="$t('adminWorkDetail.week')" align="center" />
  21 + </el-table>
  22 +
  23 + <el-pagination
  24 + :current-page="pagination.current"
  25 + :page-sizes="[10, 20, 30, 50]"
  26 + :page-size="pagination.size"
  27 + :total="pagination.total"
  28 + layout="total, sizes, prev, pager, next, jumper"
  29 + @size-change="handleSizeChange"
  30 + @current-change="handleCurrentChange"
  31 + />
  32 + </div>
  33 +</template>
  34 +
  35 +<script>
  36 +import { listAdminWorkCycle } from '@/api/work/adminWorkDetailApi'
  37 +
  38 +export default {
  39 + name: 'AWorkDetailCycle',
  40 + props: {
  41 + workId: {
  42 + type: String,
  43 + required: true
  44 + }
  45 + },
  46 + data() {
  47 + return {
  48 + tableData: [],
  49 + pagination: {
  50 + current: 1,
  51 + size: 10,
  52 + total: 0
  53 + },
  54 + loading: false
  55 + }
  56 + },
  57 + methods: {
  58 + loadData() {
  59 + this.loading = true
  60 + const params = {
  61 + workId: this.workId,
  62 + page: this.pagination.current,
  63 + row: this.pagination.size
  64 + }
  65 +
  66 + listAdminWorkCycle(params)
  67 + .then(response => {
  68 + this.tableData = response.data
  69 + this.pagination.total = response.total
  70 + })
  71 + .catch(error => {
  72 + this.$message.error(this.$t('adminWorkDetail.fetchError'))
  73 + console.error(error)
  74 + })
  75 + .finally(() => {
  76 + this.loading = false
  77 + })
  78 + },
  79 + handleSizeChange(val) {
  80 + this.pagination.size = val
  81 + this.loadData()
  82 + },
  83 + handleCurrentChange(val) {
  84 + this.pagination.current = val
  85 + this.loadData()
  86 + }
  87 + },
  88 +}
  89 +</script>
  90 +
  91 +<style lang="scss" scoped>
  92 +.a-work-detail-cycle {
  93 + padding: 20px;
  94 +
  95 + .el-pagination {
  96 + margin-top: 20px;
  97 + text-align: right;
  98 + }
  99 +}
  100 +</style>
0 101 \ No newline at end of file
... ...
src/components/work/aWorkDetailEvent.vue 0 → 100644
  1 +<template>
  2 + <div class="a-work-detail-event">
  3 + <el-row :gutter="20">
  4 + <el-col :span="4" class="content-list">
  5 + <div class="content-item"
  6 + v-for="(item,index) in contentList"
  7 + :key="index"
  8 + @click="handleContentClick(item)"
  9 + :class="{ 'active': activeContentId === item.contentId }">
  10 + 问题{{ item.seqNum }}
  11 + </div>
  12 + </el-col>
  13 + <el-col :span="20">
  14 + <el-row :gutter="20" class="search-row">
  15 + <el-col :span="6">
  16 + <el-input v-model="searchForm.staffNameLike" :placeholder="$t('adminWorkDetail.processor')" clearable />
  17 + </el-col>
  18 + <el-col :span="6">
  19 + <el-date-picker
  20 + v-model="searchForm.queryStartTime"
  21 + type="datetime"
  22 + :placeholder="$t('adminWorkDetail.startTime')"
  23 + value-format="yyyy-MM-dd HH:mm:ss"
  24 + />
  25 + </el-col>
  26 + <el-col :span="6">
  27 + <el-date-picker
  28 + v-model="searchForm.queryEndTime"
  29 + type="datetime"
  30 + :placeholder="$t('adminWorkDetail.endTime')"
  31 + value-format="yyyy-MM-dd HH:mm:ss"
  32 + />
  33 + </el-col>
  34 + <el-col :span="6">
  35 + <el-button type="primary" @click="handleSearch">{{ $t('common.search') }}</el-button>
  36 + <el-button @click="handleReset">{{ $t('common.reset') }}</el-button>
  37 + </el-col>
  38 + </el-row>
  39 +
  40 + <el-table :data="tableData" border style="width: 100%">
  41 + <el-table-column prop="preStaffName" :label="$t('adminWorkDetail.preProcessor')" align="center" />
  42 + <el-table-column prop="staffName" :label="$t('adminWorkDetail.processor')" align="center" />
  43 + <el-table-column :label="$t('adminWorkDetail.taskPeriod')" align="center">
  44 + <template slot-scope="scope">
  45 + <div>{{ scope.row.startTime }}</div>
  46 + <div>~{{ scope.row.endTime }}</div>
  47 + </template>
  48 + </el-table-column>
  49 + <el-table-column prop="remark" :label="$t('adminWorkDetail.remark')" align="center" />
  50 + <el-table-column prop="createTime" :label="$t('adminWorkDetail.createTime')" align="center" />
  51 + </el-table>
  52 +
  53 + <el-pagination
  54 + :current-page="pagination.current"
  55 + :page-sizes="[10, 20, 30, 50]"
  56 + :page-size="pagination.size"
  57 + :total="pagination.total"
  58 + layout="total, sizes, prev, pager, next, jumper"
  59 + @size-change="handleSizeChange"
  60 + @current-change="handleCurrentChange"
  61 + />
  62 + </el-col>
  63 + </el-row>
  64 + </div>
  65 +</template>
  66 +
  67 +<script>
  68 +import { listAdminWorkEvent } from '@/api/work/adminWorkDetailApi'
  69 +
  70 +export default {
  71 + name: 'AWorkDetailEvent',
  72 + props: {
  73 + workId: {
  74 + type: String,
  75 + required: true
  76 + },
  77 + contents: {
  78 + type: Array,
  79 + default: () => []
  80 + }
  81 + },
  82 + data() {
  83 + return {
  84 + contentList: [],
  85 + tableData: [],
  86 + activeContentId: '',
  87 + searchForm: {
  88 + staffNameLike: '',
  89 + queryStartTime: '',
  90 + queryEndTime: ''
  91 + },
  92 + pagination: {
  93 + current: 1,
  94 + size: 10,
  95 + total: 0
  96 + },
  97 + loading: false
  98 + }
  99 + },
  100 + watch: {
  101 + contents: {
  102 + immediate: true,
  103 + handler(val) {
  104 + this.contentList = val
  105 + if (this.contentList.length > 0) {
  106 + this.handleContentClick(this.contentList[0])
  107 + }
  108 + }
  109 + }
  110 + },
  111 + methods: {
  112 + handleContentClick(content) {
  113 + this.activeContentId = content.contentId
  114 + this.loadEventData()
  115 + },
  116 + loadEventData() {
  117 + if (!this.activeContentId) return
  118 +
  119 + this.loading = true
  120 + const params = {
  121 + workId: this.workId,
  122 + contentId: this.activeContentId,
  123 + staffNameLike: this.searchForm.staffNameLike,
  124 + queryStartTime: this.searchForm.queryStartTime,
  125 + queryEndTime: this.searchForm.queryEndTime,
  126 + page: this.pagination.current,
  127 + row: this.pagination.size
  128 + }
  129 +
  130 + listAdminWorkEvent(params)
  131 + .then(response => {
  132 + this.tableData = response.data
  133 + this.pagination.total = response.total
  134 + })
  135 + .catch(error => {
  136 + this.$message.error(this.$t('adminWorkDetail.fetchError'))
  137 + console.error(error)
  138 + })
  139 + .finally(() => {
  140 + this.loading = false
  141 + })
  142 + },
  143 + handleSearch() {
  144 + this.pagination.current = 1
  145 + this.loadEventData()
  146 + },
  147 + handleReset() {
  148 + this.searchForm = {
  149 + staffNameLike: '',
  150 + queryStartTime: '',
  151 + queryEndTime: ''
  152 + }
  153 + this.handleSearch()
  154 + },
  155 + handleSizeChange(val) {
  156 + this.pagination.size = val
  157 + this.loadEventData()
  158 + },
  159 + handleCurrentChange(val) {
  160 + this.pagination.current = val
  161 + this.loadEventData()
  162 + },
  163 + loadData() {
  164 + if (this.contentList.length > 0) {
  165 + this.handleContentClick(this.contentList[0])
  166 + }
  167 + }
  168 + }
  169 +}
  170 +</script>
  171 +
  172 +<style lang="scss" scoped>
  173 +.a-work-detail-event {
  174 + padding: 20px;
  175 +
  176 + .content-list {
  177 + border-right: 1px solid #ebeef5;
  178 + padding-right: 20px;
  179 +
  180 + .content-item {
  181 + padding: 10px;
  182 + margin-bottom: 10px;
  183 + border: 1px solid #ebeef5;
  184 + border-radius: 4px;
  185 + cursor: pointer;
  186 + text-align: center;
  187 +
  188 + &:hover {
  189 + background-color: #f5f7fa;
  190 + }
  191 +
  192 + &.active {
  193 + background-color: #ecf5ff;
  194 + border-color: #d9ecff;
  195 + }
  196 + }
  197 + }
  198 +
  199 + .search-row {
  200 + margin-bottom: 20px;
  201 +
  202 + .el-col {
  203 + display: flex;
  204 + align-items: center;
  205 +
  206 + .el-button {
  207 + margin-left: 10px;
  208 + }
  209 + }
  210 + }
  211 +
  212 + .el-pagination {
  213 + margin-top: 20px;
  214 + text-align: right;
  215 + }
  216 +}
  217 +</style>
0 218 \ No newline at end of file
... ...
src/components/work/aWorkDetailFile.vue 0 → 100644
  1 +<template>
  2 + <div class="a-work-detail-file">
  3 + <el-row :gutter="20">
  4 + <el-col :span="4" class="content-list">
  5 + <div class="content-item"
  6 + v-for="(item,index) in contentList"
  7 + :key="index"
  8 + @click="handleContentClick(item)"
  9 + :class="{ 'active': activeContentId === item.contentId }">
  10 + 问题{{ item.seqNum }}
  11 + </div>
  12 + </el-col>
  13 + <el-col :span="20">
  14 + <el-row :gutter="20" class="search-row">
  15 + <el-col :span="6">
  16 + <el-input v-model="searchForm.staffNameLike" :placeholder="$t('adminWorkDetail.processor')" clearable />
  17 + </el-col>
  18 + <el-col :span="6">
  19 + <el-date-picker
  20 + v-model="searchForm.queryStartTime"
  21 + type="datetime"
  22 + :placeholder="$t('adminWorkDetail.startTime')"
  23 + value-format="yyyy-MM-dd HH:mm:ss"
  24 + />
  25 + </el-col>
  26 + <el-col :span="6">
  27 + <el-date-picker
  28 + v-model="searchForm.queryEndTime"
  29 + type="datetime"
  30 + :placeholder="$t('adminWorkDetail.endTime')"
  31 + value-format="yyyy-MM-dd HH:mm:ss"
  32 + />
  33 + </el-col>
  34 + <el-col :span="6">
  35 + <el-button type="primary" @click="handleSearch">{{ $t('common.search') }}</el-button>
  36 + <el-button @click="handleReset">{{ $t('common.reset') }}</el-button>
  37 + </el-col>
  38 + </el-row>
  39 +
  40 + <el-table :data="tableData" border style="width: 100%">
  41 + <el-table-column prop="staffName" :label="$t('adminWorkDetail.processor')" align="center" />
  42 + <el-table-column :label="$t('adminWorkDetail.attachment')" align="center">
  43 + <template slot-scope="scope">
  44 + <el-link v-if="scope.row.fileType !== 'S'" :href="scope.row.pathUrl" target="_blank">
  45 + {{ $t('common.download') }}
  46 + </el-link>
  47 + <span v-else>--</span>
  48 + </template>
  49 + </el-table-column>
  50 + </el-table>
  51 +
  52 + <el-pagination
  53 + :current-page="pagination.current"
  54 + :page-sizes="[10, 20, 30, 50]"
  55 + :page-size="pagination.size"
  56 + :total="pagination.total"
  57 + layout="total, sizes, prev, pager, next, jumper"
  58 + @size-change="handleSizeChange"
  59 + @current-change="handleCurrentChange"
  60 + />
  61 + </el-col>
  62 + </el-row>
  63 + </div>
  64 +</template>
  65 +
  66 +<script>
  67 +import { listAdminWorkPoolFile } from '@/api/work/adminWorkDetailApi'
  68 +
  69 +export default {
  70 + name: 'AWorkDetailFile',
  71 + props: {
  72 + workId: {
  73 + type: String,
  74 + required: true
  75 + },
  76 + contents: {
  77 + type: Array,
  78 + default: () => []
  79 + }
  80 + },
  81 + data() {
  82 + return {
  83 + contentList: [],
  84 + tableData: [],
  85 + activeContentId: '',
  86 + searchForm: {
  87 + staffNameLike: '',
  88 + queryStartTime: '',
  89 + queryEndTime: ''
  90 + },
  91 + pagination: {
  92 + current: 1,
  93 + size: 10,
  94 + total: 0
  95 + },
  96 + loading: false
  97 + }
  98 + },
  99 + watch: {
  100 + contents: {
  101 + immediate: true,
  102 + handler(val) {
  103 + this.contentList = val
  104 + if (this.contentList.length > 0) {
  105 + this.handleContentClick(this.contentList[0])
  106 + }
  107 + }
  108 + }
  109 + },
  110 + methods: {
  111 + handleContentClick(content) {
  112 + this.activeContentId = content.contentId
  113 + this.loadFileData()
  114 + },
  115 + loadFileData() {
  116 + if (!this.activeContentId) return
  117 +
  118 + this.loading = true
  119 + const params = {
  120 + workId: this.workId,
  121 + contentId: this.activeContentId,
  122 + staffNameLike: this.searchForm.staffNameLike,
  123 + queryStartTime: this.searchForm.queryStartTime,
  124 + queryEndTime: this.searchForm.queryEndTime,
  125 + page: this.pagination.current,
  126 + row: this.pagination.size
  127 + }
  128 +
  129 + listAdminWorkPoolFile(params)
  130 + .then(response => {
  131 + this.tableData = response.data
  132 + this.pagination.total = response.total
  133 + })
  134 + .catch(error => {
  135 + this.$message.error(this.$t('adminWorkDetail.fetchError'))
  136 + console.error(error)
  137 + })
  138 + .finally(() => {
  139 + this.loading = false
  140 + })
  141 + },
  142 + handleSearch() {
  143 + this.pagination.current = 1
  144 + this.loadFileData()
  145 + },
  146 + handleReset() {
  147 + this.searchForm = {
  148 + staffNameLike: '',
  149 + queryStartTime: '',
  150 + queryEndTime: ''
  151 + }
  152 + this.handleSearch()
  153 + },
  154 + handleSizeChange(val) {
  155 + this.pagination.size = val
  156 + this.loadFileData()
  157 + },
  158 + handleCurrentChange(val) {
  159 + this.pagination.current = val
  160 + this.loadFileData()
  161 + },
  162 + loadData() {
  163 + if (this.contentList.length > 0) {
  164 + this.handleContentClick(this.contentList[0])
  165 + }
  166 + }
  167 + }
  168 +}
  169 +</script>
  170 +
  171 +<style lang="scss" scoped>
  172 +.a-work-detail-file {
  173 + padding: 20px;
  174 +
  175 + .content-list {
  176 + border-right: 1px solid #ebeef5;
  177 + padding-right: 20px;
  178 +
  179 + .content-item {
  180 + padding: 10px;
  181 + margin-bottom: 10px;
  182 + border: 1px solid #ebeef5;
  183 + border-radius: 4px;
  184 + cursor: pointer;
  185 + text-align: center;
  186 +
  187 + &:hover {
  188 + background-color: #f5f7fa;
  189 + }
  190 +
  191 + &.active {
  192 + background-color: #ecf5ff;
  193 + border-color: #d9ecff;
  194 + }
  195 + }
  196 + }
  197 +
  198 + .search-row {
  199 + margin-bottom: 20px;
  200 +
  201 + .el-col {
  202 + display: flex;
  203 + align-items: center;
  204 +
  205 + .el-button {
  206 + margin-left: 10px;
  207 + }
  208 + }
  209 + }
  210 +
  211 + .el-pagination {
  212 + margin-top: 20px;
  213 + text-align: right;
  214 + }
  215 +}
  216 +</style>
0 217 \ No newline at end of file
... ...
src/components/work/aWorkDetailTask.vue 0 → 100644
  1 +<template>
  2 + <div class="a-work-detail-task">
  3 + <el-row :gutter="20" class="search-row">
  4 + <el-col :span="6">
  5 + <el-input v-model="searchForm.staffNameLike" :placeholder="$t('adminWorkDetail.processor')" clearable />
  6 + </el-col>
  7 + <el-col :span="6">
  8 + <el-date-picker v-model="searchForm.queryStartTime" type="datetime" :placeholder="$t('adminWorkDetail.startTime')"
  9 + value-format="yyyy-MM-dd HH:mm:ss" />
  10 + </el-col>
  11 + <el-col :span="6">
  12 + <el-date-picker v-model="searchForm.queryEndTime" type="datetime" :placeholder="$t('adminWorkDetail.endTime')"
  13 + value-format="yyyy-MM-dd HH:mm:ss" />
  14 + </el-col>
  15 + <el-col :span="6">
  16 + <el-button type="primary" @click="handleSearch">{{ $t('common.search') }}</el-button>
  17 + <el-button @click="handleReset">{{ $t('common.reset') }}</el-button>
  18 + </el-col>
  19 + </el-row>
  20 +
  21 + <el-table :data="tableData" border style="width: 100%">
  22 + <el-table-column prop="taskId" :label="$t('adminWorkDetail.taskId')" align="center" />
  23 + <el-table-column prop="staffName" :label="$t('adminWorkDetail.processor')" align="center" />
  24 + <el-table-column prop="startTime" :label="$t('adminWorkDetail.startTime')" align="center" />
  25 + <el-table-column prop="endTime" :label="$t('adminWorkDetail.endTime')" align="center" />
  26 + <el-table-column prop="createTime" :label="$t('adminWorkDetail.createTime')" align="center" />
  27 + <el-table-column prop="stateName" :label="$t('adminWorkDetail.stateName')" align="center" />
  28 + </el-table>
  29 +
  30 + <el-pagination :current-page="pagination.current" :page-sizes="[10, 20, 30, 50]" :page-size="pagination.size"
  31 + :total="pagination.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
  32 + @current-change="handleCurrentChange" />
  33 + </div>
  34 +</template>
  35 +
  36 +<script>
  37 +import { listAdminWorkTask } from '@/api/work/adminWorkDetailApi'
  38 +
  39 +export default {
  40 + name: 'AWorkDetailTask',
  41 + props: {
  42 + workId: {
  43 + type: String,
  44 + required: true
  45 + }
  46 + },
  47 + data() {
  48 + return {
  49 + searchForm: {
  50 + staffNameLike: '',
  51 + queryStartTime: '',
  52 + queryEndTime: ''
  53 + },
  54 + tableData: [],
  55 + pagination: {
  56 + current: 1,
  57 + size: 10,
  58 + total: 0
  59 + },
  60 + loading: false
  61 + }
  62 + },
  63 + methods: {
  64 + loadData() {
  65 + this.loading = true
  66 + const params = {
  67 + workId: this.workId,
  68 + staffNameLike: this.searchForm.staffNameLike,
  69 + queryStartTime: this.searchForm.queryStartTime,
  70 + queryEndTime: this.searchForm.queryEndTime,
  71 + page: this.pagination.current,
  72 + row: this.pagination.size
  73 + }
  74 +
  75 + listAdminWorkTask(params)
  76 + .then(response => {
  77 + this.tableData = response.data
  78 + this.pagination.total = response.total
  79 + })
  80 + .catch(error => {
  81 + this.$message.error(this.$t('adminWorkDetail.fetchError'))
  82 + console.error(error)
  83 + })
  84 + .finally(() => {
  85 + this.loading = false
  86 + })
  87 + },
  88 + handleSearch() {
  89 + this.pagination.current = 1
  90 + this.loadData()
  91 + },
  92 + handleReset() {
  93 + this.searchForm = {
  94 + staffNameLike: '',
  95 + queryStartTime: '',
  96 + queryEndTime: ''
  97 + }
  98 + this.handleSearch()
  99 + },
  100 + handleSizeChange(val) {
  101 + this.pagination.size = val
  102 + this.loadData()
  103 + },
  104 + handleCurrentChange(val) {
  105 + this.pagination.current = val
  106 + this.loadData()
  107 + }
  108 + },
  109 +}
  110 +</script>
  111 +
  112 +<style lang="scss" scoped>
  113 +.a-work-detail-task {
  114 + padding: 20px;
  115 +
  116 + .search-row {
  117 + margin-bottom: 20px;
  118 +
  119 + .el-col {
  120 + display: flex;
  121 + align-items: center;
  122 +
  123 + .el-button {
  124 + margin-left: 10px;
  125 + }
  126 + }
  127 + }
  128 +
  129 + .el-pagination {
  130 + margin-top: 20px;
  131 + text-align: right;
  132 + }
  133 +}
  134 +</style>
0 135 \ No newline at end of file
... ...
src/components/work/aWorkDetailTaskItem.vue 0 → 100644
  1 +<template>
  2 + <div class="a-work-detail-task-item">
  3 + <el-row :gutter="20">
  4 + <el-col :span="4" class="task-list">
  5 + <div class="task-item" v-for="(item, index) in taskList" :key="index" @click="handleTaskClick(item)"
  6 + :class="{ 'active': activeTaskId === item.taskId }">
  7 + <div>{{ item.staffName }}</div>
  8 + <div>({{ formatDate(item.startTime) }} ~ {{ formatDate(item.endTime) }})</div>
  9 + </div>
  10 + </el-col>
  11 + <el-col :span="20">
  12 + <el-table :data="tableData" border style="width: 100%">
  13 + <el-table-column prop="content" :label="$t('adminWorkDetail.processContent')" width="400" />
  14 + <el-table-column prop="finishTime" :label="$t('adminWorkDetail.finishTime')" align="center" />
  15 + <el-table-column :label="$t('adminWorkDetail.stateName')" align="center">
  16 + <template slot-scope="scope">
  17 + <span v-if="scope.row.state === 'CC'">{{ $t('adminWorkDetail.copyProcessed') }}</span>
  18 + <span v-else-if="scope.row.state === 'C'">{{ $t('adminWorkDetail.processed') }}</span>
  19 + <span v-else>{{ $t('adminWorkDetail.pending') }}</span>
  20 + </template>
  21 + </el-table-column>
  22 + <el-table-column prop="remark" :label="$t('adminWorkDetail.remark')" align="center" />
  23 + <el-table-column :label="$t('adminWorkDetail.attachment')" align="center">
  24 + <template slot-scope="scope">
  25 + <el-link v-if="scope.row.pathUrl" :href="scope.row.pathUrl" target="_blank">
  26 + {{ $t('common.download') }}
  27 + </el-link>
  28 + <span v-else>-</span>
  29 + </template>
  30 + </el-table-column>
  31 + <el-table-column prop="score" :label="$t('adminWorkDetail.score')" align="center" />
  32 + <el-table-column prop="deductionMoney" :label="$t('adminWorkDetail.deductionMoney')" align="center" />
  33 + <el-table-column prop="deductionReason" :label="$t('adminWorkDetail.deductionReason')" align="center" />
  34 + <el-table-column prop="deductionPersonName" :label="$t('adminWorkDetail.deductionPerson')" align="center" />
  35 + <el-table-column prop="createTime" :label="$t('adminWorkDetail.createTime')" align="center" />
  36 + </el-table>
  37 + </el-col>
  38 + </el-row>
  39 + </div>
  40 +</template>
  41 +
  42 +<script>
  43 +import { listAdminWorkTask, listAdminWorkTaskItem } from '@/api/work/adminWorkDetailApi'
  44 +import {dateFormat} from '@/utils/dateUtil'
  45 +
  46 +export default {
  47 + name: 'AWorkDetailTaskItem',
  48 + props: {
  49 + workId: {
  50 + type: String,
  51 + required: true
  52 + },
  53 + contents: {
  54 + type: Array,
  55 + default: () => []
  56 + }
  57 + },
  58 + data() {
  59 + return {
  60 + taskList: [],
  61 + tableData: [],
  62 + activeTaskId: '',
  63 + loading: false
  64 + }
  65 + },
  66 + methods: {
  67 + formatDate(date) {
  68 + if (!date) return ''
  69 + return dateFormat(date)
  70 + },
  71 + loadTaskList() {
  72 + this.loading = true
  73 + const params = {
  74 + workId: this.workId,
  75 + page: 1,
  76 + row: 100
  77 + }
  78 +
  79 + listAdminWorkTask(params)
  80 + .then(response => {
  81 + this.taskList = response.data
  82 + if (this.taskList.length > 0) {
  83 + this.handleTaskClick(this.taskList[0])
  84 + }
  85 + })
  86 + .catch(error => {
  87 + this.$message.error(this.$t('adminWorkDetail.fetchError'))
  88 + console.error(error)
  89 + })
  90 + .finally(() => {
  91 + this.loading = false
  92 + })
  93 + },
  94 + handleTaskClick(task) {
  95 + this.activeTaskId = task.taskId
  96 + this.loadTaskItems(task.taskId)
  97 + },
  98 + loadTaskItems(taskId) {
  99 + this.loading = true
  100 + const params = {
  101 + workId: this.workId,
  102 + taskId: taskId,
  103 + page: 1,
  104 + row: 100
  105 + }
  106 +
  107 + listAdminWorkTaskItem(params)
  108 + .then(response => {
  109 + this.tableData = response.data
  110 + })
  111 + .catch(error => {
  112 + this.$message.error(this.$t('adminWorkDetail.fetchError'))
  113 + console.error(error)
  114 + })
  115 + .finally(() => {
  116 + this.loading = false
  117 + })
  118 + },
  119 + loadData() {
  120 + this.loadTaskList()
  121 + }
  122 + },
  123 +}
  124 +</script>
  125 +
  126 +<style lang="scss" scoped>
  127 +.a-work-detail-task-item {
  128 + padding: 20px;
  129 +
  130 + .task-list {
  131 + border-right: 1px solid #ebeef5;
  132 + padding-right: 20px;
  133 +
  134 + .task-item {
  135 + padding: 10px;
  136 + margin-bottom: 10px;
  137 + border: 1px solid #ebeef5;
  138 + border-radius: 4px;
  139 + cursor: pointer;
  140 +
  141 + &:hover {
  142 + background-color: #f5f7fa;
  143 + }
  144 +
  145 + &.active {
  146 + background-color: #ecf5ff;
  147 + border-color: #d9ecff;
  148 + }
  149 + }
  150 + }
  151 +}
  152 +</style>
0 153 \ No newline at end of file
... ...
src/components/work/aWorkDetailType.vue 0 → 100644
  1 +<template>
  2 + <div class="a-work-detail-type">
  3 + <el-table :data="tableData" border style="width: 100%">
  4 + <el-table-column prop="typeName" :label="$t('adminWorkDetail.typeName')" align="center" />
  5 + <el-table-column :label="$t('adminWorkDetail.notifyType')" align="center">
  6 + <template slot-scope="scope">
  7 + <span v-if="scope.row.smsWay === 'WECHAT'">{{ $t('adminWorkDetail.wechat') }}</span>
  8 + <span v-else-if="scope.row.smsWay === 'ALI_SMS'">{{ $t('adminWorkDetail.sms') }}</span>
  9 + <span v-else>{{ $t('adminWorkDetail.unknown') }}</span>
  10 + </template>
  11 + </el-table-column>
  12 + <el-table-column prop="createTime" :label="$t('adminWorkDetail.createTime')" align="center" />
  13 + <el-table-column prop="remark" :label="$t('adminWorkDetail.remark')" align="center" />
  14 + </el-table>
  15 +
  16 + <el-pagination
  17 + :current-page="pagination.current"
  18 + :page-sizes="[10, 20, 30, 50]"
  19 + :page-size="pagination.size"
  20 + :total="pagination.total"
  21 + layout="total, sizes, prev, pager, next, jumper"
  22 + @size-change="handleSizeChange"
  23 + @current-change="handleCurrentChange"
  24 + />
  25 + </div>
  26 +</template>
  27 +
  28 +<script>
  29 +import { listAdminWorkType } from '@/api/work/adminWorkDetailApi'
  30 +
  31 +export default {
  32 + name: 'AWorkDetailType',
  33 + props: {
  34 + wtId: {
  35 + type: String,
  36 + required: true
  37 + }
  38 + },
  39 + data() {
  40 + return {
  41 + tableData: [],
  42 + pagination: {
  43 + current: 1,
  44 + size: 10,
  45 + total: 0
  46 + },
  47 + loading: false
  48 + }
  49 + },
  50 + methods: {
  51 + loadData() {
  52 + this.loading = true
  53 + const params = {
  54 + wtId: this.wtId,
  55 + page: this.pagination.current,
  56 + row: this.pagination.size
  57 + }
  58 +
  59 + listAdminWorkType(params)
  60 + .then(response => {
  61 + this.tableData = response.data
  62 + this.pagination.total = response.total
  63 + })
  64 + .catch(error => {
  65 + this.$message.error(this.$t('adminWorkDetail.fetchError'))
  66 + console.error(error)
  67 + })
  68 + .finally(() => {
  69 + this.loading = false
  70 + })
  71 + },
  72 + handleSizeChange(val) {
  73 + this.pagination.size = val
  74 + this.loadData()
  75 + },
  76 + handleCurrentChange(val) {
  77 + this.pagination.current = val
  78 + this.loadData()
  79 + }
  80 + },
  81 +}
  82 +</script>
  83 +
  84 +<style lang="scss" scoped>
  85 +.a-work-detail-type {
  86 + padding: 20px;
  87 +
  88 + .el-pagination {
  89 + margin-top: 20px;
  90 + text-align: right;
  91 + }
  92 +}
  93 +</style>
0 94 \ No newline at end of file
... ...
src/i18n/index.js
... ... @@ -74,6 +74,8 @@ import { messages as adminInspectionTaskMessages } from &#39;../views/inspection/adm
74 74 import { messages as adminInspectionTaskDetailMessages } from '../views/inspection/adminInspectionTaskDetailLang'
75 75 import { messages as adminComplaintMessages } from '../views/complaint/adminComplaintLang'
76 76 import { messages as adminComplaintDetailMessages } from '../views/complaint/adminComplaintDetailLang'
  77 +import { messages as adminWorkPoolMessages } from '../views/work/adminWorkPoolLang'
  78 +import { messages as adminWorkDetailMessages } from '../views/work/adminWorkDetailLang'
77 79  
78 80 Vue.use(VueI18n)
79 81  
... ... @@ -152,6 +154,8 @@ const messages = {
152 154 ...adminInspectionTaskDetailMessages.en,
153 155 ...adminComplaintMessages.en,
154 156 ...adminComplaintDetailMessages.en,
  157 + ...adminWorkPoolMessages.en,
  158 + ...adminWorkDetailMessages.en,
155 159 },
156 160 zh: {
157 161 ...loginMessages.zh,
... ... @@ -226,6 +230,8 @@ const messages = {
226 230 ...adminInspectionTaskDetailMessages.zh,
227 231 ...adminComplaintMessages.zh,
228 232 ...adminComplaintDetailMessages.zh,
  233 + ...adminWorkPoolMessages.zh,
  234 + ...adminWorkDetailMessages.zh,
229 235 }
230 236 }
231 237  
... ...
src/router/index.js
... ... @@ -347,15 +347,25 @@ const routes = [
347 347 component: () => import('@/views/inspection/adminInspectionTaskDetailList.vue')
348 348 },
349 349 {
350   - path:'/pages/complaint/adminComplaint',
351   - name:'/pages/complaint/adminComplaint',
  350 + path: '/pages/complaint/adminComplaint',
  351 + name: '/pages/complaint/adminComplaint',
352 352 component: () => import('@/views/complaint/adminComplaintList.vue')
353   - },
354   - {
355   - path:'/views/complaint/adminComplaintDetail',
356   - name:'/views/complaint/adminComplaintDetail',
357   - component: () => import('@/views/complaint/adminComplaintDetailList.vue')
358   - },
  353 + },
  354 + {
  355 + path: '/views/complaint/adminComplaintDetail',
  356 + name: '/views/complaint/adminComplaintDetail',
  357 + component: () => import('@/views/complaint/adminComplaintDetailList.vue')
  358 + },
  359 + {
  360 + path: '/pages/oa/adminWorkPool',
  361 + name: '/pages/oa/adminWorkPool',
  362 + component: () => import('@/views/work/adminWorkPoolList.vue')
  363 + },
  364 + {
  365 + path: '/views/work/adminWorkDetail',
  366 + name: '/views/work/adminWorkDetail',
  367 + component: () => import('@/views/work/adminWorkDetailList.vue')
  368 + },
359 369 // 其他子路由可以在这里添加
360 370 ]
361 371 },
... ...
src/views/work/adminWorkDetailLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + adminWorkDetail: {
  4 + title: 'Work Order Details',
  5 + workId: 'Work Order ID',
  6 + workName: 'Work Order Name',
  7 + typeName: 'Type Name',
  8 + workCycle: 'Type',
  9 + once: 'One-time Work Order',
  10 + periodic: 'Periodic Work Order',
  11 + startTime: 'Start Time',
  12 + endTime: 'End Time',
  13 + createUserName: 'Creator',
  14 + curStaffName: 'Processor',
  15 + curCopyName: 'Copy To',
  16 + stateName: 'Status',
  17 + createTime: 'Create Time',
  18 + attachment: 'Attachment',
  19 + content: 'Content',
  20 + processor: 'Processor',
  21 + processContent: 'Process Content',
  22 + copyTo: 'Copy To',
  23 + workFlow: 'Work Flow',
  24 + flowAttachment: 'Flow Attachment',
  25 + workType: 'Work Type',
  26 + taskId: 'Task ID',
  27 + preProcessor: 'Previous Processor',
  28 + taskPeriod: 'Task Period',
  29 + remark: 'Remark',
  30 + finishTime: 'Finish Time',
  31 + copyProcessed: 'Copy Processed',
  32 + processed: 'Processed',
  33 + pending: 'Pending',
  34 + score: 'Score',
  35 + deductionMoney: 'Deduction Amount',
  36 + deductionReason: 'Deduction Reason',
  37 + deductionPerson: 'Deduction Person',
  38 + notifyType: 'Notification Type',
  39 + wechat: 'WeChat',
  40 + sms: 'SMS',
  41 + unknown: 'Unknown',
  42 + completeHours: 'Complete Hours',
  43 + cycle: 'Cycle',
  44 + monthDay: 'Month/Day',
  45 + weekly: 'Weekly',
  46 + month: 'Month',
  47 + day: 'Day',
  48 + week: 'Week',
  49 + fetchError: 'Failed to fetch work order details'
  50 + }
  51 + },
  52 + zh: {
  53 + adminWorkDetail: {
  54 + title: '工作单详情',
  55 + workId: '工单编号',
  56 + workName: '工单名称',
  57 + typeName: '类型名称',
  58 + workCycle: '标识',
  59 + once: '一次性工单',
  60 + periodic: '周期性工单',
  61 + startTime: '开始时间',
  62 + endTime: '结束时间',
  63 + createUserName: '发起人',
  64 + curStaffName: '处理人',
  65 + curCopyName: '抄送人',
  66 + stateName: '状态',
  67 + createTime: '创建时间',
  68 + attachment: '附件',
  69 + content: '内容',
  70 + processor: '处理人',
  71 + processContent: '处理内容',
  72 + copyTo: '抄送人',
  73 + workFlow: '工作单流转',
  74 + flowAttachment: '流转附件',
  75 + workType: '工作单类型',
  76 + taskId: '任务编号',
  77 + preProcessor: '前处理人',
  78 + taskPeriod: '任务有效期',
  79 + remark: '说明',
  80 + finishTime: '完成时间',
  81 + copyProcessed: '抄送人已办理',
  82 + processed: '处理人已办理',
  83 + pending: '待处理',
  84 + score: '评分',
  85 + deductionMoney: '扣款金额',
  86 + deductionReason: '扣款原因',
  87 + deductionPerson: '扣款人',
  88 + notifyType: '通知方式',
  89 + wechat: '微信',
  90 + sms: '短信',
  91 + unknown: '未知',
  92 + completeHours: '完成小时',
  93 + cycle: '周期',
  94 + monthDay: '月/天',
  95 + weekly: '按周',
  96 + month: '月',
  97 + day: '日',
  98 + week: '周',
  99 + fetchError: '获取工作单详情失败'
  100 + }
  101 + }
  102 +}
0 103 \ No newline at end of file
... ...
src/views/work/adminWorkDetailList.vue 0 → 100644
  1 +<template>
  2 + <div class="admin-work-detail-container">
  3 + <el-card class="box-card">
  4 + <div slot="header" class="clearfix flex justify-between">
  5 + <span>{{ $t('adminWorkDetail.title') }}</span>
  6 + <el-button style="float: right; padding: 3px 0" type="text" @click="goBack">
  7 + <i class="el-icon-close"></i>{{ $t('common.back') }}
  8 + </el-button>
  9 + </div>
  10 +
  11 + <div class="work-info-section">
  12 + <el-row :gutter="20">
  13 + <el-col :span="6">
  14 + <div class="info-item">
  15 + <label>{{ $t('adminWorkDetail.workId') }}:</label>
  16 + <span>{{ adminWorkDetailInfo.workId }}</span>
  17 + </div>
  18 + </el-col>
  19 + <el-col :span="6">
  20 + <div class="info-item">
  21 + <label>{{ $t('adminWorkDetail.workName') }}:</label>
  22 + <span>{{ adminWorkDetailInfo.workName }}</span>
  23 + </div>
  24 + </el-col>
  25 + <el-col :span="6">
  26 + <div class="info-item">
  27 + <label>{{ $t('adminWorkDetail.typeName') }}:</label>
  28 + <span>{{ adminWorkDetailInfo.typeName }}</span>
  29 + </div>
  30 + </el-col>
  31 + <el-col :span="6">
  32 + <div class="info-item">
  33 + <label>{{ $t('adminWorkDetail.workCycle') }}:</label>
  34 + <span>{{ adminWorkDetailInfo.workCycle == '1001' ? $t('adminWorkDetail.once') : $t('adminWorkDetail.periodic') }}</span>
  35 + </div>
  36 + </el-col>
  37 + </el-row>
  38 +
  39 + <el-row :gutter="20">
  40 + <el-col :span="6">
  41 + <div class="info-item">
  42 + <label>{{ $t('adminWorkDetail.startTime') }}:</label>
  43 + <span>{{ adminWorkDetailInfo.startTime }}</span>
  44 + </div>
  45 + </el-col>
  46 + <el-col :span="6">
  47 + <div class="info-item">
  48 + <label>{{ $t('adminWorkDetail.endTime') }}:</label>
  49 + <span>{{ adminWorkDetailInfo.endTime }}</span>
  50 + </div>
  51 + </el-col>
  52 + <el-col :span="6">
  53 + <div class="info-item">
  54 + <label>{{ $t('adminWorkDetail.createUserName') }}:</label>
  55 + <span>{{ adminWorkDetailInfo.createUserName }}</span>
  56 + </div>
  57 + </el-col>
  58 + <el-col :span="6">
  59 + <div class="info-item">
  60 + <label>{{ $t('adminWorkDetail.curStaffName') }}:</label>
  61 + <span>{{ adminWorkDetailInfo.curStaffName }}</span>
  62 + </div>
  63 + </el-col>
  64 + </el-row>
  65 +
  66 + <el-row :gutter="20">
  67 + <el-col :span="6">
  68 + <div class="info-item">
  69 + <label>{{ $t('adminWorkDetail.curCopyName') }}:</label>
  70 + <span>{{ adminWorkDetailInfo.curCopyName }}</span>
  71 + </div>
  72 + </el-col>
  73 + <el-col :span="6">
  74 + <div class="info-item">
  75 + <label>{{ $t('adminWorkDetail.stateName') }}:</label>
  76 + <span>{{ adminWorkDetailInfo.stateName }}</span>
  77 + </div>
  78 + </el-col>
  79 + <el-col :span="6">
  80 + <div class="info-item">
  81 + <label>{{ $t('adminWorkDetail.createTime') }}:</label>
  82 + <span>{{ adminWorkDetailInfo.createTime }}</span>
  83 + </div>
  84 + </el-col>
  85 + <el-col :span="6">
  86 + <div class="info-item">
  87 + <label>{{ $t('adminWorkDetail.attachment') }}:</label>
  88 + <span>
  89 + <el-link v-if="adminWorkDetailInfo.pathUrl" :href="adminWorkDetailInfo.pathUrl" target="_blank">
  90 + {{ $t('common.download') }}
  91 + </el-link>
  92 + <span v-else>-</span>
  93 + </span>
  94 + </div>
  95 + </el-col>
  96 + </el-row>
  97 + </div>
  98 +
  99 + <divider></divider>
  100 +
  101 + <el-tabs v-model="adminWorkDetailInfo._currentTab" @tab-click="changeTab(adminWorkDetailInfo._currentTab)">
  102 + <el-tab-pane :label="$t('adminWorkDetail.content')" name="adminWorkDetailContent">
  103 + <div class="content-section" v-for="(item,index) in adminWorkDetailInfo.contents" :key="index">
  104 + <div>{{item.seqNum}}、</div>
  105 + <div v-html="item.content" style="width: 80%;" class="text-left"></div>
  106 + </div>
  107 + </el-tab-pane>
  108 +
  109 + <el-tab-pane :label="$t('adminWorkDetail.processor')" name="aWorkDetailTask">
  110 + <a-work-detail-task ref="aWorkDetailTask" :work-id="adminWorkDetailInfo.workId"></a-work-detail-task>
  111 + </el-tab-pane>
  112 +
  113 + <el-tab-pane :label="$t('adminWorkDetail.processContent')" name="aWorkDetailTaskItem">
  114 + <a-work-detail-task-item ref="aWorkDetailTaskItem" :work-id="adminWorkDetailInfo.workId" :contents="adminWorkDetailInfo.contents"></a-work-detail-task-item>
  115 + </el-tab-pane>
  116 +
  117 + <el-tab-pane :label="$t('adminWorkDetail.copyTo')" name="aWorkDetailCopy">
  118 + <a-work-detail-copy ref="aWorkDetailCopy" :work-id="adminWorkDetailInfo.workId"></a-work-detail-copy>
  119 + </el-tab-pane>
  120 +
  121 + <el-tab-pane :label="$t('adminWorkDetail.workFlow')" name="aWorkDetailEvent">
  122 + <a-work-detail-event ref="aWorkDetailEvent" :work-id="adminWorkDetailInfo.workId" :contents="adminWorkDetailInfo.contents"></a-work-detail-event>
  123 + </el-tab-pane>
  124 +
  125 + <el-tab-pane :label="$t('adminWorkDetail.flowAttachment')" name="aWorkDetailFile">
  126 + <a-work-detail-file ref="aWorkDetailFile" :work-id="adminWorkDetailInfo.workId" :contents="adminWorkDetailInfo.contents"></a-work-detail-file>
  127 + </el-tab-pane>
  128 +
  129 + <el-tab-pane :label="$t('adminWorkDetail.workType')" name="aWorkDetailType">
  130 + <a-work-detail-type ref="aWorkDetailType" :wt-id="adminWorkDetailInfo.wtId"></a-work-detail-type>
  131 + </el-tab-pane>
  132 +
  133 + <el-tab-pane v-if="adminWorkDetailInfo.workCycle == '2002'" :label="$t('adminWorkDetail.workCycle')" name="aWorkDetailCycle">
  134 + <a-work-detail-cycle ref="aWorkDetailCycle" :work-id="adminWorkDetailInfo.workId"></a-work-detail-cycle>
  135 + </el-tab-pane>
  136 + </el-tabs>
  137 + </el-card>
  138 + </div>
  139 +</template>
  140 +
  141 +<script>
  142 +import { getWorkDetail } from '@/api/work/adminWorkDetailApi'
  143 +import AWorkDetailTask from '@/components/work/aWorkDetailTask'
  144 +import AWorkDetailTaskItem from '@/components/work/aWorkDetailTaskItem'
  145 +import AWorkDetailCopy from '@/components/work/aWorkDetailCopy'
  146 +import AWorkDetailEvent from '@/components/work/aWorkDetailEvent'
  147 +import AWorkDetailFile from '@/components/work/aWorkDetailFile'
  148 +import AWorkDetailType from '@/components/work/aWorkDetailType'
  149 +import AWorkDetailCycle from '@/components/work/aWorkDetailCycle'
  150 +import divider from '@/components/system/divider'
  151 +
  152 +export default {
  153 + name: 'AdminWorkDetail',
  154 + components: {
  155 + AWorkDetailTask,
  156 + AWorkDetailTaskItem,
  157 + AWorkDetailCopy,
  158 + AWorkDetailEvent,
  159 + AWorkDetailFile,
  160 + AWorkDetailType,
  161 + AWorkDetailCycle,
  162 + divider
  163 + },
  164 + data() {
  165 + return {
  166 + adminWorkDetailInfo: {
  167 + workId: '',
  168 + wtId: '',
  169 + workName: '',
  170 + typeName: '',
  171 + workCycle: '',
  172 + startTime: '',
  173 + endTime: '',
  174 + createUserName: '',
  175 + curStaffName: '',
  176 + curCopyName: '',
  177 + stateName: '',
  178 + createTime: '',
  179 + pathUrl: '',
  180 + _currentTab: 'adminWorkDetailContent',
  181 + contents: []
  182 + }
  183 + }
  184 + },
  185 + created() {
  186 + this.adminWorkDetailInfo.workId = this.$route.query.workId
  187 + if (this.$route.query.currentTab) {
  188 + this.adminWorkDetailInfo._currentTab = this.$route.query.currentTab
  189 + }
  190 + this.loadWorkInfo()
  191 + },
  192 + methods: {
  193 + async loadWorkInfo() {
  194 + try {
  195 + const params = {
  196 + workId: this.adminWorkDetailInfo.workId,
  197 + page: 1,
  198 + row: 1
  199 + }
  200 + const { data } = await getWorkDetail(params)
  201 + if (data && data.length > 0) {
  202 + Object.assign(this.adminWorkDetailInfo, data[0])
  203 + }
  204 + } catch (error) {
  205 + this.$message.error(this.$t('adminWorkDetail.fetchError'))
  206 + }
  207 + },
  208 + changeTab(tab) {
  209 + setTimeout(()=>{
  210 + if (this.$refs[tab] ) {
  211 + this.$refs[tab].loadData()
  212 + }
  213 + },500)
  214 + },
  215 + goBack() {
  216 + this.$router.go(-1)
  217 + }
  218 + }
  219 +}
  220 +</script>
  221 +
  222 +<style lang="scss" scoped>
  223 +.admin-work-detail-container {
  224 + padding: 20px;
  225 +
  226 + .box-card {
  227 + margin-bottom: 20px;
  228 + }
  229 +
  230 + .work-info-section {
  231 + margin-bottom: 20px;
  232 +
  233 + .info-item {
  234 + margin-bottom: 15px;
  235 + text-align: left;
  236 +
  237 + label {
  238 + color: #909399;
  239 + font-size: 14px;
  240 + margin-bottom: 5px;
  241 + margin-right: 5px;
  242 + }
  243 +
  244 + span {
  245 + font-size: 14px;
  246 + color: #606266;
  247 + }
  248 + }
  249 + }
  250 +
  251 + .content-section {
  252 + display: flex;
  253 + padding: 10px 0;
  254 + border-bottom: 1px solid #ebeef5;
  255 +
  256 + &:last-child {
  257 + border-bottom: none;
  258 + }
  259 + }
  260 +}
  261 +</style>
0 262 \ No newline at end of file
... ...
src/views/work/adminWorkPoolLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + adminWorkPool: {
  4 + search: {
  5 + title: 'Search Conditions',
  6 + workName: 'Work Order Name',
  7 + createUser: 'Creator',
  8 + staffName: 'Handler',
  9 + startTime: 'Start Time',
  10 + endTime: 'End Time'
  11 + },
  12 + list: {
  13 + title: 'Work Order Pool'
  14 + },
  15 + table: {
  16 + id: 'ID',
  17 + communityName: 'Community Name',
  18 + workName: 'Work Order Name',
  19 + typeName: 'Type Name',
  20 + workCycle: 'Cycle',
  21 + createUser: 'Creator',
  22 + staffName: 'Handler',
  23 + timeRange: 'Time Range',
  24 + status: 'Status',
  25 + createTime: 'Create Time',
  26 + finishTime: 'Finish Time'
  27 + },
  28 + status: {
  29 + timeout: 'Timeout'
  30 + },
  31 + workCycle: {
  32 + once: 'One-time',
  33 + periodic: 'Periodic'
  34 + },
  35 + community: {
  36 + title: 'Community Selection',
  37 + all: 'All Communities',
  38 + fetchError: 'Failed to load communities'
  39 + },
  40 + fetchError: 'Failed to load work orders'
  41 + }
  42 + },
  43 + zh: {
  44 + adminWorkPool: {
  45 + search: {
  46 + title: '查询条件',
  47 + workName: '工单名称',
  48 + createUser: '发起人',
  49 + staffName: '处理人',
  50 + startTime: '开始时间',
  51 + endTime: '结束时间'
  52 + },
  53 + list: {
  54 + title: '工作单池'
  55 + },
  56 + table: {
  57 + id: '编号',
  58 + communityName: '小区名称',
  59 + workName: '工单名称',
  60 + typeName: '类型名称',
  61 + workCycle: '标识',
  62 + createUser: '发起人',
  63 + staffName: '处理人',
  64 + timeRange: '时间段',
  65 + status: '状态',
  66 + createTime: '创建时间',
  67 + finishTime: '完成时间'
  68 + },
  69 + status: {
  70 + timeout: '超时'
  71 + },
  72 + workCycle: {
  73 + once: '一次性工单',
  74 + periodic: '周期性工单'
  75 + },
  76 + community: {
  77 + title: '小区选择',
  78 + all: '全部小区',
  79 + fetchError: '加载小区失败'
  80 + },
  81 + fetchError: '加载工单失败'
  82 + }
  83 + }
  84 +}
0 85 \ No newline at end of file
... ...
src/views/work/adminWorkPoolList.vue 0 → 100644
  1 +<template>
  2 + <div class="admin-work-pool-container">
  3 + <el-row :gutter="20">
  4 + <el-col :span="3">
  5 + <select-admin-community @changeCommunity="handleCommunityChange" />
  6 + </el-col>
  7 + <el-col :span="21">
  8 + <el-card class="box-card">
  9 + <div slot="header" class="clearfix flex justify-between">
  10 + <span>{{ $t('adminWorkPool.search.title') }}</span>
  11 + </div>
  12 + <el-row :gutter="20">
  13 + <el-col :span="4">
  14 + <el-input v-model="searchForm.workNameLike" :placeholder="$t('adminWorkPool.search.workName')" clearable />
  15 + </el-col>
  16 + <el-col :span="4">
  17 + <el-input v-model="searchForm.createUserNameLike" :placeholder="$t('adminWorkPool.search.createUser')"
  18 + clearable />
  19 + </el-col>
  20 + <el-col :span="4">
  21 + <el-input v-model="searchForm.staffNameLike" :placeholder="$t('adminWorkPool.search.staffName')"
  22 + clearable />
  23 + </el-col>
  24 + <el-col :span="4">
  25 + <el-date-picker v-model="searchForm.queryStartTime" type="datetime"
  26 + :placeholder="$t('adminWorkPool.search.startTime')" value-format="yyyy-MM-dd HH:mm:ss" />
  27 + </el-col>
  28 + <el-col :span="4">
  29 + <el-date-picker v-model="searchForm.queryEndTime" type="datetime"
  30 + :placeholder="$t('adminWorkPool.search.endTime')" value-format="yyyy-MM-dd HH:mm:ss" />
  31 + </el-col>
  32 + <el-col :span="4">
  33 + <el-button type="primary" @click="handleSearch">
  34 + <i class="el-icon-search"></i>
  35 + {{ $t('common.search') }}
  36 + </el-button>
  37 + <el-button @click="handleReset">
  38 + <i class="el-icon-refresh"></i>
  39 + {{ $t('common.reset') }}
  40 + </el-button>
  41 + </el-col>
  42 + </el-row>
  43 + </el-card>
  44 +
  45 + <el-card class="box-card">
  46 + <div slot="header" class="clearfix flex justify-between">
  47 + <span>{{ $t('adminWorkPool.list.title') }}</span>
  48 + </div>
  49 + <el-table v-loading="loading" :data="tableData" border style="width: 100%">
  50 + <el-table-column prop="workId" :label="$t('adminWorkPool.table.id')" align="center" />
  51 + <el-table-column prop="communityName" :label="$t('adminWorkPool.table.communityName')" align="center" />
  52 + <el-table-column prop="workName" :label="$t('adminWorkPool.table.workName')" align="center" />
  53 + <el-table-column prop="typeName" :label="$t('adminWorkPool.table.typeName')" align="center" />
  54 + <el-table-column :label="$t('adminWorkPool.table.workCycle')" align="center">
  55 + <template slot-scope="scope">
  56 + {{ scope.row.workCycle === '1001' ? $t('adminWorkPool.workCycle.once') :
  57 + $t('adminWorkPool.workCycle.periodic') }}
  58 + </template>
  59 + </el-table-column>
  60 + <el-table-column prop="createUserName" :label="$t('adminWorkPool.table.createUser')" align="center" />
  61 + <el-table-column prop="staffName" :label="$t('adminWorkPool.table.staffName')" align="center">
  62 + <template slot-scope="scope">
  63 + {{ scope.row.staffName || '-' }}
  64 + </template>
  65 + </el-table-column>
  66 + <el-table-column :label="$t('adminWorkPool.table.timeRange')" align="center">
  67 + <template slot-scope="scope">
  68 + {{ scope.row.startTime }}<br />~{{ scope.row.endTime }}
  69 + </template>
  70 + </el-table-column>
  71 + <el-table-column :label="$t('adminWorkPool.table.status')" align="center">
  72 + <template slot-scope="scope">
  73 + {{ scope.row.stateName }}
  74 + <span v-if="scope.row.state === 'C' && scope.row.taskTimeout === 'Y'">
  75 + ({{ $t('adminWorkPool.status.timeout') }})
  76 + </span>
  77 + </template>
  78 + </el-table-column>
  79 + <el-table-column prop="createTime" :label="$t('adminWorkPool.table.createTime')" align="center" />
  80 + <el-table-column prop="finishTime" :label="$t('adminWorkPool.table.finishTime')" align="center">
  81 + <template slot-scope="scope">
  82 + {{ scope.row.finishTime || '-' }}
  83 + </template>
  84 + </el-table-column>
  85 + <el-table-column :label="$t('common.operation')" align="center" width="120">
  86 + <template slot-scope="scope">
  87 + <el-button size="mini" type="primary" @click="handleDetail(scope.row)">
  88 + {{ $t('common.detail') }}
  89 + </el-button>
  90 + </template>
  91 + </el-table-column>
  92 + </el-table>
  93 +
  94 + <el-pagination :current-page="pagination.current" :page-sizes="[10, 20, 30, 50]" :page-size="pagination.size"
  95 + :total="pagination.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
  96 + @current-change="handlePageChange" />
  97 + </el-card>
  98 + </el-col>
  99 + </el-row>
  100 + </div>
  101 +</template>
  102 +
  103 +<script>
  104 +import { listAdminWorkTask } from '@/api/work/adminWorkPoolApi'
  105 +import SelectAdminCommunity from '@/components/community/selectAdminCommunity'
  106 +
  107 +export default {
  108 + name: 'AdminWorkPoolList',
  109 + components: {
  110 + SelectAdminCommunity
  111 + },
  112 + data() {
  113 + return {
  114 + loading: false,
  115 + searchForm: {
  116 + workNameLike: '',
  117 + createUserNameLike: '',
  118 + staffNameLike: '',
  119 + queryStartTime: '',
  120 + queryEndTime: '',
  121 + communityId: '',
  122 + state: '',
  123 + page: 1,
  124 + row: 10
  125 + },
  126 + tableData: [],
  127 + pagination: {
  128 + current: 1,
  129 + size: 10,
  130 + total: 0
  131 + }
  132 + }
  133 + },
  134 + created() {
  135 + this.getList()
  136 + },
  137 + methods: {
  138 + async getList() {
  139 + try {
  140 + this.loading = true
  141 + const params = { ...this.searchForm }
  142 + if (params.state === 'timeout') {
  143 + params.state = 'C'
  144 + params.taskTimeout = 'Y'
  145 + }
  146 + const { data, total } = await listAdminWorkTask(params)
  147 + this.tableData = data
  148 + this.pagination.total = total
  149 + } catch (error) {
  150 + this.$message.error(this.$t('adminWorkPool.fetchError'))
  151 + } finally {
  152 + this.loading = false
  153 + }
  154 + },
  155 + handleSearch() {
  156 + this.searchForm.page = 1
  157 + this.pagination.current = 1
  158 + this.getList()
  159 + },
  160 + handleReset() {
  161 + this.searchForm = {
  162 + workNameLike: '',
  163 + createUserNameLike: '',
  164 + staffNameLike: '',
  165 + queryStartTime: '',
  166 + queryEndTime: '',
  167 + communityId: this.searchForm.communityId,
  168 + state: '',
  169 + page: 1,
  170 + row: 10
  171 + }
  172 + this.getList()
  173 + },
  174 + handleCommunityChange(community) {
  175 + this.searchForm.communityId = community.communityId
  176 + this.handleSearch()
  177 + },
  178 + handleDetail(row) {
  179 + this.$router.push(`/views/work/adminWorkDetail?workId=${row.workId}`)
  180 + },
  181 + handleSizeChange(val) {
  182 + this.searchForm.row = val
  183 + this.pagination.size = val
  184 + this.getList()
  185 + },
  186 + handlePageChange(val) {
  187 + this.searchForm.page = val
  188 + this.pagination.current = val
  189 + this.getList()
  190 + }
  191 + }
  192 +}
  193 +</script>
  194 +
  195 +<style lang="scss" scoped>
  196 +.admin-work-pool-container {
  197 + padding: 20px;
  198 +
  199 + .box-card {
  200 + margin-bottom: 20px;
  201 + }
  202 +
  203 + .el-pagination {
  204 + margin-top: 20px;
  205 + text-align: right;
  206 + }
  207 +}
  208 +</style>
0 209 \ No newline at end of file
... ...