evaluationDepartment.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. <template>
  2. <div class="safety-platform-container">
  3. <header class="safety-platform-container__header">
  4. <div class="breadcrumb-title"> 安全考核自评 </div>
  5. </header>
  6. <main class="safety-platform-container__main">
  7. <div class="search-table-container">
  8. <header>
  9. <div class="act-search">
  10. <section class="select-box">
  11. <div class="select-box--item">
  12. <span>考核表名称:</span>
  13. <el-input
  14. v-model="tableQuery.queryParam.evaluationTableName"
  15. placeholder="搜索考核表名称"
  16. class="act-search-input"
  17. />
  18. </div>
  19. <div class="select-box--item">
  20. <span>状态:</span>
  21. <el-select
  22. v-model="tableQuery.queryParam.status"
  23. placeholder="请选择状态"
  24. clearable
  25. >
  26. <el-option
  27. v-for="item in EVALUATION_SYSTEM_STATUS_OPTIONS"
  28. :key="item.value"
  29. :label="item.label"
  30. :value="item.value"
  31. />
  32. </el-select>
  33. </div>
  34. <div>
  35. <span>计划日期范围:</span>
  36. <el-date-picker
  37. v-model="tableQuery.queryParam.dateRange"
  38. type="daterange"
  39. range-separator="至"
  40. start-placeholder="开始日期"
  41. end-placeholder="结束日期"
  42. value-format="YYYY-MM-DD"
  43. format="YYYY-MM-DD"
  44. />
  45. </div>
  46. </section>
  47. <section class="search-btn">
  48. <el-button type="primary" @click="handleSearch">查询</el-button>
  49. <el-button @click="handleReset">重置</el-button>
  50. </section>
  51. </div>
  52. </header>
  53. <div class="batch-table">
  54. <BasicTable
  55. ref="basicTableRef"
  56. :tableData="tableData"
  57. :tableConfig="tableConfig"
  58. @update:pageSize="handleSizeChange"
  59. @update:pageNumber="handleCurrentChange"
  60. @update:selection="handleSelectionChange"
  61. >
  62. <template #status="scope">
  63. <span>
  64. {{ EVALUATION_SYSTEM_STATUS_LABEL[String(scope.row.status)] || scope.row.statusName || '-' }}
  65. </span>
  66. </template>
  67. <template #evaluationDocument="scope">
  68. <div
  69. class="file-container--div"
  70. v-for="item in parseAttachments(scope.row.evaluationDocument)"
  71. :key="item.fileUrl"
  72. >
  73. <img
  74. class="file-container--div__icon"
  75. @click="previewOnline(item.fileUrl, item.fileType as keyof typeof FILE_TYPE_ICON)"
  76. :src="FILE_TYPE_ICON[item.fileType]"
  77. />
  78. <span
  79. class="file-container--div__name"
  80. @click="previewOnline(item.fileUrl, item.fileType as keyof typeof FILE_TYPE_ICON)"
  81. >{{ item.fileName }}</span
  82. >
  83. <img
  84. class="file-container--div__download"
  85. :src="DownloadIcon"
  86. @click="downloadFile(item.fileUrl, item.fileName)"
  87. />
  88. </div>
  89. </template>
  90. <template #action="scope">
  91. <div class="action-container--div" style="justify-content: left">
  92. <!-- 待反馈(2):显示反馈 -->
  93. <template v-if="Number(scope.row.status) === 2">
  94. <ActionButton text="反馈" @click="handleFeedback(scope.row.id)" />
  95. </template>
  96. <!-- 已完成(1):显示反馈和先进个人申报 -->
  97. <template v-else-if="Number(scope.row.status) === 1">
  98. <!-- <ActionButton text="反馈" @click="handleFeedback(scope.row.id)" /> -->
  99. <ActionButton text="先进个人申报" @click="handleAdvancedPerson(scope.row)" />
  100. </template>
  101. <!-- 已作废(5):显示反馈 -->
  102. <template v-else-if="Number(scope.row.status) === 5">
  103. <ActionButton text="反馈" @click="handleFeedback(scope.row.id)" />
  104. </template>
  105. </div>
  106. </template>
  107. </BasicTable>
  108. </div>
  109. </div>
  110. </main>
  111. <PreviewOnline ref="previewOnlineRef" />
  112. </div>
  113. </template>
  114. <script lang="ts" setup>
  115. import { onMounted, reactive, ref } from 'vue';
  116. import BasicTable from '@/components/BasicTable.vue';
  117. import useTableConfig from '@/hooks/useTableConfigHook';
  118. import ActionButton from '@/components/ActionButton.vue';
  119. import { TABLE_OPTIONS, EVALUATION_DEPARTMENT_TABLE_COLUMNS } from './configs/tables';
  120. import { EVALUATION_SYSTEM_STATUS_OPTIONS, EVALUATION_SYSTEM_STATUS_LABEL } from '../evaluationSystem/configs/status';
  121. import { useRouter } from 'vue-router';
  122. import type { QueryPageRequest } from '@/types/basic-query';
  123. import DownloadIcon from '@/views/disaster/disaster-control/src/svg/download.svg';
  124. import { downloadFile } from '@/views/disaster/utils';
  125. import PreviewOnline from '@/views/disaster/components/PreviewOnline.vue';
  126. import { FILE_TYPE_ICON } from '@/components/UploadFiles/constants';
  127. import { querySecurityExamineDept } from '@/api/evaluationSystem';
  128. import type { QuerySecurityExamineDeptParams } from '@/api/evaluationSystem';
  129. const router = useRouter();
  130. // 表格
  131. const basicTableRef = ref<InstanceType<typeof BasicTable>>();
  132. const { tableConfig, pagination } = useTableConfig(EVALUATION_DEPARTMENT_TABLE_COLUMNS, TABLE_OPTIONS);
  133. const tableData = ref<any[]>([]);
  134. const tableQuery = reactive<QueryPageRequest<any>>({
  135. pageNumber: pagination.pageNumber,
  136. pageSize: pagination.pageSize,
  137. queryParam: {
  138. evaluationTableName: '',
  139. status: undefined as number | undefined,
  140. dateRange: null,
  141. startTime: '',
  142. endTime: '',
  143. },
  144. });
  145. const handleSizeChange = (value: number) => {
  146. pagination.pageSize = value;
  147. tableQuery.pageSize = value;
  148. getTableData();
  149. };
  150. const handleCurrentChange = (value: number) => {
  151. pagination.pageNumber = value;
  152. tableQuery.pageNumber = value;
  153. getTableData();
  154. };
  155. const selectionItems = ref<any[]>([]);
  156. const handleSelectionChange = (selection: any[]) => {
  157. selectionItems.value = selection;
  158. };
  159. async function getTableData() {
  160. tableConfig.loading = true;
  161. try {
  162. const params: QuerySecurityExamineDeptParams = {
  163. pageNumber: tableQuery.pageNumber,
  164. pageSize: tableQuery.pageSize,
  165. queryParam: {
  166. exName: tableQuery.queryParam.evaluationTableName || undefined,
  167. status: tableQuery.queryParam.status !== undefined && tableQuery.queryParam.status !== null
  168. ? tableQuery.queryParam.status
  169. : undefined,
  170. deptName: undefined, // 部门名称(如果需要可以添加搜索条件)
  171. planStartTime: tableQuery.queryParam.startTime || undefined,
  172. planEndTime: tableQuery.queryParam.endTime || undefined,
  173. },
  174. };
  175. const res = await querySecurityExamineDept(params);
  176. if (res) {
  177. // 映射返回数据字段到表格字段
  178. tableData.value = res.records.map((item) => ({
  179. id: item.id,
  180. evaluationTableName: item.exName, // 考核表名称
  181. status: item.status, // 状态(使用数字状态码)
  182. statusName: item.statusName, // 状态名称
  183. evaluationDocument: item.attachments, // 考核文档
  184. plannedCompletionTime: item.planEndTime || '-', // 计划完成时间(使用计划结束时间)
  185. // 保留原始数据,供其他操作使用
  186. psemId: item.psemId,
  187. deptId: item.deptId,
  188. deptName: item.deptName,
  189. scores: item.scores,
  190. scoreRank: item.scoreRank,
  191. isAdvancedGroup: item.isAdvancedGroup,
  192. }));
  193. pagination.total = res.totalRow;
  194. }
  195. } catch (e) {
  196. console.error('获取部门考核列表失败:', e);
  197. tableData.value = [];
  198. pagination.total = 0;
  199. } finally {
  200. tableConfig.loading = false;
  201. }
  202. }
  203. const handleSearch = () => {
  204. // 处理日期范围
  205. if (tableQuery.queryParam.dateRange && tableQuery.queryParam.dateRange.length === 2) {
  206. tableQuery.queryParam.startTime = tableQuery.queryParam.dateRange[0];
  207. tableQuery.queryParam.endTime = tableQuery.queryParam.dateRange[1];
  208. } else {
  209. tableQuery.queryParam.startTime = '';
  210. tableQuery.queryParam.endTime = '';
  211. }
  212. pagination.pageNumber = 1;
  213. tableQuery.pageNumber = 1;
  214. getTableData();
  215. };
  216. const handleReset = () => {
  217. tableQuery.queryParam.evaluationTableName = '';
  218. tableQuery.queryParam.status = undefined;
  219. tableQuery.queryParam.dateRange = null;
  220. handleSearch();
  221. };
  222. const handleFeedback = (id: number) => {
  223. router.push({
  224. name: 'EvaluationDepartmentItem',
  225. query: {
  226. id,
  227. operate: 'evaluationDepartment-feedback',
  228. },
  229. });
  230. };
  231. const handleAdvancedPerson = (row: any) => {
  232. router.push({
  233. name: 'EvaluationDepartmentItem',
  234. query: {
  235. id: row.id,
  236. operate: 'evaluationDepartment-advanced-person',
  237. isAdvancedGroup: row.isAdvancedGroup,
  238. },
  239. });
  240. };
  241. // 预览
  242. const previewOnlineRef = ref<InstanceType<typeof PreviewOnline>>();
  243. const previewOnline = (url: string | undefined, type: keyof typeof FILE_TYPE_ICON) => {
  244. if (url) {
  245. previewOnlineRef.value?.open(url, type);
  246. }
  247. };
  248. // 解析逗号分隔的URL字符串为文件列表
  249. const parseAttachments = (attachmentsStr: string | undefined): Array<{
  250. fileUrl: string;
  251. fileName: string;
  252. fileType: string;
  253. }> => {
  254. if (!attachmentsStr || !attachmentsStr.trim()) {
  255. return [];
  256. }
  257. // 按逗号分割URL
  258. const urls = attachmentsStr.split(',').map(url => url.trim()).filter(url => url);
  259. return urls.map((url) => {
  260. // 从URL中提取文件名
  261. const urlParts = url.split('/');
  262. const fileName = urlParts[urlParts.length - 1] || '未知文件';
  263. // 根据文件扩展名判断文件类型
  264. const extension = fileName.split('.').pop()?.toLowerCase() || '';
  265. let fileType = 'pdf';
  266. if (extension === 'doc' || extension === 'docx') {
  267. fileType = 'word';
  268. } else if (extension === 'xls' || extension === 'xlsx') {
  269. fileType = 'excel';
  270. } else if (extension === 'ppt' || extension === 'pptx') {
  271. fileType = 'ppt';
  272. }
  273. return {
  274. fileUrl: url,
  275. fileName,
  276. fileType,
  277. };
  278. });
  279. };
  280. onMounted(() => {
  281. getTableData();
  282. });
  283. </script>
  284. <style scoped lang="scss">
  285. @use '@/styles/page-details-layout.scss' as *;
  286. @use '@/styles/page-main-layout.scss' as *;
  287. @use '@/styles/basic-table-action.scss' as *;
  288. @use '@/styles/basic-table-file.scss' as *;
  289. @use '@/views/traffic/violation/style/act-search-table.scss' as *;
  290. </style>