pagging.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. import {
  2. ref,
  3. watch,
  4. onActivated,
  5. onMounted,
  6. reactive,
  7. isReactive,
  8. Ref,
  9. nextTick,
  10. } from "vue";
  11. import { UN_REQ_NUM } from "@/constant/sys";
  12. import { dateFormat, mix, throttle } from "@/util";
  13. import { ElMessage } from "element-plus";
  14. import { confirm } from "@/helper/message";
  15. import { PaggingReq, PaggingRes } from "@/request";
  16. // 构建数据源列表操作
  17. const genTableOperate = <T>() => {
  18. const tableState = ref({
  19. rows: [] as T[],
  20. selectRows: [] as T[],
  21. });
  22. return {
  23. tableState,
  24. changeSelectRows(selected: T[]) {
  25. tableState.value.selectRows = selected as any;
  26. },
  27. };
  28. };
  29. // 构建分页配置状态
  30. const genPagOperate = () => {
  31. const pagStore = ref({
  32. currentPage: 1,
  33. size: 12,
  34. total: 0,
  35. });
  36. return {
  37. pagStore,
  38. sizeChange(size: number) {
  39. pagStore.value.size = size;
  40. },
  41. currentChange(page: number) {
  42. pagStore.value.currentPage = page;
  43. },
  44. };
  45. };
  46. // 搜索状态操作
  47. const genQueryOperate = <Q>(paramsTemlate?: Q) => {
  48. const paramsStore = ref(paramsTemlate && { ...paramsTemlate }) as Ref<Q>;
  49. return {
  50. paramsStore,
  51. reset() {
  52. if (paramsTemlate) {
  53. mix(paramsStore.value, true, paramsTemlate);
  54. }
  55. },
  56. };
  57. };
  58. type Operate<P, RAW, NRAW> = {
  59. get: (param: PaggingReq<P>) => Promise<PaggingRes<RAW>> | PaggingRes<RAW>;
  60. set?: (param: RAW) => void;
  61. add?: (param: NRAW) => void;
  62. del?: (param: RAW) => void;
  63. mapper?: { delMsg?: string };
  64. };
  65. type PaggingProps<P, RAW, NRAW> = Operate<P, RAW, NRAW> & {
  66. rowKey?: keyof RAW;
  67. itemTemplate?: Partial<RAW | NRAW>;
  68. paramsTemlate?: P;
  69. };
  70. export const usePagging = <PARAM, RAW, NRAW>(
  71. props: PaggingProps<PARAM, RAW, NRAW>
  72. ) => {
  73. const tableOperate = genTableOperate<RAW>();
  74. const pagOperate = genPagOperate();
  75. const queryOperate = genQueryOperate(props.paramsTemlate);
  76. const loading = ref(false);
  77. const refreshRaw = async () => {
  78. loading.value = true;
  79. const pag = pagOperate.pagStore.value;
  80. const paramsRaw = {
  81. ...queryOperate.paramsStore.value,
  82. pageNum: pag.currentPage,
  83. pageSize: pag.size,
  84. } as any;
  85. const params: any = Object.keys(paramsRaw)
  86. .filter((key) => ![UN_REQ_NUM, "" + UN_REQ_NUM].includes(paramsRaw[key]))
  87. .reduce((t, k) => {
  88. t[k] = paramsRaw[k];
  89. if (t[k] instanceof Date) {
  90. t[k] = dateFormat(t[k], "yyyy-MM-dd");
  91. }
  92. return t;
  93. }, {} as any);
  94. const data = await props.get(params);
  95. pag.total = data.total;
  96. tableOperate.tableState.value.rows = data.list as any;
  97. await nextTick();
  98. loading.value = false;
  99. };
  100. const refresh = throttle(refreshRaw, 300);
  101. const itemAPI = {
  102. async set(data: RAW) {
  103. if (props.set) {
  104. await props.set(data);
  105. await refresh();
  106. }
  107. },
  108. async add(data: NRAW) {
  109. if (props.add) {
  110. await props.add(data);
  111. await refresh();
  112. }
  113. },
  114. async del(data: RAW) {
  115. if (props.del) {
  116. await props.del(data);
  117. await refresh();
  118. }
  119. },
  120. };
  121. watch(
  122. () => [queryOperate?.paramsStore, ...(isReactive(props) ? [props] : [])],
  123. refresh,
  124. { deep: true }
  125. );
  126. onActivated(refresh);
  127. onMounted(refresh);
  128. const state = reactive({
  129. pag: pagOperate.pagStore!,
  130. table: tableOperate.tableState!,
  131. query: queryOperate.paramsStore!,
  132. });
  133. return {
  134. async del(data: RAW) {
  135. if (await confirm(props.mapper?.delMsg || "确定要删除此数据吗?")) {
  136. const result = await itemAPI.del!(data);
  137. ElMessage.success("删除成功");
  138. return result;
  139. }
  140. },
  141. async deleteSelected() {
  142. const rows = tableOperate.tableState.value.selectRows;
  143. if (rows.length === 0) {
  144. ElMessage.error("请勾选数据后再删除数据!");
  145. } else if (
  146. await confirm(
  147. props.mapper?.delMsg || `确定要删除这${rows.length}条数据吗?`
  148. )
  149. ) {
  150. await Promise.all(rows.map((item) => itemAPI?.del!(item as any)));
  151. ElMessage.success("删除成功");
  152. refresh();
  153. }
  154. },
  155. changPageCurrent: (data: number) => {
  156. pagOperate.currentChange(data);
  157. refresh();
  158. },
  159. changPageSize: (data: number) => {
  160. pagOperate.sizeChange(data);
  161. refresh();
  162. },
  163. state,
  164. loading,
  165. add: itemAPI.add,
  166. set: itemAPI.set,
  167. changeSelectRows: tableOperate.changeSelectRows,
  168. refresh,
  169. queryReset: queryOperate.reset,
  170. };
  171. };