Notice.vue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  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. <SelectableInput ref="selectableInputRef" :options="ACT_TABLE_SEARCH_OPTIONS" />
  12. <div class="select-box--item">
  13. <span>违规类型:</span>
  14. <el-select
  15. v-model="searchData.violationType"
  16. placeholder="请选择违规类型"
  17. class="select-box--select"
  18. clearable
  19. >
  20. <el-option
  21. v-for="item in ACT_VIOLATION_TYPE_OPTIONS"
  22. :key="item.value"
  23. :value="item.value"
  24. :label="item.label"
  25. :disabled="item.disabled"
  26. />
  27. </el-select>
  28. </div>
  29. <div class="select-box--item">
  30. <span>通知状态:</span>
  31. <el-select
  32. v-model="searchData.isNotice"
  33. placeholder="请选择通知状态"
  34. class="select-box--select"
  35. clearable
  36. >
  37. <el-option
  38. v-for="item in ACT_NOTICE_STATE_OPTIONS"
  39. :key="item.value"
  40. :value="item.value"
  41. :label="item.label"
  42. :disabled="item.disabled"
  43. />
  44. </el-select>
  45. </div>
  46. <div>
  47. <span>时间:</span>
  48. <el-date-picker
  49. v-model="searchData.searchTime"
  50. type="datetimerange"
  51. range-separator="至"
  52. start-placeholder="开始时间"
  53. end-placeholder="结束时间"
  54. />
  55. </div>
  56. </section>
  57. <section class="search-btn">
  58. <el-button type="primary" @click="handleSearch">查询</el-button>
  59. <el-button @click="handleReset">重置</el-button>
  60. <el-button v-if="noticeManagementPermission" @click="handleDownload">导出</el-button>
  61. </section>
  62. </div>
  63. </header>
  64. <!-- 表格 -->
  65. <BasicTable
  66. :tableData="tableData"
  67. :tableConfig="tableConfig"
  68. @update:pageSize="handleSizeChange"
  69. @update:pageNumber="handleCurrentChange"
  70. >
  71. <template #violateType="scope">
  72. <span>{{ ACT_VIOLATION_TYPE_LABEL[scope.row.violateType] }}</span>
  73. </template>
  74. <template #capturePhotos="scope">
  75. <ImageViewer :file-list="scope.row.capturePhotos" />
  76. </template>
  77. <template #createSource="scope">
  78. <span>{{ ACT_NOTICE_DATA_SOURCE_LABEL[scope.row.createSource] }}</span>
  79. </template>
  80. <template #isNotice="scope">
  81. <div class="notice-state">
  82. <div
  83. :style="{
  84. backgroundColor: ACT_NOTICE_STATE_COLOR[scope.row.isNotice],
  85. width: '6px',
  86. height: '6px',
  87. borderRadius: '50%',
  88. marginRight: '5px',
  89. }"
  90. ></div>
  91. <span>{{ ACT_NOTICE_STATE_LABEL[scope.row.isNotice] }}</span>
  92. </div>
  93. </template>
  94. </BasicTable>
  95. </div>
  96. </main>
  97. </div>
  98. </template>
  99. <script setup lang="ts">
  100. import BasicTable from '@/components/BasicTable.vue';
  101. import useTableConfig from '@/hooks/useTableConfigHook';
  102. import SelectableInput from '@/components/formItems/selectableInput/SelectableInput.vue';
  103. import dayjs from 'dayjs';
  104. import { ElMessage } from 'element-plus';
  105. import { TABLE_OPTIONS, VIOLATION_NOTICE_TABLE_COLUMNS } from '../act/configs/tables';
  106. import {
  107. ACT_NOTICE_DATA_SOURCE_LABEL,
  108. ACT_VIOLATION_TYPE,
  109. ACT_VIOLATION_TYPE_LABEL,
  110. ACT_TABLE_SEARCH_OPTIONS,
  111. ACT_VIOLATION_TYPE_OPTIONS,
  112. ACT_NOTICE_STATE_OPTIONS,
  113. ACT_NOTICE_STATE,
  114. ACT_NOTICE_STATE_LABEL,
  115. ACT_NOTICE_STATE_COLOR,
  116. NOTICE_MANAGEMENT_PROMISSION_CODE,
  117. } from '../act/constants';
  118. import { ref, reactive, onMounted } from 'vue';
  119. import { useRouter } from 'vue-router';
  120. import type { QueryPageRequest } from '@/types/basic-query';
  121. import type { ActTableSearch, ActTableQuery, ActTableData } from '../act/types';
  122. import { getActTableList, exportActViolation } from '@/api/traffic-violation/traffic-act';
  123. import { downloadFile } from '@/views/disaster/utils/download';
  124. import ImageViewer from '../act/components/ImageViewer.vue';
  125. import { useUserInfoHook } from '@/hooks/useUserInfoHook';
  126. const { permissions } = useUserInfoHook();
  127. const noticeManagementPermission = ref<Boolean>(
  128. Boolean(permissions.find((item: { code: string }) => item.code === NOTICE_MANAGEMENT_PROMISSION_CODE)),
  129. );
  130. // 搜索栏
  131. const selectableInputRef = ref<InstanceType<typeof SelectableInput>>();
  132. const searchData = reactive<ActTableSearch>({});
  133. function getQuery() {
  134. if (!selectableInputRef.value) return;
  135. tabelQuery.queryParam = {
  136. pageType: 2,
  137. };
  138. const selectableSearch = selectableInputRef.value.getValue();
  139. if (selectableSearch) {
  140. tabelQuery.queryParam[selectableSearch.key as string] = selectableSearch.value;
  141. }
  142. if (searchData.isNotice) {
  143. tabelQuery.queryParam.isNotice = searchData.isNotice;
  144. }
  145. if (searchData.violationType) {
  146. tabelQuery.queryParam.violationType = searchData.violationType;
  147. }
  148. if (searchData.searchTime) {
  149. tabelQuery.queryParam.startTime = dayjs(searchData.searchTime[0]).format('YYYY-MM-DD HH:MM:ss');
  150. tabelQuery.queryParam.endTime = dayjs(searchData.searchTime[1]).format('YYYY-MM-DD HH:MM:ss');
  151. }
  152. }
  153. function handleSearch() {
  154. getQuery();
  155. getTableData();
  156. }
  157. function handleReset() {
  158. selectableInputRef.value?.clearValue();
  159. searchData.carNumber = undefined;
  160. searchData.violateName = undefined;
  161. searchData.deptName = undefined;
  162. searchData.violationType = undefined;
  163. searchData.searchTime = undefined;
  164. }
  165. async function handleDownload() {
  166. getQuery();
  167. try {
  168. const res = await exportActViolation(tabelQuery.queryParam);
  169. if (res.size === 0) return;
  170. const blob = new Blob([res], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
  171. const url = window.URL.createObjectURL(blob);
  172. downloadFile(url, '违规行为记录.xlsx');
  173. } catch (e) {
  174. ElMessage.error('下载失败');
  175. console.log(e);
  176. }
  177. }
  178. // 表格
  179. const basicTableRef = ref<InstanceType<typeof BasicTable>>();
  180. const { tableConfig, pagination } = useTableConfig(VIOLATION_NOTICE_TABLE_COLUMNS, TABLE_OPTIONS);
  181. const tableData = ref<ActTableData[]>([]);
  182. const tabelQuery = reactive<QueryPageRequest<ActTableQuery>>({
  183. pageNumber: pagination.pageNumber,
  184. pageSize: pagination.pageSize,
  185. queryParam: {
  186. pageType: 2,
  187. },
  188. });
  189. const handleSizeChange = (value: number) => {
  190. pagination.pageNumber = value;
  191. tabelQuery.pageSize = value;
  192. getTableData();
  193. };
  194. const handleCurrentChange = (value: number) => {
  195. pagination.pageNumber = value;
  196. tabelQuery.pageSize = value;
  197. getTableData();
  198. };
  199. async function getTableData() {
  200. tableConfig.loading = true;
  201. const res = await getActTableList(tabelQuery);
  202. tableData.value = res.records;
  203. pagination.total = res.totalRow;
  204. tableConfig.loading = false;
  205. }
  206. onMounted(async () => {
  207. await getTableData();
  208. });
  209. </script>
  210. <style scoped lang="scss">
  211. @use '@/styles/page-details-layout.scss' as *;
  212. @use '@/styles/page-main-layout.scss' as *;
  213. @use '@/styles/basic-table-action.scss' as *;
  214. .act-search-input {
  215. max-width: 500px;
  216. }
  217. .act-search {
  218. display: flex;
  219. align-items: center;
  220. justify-content: space-between;
  221. width: 100%;
  222. }
  223. .select-box {
  224. display: flex;
  225. align-items: center;
  226. flex-wrap: wrap;
  227. gap: 32px;
  228. &--item {
  229. @include flex-center;
  230. white-space: nowrap;
  231. }
  232. span {
  233. color: rgba(0, 0, 0, 0.85);
  234. font-size: 14px;
  235. }
  236. .el-select {
  237. width: 200px;
  238. }
  239. }
  240. .search-btn {
  241. display: flex;
  242. }
  243. .notice-state {
  244. display: flex;
  245. align-items: center;
  246. justify-self: center;
  247. }
  248. </style>