Commit a984eac9658748134d56bb07b33958f1624dc7d4
1 parent
a74c6b08
feat: 完善xtable组件
Showing
4 changed files
with
169 additions
and
63 deletions
yudao-ui-admin-vue3/src/components/XTable/src/XTable.vue
| @@ -12,6 +12,12 @@ import { useAppStore } from '@/store/modules/app' | @@ -12,6 +12,12 @@ import { useAppStore } from '@/store/modules/app' | ||
| 12 | import { useDesign } from '@/hooks/web/useDesign' | 12 | import { useDesign } from '@/hooks/web/useDesign' |
| 13 | import { XTableProps } from './type' | 13 | import { XTableProps } from './type' |
| 14 | import { isBoolean, isFunction } from '@/utils/is' | 14 | import { isBoolean, isFunction } from '@/utils/is' |
| 15 | +import { useMessage } from '@/hooks/web/useMessage' | ||
| 16 | +import download from '@/utils/download' | ||
| 17 | +import { useI18n } from '@/hooks/web/useI18n' | ||
| 18 | + | ||
| 19 | +const { t } = useI18n() | ||
| 20 | +const message = useMessage() // 消息弹窗 | ||
| 15 | 21 | ||
| 16 | const appStore = useAppStore() | 22 | const appStore = useAppStore() |
| 17 | 23 | ||
| @@ -21,30 +27,6 @@ const prefixCls = getPrefixCls('x-vxe-table') | @@ -21,30 +27,6 @@ const prefixCls = getPrefixCls('x-vxe-table') | ||
| 21 | const attrs = useAttrs() | 27 | const attrs = useAttrs() |
| 22 | const emit = defineEmits(['register']) | 28 | const emit = defineEmits(['register']) |
| 23 | 29 | ||
| 24 | -const props = defineProps({ | ||
| 25 | - options: { | ||
| 26 | - type: Object as PropType<XTableProps>, | ||
| 27 | - default: () => {} | ||
| 28 | - } | ||
| 29 | -}) | ||
| 30 | -const innerProps = ref<Partial<XTableProps>>() | ||
| 31 | - | ||
| 32 | -const getProps = computed(() => { | ||
| 33 | - const options = innerProps.value || props.options | ||
| 34 | - options.size = currentSize as any | ||
| 35 | - options.height = 700 | ||
| 36 | - getColumnsConfig(options) | ||
| 37 | - getProxyConfig(options) | ||
| 38 | - getPageConfig(options) | ||
| 39 | - getToolBarConfig(options) | ||
| 40 | - // console.log(options); | ||
| 41 | - return { | ||
| 42 | - ...options, | ||
| 43 | - ...attrs | ||
| 44 | - } | ||
| 45 | -}) | ||
| 46 | - | ||
| 47 | -const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref | ||
| 48 | watch( | 30 | watch( |
| 49 | () => appStore.getIsDark, | 31 | () => appStore.getIsDark, |
| 50 | () => { | 32 | () => { |
| @@ -57,6 +39,7 @@ watch( | @@ -57,6 +39,7 @@ watch( | ||
| 57 | }, | 39 | }, |
| 58 | { immediate: true } | 40 | { immediate: true } |
| 59 | ) | 41 | ) |
| 42 | + | ||
| 60 | const currentSize = computed(() => { | 43 | const currentSize = computed(() => { |
| 61 | let resSize: SizeType = 'small' | 44 | let resSize: SizeType = 'small' |
| 62 | const appsize = appStore.getCurrentSize | 45 | const appsize = appStore.getCurrentSize |
| @@ -74,25 +57,42 @@ const currentSize = computed(() => { | @@ -74,25 +57,42 @@ const currentSize = computed(() => { | ||
| 74 | return resSize | 57 | return resSize |
| 75 | }) | 58 | }) |
| 76 | 59 | ||
| 77 | -const reload = () => { | ||
| 78 | - const g = unref(xGrid) | ||
| 79 | - if (!g) { | ||
| 80 | - return | 60 | +const props = defineProps({ |
| 61 | + options: { | ||
| 62 | + type: Object as PropType<XTableProps>, | ||
| 63 | + default: () => {} | ||
| 81 | } | 64 | } |
| 82 | - g.commitProxy('query') | ||
| 83 | -} | 65 | +}) |
| 66 | +const innerProps = ref<Partial<XTableProps>>() | ||
| 84 | 67 | ||
| 85 | -const getSearchData = () => { | ||
| 86 | - const g = unref(xGrid) | ||
| 87 | - if (!g) { | ||
| 88 | - return | 68 | +const getProps = computed(() => { |
| 69 | + const options = innerProps.value || props.options | ||
| 70 | + options.size = currentSize as any | ||
| 71 | + options.height = 700 | ||
| 72 | + getOptionInitConfig(options) | ||
| 73 | + getColumnsConfig(options) | ||
| 74 | + getProxyConfig(options) | ||
| 75 | + getPageConfig(options) | ||
| 76 | + getToolBarConfig(options) | ||
| 77 | + // console.log(options); | ||
| 78 | + return { | ||
| 79 | + ...options, | ||
| 80 | + ...attrs | ||
| 89 | } | 81 | } |
| 90 | - const queryParams = Object.assign({}, JSON.parse(JSON.stringify(g.getProxyInfo()?.form))) | ||
| 91 | - return queryParams | ||
| 92 | -} | 82 | +}) |
| 83 | + | ||
| 84 | +const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref | ||
| 93 | 85 | ||
| 94 | let proxyForm = false | 86 | let proxyForm = false |
| 95 | 87 | ||
| 88 | +const getOptionInitConfig = (options: XTableProps) => { | ||
| 89 | + options.size = currentSize as any | ||
| 90 | + options.rowConfig = { | ||
| 91 | + isCurrent: true, // 当鼠标点击行时,是否要高亮当前行 | ||
| 92 | + isHover: true // 当鼠标移到行时,是否要高亮当前行 | ||
| 93 | + } | ||
| 94 | +} | ||
| 95 | + | ||
| 96 | // columns | 96 | // columns |
| 97 | const getColumnsConfig = (options: XTableProps) => { | 97 | const getColumnsConfig = (options: XTableProps) => { |
| 98 | const { allSchemas } = options | 98 | const { allSchemas } = options |
| @@ -131,21 +131,55 @@ const getProxyConfig = (options: XTableProps) => { | @@ -131,21 +131,55 @@ const getProxyConfig = (options: XTableProps) => { | ||
| 131 | if (options.params) { | 131 | if (options.params) { |
| 132 | queryParams = Object.assign(queryParams, options.params) | 132 | queryParams = Object.assign(queryParams, options.params) |
| 133 | } | 133 | } |
| 134 | - queryParams.pageSize = page.currentPage | ||
| 135 | - queryParams.page = page.pageSize | ||
| 136 | - | 134 | + if (!options?.treeConfig) { |
| 135 | + queryParams.pageSize = page.pageSize | ||
| 136 | + queryParams.pageNo = page.currentPage | ||
| 137 | + } | ||
| 137 | return new Promise(async (resolve) => { | 138 | return new Promise(async (resolve) => { |
| 138 | resolve(await getListApi(queryParams)) | 139 | resolve(await getListApi(queryParams)) |
| 139 | }) | 140 | }) |
| 141 | + }, | ||
| 142 | + delete: ({ body }) => { | ||
| 143 | + return new Promise(async (resolve) => { | ||
| 144 | + if (options.deleteApi) { | ||
| 145 | + resolve(await options.deleteApi(JSON.stringify(body))) | ||
| 146 | + } else { | ||
| 147 | + Promise.reject('未设置deleteApi') | ||
| 148 | + } | ||
| 149 | + }) | ||
| 150 | + }, | ||
| 151 | + queryAll: ({ form }) => { | ||
| 152 | + const queryParams = Object.assign({}, JSON.parse(JSON.stringify(form))) | ||
| 153 | + return new Promise(async (resolve) => { | ||
| 154 | + if (options.getAllListApi) { | ||
| 155 | + resolve(await options.getAllListApi(queryParams)) | ||
| 156 | + } else { | ||
| 157 | + resolve(await getListApi(queryParams)) | ||
| 158 | + } | ||
| 159 | + }) | ||
| 140 | } | 160 | } |
| 141 | } | 161 | } |
| 142 | } | 162 | } |
| 143 | } | 163 | } |
| 164 | + if (options.exportListApi) { | ||
| 165 | + options.exportConfig = { | ||
| 166 | + filename: options?.exportName, | ||
| 167 | + // 默认选中类型 | ||
| 168 | + type: 'csv', | ||
| 169 | + // 自定义数据量列表 | ||
| 170 | + modes: options?.getAllListApi ? ['current', 'all'] : ['current'], | ||
| 171 | + columns: options?.allSchemas?.printSchema | ||
| 172 | + } | ||
| 173 | + } | ||
| 144 | } | 174 | } |
| 145 | 175 | ||
| 146 | // 分页 | 176 | // 分页 |
| 147 | const getPageConfig = (options: XTableProps) => { | 177 | const getPageConfig = (options: XTableProps) => { |
| 148 | - const { pagination, pagerConfig } = options | 178 | + const { pagination, pagerConfig, treeConfig } = options |
| 179 | + if (treeConfig) { | ||
| 180 | + options.treeConfig = options.treeConfig | ||
| 181 | + return | ||
| 182 | + } | ||
| 149 | if (pagerConfig) return | 183 | if (pagerConfig) return |
| 150 | if (pagination) { | 184 | if (pagination) { |
| 151 | if (isBoolean(pagination)) { | 185 | if (isBoolean(pagination)) { |
| @@ -171,6 +205,28 @@ const getPageConfig = (options: XTableProps) => { | @@ -171,6 +205,28 @@ const getPageConfig = (options: XTableProps) => { | ||
| 171 | return | 205 | return |
| 172 | } | 206 | } |
| 173 | options.pagerConfig = pagination | 207 | options.pagerConfig = pagination |
| 208 | + } else { | ||
| 209 | + if (pagination != false) { | ||
| 210 | + options.pagerConfig = { | ||
| 211 | + border: false, // 带边框 | ||
| 212 | + background: true, // 带背景颜色 | ||
| 213 | + perfect: false, // 配套的样式 | ||
| 214 | + pageSize: 10, // 每页大小 | ||
| 215 | + pagerCount: 7, // 显示页码按钮的数量 | ||
| 216 | + autoHidden: false, // 当只有一页时自动隐藏 | ||
| 217 | + pageSizes: [5, 10, 20, 30, 50, 100], // 每页大小选项列表 | ||
| 218 | + layouts: [ | ||
| 219 | + 'PrevJump', | ||
| 220 | + 'PrevPage', | ||
| 221 | + 'JumpNumber', | ||
| 222 | + 'NextPage', | ||
| 223 | + 'NextJump', | ||
| 224 | + 'Sizes', | ||
| 225 | + 'FullJump', | ||
| 226 | + 'Total' | ||
| 227 | + ] | ||
| 228 | + } | ||
| 229 | + } | ||
| 174 | } | 230 | } |
| 175 | } | 231 | } |
| 176 | 232 | ||
| @@ -190,12 +246,70 @@ const getToolBarConfig = (options: XTableProps) => { | @@ -190,12 +246,70 @@ const getToolBarConfig = (options: XTableProps) => { | ||
| 190 | } | 246 | } |
| 191 | } | 247 | } |
| 192 | 248 | ||
| 249 | +// 刷新列表 | ||
| 250 | +const reload = () => { | ||
| 251 | + const g = unref(xGrid) | ||
| 252 | + if (!g) { | ||
| 253 | + return | ||
| 254 | + } | ||
| 255 | + g.commitProxy('query') | ||
| 256 | +} | ||
| 257 | + | ||
| 258 | +// 删除 | ||
| 259 | +const deleteData = async (ids: string | number) => { | ||
| 260 | + const g = unref(xGrid) | ||
| 261 | + if (!g) { | ||
| 262 | + return | ||
| 263 | + } | ||
| 264 | + const options = innerProps.value || props.options | ||
| 265 | + if (!options.deleteApi) { | ||
| 266 | + console.error('未传入delListApi') | ||
| 267 | + return | ||
| 268 | + } | ||
| 269 | + return new Promise(async () => { | ||
| 270 | + message.delConfirm().then(async () => { | ||
| 271 | + await (options?.deleteApi && options?.deleteApi(ids)) | ||
| 272 | + message.success(t('common.delSuccess')) | ||
| 273 | + // 刷新列表 | ||
| 274 | + reload() | ||
| 275 | + }) | ||
| 276 | + }) | ||
| 277 | +} | ||
| 278 | + | ||
| 279 | +// 导出 | ||
| 280 | +const exportList = async (fileName?: string) => { | ||
| 281 | + const g = unref(xGrid) | ||
| 282 | + if (!g) { | ||
| 283 | + return | ||
| 284 | + } | ||
| 285 | + const options = innerProps.value || props.options | ||
| 286 | + if (!options?.exportListApi) { | ||
| 287 | + console.error('未传入exportListApi') | ||
| 288 | + return | ||
| 289 | + } | ||
| 290 | + const queryParams = Object.assign({}, JSON.parse(JSON.stringify(g.getProxyInfo()?.form))) | ||
| 291 | + message.exportConfirm().then(async () => { | ||
| 292 | + const res = await (options?.exportListApi && options?.exportListApi(queryParams)) | ||
| 293 | + download.excel(res as unknown as Blob, fileName ? fileName : 'excel.xls') | ||
| 294 | + }) | ||
| 295 | +} | ||
| 296 | + | ||
| 297 | +// 获取查询参数 | ||
| 298 | +const getSearchData = () => { | ||
| 299 | + const g = unref(xGrid) | ||
| 300 | + if (!g) { | ||
| 301 | + return | ||
| 302 | + } | ||
| 303 | + const queryParams = Object.assign({}, JSON.parse(JSON.stringify(g.getProxyInfo()?.form))) | ||
| 304 | + return queryParams | ||
| 305 | +} | ||
| 306 | + | ||
| 193 | const setProps = (prop: Partial<XTableProps>) => { | 307 | const setProps = (prop: Partial<XTableProps>) => { |
| 194 | innerProps.value = { ...unref(innerProps), ...prop } | 308 | innerProps.value = { ...unref(innerProps), ...prop } |
| 195 | } | 309 | } |
| 196 | 310 | ||
| 197 | -defineExpose({ reload, Ref: xGrid, getSearchData }) | ||
| 198 | -emit('register', { reload, getSearchData, setProps }) | 311 | +defineExpose({ reload, Ref: xGrid, getSearchData, deleteData, exportList }) |
| 312 | +emit('register', { reload, getSearchData, setProps, deleteData, exportList }) | ||
| 199 | </script> | 313 | </script> |
| 200 | <style lang="scss"> | 314 | <style lang="scss"> |
| 201 | @import './style/index.scss'; | 315 | @import './style/index.scss'; |
yudao-ui-admin-vue3/src/components/XTable/src/type.ts
| 1 | import { CrudSchema } from '@/hooks/web/useCrudSchemas' | 1 | import { CrudSchema } from '@/hooks/web/useCrudSchemas' |
| 2 | -import type { VxeGridProps, VxeGridPropTypes } from 'vxe-table' | 2 | +import type { VxeGridProps, VxeGridPropTypes, VxeTablePropTypes } from 'vxe-table' |
| 3 | 3 | ||
| 4 | export type XTableProps<D = any> = VxeGridProps<D> & { | 4 | export type XTableProps<D = any> = VxeGridProps<D> & { |
| 5 | allSchemas?: CrudSchema | 5 | allSchemas?: CrudSchema |
| 6 | + height?: number // 高度 默认730 | ||
| 7 | + topActionSlots?: boolean // 是否开启表格内顶部操作栏插槽 | ||
| 8 | + treeConfig?: VxeTablePropTypes.TreeConfig // 树形表单配置 | ||
| 6 | getListApi?: Function | 9 | getListApi?: Function |
| 10 | + getAllListApi?: Function | ||
| 7 | deleteApi?: Function | 11 | deleteApi?: Function |
| 8 | exportListApi?: Function | 12 | exportListApi?: Function |
| 13 | + exportName?: string // 导出文件夹名称 | ||
| 9 | params?: any | 14 | params?: any |
| 10 | pagination?: boolean | VxeGridPropTypes.PagerConfig | 15 | pagination?: boolean | VxeGridPropTypes.PagerConfig |
| 11 | toolBar?: boolean | VxeGridPropTypes.ToolbarConfig | 16 | toolBar?: boolean | VxeGridPropTypes.ToolbarConfig |
yudao-ui-admin-vue3/src/hooks/web/useXTable.ts
| @@ -4,6 +4,8 @@ import { XTableProps } from '@/components/XTable/src/type' | @@ -4,6 +4,8 @@ import { XTableProps } from '@/components/XTable/src/type' | ||
| 4 | export interface tableMethod { | 4 | export interface tableMethod { |
| 5 | reload: () => void | 5 | reload: () => void |
| 6 | setProps: (props: XTableProps) => void | 6 | setProps: (props: XTableProps) => void |
| 7 | + deleteData: (ids: string | number) => void | ||
| 8 | + exportList: (fileName?: string) => void | ||
| 7 | } | 9 | } |
| 8 | 10 | ||
| 9 | export function useXTable(props: XTableProps): [Function, tableMethod] { | 11 | export function useXTable(props: XTableProps): [Function, tableMethod] { |
| @@ -22,7 +24,9 @@ export function useXTable(props: XTableProps): [Function, tableMethod] { | @@ -22,7 +24,9 @@ export function useXTable(props: XTableProps): [Function, tableMethod] { | ||
| 22 | } | 24 | } |
| 23 | const methods: tableMethod = { | 25 | const methods: tableMethod = { |
| 24 | reload: () => getInstance().reload(), | 26 | reload: () => getInstance().reload(), |
| 25 | - setProps: (props) => getInstance().setProps(props) | 27 | + setProps: (props) => getInstance().setProps(props), |
| 28 | + deleteData: (ids: string | number) => getInstance().deleteData(ids), | ||
| 29 | + exportList: (fileName?: string) => getInstance().exportList(fileName) | ||
| 26 | } | 30 | } |
| 27 | return [register, methods] | 31 | return [register, methods] |
| 28 | } | 32 | } |
yudao-ui-admin-vue3/src/plugins/vxeTable/index.ts
| 1 | -import { App, unref, watch } from 'vue' | 1 | +import { App, unref } from 'vue' |
| 2 | import XEUtils from 'xe-utils' | 2 | import XEUtils from 'xe-utils' |
| 3 | -import './index.scss' | ||
| 4 | import './renderer' | 3 | import './renderer' |
| 5 | import { i18n } from '@/plugins/vueI18n' | 4 | import { i18n } from '@/plugins/vueI18n' |
| 6 | -import { useAppStore } from '@/store/modules/app' | ||
| 7 | import zhCN from 'vxe-table/lib/locale/lang/zh-CN' | 5 | import zhCN from 'vxe-table/lib/locale/lang/zh-CN' |
| 8 | import enUS from 'vxe-table/lib/locale/lang/en-US' | 6 | import enUS from 'vxe-table/lib/locale/lang/en-US' |
| 9 | import { | 7 | import { |
| @@ -46,21 +44,6 @@ import { | @@ -46,21 +44,6 @@ import { | ||
| 46 | Table | 44 | Table |
| 47 | } from 'vxe-table' | 45 | } from 'vxe-table' |
| 48 | 46 | ||
| 49 | -const appStore = useAppStore() | ||
| 50 | -watch( | ||
| 51 | - () => appStore.getIsDark, | ||
| 52 | - () => { | ||
| 53 | - if (appStore.getIsDark) { | ||
| 54 | - import('./theme/dark.scss') | ||
| 55 | - } else { | ||
| 56 | - import('./theme/light.scss') | ||
| 57 | - } | ||
| 58 | - }, | ||
| 59 | - { | ||
| 60 | - deep: true, | ||
| 61 | - immediate: true | ||
| 62 | - } | ||
| 63 | -) | ||
| 64 | // 全局默认参数 | 47 | // 全局默认参数 |
| 65 | VXETable.setup({ | 48 | VXETable.setup({ |
| 66 | size: 'medium', // 全局尺寸 | 49 | size: 'medium', // 全局尺寸 |