useVxeGrid.ts 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. import { computed, nextTick, reactive } from 'vue'
  2. import { SizeType, VxeGridProps, VxeTablePropTypes } from 'vxe-table'
  3. import { useAppStore } from '@/store/modules/app'
  4. import { VxeAllSchemas } from './useVxeCrudSchemas'
  5. import { useI18n } from '@/hooks/web/useI18n'
  6. import { useMessage } from '@/hooks/web/useMessage'
  7. import download from '@/utils/download'
  8. const { t } = useI18n()
  9. const message = useMessage() // 消息弹窗
  10. interface UseVxeGridConfig<T = any> {
  11. allSchemas: VxeAllSchemas
  12. height?: number // 高度 默认730
  13. topActionSlots?: boolean // 是否开启表格内顶部操作栏插槽
  14. treeConfig?: VxeTablePropTypes.TreeConfig // 树形表单配置
  15. isList?: boolean // 是否不带分页的list
  16. getListApi: (option: any) => Promise<T> // 获取列表接口
  17. getAllListApi?: (option: any) => Promise<T> // 获取全部数据接口 用于VXE导出
  18. deleteApi?: (option: any) => Promise<T> // 删除接口
  19. exportListApi?: (option: any) => Promise<T> // 导出接口
  20. exportName?: string // 导出文件夹名称
  21. queryParams?: any // 其他查询参数
  22. }
  23. const appStore = useAppStore()
  24. const currentSize = computed(() => {
  25. let resSize: SizeType = 'small'
  26. const appsize = appStore.getCurrentSize
  27. switch (appsize) {
  28. case 'large':
  29. resSize = 'medium'
  30. break
  31. case 'default':
  32. resSize = 'small'
  33. break
  34. case 'small':
  35. resSize = 'mini'
  36. break
  37. }
  38. return resSize
  39. })
  40. export const useVxeGrid = <T = any>(config?: UseVxeGridConfig<T>) => {
  41. /**
  42. * grid options 初始化
  43. */
  44. const gridOptions = reactive<VxeGridProps<any>>({
  45. loading: true,
  46. size: currentSize as any,
  47. height: config?.height ? config.height : 730,
  48. rowConfig: {
  49. isCurrent: true, // 当鼠标点击行时,是否要高亮当前行
  50. isHover: true // 当鼠标移到行时,是否要高亮当前行
  51. },
  52. toolbarConfig: {
  53. slots:
  54. !config?.topActionSlots && config?.topActionSlots != false
  55. ? { buttons: 'toolbar_buttons' }
  56. : {}
  57. },
  58. printConfig: {
  59. columns: config?.allSchemas.printSchema
  60. },
  61. formConfig: {
  62. enabled: true,
  63. titleWidth: 100,
  64. titleAlign: 'right',
  65. items: config?.allSchemas.searchSchema
  66. },
  67. columns: config?.allSchemas.tableSchema,
  68. proxyConfig: {
  69. seq: true, // 启用动态序号代理(分页之后索引自动计算为当前页的起始序号)
  70. form: true, // 启用表单代理,当点击表单提交按钮时会自动触发 reload 行为
  71. props: { result: 'list', total: 'total' },
  72. ajax: {
  73. query: ({ page, form }) => {
  74. let queryParams: any = Object.assign({}, JSON.parse(JSON.stringify(form)))
  75. if (config?.queryParams) {
  76. queryParams = Object.assign(queryParams, config.queryParams)
  77. }
  78. if (!config?.treeConfig) {
  79. queryParams.pageSize = page.pageSize
  80. queryParams.pageNo = page.currentPage
  81. }
  82. gridOptions.loading = false
  83. return new Promise(async (resolve) => {
  84. resolve(await config?.getListApi(queryParams))
  85. })
  86. },
  87. delete: ({ body }) => {
  88. return new Promise(async (resolve) => {
  89. if (config?.deleteApi) {
  90. resolve(await config?.deleteApi(JSON.stringify(body)))
  91. } else {
  92. Promise.reject('未设置deleteApi')
  93. }
  94. })
  95. },
  96. queryAll: ({ form }) => {
  97. const queryParams = Object.assign({}, JSON.parse(JSON.stringify(form)))
  98. return new Promise(async (resolve) => {
  99. if (config?.getAllListApi) {
  100. resolve(await config?.getAllListApi(queryParams))
  101. } else {
  102. resolve(await config?.getListApi(queryParams))
  103. }
  104. })
  105. }
  106. }
  107. },
  108. exportConfig: {
  109. filename: config?.exportName,
  110. // 默认选中类型
  111. type: 'csv',
  112. // 自定义数据量列表
  113. modes: config?.getAllListApi ? ['current', 'all'] : ['current'],
  114. columns: config?.allSchemas.printSchema
  115. }
  116. })
  117. if (config?.treeConfig) {
  118. gridOptions.treeConfig = config.treeConfig
  119. } else if (config?.isList) {
  120. gridOptions.proxyConfig = {
  121. seq: true, // 启用动态序号代理(分页之后索引自动计算为当前页的起始序号)
  122. form: true, // 启用表单代理,当点击表单提交按钮时会自动触发 reload 行为
  123. props: { result: 'data' },
  124. ajax: {
  125. query: ({ form }) => {
  126. let queryParams: any = Object.assign({}, JSON.parse(JSON.stringify(form)))
  127. if (config?.queryParams) {
  128. queryParams = Object.assign(queryParams, config.queryParams)
  129. }
  130. gridOptions.loading = false
  131. return new Promise(async (resolve) => {
  132. resolve(await config?.getListApi(queryParams))
  133. })
  134. }
  135. }
  136. }
  137. } else {
  138. gridOptions.pagerConfig = {
  139. border: false, // 带边框
  140. background: true, // 带背景颜色
  141. perfect: false, // 配套的样式
  142. pageSize: 10, // 每页大小
  143. pagerCount: 7, // 显示页码按钮的数量
  144. autoHidden: false, // 当只有一页时自动隐藏
  145. pageSizes: [5, 10, 20, 30, 50, 100], // 每页大小选项列表
  146. layouts: [
  147. 'PrevJump',
  148. 'PrevPage',
  149. 'JumpNumber',
  150. 'NextPage',
  151. 'NextJump',
  152. 'Sizes',
  153. 'FullJump',
  154. 'Total'
  155. ]
  156. }
  157. }
  158. /**
  159. * 刷新列表
  160. * @param ref
  161. * @returns
  162. */
  163. const getList = async (ref) => {
  164. if (!ref) {
  165. console.error('未传入gridRef')
  166. return
  167. }
  168. await nextTick()
  169. ref.value.commitProxy('query')
  170. }
  171. // 获取查询参数
  172. const getSearchData = async (ref) => {
  173. if (!ref) {
  174. console.error('未传入gridRef')
  175. return
  176. }
  177. await nextTick()
  178. const queryParams = Object.assign(
  179. {},
  180. JSON.parse(JSON.stringify(ref.value.getProxyInfo()?.form))
  181. )
  182. return queryParams
  183. }
  184. /**
  185. * 删除
  186. * @param ref
  187. * @param ids rowid
  188. * @returns
  189. */
  190. const deleteData = async (ref, ids: string | number) => {
  191. if (!ref) {
  192. console.error('未传入gridRef')
  193. return
  194. }
  195. if (!config?.deleteApi) {
  196. console.error('未传入delListApi')
  197. return
  198. }
  199. await nextTick()
  200. return new Promise(async () => {
  201. message.delConfirm().then(async () => {
  202. await (config?.deleteApi && config?.deleteApi(ids))
  203. message.success(t('common.delSuccess'))
  204. // 刷新列表
  205. ref.value.commitProxy('query')
  206. })
  207. })
  208. }
  209. /**
  210. * 导出
  211. * @param ref
  212. * @param fileName 文件名,默认excel.xls
  213. * @returns
  214. */
  215. const exportList = async (ref, fileName?: string) => {
  216. if (!ref) {
  217. console.error('未传入gridRef')
  218. return
  219. }
  220. if (!config?.exportListApi) {
  221. console.error('未传入exportListApi')
  222. return
  223. }
  224. await nextTick()
  225. const queryParams = Object.assign(
  226. {},
  227. JSON.parse(JSON.stringify(ref.value?.getProxyInfo()?.form))
  228. )
  229. message.exportConfirm().then(async () => {
  230. const res = await (config?.exportListApi && config?.exportListApi(queryParams))
  231. download.excel(res as unknown as Blob, fileName ? fileName : 'excel.xls')
  232. })
  233. }
  234. /**
  235. * 表格最大/最小化
  236. * @param ref
  237. * @returns
  238. */
  239. const zoom = async (ref) => {
  240. if (!ref) {
  241. console.error('未传入gridRef')
  242. return
  243. }
  244. await nextTick()
  245. ref.value.zoom(!ref.value.isMaximized())
  246. }
  247. return {
  248. gridOptions,
  249. getList,
  250. getSearchData,
  251. deleteData,
  252. exportList,
  253. zoom
  254. }
  255. }