PopupSubTable.vue 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. <template>
  2. <a-card title="弹出子表示例" :bordered="false">
  3. <!--
  4. 【弹出子表大体思路】
  5. 1. 必须要有 clickRowShowSubForm 属性,如果该属性设为false,那么就不会弹出子表
  6. 2. 必须要有 subForm 插槽,用于规定弹出子表的内容
  7. 3. highlightCurrentRow 属性可有可无,如果有则点击一行的时候,该行会背景色会常亮
  8. -->
  9. <!--
  10. 【弹出详细信息大体思路】
  11. 1. 必须要有 clickRowShowMainForm 属性,如果该属性设为false,那么就不会弹出详细信息
  12. 2. 必须要有 mainForm 插槽,用于规定弹出的内容
  13. -->
  14. <JVxeTable
  15. toolbar
  16. rowNumber
  17. rowSelection
  18. highlightCurrentRow
  19. clickRowShowSubForm
  20. clickRowShowMainForm
  21. :height="750"
  22. :loading="loading"
  23. :columns="columns"
  24. :dataSource="dataSource"
  25. @detailsConfirm="handleDetailsConfirm"
  26. >
  27. <!-- 主表单 -->
  28. <template #mainForm="{ row }">
  29. <template v-if="row">
  30. <a-form ref="form2" :model="row" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol">
  31. <a-row :gutter="8">
  32. <a-col :span="8">
  33. <a-form-item label="ID" name="id">
  34. <a-input v-model:value="row.id" disabled />
  35. </a-form-item>
  36. </a-col>
  37. <a-col :span="8">
  38. <a-form-item label="序号" name="num">
  39. <a-input v-model:value="row.num" />
  40. </a-form-item>
  41. </a-col>
  42. <a-col :span="8">
  43. <a-form-item label="船名" name="ship_name">
  44. <a-input v-model:value="row.ship_name" />
  45. </a-form-item>
  46. </a-col>
  47. <a-col :span="8">
  48. <a-form-item label="呼叫" name="call">
  49. <a-input v-model:value="row.call" />
  50. </a-form-item>
  51. </a-col>
  52. <a-col :span="8">
  53. <a-form-item label="长" name="len">
  54. <a-input v-model:value="row.len" />
  55. </a-form-item>
  56. </a-col>
  57. <a-col :span="8">
  58. <a-form-item label="吨" name="ton">
  59. <a-input v-model:value="row.ton" />
  60. </a-form-item>
  61. </a-col>
  62. <a-col :span="8">
  63. <a-form-item label="付款方" name="payer">
  64. <a-input v-model:value="row.payer" />
  65. </a-form-item>
  66. </a-col>
  67. <a-col :span="8">
  68. <a-form-item label="数" name="count">
  69. <a-input v-model:value="row.count" />
  70. </a-form-item>
  71. </a-col>
  72. <a-col :span="8">
  73. <a-form-item label="公司" name="company">
  74. <a-input v-model:value="row.company" />
  75. </a-form-item>
  76. </a-col>
  77. <a-col :span="8">
  78. <a-form-item label="动向" name="trend">
  79. <a-input v-model:value="row.trend" />
  80. </a-form-item>
  81. </a-col>
  82. </a-row>
  83. </a-form>
  84. </template>
  85. </template>
  86. <!-- 子表单 -->
  87. <template #subForm="{ row }">
  88. <template v-if="loadSubData(row)">
  89. <JVxeTable
  90. ref="subFormTable"
  91. height="auto"
  92. :max-height="350"
  93. :loading="subTable.loading"
  94. :columns="subTable.columns"
  95. :dataSource="subTable.dataSource"
  96. />
  97. </template>
  98. </template>
  99. </JVxeTable>
  100. </a-card>
  101. </template>
  102. <script lang="ts" setup>
  103. // 弹出子表示例
  104. import { reactive, ref } from 'vue';
  105. import { defHttp } from '/@/utils/http/axios';
  106. import { JVxeColumn, JVxeTypes } from '/@/components/jeecg/JVxeTable/types';
  107. import { useMessage } from '/@/hooks/web/useMessage';
  108. const { createMessage } = useMessage();
  109. const loading = ref(false);
  110. const dataSource = ref([]);
  111. const columns = ref<JVxeColumn[]>([
  112. { key: 'num', title: '序号', width: '80px' },
  113. { key: 'ship_name', title: '船名', width: '180px', type: JVxeTypes.input },
  114. { key: 'call', title: '呼叫', width: '80px' },
  115. { key: 'len', title: '长', width: '80px' },
  116. { key: 'ton', title: '吨', width: '120px' },
  117. { key: 'payer', title: '付款方', width: '120px' },
  118. { key: 'count', title: '数', width: '40px' },
  119. {
  120. key: 'company',
  121. title: '公司',
  122. minWidth: '180px',
  123. // 是否点击显示详细信息
  124. // 只有当前单元格不能编辑的时候才能生效
  125. // 如果不设的话,点击就只弹出子表,不会弹出主表的详细信息
  126. showDetails: true,
  127. },
  128. { key: 'trend', title: '动向', width: '120px' },
  129. ]);
  130. const selectedRows = ref([]);
  131. // 子表的信息
  132. const subTable = reactive({
  133. currentRowId: null,
  134. loading: false,
  135. pagination: { current: 1, pageSize: 200, pageSizeOptions: ['100', '200'], total: 0 },
  136. selectedRows: [],
  137. dataSource: [],
  138. columns: [
  139. { key: 'dd_num', title: '调度序号', width: '120px' },
  140. { key: 'tug', title: '拖轮', width: '180px', type: JVxeTypes.input },
  141. { key: 'work_start_time', title: '作业开始时间', width: '180px', type: JVxeTypes.input },
  142. { key: 'work_stop_time', title: '作业结束时间', width: '180px', type: JVxeTypes.input },
  143. { key: 'type', title: '船舶分类', width: '120px', type: JVxeTypes.input },
  144. { key: 'port_area', title: '所属港区', minWidth: '120px', type: JVxeTypes.input },
  145. ] as JVxeColumn[],
  146. });
  147. // form表单 col
  148. const labelCol = reactive({ span: 4 });
  149. const wrapperCol = reactive({ span: 20 });
  150. const rules = reactive({
  151. num: [{ required: true, message: '必须输入序号' }],
  152. });
  153. // 查询url地址
  154. enum Api {
  155. getData = '/mock/vxe/getData',
  156. }
  157. loadData();
  158. // 加载数据
  159. function loadData() {
  160. // 封装查询条件
  161. // 调用查询数据接口
  162. loading.value = true;
  163. defHttp
  164. .get({
  165. url: Api.getData,
  166. params: {
  167. pageNo: 1,
  168. pageSize: 30,
  169. },
  170. })
  171. .then((result) => {
  172. // 将查询的数据赋值给 dataSource
  173. dataSource.value = result.records;
  174. // 重置选择
  175. selectedRows.value = [];
  176. })
  177. .finally(() => {
  178. // 这里是无论成功或失败都会执行的方法,在这里关闭loading
  179. loading.value = false;
  180. });
  181. }
  182. // 查询子表数据
  183. function loadSubData(row) {
  184. if (row) {
  185. // 这里一定要做限制,限制不能重复查询,否者会出现死循环
  186. if (subTable.currentRowId === row.id) {
  187. return true;
  188. }
  189. subTable.currentRowId = row.id;
  190. subTable.loading = true;
  191. defHttp
  192. .get({
  193. url: Api.getData,
  194. params: {
  195. pageNo: 1,
  196. pageSize: 30,
  197. parentId: row.id,
  198. },
  199. })
  200. .then((result) => {
  201. // 将查询的数据赋值给 dataSource
  202. subTable.dataSource = result.records;
  203. })
  204. .finally(() => {
  205. // 这里是无论成功或失败都会执行的方法,在这里关闭loading
  206. subTable.loading = false;
  207. });
  208. return true;
  209. } else {
  210. return false;
  211. }
  212. }
  213. // 详细信息里点了确认按钮
  214. function handleDetailsConfirm({ row, $table, callback }) {
  215. console.log('保存的数据:', row);
  216. // 校验当前行
  217. $table.validate(row).then((errMap) => {
  218. // 校验通过
  219. if (!errMap) {
  220. // 校验子表,如果需要的话,可以操作下面这个对象:
  221. callback(true);
  222. loading.value = true;
  223. setTimeout(() => {
  224. loading.value = false;
  225. createMessage.success('保存成功');
  226. }, 1000);
  227. } else {
  228. callback(false);
  229. createMessage.warn('校验失败');
  230. }
  231. });
  232. }
  233. </script>
  234. <style scoped></style>