hazardList.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. <template>
  2. <view class="mainBox">
  3. <uni-nav-bar fixed statusBar left-icon="back" :title="navTitle" @clickLeft="back" />
  4. <!-- 搜索区域(仅保留隐患名称) -->
  5. <view class="top-wrapper">
  6. <input class="search-input" v-model="keyword" placeholder="请输入隐患名称" />
  7. <button class="search_btn" @click="handleSearch">搜索</button>
  8. </view>
  9. <view class="wrapper">
  10. <u-list @scrolltolower="scrolltolower" class="listContent">
  11. <view v-for="(item, idx) in tableList" :key="item.id" style="position: relative">
  12. <myCard
  13. :item="item"
  14. :index="idx + 1"
  15. :btnList="getBtnList(item)"
  16. :columns="cardColumns"
  17. :title="item.title"
  18. :status="getStatusLabel(item.status)"
  19. @goDetail="goDetail"
  20. @edit="handleEdit(item)"
  21. @handleFix="handleFix(item)"
  22. @handleVerify="handleVerify(item)"
  23. @handleDelete="handleDelete(item)"
  24. />
  25. </view>
  26. <view style="width: 100%; height: 40rpx"></view>
  27. <view style="margin-top: 20vh" v-if="tableList.length == 0">
  28. <u-empty iconSize="150" textSize="32" text="暂无数据" />
  29. </view>
  30. </u-list>
  31. </view>
  32. <!-- 新增按钮 -->
  33. <view class="add" @click="handleAdd">
  34. <u-icon name="plus" color="#fff"></u-icon>
  35. </view>
  36. <hazardDialog ref="hazardDialogRef" @reload="reloadList" />
  37. </view>
  38. </template>
  39. <script>
  40. import myCard from '@/components/myCard.vue';
  41. import hazardDialog from './hazardDialog.vue';
  42. import { getList, remove, checkAcceptor, checkRectifier } from '@/api/hazardManagement/index.js';
  43. export default {
  44. components: { myCard, hazardDialog },
  45. data() {
  46. return {
  47. keyword: '',
  48. tableList: [],
  49. page: 1,
  50. size: 10,
  51. isEnd: false,
  52. userInfo: {},
  53. cardColumns: [
  54. [{ prop: 'code', label: '隐患编号', className: 'perce100' }],
  55. [{ prop: 'deviceName', label: '设备名称', className: 'perce50' }, { prop: 'areaName', label: '区域', className: 'perce50' }],
  56. [{ prop: 'foundTime', label: '发现时间', className: 'perce100' }],
  57. [{ prop: 'fixUserName', label: '整改责任人', className: 'perce100' }],
  58. [{ prop: 'fixDeadline', label: '计划整改时限', className: 'perce100' }],
  59. [{ label: '操作', prop: 'action', type: 'action', className: 'perce100' }]
  60. ],
  61. statusOptions: [
  62. { value: 0, label: '待确认' },
  63. { value: 1, label: '待整改' },
  64. { value: 2, label: '整改中' },
  65. { value: 3, label: '待验收' },
  66. { value: 4, label: '已验收' },
  67. { value: 'CLOSED', label: '已关闭' }
  68. ]
  69. };
  70. },
  71. computed: {
  72. navTitle() { return '隐患管理'; }
  73. },
  74. created() {
  75. this.userInfo = uni.getStorageSync('userInfo') || {};
  76. this.getList();
  77. },
  78. methods: {
  79. back() { uni.navigateBack(); },
  80. // 按钮列表(根据状态动态生成)
  81. getBtnList(item) {
  82. const btns = [];
  83. if (this.canFix(item)) {
  84. btns.push({ name: '整改', apiName: 'handleFix', btnType: 'primary', judge: [{ fn: () => true }] });
  85. }
  86. if (this.canVerify(item)) {
  87. btns.push({ name: '验收', apiName: 'handleVerify', btnType: 'success', judge: [{ fn: () => true }] });
  88. }
  89. if (this.canEdit(item)) {
  90. btns.push({ name: '编辑', apiName: 'edit', btnType: 'primary', judge: [{ fn: () => true }] });
  91. }
  92. if (this.canDelete(item)) {
  93. btns.push({ name: '删除', apiName: 'handleDelete', btnType: 'danger', judge: [{ fn: () => true }] });
  94. }
  95. return btns;
  96. },
  97. canEdit(row) { return [0].includes(row.status); },
  98. canDelete(row) { return [0].includes(row.status); },
  99. canFix(row) { return [0, 1, 2].includes(row.status); },
  100. canVerify(row) { return [3].includes(row.status); },
  101. getStatusLabel(status) {
  102. const item = this.statusOptions.find(opt => opt.value == status);
  103. return item ? item.label : status;
  104. },
  105. // 列表操作
  106. goDetail(item) {
  107. this.$refs.hazardDialogRef.open('view', item);
  108. },
  109. handleAdd() {
  110. this.$refs.hazardDialogRef.open('add');
  111. },
  112. handleEdit(item) {
  113. this.$refs.hazardDialogRef.open('edit', item);
  114. },
  115. async handleFix(item) {
  116. try {
  117. const data = await checkRectifier(item.id);
  118. if (!data.isRectifier) {
  119. uni.showToast({ title: '您不是整改责任人', icon: 'none' });
  120. return;
  121. }
  122. this.$refs.hazardDialogRef.open('fix', item, 'fix');
  123. } catch (e) {
  124. console.error(e);
  125. }
  126. },
  127. async handleVerify(item) {
  128. try {
  129. const data = await checkAcceptor(item.id);
  130. if (!data.isAcceptor) {
  131. uni.showToast({ title: '您不是验收人', icon: 'none' });
  132. return;
  133. }
  134. this.$refs.hazardDialogRef.open('verify', item, 'verify');
  135. } catch (e) {
  136. console.error(e);
  137. }
  138. },
  139. async handleDelete(item) {
  140. const res = await uni.showModal({
  141. title: '提示',
  142. content: `确认删除隐患「${item.title}」吗?`
  143. });
  144. if (res.confirm) {
  145. try {
  146. await remove([item.id]);
  147. uni.showToast({ title: '删除成功', icon: 'success' });
  148. this.reloadList();
  149. } catch (e) {
  150. console.error(e);
  151. }
  152. }
  153. },
  154. // 数据加载
  155. reloadList() {
  156. this.page = 1;
  157. this.isEnd = false;
  158. this.getList();
  159. },
  160. handleSearch() {
  161. this.page = 1;
  162. this.isEnd = false;
  163. this.getList();
  164. },
  165. async getList() {
  166. if (this.isEnd) return;
  167. uni.showLoading({ title: '加载中' });
  168. try {
  169. const params = {
  170. pageNum: this.page,
  171. size: this.size,
  172. title: this.keyword || undefined
  173. };
  174. const res = await getList(params);
  175. const list = res.list || [];
  176. if (this.page === 1) this.tableList = list;
  177. else this.tableList.push(...list);
  178. this.isEnd = list.length < this.size || this.tableList.length >= res.count;
  179. this.page += 1;
  180. } catch (e) {
  181. console.error(e);
  182. } finally {
  183. uni.hideLoading();
  184. }
  185. },
  186. scrolltolower() {
  187. if (!this.isEnd) this.getList();
  188. }
  189. }
  190. };
  191. </script>
  192. <style lang="scss" scoped>
  193. @import "../common-style.scss";
  194. .top-wrapper {
  195. background: #fff;
  196. padding: 20rpx 32rpx;
  197. display: flex;
  198. align-items: center;
  199. border-bottom: 2rpx solid #eee;
  200. .search-input {
  201. flex: 1;
  202. height: 70rpx;
  203. border: 2rpx solid #e9edf2;
  204. border-radius: 48rpx;
  205. padding: 0 24rpx;
  206. font-size: 28rpx;
  207. background: #fafafa;
  208. }
  209. .search_btn {
  210. width: 140rpx;
  211. height: 70rpx;
  212. line-height: 70rpx;
  213. background: $theme-color;
  214. font-size: 28rpx;
  215. color: #fff;
  216. margin-left: 20rpx;
  217. border-radius: 48rpx;
  218. text-align: center;
  219. }
  220. }
  221. </style>