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 | 12 | import { useDesign } from '@/hooks/web/useDesign' |
| 13 | 13 | import { XTableProps } from './type' |
| 14 | 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 | 22 | const appStore = useAppStore() |
| 17 | 23 | |
| ... | ... | @@ -21,30 +27,6 @@ const prefixCls = getPrefixCls('x-vxe-table') |
| 21 | 27 | const attrs = useAttrs() |
| 22 | 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 | 30 | watch( |
| 49 | 31 | () => appStore.getIsDark, |
| 50 | 32 | () => { |
| ... | ... | @@ -57,6 +39,7 @@ watch( |
| 57 | 39 | }, |
| 58 | 40 | { immediate: true } |
| 59 | 41 | ) |
| 42 | + | |
| 60 | 43 | const currentSize = computed(() => { |
| 61 | 44 | let resSize: SizeType = 'small' |
| 62 | 45 | const appsize = appStore.getCurrentSize |
| ... | ... | @@ -74,25 +57,42 @@ const currentSize = computed(() => { |
| 74 | 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 | 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 | 96 | // columns |
| 97 | 97 | const getColumnsConfig = (options: XTableProps) => { |
| 98 | 98 | const { allSchemas } = options |
| ... | ... | @@ -131,21 +131,55 @@ const getProxyConfig = (options: XTableProps) => { |
| 131 | 131 | if (options.params) { |
| 132 | 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 | 138 | return new Promise(async (resolve) => { |
| 138 | 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 | 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 | 183 | if (pagerConfig) return |
| 150 | 184 | if (pagination) { |
| 151 | 185 | if (isBoolean(pagination)) { |
| ... | ... | @@ -171,6 +205,28 @@ const getPageConfig = (options: XTableProps) => { |
| 171 | 205 | return |
| 172 | 206 | } |
| 173 | 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 | 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 | 307 | const setProps = (prop: Partial<XTableProps>) => { |
| 194 | 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 | 313 | </script> |
| 200 | 314 | <style lang="scss"> |
| 201 | 315 | @import './style/index.scss'; | ... | ... |
yudao-ui-admin-vue3/src/components/XTable/src/type.ts
| 1 | 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 | 4 | export type XTableProps<D = any> = VxeGridProps<D> & { |
| 5 | 5 | allSchemas?: CrudSchema |
| 6 | + height?: number // 高度 默认730 | |
| 7 | + topActionSlots?: boolean // 是否开启表格内顶部操作栏插槽 | |
| 8 | + treeConfig?: VxeTablePropTypes.TreeConfig // 树形表单配置 | |
| 6 | 9 | getListApi?: Function |
| 10 | + getAllListApi?: Function | |
| 7 | 11 | deleteApi?: Function |
| 8 | 12 | exportListApi?: Function |
| 13 | + exportName?: string // 导出文件夹名称 | |
| 9 | 14 | params?: any |
| 10 | 15 | pagination?: boolean | VxeGridPropTypes.PagerConfig |
| 11 | 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 | 4 | export interface tableMethod { |
| 5 | 5 | reload: () => void |
| 6 | 6 | setProps: (props: XTableProps) => void |
| 7 | + deleteData: (ids: string | number) => void | |
| 8 | + exportList: (fileName?: string) => void | |
| 7 | 9 | } |
| 8 | 10 | |
| 9 | 11 | export function useXTable(props: XTableProps): [Function, tableMethod] { |
| ... | ... | @@ -22,7 +24,9 @@ export function useXTable(props: XTableProps): [Function, tableMethod] { |
| 22 | 24 | } |
| 23 | 25 | const methods: tableMethod = { |
| 24 | 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 | 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 | 2 | import XEUtils from 'xe-utils' |
| 3 | -import './index.scss' | |
| 4 | 3 | import './renderer' |
| 5 | 4 | import { i18n } from '@/plugins/vueI18n' |
| 6 | -import { useAppStore } from '@/store/modules/app' | |
| 7 | 5 | import zhCN from 'vxe-table/lib/locale/lang/zh-CN' |
| 8 | 6 | import enUS from 'vxe-table/lib/locale/lang/en-US' |
| 9 | 7 | import { |
| ... | ... | @@ -46,21 +44,6 @@ import { |
| 46 | 44 | Table |
| 47 | 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 | 48 | VXETable.setup({ |
| 66 | 49 | size: 'medium', // 全局尺寸 | ... | ... |