drillOrderSelect.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. <template>
  2. <u-popup
  3. :show="visible"
  4. mode="bottom"
  5. :round="10"
  6. :closeOnClickOverlay="false"
  7. @close="cancel"
  8. class="drill-select-popup"
  9. >
  10. <view class="popup-content">
  11. <view class="popup-header"
  12. ><text class="popup-title">选择应急演练工单</text
  13. ><view class="close-btn" @click="cancel">×</view></view
  14. >
  15. <view class="search-row">
  16. <input
  17. class="search-input"
  18. v-model="searchKey"
  19. placeholder="请输入演练名称"
  20. />
  21. <button class="search-btn" @click="reload">搜索</button>
  22. </view>
  23. <scroll-view class="popup-body" scroll-y @scrolltolower="loadMore">
  24. <view
  25. v-for="(item, idx) in listData"
  26. :key="item.id"
  27. class="card-wrapper"
  28. @click="selectItem(item)"
  29. >
  30. <myCard
  31. :item="item"
  32. :index="idx + 1"
  33. :columns="cardColumns"
  34. :title="item.name"
  35. :showRadio="true"
  36. :radioValue="selectedId"
  37. @radioChange="selectItem"
  38. />
  39. </view>
  40. <view style="height: 20rpx"></view>
  41. <view v-if="loading" class="load-more">加载中...</view>
  42. <view v-if="isEnd && listData.length > 0" class="load-more"
  43. >没有更多了</view
  44. >
  45. <u-empty v-if="!loading && listData.length === 0" text="暂无工单" />
  46. </scroll-view>
  47. <view class="popup-footer">
  48. <u-button type="default" @click="cancel">取消</u-button>
  49. <u-button type="primary" :disabled="!selectedRow" @click="confirm"
  50. >确定</u-button
  51. >
  52. </view>
  53. </view>
  54. <u-toast ref="uToast" />
  55. </u-popup>
  56. </template>
  57. <script>
  58. import myCard from "@/components/myCard.vue";
  59. import { getList } from "@/api/emergencyDrill/workOrder.js";
  60. export default {
  61. components: { myCard },
  62. data() {
  63. return {
  64. visible: false,
  65. searchKey: "",
  66. listData: [],
  67. page: 1,
  68. size: 10,
  69. isEnd: false,
  70. loading: false,
  71. selectedRow: null,
  72. selectedId: null,
  73. cardColumns: [
  74. [{ prop: "planName", label: "演练计划名称", className: "perce100" }],
  75. [
  76. { prop: "planLocation", label: "演练地点", className: "perce50" },
  77. {
  78. prop: "superviseDeptName",
  79. label: "主管部门",
  80. className: "perce50",
  81. },
  82. ],
  83. ],
  84. };
  85. },
  86. methods: {
  87. open() {
  88. this.visible = true;
  89. this.searchKey = "";
  90. this.page = 1;
  91. this.isEnd = false;
  92. this.listData = [];
  93. this.selectedRow = null;
  94. this.selectedId = null;
  95. this.getList();
  96. },
  97. cancel() {
  98. this.visible = false;
  99. },
  100. selectItem(item) {
  101. this.selectedRow = item;
  102. this.selectedId = item.id;
  103. },
  104. confirm() {
  105. if (!this.selectedRow) {
  106. this.$refs.uToast.show({ type: "warning", message: "请选择一条工单" });
  107. return;
  108. }
  109. this.$emit("confirm", this.selectedRow);
  110. this.cancel();
  111. },
  112. reload() {
  113. this.page = 1;
  114. this.isEnd = false;
  115. this.listData = [];
  116. this.getList();
  117. },
  118. async getList() {
  119. if (this.loading || this.isEnd) return;
  120. this.loading = true;
  121. try {
  122. const params = {
  123. pageNum: this.page,
  124. size: this.size,
  125. name: this.searchKey || undefined,
  126. };
  127. const res = await getList(params);
  128. const list = res.list || [];
  129. if (this.page === 1) this.listData = list;
  130. else this.listData = this.listData.concat(list);
  131. this.isEnd =
  132. list.length < this.size || this.listData.length >= res.count;
  133. this.page += 1;
  134. } catch (e) {
  135. this.$refs.uToast.show({ type: "error", message: e.message });
  136. } finally {
  137. this.loading = false;
  138. }
  139. },
  140. loadMore() {
  141. if (!this.isEnd && !this.loading) this.getList();
  142. },
  143. },
  144. };
  145. </script>
  146. <style lang="scss" scoped>
  147. .drill-select-popup {
  148. /deep/ .u-popup__content {
  149. border-radius: 32rpx 32rpx 0 0;
  150. overflow: hidden;
  151. }
  152. }
  153. .popup-content {
  154. height: 75vh;
  155. display: flex;
  156. flex-direction: column;
  157. background: #eff2f7;
  158. }
  159. .popup-header {
  160. display: flex;
  161. justify-content: space-between;
  162. align-items: center;
  163. padding: 30rpx 32rpx;
  164. background: #fff;
  165. border-bottom: 2rpx solid #eef2f6;
  166. flex-shrink: 0;
  167. .popup-title {
  168. font-size: 36rpx;
  169. font-weight: bold;
  170. }
  171. .close-btn {
  172. width: 60rpx;
  173. height: 60rpx;
  174. display: flex;
  175. align-items: center;
  176. justify-content: center;
  177. font-size: 52rpx;
  178. color: #8e9aae;
  179. }
  180. }
  181. .search-row {
  182. display: flex;
  183. align-items: center;
  184. padding: 16rpx 24rpx;
  185. background: #fff;
  186. gap: 12rpx;
  187. flex-shrink: 0;
  188. .search-input {
  189. flex: 1;
  190. height: 64rpx;
  191. background: #f5f7fb;
  192. border-radius: 48rpx;
  193. padding: 0 24rpx;
  194. font-size: 26rpx;
  195. }
  196. .search-btn {
  197. height: 64rpx;
  198. padding: 0 32rpx;
  199. background: $theme-color;
  200. border-radius: 48rpx;
  201. color: #fff;
  202. font-size: 26rpx;
  203. line-height: 64rpx;
  204. }
  205. }
  206. .popup-body {
  207. flex: 1;
  208. overflow-y: auto;
  209. padding: 16rpx 24rpx;
  210. }
  211. .card-wrapper {
  212. margin-top: 16rpx;
  213. }
  214. .popup-footer {
  215. display: flex;
  216. padding: 16rpx 24rpx;
  217. background: #fff;
  218. border-top: 2rpx solid #eef2f6;
  219. gap: 16rpx;
  220. flex-shrink: 0;
  221. /deep/ .u-button {
  222. flex: 1;
  223. border-radius: 48rpx;
  224. height: 72rpx;
  225. }
  226. }
  227. .load-more {
  228. text-align: center;
  229. font-size: 26rpx;
  230. color: #aaa;
  231. padding: 20rpx 0;
  232. }
  233. </style>