index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. <template>
  2. <div class="ele-body">
  3. <el-card shadow="never">
  4. <div>
  5. <!-- 搜索区域 -->
  6. <div class="search-area">
  7. <seek-page
  8. ref="seekPage"
  9. :seekList="seekList"
  10. @search="handleSearch"
  11. :formLength="4"
  12. />
  13. </div>
  14. <!-- 列表视图 -->
  15. <div class="list-view">
  16. <ele-pro-table
  17. ref="table"
  18. row-key="id"
  19. :columns="columns"
  20. :datasource="datasource"
  21. :cache-key="cacheKeyUrl"
  22. height="calc(100vh - 320px)"
  23. @columns-change="handleColumnChange"
  24. @selection-change="handleSelectionChange"
  25. >
  26. <template v-slot:toolbar>
  27. <div class="toolbar-left">
  28. <el-button
  29. type="primary"
  30. size="small"
  31. icon="el-icon-plus"
  32. @click="handleAdd"
  33. >新增</el-button
  34. >
  35. <el-button
  36. type="danger"
  37. size="small"
  38. icon="el-icon-delete"
  39. :disabled="!selectedRows.length"
  40. @click="handleBatchDelete"
  41. >批量删除</el-button
  42. >
  43. </div>
  44. </template>
  45. <template v-slot:ticketCount="{ row }">
  46. <span>{{ row.ticketList?.length || '-' }}</span>
  47. </template>
  48. <template v-slot:action="{ row }">
  49. <div class="action-links">
  50. <el-link
  51. type="primary"
  52. :underline="false"
  53. @click="handleWorkTicket(row)"
  54. >作业票管理</el-link
  55. >
  56. <el-link
  57. type="primary"
  58. :underline="false"
  59. @click="handleView(row)"
  60. >查看</el-link
  61. >
  62. <el-link
  63. type="primary"
  64. :underline="false"
  65. @click="handleEdit(row)"
  66. >编辑</el-link
  67. >
  68. <el-link
  69. type="danger"
  70. :underline="false"
  71. @click="handleDelete(row)"
  72. >删除</el-link
  73. >
  74. </div>
  75. </template>
  76. </ele-pro-table>
  77. </div>
  78. <!-- 新增/编辑弹窗 -->
  79. <add ref="dialogRef" @reload="$refs.table.reload()" />
  80. <!-- 作业票管理弹窗 -->
  81. <work-ticket-dialog ref="ticketDialogRef" />
  82. </div>
  83. </el-card>
  84. </div>
  85. </template>
  86. <script>
  87. import add from './add.vue';
  88. import WorkTicketDialog from '@/views/DangerousWorkList/workTicketDialog.vue';
  89. import tabMixins from '@/mixins/tableColumnsMixin';
  90. import { page as getPage, remove, toSortParams } from '@/api/dangerousWork';
  91. export default {
  92. components: {
  93. add,
  94. WorkTicketDialog
  95. },
  96. mixins: [tabMixins],
  97. data() {
  98. return {
  99. // 表格选中的数据
  100. selectedRows: [],
  101. // 表格列配置
  102. columns: [
  103. {
  104. columnKey: 'selection',
  105. type: 'selection',
  106. width: 50,
  107. align: 'center',
  108. reserveSelection: true,
  109. fixed: 'left'
  110. },
  111. {
  112. columnKey: 'index',
  113. label: '序号',
  114. type: 'index',
  115. width: 60,
  116. align: 'center'
  117. },
  118. {
  119. prop: 'workCode',
  120. label: '作业编码',
  121. align: 'center',
  122. minWidth: 180,
  123. showOverflowTooltip: true
  124. },
  125. {
  126. prop: 'workName',
  127. label: '作业名称',
  128. align: 'center',
  129. minWidth: 180,
  130. showOverflowTooltip: true
  131. },
  132. {
  133. prop: 'applyDeptName',
  134. label: '申请单位',
  135. align: 'center',
  136. minWidth: 120
  137. },
  138. {
  139. prop: 'applicantName',
  140. label: '申请人',
  141. align: 'center',
  142. minWidth: 120,
  143. showOverflowTooltip: true
  144. },
  145. {
  146. prop: 'workLocation',
  147. label: '作业地点',
  148. align: 'center',
  149. minWidth: 150,
  150. showOverflowTooltip: true
  151. },
  152. {
  153. prop: 'startTime',
  154. label: '作业开始时间',
  155. align: 'center',
  156. minWidth: 160,
  157. sortable: true
  158. },
  159. {
  160. prop: 'endTime',
  161. label: '作业结束时间',
  162. align: 'center',
  163. minWidth: 160,
  164. sortable: true
  165. },
  166. {
  167. columnKey: 'action',
  168. label: '操作',
  169. width: 260,
  170. align: 'center',
  171. slot: 'action'
  172. }
  173. ],
  174. cacheKeyUrl: 'ehs-dangerousWork-list',
  175. // 是否已完成首次初始化(keep-alive 首次进入不重置,避免重复请求)
  176. inited: false
  177. };
  178. },
  179. computed: {
  180. seekList() {
  181. return [
  182. {
  183. label: '作业名称:',
  184. value: 'workName',
  185. type: 'input',
  186. width: 220,
  187. placeholder: '请输入作业名称'
  188. },
  189. {
  190. label: '作业编码:',
  191. value: 'workCode',
  192. type: 'input',
  193. width: 220,
  194. placeholder: '请输入作业编码'
  195. },
  196. {
  197. label: '申请人:',
  198. value: 'applicantName',
  199. type: 'input',
  200. width: 220,
  201. placeholder: '请输入申请人'
  202. },
  203. {
  204. label: '申请单位:',
  205. value: 'applyDeptId',
  206. type: 'deptSelect',
  207. width: 240,
  208. placeholder: '请选择申请单位'
  209. },
  210. {
  211. label: '作业开始时间:',
  212. value: 'startTime',
  213. type: 'date',
  214. dateType: 'datetimerange',
  215. width: 360,
  216. valueAr: ['startTimeBegin', 'startTimeEnd'],
  217. placeholder: '请选择作业开始时间'
  218. }
  219. ];
  220. }
  221. },
  222. mounted() {},
  223. // 每次进入菜单都回到初始值:页码第一页、搜索条件清空
  224. activated() {
  225. if (!this.inited) {
  226. this.inited = true;
  227. return;
  228. }
  229. this.resetSearch();
  230. },
  231. methods: {
  232. // 重置为初始值(页码、搜索条件、选中项)
  233. resetSearch() {
  234. this.clearSelection();
  235. if (this.$refs.seekPage) {
  236. // seek-page 的 reset 会清空条件并触发 search -> reload({ page: 1 })
  237. this.$refs.seekPage.reset();
  238. } else {
  239. this.$refs.table.reload({ page: 1, where: {} });
  240. }
  241. },
  242. // 作业票管理
  243. handleWorkTicket(row) {
  244. this.$refs.ticketDialogRef.open(row);
  245. },
  246. // 新增危险作业
  247. handleAdd() {
  248. this.$refs.dialogRef.open();
  249. },
  250. // 编辑
  251. handleEdit(row) {
  252. this.$refs.dialogRef.open(row, 'edit');
  253. },
  254. // 查看
  255. handleView(row) {
  256. this.$refs.dialogRef.open(row, 'view');
  257. },
  258. // 删除
  259. handleDelete(row) {
  260. this.$confirm(
  261. '确认删除吗?删除后该危险作业下的作业票将一并删除。',
  262. '提示',
  263. {
  264. confirmButtonText: '确定',
  265. cancelButtonText: '取消',
  266. type: 'warning'
  267. }
  268. )
  269. .then(() => {
  270. remove([row.id]).then(() => {
  271. this.$message.success('删除成功');
  272. this.clearSelection();
  273. this.$refs.table.reload();
  274. });
  275. })
  276. .catch(() => {});
  277. },
  278. // 多选
  279. handleSelectionChange(rows) {
  280. this.selectedRows = rows || [];
  281. },
  282. // 清空选中项
  283. clearSelection() {
  284. this.selectedRows = [];
  285. this.$refs.table && this.$refs.table.clearSelection();
  286. },
  287. // 批量删除
  288. handleBatchDelete() {
  289. const ids = this.selectedRows.map((row) => row.id);
  290. if (!ids.length) {
  291. this.$message.warning('请至少选择一条数据');
  292. return;
  293. }
  294. this.$confirm(
  295. `确认删除选中的 ${ids.length} 条危险作业吗?其下作业票将一并删除。`,
  296. '提示',
  297. {
  298. confirmButtonText: '确定',
  299. cancelButtonText: '取消',
  300. type: 'warning'
  301. }
  302. )
  303. .then(() => {
  304. remove(ids).then(() => {
  305. this.$message.success('删除成功');
  306. this.clearSelection();
  307. this.$refs.table.reload({ page: 1 });
  308. });
  309. })
  310. .catch(() => {});
  311. },
  312. // 搜索
  313. handleSearch(where) {
  314. this.$refs.table.reload({ page: 1, where });
  315. },
  316. // 表格数据源
  317. async datasource({ page, limit, where, order }) {
  318. const body = {
  319. ...where,
  320. ...toSortParams(order),
  321. pageNum: page,
  322. size: limit
  323. };
  324. // 去掉未填写的查询条件,避免空字符串传给后端类型转换报错
  325. Object.keys(body).forEach((key) => {
  326. if (
  327. body[key] === '' ||
  328. body[key] === null ||
  329. body[key] === undefined
  330. ) {
  331. delete body[key];
  332. }
  333. });
  334. return await getPage(body);
  335. }
  336. }
  337. };
  338. </script>
  339. <style lang="scss" scoped>
  340. .major-hazard-monitoring {
  341. padding: 15px;
  342. background-color: #f0f2f5;
  343. .full-height {
  344. height: 100%;
  345. }
  346. .tree-col,
  347. .table-col {
  348. height: 100%;
  349. }
  350. // 左侧树形卡片
  351. .tree-card {
  352. height: 100%;
  353. ::v-deep .el-card__body {
  354. height: 100%;
  355. padding: 0;
  356. display: flex;
  357. flex-direction: column;
  358. }
  359. .tree-title {
  360. padding: 15px;
  361. font-weight: bold;
  362. font-size: 14px;
  363. border-bottom: 1px solid #ebeef5;
  364. background-color: #fff;
  365. }
  366. .tree-content {
  367. flex: 1;
  368. overflow: auto;
  369. padding: 10px;
  370. ::v-deep .el-tree {
  371. .el-tree-node__content {
  372. height: 32px;
  373. line-height: 32px;
  374. }
  375. .el-tree-node.is-current > .el-tree-node__content {
  376. background-color: #f5f7fa;
  377. color: #409eff;
  378. }
  379. }
  380. }
  381. }
  382. // 右侧表格卡片
  383. .table-card {
  384. height: 100%;
  385. ::v-deep .el-card__body {
  386. height: 100%;
  387. padding: 15px;
  388. display: flex;
  389. flex-direction: column;
  390. }
  391. }
  392. // 搜索区域
  393. .search-area {
  394. margin-bottom: 15px;
  395. padding-bottom: 15px;
  396. border-bottom: 1px solid #ebeef5;
  397. }
  398. // 列表视图
  399. .list-view {
  400. flex: 1;
  401. overflow: hidden;
  402. ::v-deep .ele-pro-table {
  403. .el-table {
  404. border: 1px solid #ebeef5;
  405. border-radius: 4px;
  406. }
  407. }
  408. }
  409. // 工具栏
  410. ::v-deep .ele-pro-table .ele-pro-table-toolbar {
  411. display: flex;
  412. justify-content: space-between;
  413. align-items: center;
  414. }
  415. // 操作链接
  416. .action-links {
  417. display: flex;
  418. flex-wrap: wrap;
  419. justify-content: center;
  420. gap: 8px;
  421. .el-link {
  422. font-size: 12px;
  423. }
  424. }
  425. }
  426. </style>