PageTaskExecution.vue 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. <template>
  2. <div class="disaster-precaution-container">
  3. <header class="disaster-precaution-container__header">
  4. <span class="disaster-precaution-container__title">检查任务执行</span>
  5. </header>
  6. <main class="disaster-precaution-container__main">
  7. <div class="disaster-precaution">
  8. <header class="disaster-precaution__header">
  9. <Search
  10. :searchConfig="TASK_EXECUTION_SEARCH_CONFIG"
  11. :searchData="searchData"
  12. @update:searchData="handleSearch"
  13. />
  14. </header>
  15. <BasicTable
  16. :table-config="tableConfig"
  17. :table-data="tableData"
  18. @update:pageSize="handleSizeChange"
  19. @update:pageNumber="handleCurrentChange"
  20. >
  21. <template #taskName="scope">
  22. <div class="task-name--div">
  23. <el-tooltip :content="scope.row.name" placement="top" effect="light">
  24. <span>{{ scope.row.name }}</span>
  25. </el-tooltip>
  26. <img :src="OverdueIcon" v-if="scope.row.overdue" />
  27. </div>
  28. </template>
  29. <template #inspectType="scope">
  30. <span>{{ INSPECT_TYPE_MAP[scope.row.inspectType] }}</span>
  31. </template>
  32. <template #taskStage="scope">
  33. <span>{{ TASK_STAGE_MAP[scope.row.taskState] }}</span>
  34. </template>
  35. <!-- action button 不仅分任务情况 还要分 人物权限 -->
  36. <template #action="scope">
  37. <!-- 检查任务操作入口 -->
  38. <div class="action-container" v-if="scope.row.taskState === TASK_STAGE.PENDING_CHECK">
  39. <ActionButton text="去检查" @click="handleCheckItem(scope.row.id, 'check')" />
  40. <!-- 仅检查责任人可以看到 -->
  41. <ActionButton
  42. text="添加检查人"
  43. @click="handleAddCheckUser(scope.row)"
  44. v-if="scope.row.userTypeList.includes(USER_TYPE.CHECK_RESPONSIBLE)"
  45. />
  46. </div>
  47. <!-- 审批任务操作入口 -->
  48. <div class="action-container" v-else-if="scope.row.taskState === TASK_STAGE.PENDING_APPROVAL">
  49. <!-- 审批人员可以看到 -->
  50. <ActionButton
  51. text="去审批"
  52. v-if="scope.row.userTypeList.includes(USER_TYPE.APPROVER)"
  53. @click="handleCheckItem(scope.row.id, 'approve')"
  54. />
  55. <!-- 检查责任人、检查执行人员可以看到 -->
  56. <ActionButton
  57. v-else
  58. text="撤回"
  59. :popconfirm="{
  60. title: '确定撤回吗?',
  61. }"
  62. @confirm="handleWithdrawTask(scope.row.id, scope.row.taskState)"
  63. />
  64. </div>
  65. <!-- 完成任务操作入口 -->
  66. <div class="action-container" v-else-if="scope.row.taskState === TASK_STAGE.COMPLETED">
  67. <ActionButton text="查看" @click="handleCheckItem(scope.row.id, 'view')" />
  68. <!-- 仅审批人员可以看到 -->
  69. <ActionButton
  70. v-if="
  71. scope.row.userTypeList.includes(USER_TYPE.APPROVER) && !isOverdue24Hours(scope.row.dueCompleteTime)
  72. "
  73. text="撤回"
  74. :popconfirm="{
  75. title: '确定撤回吗?',
  76. }"
  77. @confirm="handleWithdrawTask(scope.row.id, scope.row.taskState)"
  78. />
  79. </div>
  80. </template>
  81. </BasicTable>
  82. </div>
  83. </main>
  84. </div>
  85. </template>
  86. <script setup lang="ts">
  87. import { ref, onMounted, reactive, onUnmounted } from 'vue';
  88. import BasicTable from '@/components/BasicTable.vue';
  89. import ActionButton from '@/components/ActionButton.vue';
  90. import Search from '@/views/disaster/components/Search.vue';
  91. import useTableConfig from '@/hooks/useTableConfigHook';
  92. import {
  93. getTaskExecutionList,
  94. getTaskInspectorList,
  95. withdrawTaskInspect,
  96. withdrawTaskApproval,
  97. } from '@/api/disaster-precaution';
  98. import type { TaskExecutionListResponse } from '@/types/disaster-precaution';
  99. import OverdueIcon from '@/assets/svg/overdue.svg';
  100. import { TASK_STAGE } from './src/constants/task-execution';
  101. import { INSPECT_TYPE_MAP, TASK_STAGE_MAP } from './src/constants/task-execution';
  102. import { TABLE_OPTIONS_EXECUTION, TASK_EXECUTION_TABLE_COLUMNS, TASK_EXECUTION_SEARCH_CONFIG } from './src/config';
  103. import type { TaskExecutionListQuery } from '@/types/disaster-precaution';
  104. import type { QueryPageRequest } from '@/types/disaster';
  105. import { USER_TYPE } from './src/constants/task-execution';
  106. import type { UserInfo } from '@/types/push-object';
  107. import { useRouter } from 'vue-router';
  108. import { ElMessage } from 'element-plus';
  109. const router = useRouter();
  110. const userInfo = ref(false);
  111. const searchData = reactive({
  112. inspectType: '',
  113. taskState: '',
  114. });
  115. const tableData = ref<TaskExecutionListResponse[]>([]);
  116. const { tableConfig, pagination } = useTableConfig(TASK_EXECUTION_TABLE_COLUMNS, TABLE_OPTIONS_EXECUTION);
  117. // 添加刷新时间变量,用于触发视图更新
  118. const refreshTime = ref(Date.now());
  119. let refreshTimer: number | null = null;
  120. let taskManagementListQuery: QueryPageRequest<TaskExecutionListQuery> = {
  121. pageNumber: pagination.pageNumber,
  122. pageSize: pagination.pageSize,
  123. queryParam: {},
  124. };
  125. const handleSearch = () => {
  126. taskManagementListQuery.queryParam = {};
  127. if (searchData.inspectType !== '') {
  128. taskManagementListQuery.queryParam.inspectType = searchData.inspectType;
  129. }
  130. if (searchData.taskState !== '') {
  131. taskManagementListQuery.queryParam.taskState = searchData.taskState;
  132. }
  133. getTableData();
  134. };
  135. const handleSizeChange = (value: number) => {
  136. pagination.pageSize = value;
  137. taskManagementListQuery.pageSize = value;
  138. getTableData();
  139. };
  140. const handleCurrentChange = (value: number) => {
  141. pagination.pageNumber = value;
  142. taskManagementListQuery.pageNumber = value;
  143. getTableData();
  144. };
  145. const currentTaskId = ref<number>();
  146. const currentTaskInspectorList = ref<UserInfo[]>([]);
  147. const handleAddCheckUser = async (row: TaskExecutionListResponse) => {
  148. currentTaskId.value = row.id;
  149. console.log(row);
  150. // const res = await getTaskInspectorList(currentTaskId.value);
  151. // currentTaskInspectorList.value = res.map((item) => {
  152. // return {
  153. // ...item,
  154. // isSelected: true,
  155. // };
  156. // });
  157. // userInfo.value = true;
  158. };
  159. const defaultRouterName = 'disaster-precaution-task-execution-detail';
  160. const handleCheckItem = (id: number, operationType: 'check' | 'approve' | 'view') => {
  161. router.push({
  162. name: defaultRouterName,
  163. params: {
  164. id,
  165. },
  166. query: {
  167. operationType,
  168. },
  169. });
  170. };
  171. const handleWithdrawTask = async (id: number, state: number) => {
  172. if (state === TASK_STAGE.PENDING_APPROVAL) {
  173. await withdrawTaskInspect(id);
  174. } else if (state === TASK_STAGE.COMPLETED) {
  175. await withdrawTaskApproval(id);
  176. }
  177. ElMessage.success('撤回成功');
  178. getTableData();
  179. };
  180. const getTableData = async () => {
  181. tableConfig.loading = true;
  182. const res = await getTaskExecutionList(taskManagementListQuery);
  183. tableData.value = res.records;
  184. pagination.total = res.totalRow;
  185. tableConfig.loading = false;
  186. };
  187. // 判断是否超过应完成时间24小时
  188. const isOverdue24Hours = (dueCompleteTime: string) => {
  189. if (!dueCompleteTime) return false;
  190. const dueTime = new Date(dueCompleteTime).getTime();
  191. const currentTime = refreshTime.value;
  192. // 计算24小时的毫秒数: 24 * 60 * 60 * 1000 = 86400000
  193. return currentTime > dueTime + 86400000;
  194. };
  195. onMounted(() => {
  196. getTableData();
  197. // 设置定时器,每分钟更新一次时间
  198. refreshTimer = window.setInterval(() => {
  199. refreshTime.value = Date.now();
  200. }, 1000);
  201. });
  202. // 组件销毁时清除定时器
  203. onUnmounted(() => {
  204. if (refreshTimer !== null) {
  205. clearInterval(refreshTimer);
  206. refreshTimer = null;
  207. }
  208. });
  209. </script>
  210. <style scoped lang="scss">
  211. @use '../style/disaster.scss' as *;
  212. @use './src/style/task-execution.scss' as *;
  213. </style>