Default.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. <template>
  2. <div class="box">
  3. <div style="margin-bottom: 10px; display: flex" v-if="hasDevModePermisson()">
  4. <div style="line-height: 33px">预审后生效模式:</div>
  5. <el-switch :model-value="devMode" @change="switchDevMode" />
  6. </div>
  7. <div class="search-form">
  8. <QueryForm
  9. :is-show-tab="false"
  10. :ai-options="aiMainOptions"
  11. :manual-options="manualMainOptions"
  12. :location-options="locationOptions"
  13. @on-search="handleSearch"
  14. @on-reset="handleReset"
  15. @on-export="handleExport"
  16. />
  17. </div>
  18. <div class="table-list">
  19. <div v-if="showActionBar" class="action-bar">
  20. <span class="num-text">已选{{ chooseNum }}项</span>
  21. <el-button
  22. :class="isActiveCancelHide ? 'btn-active' : 'btn-normal'"
  23. @click="handleCancelHideAll"
  24. >全部生效</el-button
  25. >
  26. <el-button :class="isActiveHide ? 'btn-active' : 'btn-normal'" @click="handleHideAll"
  27. >全部失效</el-button
  28. >
  29. <el-button :class="isActiveDelete ? 'btn-active' : 'btn-normal'" @click="handleDeleteAll"
  30. >删除</el-button
  31. >
  32. <el-button
  33. v-if="!cancelUrgentFlag"
  34. :class="isActiveUrgent ? 'btn-active' : 'btn-normal'"
  35. @click="handleUrgentAll"
  36. >标记加急</el-button
  37. >
  38. <el-button
  39. v-if="cancelUrgentFlag"
  40. :class="isActiveCancelUrgent ? 'btn-active' : 'btn-normal'"
  41. @click="handleCancelUrgentAll"
  42. >取消加急</el-button
  43. >
  44. <el-button
  45. v-if="hasPermisson()"
  46. :class="isActiveCopy ? 'btn-active' : 'btn-normal'"
  47. @click="handleCopyToShow"
  48. >复制到展示数据</el-button
  49. >
  50. <span class="close-btn" @click="handleSelectNone"></span>
  51. </div>
  52. <AlertTable
  53. ref="alertTableRef"
  54. class="table-bar"
  55. :is-show-tab="false"
  56. :table-data="tableData"
  57. :on-detail="handleDetail"
  58. :on-urgent="handleUrgent"
  59. :on-show="handleShow"
  60. :on-delete="handleDelete"
  61. @update:selection="handlePop"
  62. />
  63. </div>
  64. <div class="pagination-box">
  65. <Pagination
  66. v-model:page="query.pageNumber"
  67. v-model:size="query.pageSize"
  68. :total="total"
  69. @update:page="handlePageChange"
  70. @update:size="handleSizeChange"
  71. />
  72. </div>
  73. <DetailDialog
  74. v-if="isDetailDialogShow"
  75. :description="detailDescription"
  76. :image-paths="detailPictures"
  77. :video-paths="detailVideos"
  78. @close="closeDetailDialog"
  79. />
  80. </div>
  81. </template>
  82. <script setup lang="ts">
  83. import { ref, onMounted, onBeforeMount } from 'vue';
  84. import { ElMessage, ElMessageBox } from 'element-plus';
  85. import axios, { AxiosRequestConfig } from 'axios';
  86. import QueryForm from '../common/QueryForm.vue';
  87. import AlertTable from '../common/AlertTable.vue';
  88. import DetailDialog from '../common/DetailDialog.vue';
  89. import Pagination from '../common/Pagination.vue';
  90. // import { useIssueType } from '../../hooks/useIssueType';
  91. import { useWorkLocation } from '../../hooks/useWorkLocation';
  92. import { useIssueMainType } from '../../hooks/useIssueMainType';
  93. import {
  94. getDefaultTableData,
  95. deleteDefaultTableData,
  96. copyToShowTableData,
  97. updateDefaultHide,
  98. updateDefaultHideAll,
  99. updateDefaultPriority,
  100. updateDefaultPriorityAll,
  101. } from '@/api/datamanagement/alert-default';
  102. import { getDevMode, switchDevMode as SDM } from '@/api/datamanagement/getDevMode';
  103. import { useUserStore } from '@/store/modules/user';
  104. import { useGlobSetting } from '@/hooks/setting';
  105. const userStore = useUserStore();
  106. // const { aiOptions, manualOptions, getAIOptions, getManualOptions } = useIssueType();
  107. const { locationOptions, getLocationOptions } = useWorkLocation();
  108. const { aiMainOptions, manualMainOptions, getAIMainOptions, getManualMainOptions } =
  109. useIssueMainType();
  110. const headers = {
  111. Satoken: userStore.getToken,
  112. Tenantid: userStore.getTenantId,
  113. };
  114. const { urlPrefix } = useGlobSetting();
  115. const alertTableRef = ref<typeof AlertTable>();
  116. const tableData = ref([]);
  117. const showActionBar = ref(false);
  118. const chooseNum = ref(0);
  119. const chooseId = ref<number[]>([]);
  120. // const cancelHideFlag = ref(true); // true取消隐藏 / false全部隐藏
  121. const cancelUrgentFlag = ref(true); // true取消加急 / false全部加急
  122. const isActiveHide = ref(false);
  123. const isActiveCancelHide = ref(false);
  124. const isActiveDelete = ref(false);
  125. const isActiveUrgent = ref(false);
  126. const isActiveCancelUrgent = ref(false);
  127. const isActiveCopy = ref(false);
  128. // 详情
  129. const isDetailDialogShow = ref(false);
  130. const detailDescription = ref('');
  131. const detailPictures = ref<string[]>([]);
  132. const detailVideos = ref<string[]>([]);
  133. // 分页
  134. const total = ref(0);
  135. const query = ref({
  136. pageNumber: 1,
  137. pageSize: 10,
  138. });
  139. // 查询
  140. const handleSearch = (queryForm) => {
  141. query.value = queryForm;
  142. getTableData();
  143. };
  144. // 重置
  145. const handleReset = (queryForm) => {
  146. query.value = queryForm;
  147. getTableData();
  148. };
  149. // 导出
  150. const handleExport = async (queryForm, workShop) => {
  151. const tempWorkShopIds = ref<number[]>([]);
  152. if (workShop.length === 0) {
  153. locationOptions.value.forEach((item) => {
  154. tempWorkShopIds.value.push(item.value);
  155. });
  156. } else {
  157. tempWorkShopIds.value = workShop;
  158. }
  159. try {
  160. const now = new Date();
  161. const year = now.getFullYear();
  162. const month = String(now.getMonth() + 1).padStart(2, '0');
  163. const day = String(now.getDate()).padStart(2, '0');
  164. const currentDate = `${year}${month}${day}`;
  165. const requestBody = {
  166. endTime: queryForm.endTime,
  167. fileName: '',
  168. isExportHidden: true,
  169. startTime: queryForm.startTime,
  170. workshopIds: tempWorkShopIds.value,
  171. };
  172. const config: AxiosRequestConfig = {
  173. headers,
  174. responseType: 'blob',
  175. };
  176. const response = await axios.post(urlPrefix + '/issue/export', requestBody, config);
  177. const blob = new Blob([response.data], {
  178. type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  179. });
  180. // 创建下载链接
  181. let downloadLink: HTMLAnchorElement | null = document.createElement('a');
  182. const url = window.URL.createObjectURL(blob);
  183. downloadLink.href = url;
  184. downloadLink.download = `安全违规问题数据统计表${currentDate}.xlsx`;
  185. downloadLink.click();
  186. // 移除下载链接
  187. window.URL.revokeObjectURL(url);
  188. downloadLink = null;
  189. } catch (error) {
  190. console.error('Error downloading file:', error);
  191. }
  192. };
  193. // 多选
  194. const handlePop = (selection) => {
  195. chooseId.value = [];
  196. // cancelHideFlag.value = true;
  197. cancelUrgentFlag.value = true;
  198. selection.forEach((item) => {
  199. if (chooseId.value.indexOf(item.id) === -1) chooseId.value.push(item.id);
  200. // 只要有一个item.isHide === false 说明多选的这些选项不是全都隐藏/失效,不用变成“取消隐藏”/全部生效
  201. // if (item.isHide === false) cancelHideFlag.value = false;
  202. // 只要有一个item.priority === 0 说明不是全都加急状态,不用变成“取消加急”
  203. if (item.priority === 0) cancelUrgentFlag.value = false;
  204. });
  205. chooseNum.value = selection.length;
  206. showActionBar.value = chooseNum.value > 0 ? true : false;
  207. };
  208. // 取消多选
  209. const handleSelectNone = () => {
  210. chooseId.value = [];
  211. chooseNum.value = 0;
  212. alertTableRef.value?.clearAll();
  213. showActionBar.value = false;
  214. };
  215. // 全部隐藏
  216. const handleHideAll = () => {
  217. if (showActionBar.value) isActiveHide.value = !isActiveHide.value;
  218. const updateList = {
  219. ids: chooseId.value,
  220. hide: true,
  221. };
  222. updateDefaultHideAll(updateList).then(() => {
  223. handleSelectNone();
  224. getTableData();
  225. ElMessage({
  226. message: '操作成功',
  227. type: 'success',
  228. });
  229. setTimeout(function () {
  230. isActiveHide.value = !isActiveHide.value;
  231. }, 1000);
  232. });
  233. };
  234. // 取消隐藏
  235. const handleCancelHideAll = () => {
  236. if (showActionBar.value) isActiveCancelHide.value = !isActiveCancelHide.value;
  237. const updateList = {
  238. ids: chooseId.value,
  239. hide: false,
  240. };
  241. updateDefaultHideAll(updateList).then(() => {
  242. handleSelectNone();
  243. getTableData();
  244. ElMessage({
  245. message: '操作成功',
  246. type: 'success',
  247. });
  248. setTimeout(function () {
  249. isActiveCancelHide.value = !isActiveCancelHide.value;
  250. }, 1000);
  251. });
  252. };
  253. // 批量删除
  254. const handleDeleteAll = () => {
  255. if (showActionBar.value) isActiveDelete.value = !isActiveDelete.value;
  256. ElMessageBox.confirm('删除之后,数据无法恢复', '请确认是否删除数据', {
  257. confirmButtonText: '确定',
  258. cancelButtonText: '取消',
  259. type: 'warning',
  260. customClass: 'deleteMessage',
  261. center: true,
  262. })
  263. .then(() => {
  264. deleteDefaultTableData(chooseId.value).then(() => {
  265. ElMessage({
  266. type: 'success',
  267. message: '删除成功',
  268. });
  269. getTableData();
  270. handleSelectNone();
  271. isActiveDelete.value = !isActiveDelete.value;
  272. });
  273. })
  274. .catch(() => {
  275. ElMessage({
  276. type: 'info',
  277. message: '取消删除',
  278. });
  279. isActiveDelete.value = !isActiveDelete.value;
  280. });
  281. };
  282. // 标记加急,设置priority = 1
  283. const handleUrgentAll = () => {
  284. if (showActionBar.value) isActiveUrgent.value = !isActiveUrgent.value;
  285. const updateList = {
  286. ids: chooseId.value,
  287. priority: 1,
  288. };
  289. updateDefaultPriorityAll(updateList).then(() => {
  290. handleSelectNone();
  291. getTableData();
  292. ElMessage({
  293. message: '已加急',
  294. type: 'success',
  295. });
  296. setTimeout(function () {
  297. isActiveUrgent.value = !isActiveUrgent.value;
  298. }, 1000);
  299. });
  300. };
  301. // 取消加急
  302. const handleCancelUrgentAll = () => {
  303. if (showActionBar.value) isActiveCancelUrgent.value = !isActiveCancelUrgent.value;
  304. const updateList = {
  305. ids: chooseId.value,
  306. priority: 0,
  307. };
  308. updateDefaultPriorityAll(updateList).then(() => {
  309. handleSelectNone();
  310. getTableData();
  311. ElMessage({
  312. message: '已取消加急',
  313. type: 'success',
  314. });
  315. setTimeout(function () {
  316. isActiveCancelUrgent.value = !isActiveCancelUrgent.value;
  317. }, 1000);
  318. });
  319. };
  320. // 复制到展示数据
  321. const handleCopyToShow = () => {
  322. if (showActionBar.value) isActiveCopy.value = !isActiveCopy.value;
  323. copyToShowTableData(chooseId.value).then(() => {
  324. ElMessage({
  325. message: '复制成功',
  326. type: 'success',
  327. });
  328. setTimeout(function () {
  329. isActiveCopy.value = !isActiveCopy.value;
  330. }, 1000);
  331. handleSelectNone();
  332. });
  333. };
  334. // 详情
  335. const closeDetailDialog = () => {
  336. isDetailDialogShow.value = false;
  337. };
  338. const handleDetail = (row) => {
  339. isDetailDialogShow.value = true;
  340. detailDescription.value = row.description;
  341. detailPictures.value = row.pictures;
  342. detailVideos.value = row.videos;
  343. };
  344. // 单个加急priority=1/取消加急priority=0
  345. const handleUrgent = (row) => {
  346. const tempPriority = row.priority === 0 ? 1 : 0;
  347. const updateList = {
  348. id: row.id,
  349. priority: tempPriority,
  350. };
  351. updateDefaultPriority(updateList).then(() => {
  352. getTableData();
  353. });
  354. };
  355. // 单个显示hide=false/隐藏hide=true
  356. const handleShow = (row) => {
  357. const tempHide = row.isHide === false ? true : false;
  358. const updateList = {
  359. id: row.id,
  360. hide: tempHide,
  361. };
  362. updateDefaultHide(updateList).then(() => {
  363. getTableData();
  364. });
  365. };
  366. // 删除
  367. const handleDelete = (row) => {
  368. ElMessageBox.confirm('删除之后,数据无法恢复', '请确认是否删除数据', {
  369. confirmButtonText: '确定',
  370. cancelButtonText: '取消',
  371. type: 'warning',
  372. customClass: 'deleteMessage',
  373. center: true,
  374. })
  375. .then(() => {
  376. deleteDefaultTableData([row.id]).then(() => {
  377. ElMessage({
  378. type: 'success',
  379. message: '删除成功',
  380. });
  381. getTableData();
  382. });
  383. })
  384. .catch(() => {
  385. ElMessage({
  386. type: 'info',
  387. message: '取消删除',
  388. });
  389. });
  390. };
  391. // 换页,重新获取表格
  392. const handlePageChange = (val) => {
  393. query.value.pageNumber = val;
  394. getTableData();
  395. };
  396. const handleSizeChange = (val) => {
  397. query.value.pageSize = val;
  398. getTableData();
  399. };
  400. const getTableData = () => {
  401. getDefaultTableData(query.value).then((res) => {
  402. console.log(res);
  403. tableData.value = res.records;
  404. total.value = res.totalRow;
  405. });
  406. };
  407. const hasPermisson = () => {
  408. return userStore.checkPermission('question_mock_edit_admin');
  409. };
  410. onMounted(() => {
  411. getTableData();
  412. });
  413. const devMode = ref(true);
  414. getDevMode().then((res) => {
  415. devMode.value = res;
  416. });
  417. const switchDevMode = () => {
  418. SDM();
  419. devMode.value = !devMode.value;
  420. };
  421. const hasDevModePermisson = () => {
  422. return userStore.checkPermission('control_activation');
  423. };
  424. onBeforeMount(() => {
  425. // getAIOptions();
  426. // getManualOptions();
  427. getLocationOptions();
  428. getAIMainOptions();
  429. getManualMainOptions();
  430. });
  431. </script>
  432. <style scoped lang="scss">
  433. .box {
  434. display: flex;
  435. flex-direction: column;
  436. }
  437. .table-list {
  438. flex: 1;
  439. // height: calc(100vh - 350px);
  440. // overflow-y: scroll;
  441. .action-bar {
  442. display: flex;
  443. align-items: center;
  444. position: absolute;
  445. min-width: calc(100vw - 266px);
  446. height: 50px;
  447. border-radius: 4px 4px 0px 0px;
  448. background-color: #ddefff;
  449. z-index: 10;
  450. .num-text {
  451. margin: 0 34px 0 25px;
  452. color: rgba(0, 0, 0, 0.85);
  453. font-weight: 500;
  454. }
  455. .btn-normal {
  456. color: #1890ff;
  457. background: transparent;
  458. border: 1px solid #1890ff;
  459. border-radius: 2px;
  460. }
  461. .btn-active {
  462. color: #ffffff;
  463. background-color: #1890ff;
  464. }
  465. .close-btn {
  466. margin-left: auto;
  467. margin-right: 20px;
  468. }
  469. .close-btn:before {
  470. content: '\2716';
  471. color: #000;
  472. cursor: pointer;
  473. }
  474. }
  475. .table-bar {
  476. position: relative;
  477. }
  478. }
  479. .pagination-box {
  480. height: 50px;
  481. margin-top: 10px;
  482. }
  483. </style>
  484. <style lang="scss">
  485. .deleteMessage {
  486. padding: 20px 24px;
  487. box-shadow: 0px 12px 48px 16px rgba(0, 0, 0, 0.03), 0px 9px 28px 0px rgba(0, 0, 0, 0.05),
  488. 0px 6px 16px -8px rgba(0, 0, 0, 0.08);
  489. border-radius: 8px;
  490. .el-message-box__headerbtn {
  491. margin-top: 12px;
  492. margin-right: 12px;
  493. }
  494. .el-message-box__title {
  495. justify-content: start;
  496. color: rgba(0, 0, 0, 0.88);
  497. font-size: 16px;
  498. font-weight: 500;
  499. }
  500. .el-message-box__container {
  501. justify-content: start;
  502. margin-left: 23px;
  503. }
  504. .el-message-box__btns {
  505. display: block;
  506. float: right;
  507. }
  508. }
  509. </style>