feat: 封装xTable 组件
parent
6f8384af70
commit
f831b43dec
|
@ -0,0 +1,3 @@
|
||||||
|
import XTable from './src/XTable.vue'
|
||||||
|
|
||||||
|
export { XTable }
|
|
@ -0,0 +1,202 @@
|
||||||
|
<template>
|
||||||
|
<VxeGrid v-bind="getProps" ref="xGrid" :class="`${prefixCls}`" class="xtable-scrollbar">
|
||||||
|
<template #[item]="data" v-for="item in Object.keys($slots)" :key="item">
|
||||||
|
<slot :name="item" v-bind="data || {}"></slot>
|
||||||
|
</template>
|
||||||
|
</VxeGrid>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup name="XTable">
|
||||||
|
import { computed, PropType, ref, unref, useAttrs, watch } from 'vue'
|
||||||
|
import { SizeType, VxeGridInstance } from 'vxe-table'
|
||||||
|
import { useAppStore } from '@/store/modules/app'
|
||||||
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
|
import { XTableProps } from './type'
|
||||||
|
import { isBoolean, isFunction } from '@/utils/is'
|
||||||
|
|
||||||
|
const appStore = useAppStore()
|
||||||
|
|
||||||
|
const { getPrefixCls } = useDesign()
|
||||||
|
const prefixCls = getPrefixCls('x-vxe-table')
|
||||||
|
|
||||||
|
const attrs = useAttrs()
|
||||||
|
const emit = defineEmits(['register'])
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
options: {
|
||||||
|
type: Object as PropType<XTableProps>,
|
||||||
|
default: () => {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const innerProps = ref<Partial<XTableProps>>()
|
||||||
|
|
||||||
|
const getProps = computed(() => {
|
||||||
|
const options = innerProps.value || props.options
|
||||||
|
options.size = currentSize as any
|
||||||
|
options.height = 700
|
||||||
|
getColumnsConfig(options)
|
||||||
|
getProxyConfig(options)
|
||||||
|
getPageConfig(options)
|
||||||
|
getToolBarConfig(options)
|
||||||
|
// console.log(options);
|
||||||
|
return {
|
||||||
|
...options,
|
||||||
|
...attrs
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
|
||||||
|
watch(
|
||||||
|
() => appStore.getIsDark,
|
||||||
|
() => {
|
||||||
|
if (appStore.getIsDark == true) {
|
||||||
|
import('./style/dark.scss')
|
||||||
|
}
|
||||||
|
if (appStore.getIsDark == false) {
|
||||||
|
import('./style/light.scss')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
const currentSize = computed(() => {
|
||||||
|
let resSize: SizeType = 'small'
|
||||||
|
const appsize = appStore.getCurrentSize
|
||||||
|
switch (appsize) {
|
||||||
|
case 'large':
|
||||||
|
resSize = 'medium'
|
||||||
|
break
|
||||||
|
case 'default':
|
||||||
|
resSize = 'small'
|
||||||
|
break
|
||||||
|
case 'small':
|
||||||
|
resSize = 'mini'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return resSize
|
||||||
|
})
|
||||||
|
|
||||||
|
const reload = () => {
|
||||||
|
const g = unref(xGrid)
|
||||||
|
if (!g) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
g.commitProxy('query')
|
||||||
|
}
|
||||||
|
|
||||||
|
const getSearchData = () => {
|
||||||
|
const g = unref(xGrid)
|
||||||
|
if (!g) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const queryParams = Object.assign({}, JSON.parse(JSON.stringify(g.getProxyInfo()?.form)))
|
||||||
|
return queryParams
|
||||||
|
}
|
||||||
|
|
||||||
|
let proxyForm = false
|
||||||
|
|
||||||
|
// columns
|
||||||
|
const getColumnsConfig = (options: XTableProps) => {
|
||||||
|
const { allSchemas } = options
|
||||||
|
if (!allSchemas) return
|
||||||
|
if (allSchemas.printSchema) {
|
||||||
|
options.printConfig = {
|
||||||
|
columns: allSchemas.printSchema
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allSchemas.formSchema) {
|
||||||
|
proxyForm = true
|
||||||
|
options.formConfig = {
|
||||||
|
enabled: true,
|
||||||
|
titleWidth: 100,
|
||||||
|
titleAlign: 'right',
|
||||||
|
items: allSchemas.searchSchema
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allSchemas.tableSchema) {
|
||||||
|
options.columns = allSchemas.tableSchema
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 动态请求
|
||||||
|
const getProxyConfig = (options: XTableProps) => {
|
||||||
|
const { getListApi, proxyConfig, data } = options
|
||||||
|
if (proxyConfig || data) return
|
||||||
|
if (getListApi && isFunction(getListApi)) {
|
||||||
|
options.proxyConfig = {
|
||||||
|
seq: true, // 启用动态序号代理(分页之后索引自动计算为当前页的起始序号)
|
||||||
|
form: proxyForm, // 启用表单代理,当点击表单提交按钮时会自动触发 reload 行为
|
||||||
|
props: { result: 'list', total: 'total' },
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page, form }) => {
|
||||||
|
let queryParams: any = Object.assign({}, JSON.parse(JSON.stringify(form)))
|
||||||
|
if (options.params) {
|
||||||
|
queryParams = Object.assign(queryParams, options.params)
|
||||||
|
}
|
||||||
|
queryParams.pageSize = page.currentPage
|
||||||
|
queryParams.page = page.pageSize
|
||||||
|
|
||||||
|
return new Promise(async (resolve) => {
|
||||||
|
resolve(await getListApi(queryParams))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
const getPageConfig = (options: XTableProps) => {
|
||||||
|
const { pagination, pagerConfig } = options
|
||||||
|
if (pagerConfig) return
|
||||||
|
if (pagination) {
|
||||||
|
if (isBoolean(pagination)) {
|
||||||
|
options.pagerConfig = {
|
||||||
|
border: false, // 带边框
|
||||||
|
background: true, // 带背景颜色
|
||||||
|
perfect: false, // 配套的样式
|
||||||
|
pageSize: 10, // 每页大小
|
||||||
|
pagerCount: 7, // 显示页码按钮的数量
|
||||||
|
autoHidden: false, // 当只有一页时自动隐藏
|
||||||
|
pageSizes: [5, 10, 20, 30, 50, 100], // 每页大小选项列表
|
||||||
|
layouts: [
|
||||||
|
'PrevJump',
|
||||||
|
'PrevPage',
|
||||||
|
'JumpNumber',
|
||||||
|
'NextPage',
|
||||||
|
'NextJump',
|
||||||
|
'Sizes',
|
||||||
|
'FullJump',
|
||||||
|
'Total'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
options.pagerConfig = pagination
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// tool bar
|
||||||
|
const getToolBarConfig = (options: XTableProps) => {
|
||||||
|
const { toolBar, toolbarConfig } = options
|
||||||
|
if (toolbarConfig) return
|
||||||
|
if (toolBar) {
|
||||||
|
if (!isBoolean(toolBar)) {
|
||||||
|
options.toolbarConfig = toolBar
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
options.toolbarConfig = {
|
||||||
|
slots: { buttons: 'toolbar_buttons' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const setProps = (prop: Partial<XTableProps>) => {
|
||||||
|
innerProps.value = { ...unref(innerProps), ...prop }
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ reload, Ref: xGrid, getSearchData })
|
||||||
|
emit('register', { reload, getSearchData, setProps })
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
@import './style/index.scss';
|
||||||
|
</style>
|
|
@ -0,0 +1,81 @@
|
||||||
|
// 修改样式变量
|
||||||
|
//@import 'vxe-table/styles/variable.scss';
|
||||||
|
|
||||||
|
/*font*/
|
||||||
|
$vxe-font-color: #e5e7eb;
|
||||||
|
// $vxe-font-size: 14px !default;
|
||||||
|
// $vxe-font-size-medium: 16px !default;
|
||||||
|
// $vxe-font-size-small: 14px !default;
|
||||||
|
// $vxe-font-size-mini: 12px !default;
|
||||||
|
|
||||||
|
/*color*/
|
||||||
|
$vxe-primary-color: #409eff !default;
|
||||||
|
$vxe-success-color: #67c23a !default;
|
||||||
|
$vxe-info-color: #909399 !default;
|
||||||
|
$vxe-warning-color: #e6a23c !default;
|
||||||
|
$vxe-danger-color: #f56c6c !default;
|
||||||
|
$vxe-disabled-color: #bfbfbf !default;
|
||||||
|
$vxe-primary-disabled-color: #c0c4cc !default;
|
||||||
|
|
||||||
|
/*loading*/
|
||||||
|
$vxe-loading-color: $vxe-primary-color !default;
|
||||||
|
$vxe-loading-background-color: #1d1e1f !default;
|
||||||
|
$vxe-loading-z-index: 999 !default;
|
||||||
|
|
||||||
|
/*icon*/
|
||||||
|
$vxe-icon-font-family: Verdana, Arial, Tahoma !default;
|
||||||
|
$vxe-icon-background-color: #e5e7eb !default;
|
||||||
|
|
||||||
|
/*toolbar*/
|
||||||
|
$vxe-toolbar-background-color: #1d1e1f !default;
|
||||||
|
$vxe-toolbar-button-border: #dcdfe6 !default;
|
||||||
|
$vxe-toolbar-custom-active-background-color: #d9dadb !default;
|
||||||
|
$vxe-toolbar-panel-background-color: #e5e7eb !default;
|
||||||
|
|
||||||
|
$vxe-table-font-color: #e5e7eb;
|
||||||
|
$vxe-table-header-background-color: #1d1e1f;
|
||||||
|
$vxe-table-body-background-color: #141414;
|
||||||
|
$vxe-table-row-striped-background-color: #1d1d1d;
|
||||||
|
$vxe-table-row-hover-background-color: #1d1e1f;
|
||||||
|
$vxe-table-row-hover-striped-background-color: #1e1e1e;
|
||||||
|
$vxe-table-footer-background-color: #1d1e1f;
|
||||||
|
$vxe-table-row-current-background-color: #302d2d;
|
||||||
|
$vxe-table-column-current-background-color: #302d2d;
|
||||||
|
$vxe-table-column-hover-background-color: #302d2d;
|
||||||
|
$vxe-table-row-hover-current-background-color: #302d2d;
|
||||||
|
$vxe-table-row-checkbox-checked-background-color: #3e3c37 !default;
|
||||||
|
$vxe-table-row-hover-checkbox-checked-background-color: #615a4a !default;
|
||||||
|
$vxe-table-menu-background-color: #1d1e1f;
|
||||||
|
$vxe-table-border-width: 1px !default;
|
||||||
|
$vxe-table-border-color: #4c4d4f !default;
|
||||||
|
$vxe-table-fixed-left-scrolling-box-shadow: 8px 0px 10px -5px rgba(0, 0, 0, 0.12) !default;
|
||||||
|
$vxe-table-fixed-right-scrolling-box-shadow: -8px 0px 10px -5px rgba(0, 0, 0, 0.12) !default;
|
||||||
|
|
||||||
|
$vxe-form-background-color: #141414;
|
||||||
|
|
||||||
|
/*pager*/
|
||||||
|
$vxe-pager-background-color: #1d1e1f !default;
|
||||||
|
$vxe-pager-perfect-background-color: #262727 !default;
|
||||||
|
$vxe-pager-perfect-button-background-color: #a7a3a3 !default;
|
||||||
|
|
||||||
|
$vxe-input-background-color: #141414;
|
||||||
|
$vxe-input-border-color: #4c4d4f !default;
|
||||||
|
|
||||||
|
$vxe-select-option-hover-background-color: #262626 !default;
|
||||||
|
$vxe-select-panel-background-color: #141414 !default;
|
||||||
|
$vxe-select-empty-color: #262626 !default;
|
||||||
|
$vxe-optgroup-title-color: #909399 !default;
|
||||||
|
|
||||||
|
/*button*/
|
||||||
|
$vxe-button-default-background-color: #262626;
|
||||||
|
$vxe-button-dropdown-panel-background-color: #141414;
|
||||||
|
|
||||||
|
/*modal*/
|
||||||
|
$vxe-modal-header-background-color: #141414;
|
||||||
|
$vxe-modal-body-background-color: #141414;
|
||||||
|
$vxe-modal-border-color: #3b3b3b;
|
||||||
|
|
||||||
|
/*pulldown*/
|
||||||
|
$vxe-pulldown-panel-background-color: #262626 !default;
|
||||||
|
|
||||||
|
@import 'vxe-table/styles/index';
|
|
@ -0,0 +1,6 @@
|
||||||
|
@import 'vxe-table/styles/variable.scss';
|
||||||
|
@import 'vxe-table/styles/modules.scss';
|
||||||
|
// @import './theme/light.scss';
|
||||||
|
i {
|
||||||
|
border-color: initial;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
// 修改样式变量
|
||||||
|
// /*font*/
|
||||||
|
// $vxe-font-size: 12px !default;
|
||||||
|
// $vxe-font-size-medium: 16px !default;
|
||||||
|
// $vxe-font-size-small: 14px !default;
|
||||||
|
// $vxe-font-size-mini: 12px !default;
|
||||||
|
/*color*/
|
||||||
|
$vxe-primary-color: #409eff !default;
|
||||||
|
$vxe-success-color: #67c23a !default;
|
||||||
|
$vxe-info-color: #909399 !default;
|
||||||
|
$vxe-warning-color: #e6a23c !default;
|
||||||
|
$vxe-danger-color: #f56c6c !default;
|
||||||
|
$vxe-disabled-color: #bfbfbf !default;
|
||||||
|
$vxe-primary-disabled-color: #c0c4cc !default;
|
||||||
|
|
||||||
|
@import 'vxe-table/styles/index.scss';
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { CrudSchema } from '@/hooks/web/useCrudSchemas'
|
||||||
|
import type { VxeGridProps, VxeGridPropTypes } from 'vxe-table'
|
||||||
|
|
||||||
|
export type XTableProps<D = any> = VxeGridProps<D> & {
|
||||||
|
allSchemas?: CrudSchema
|
||||||
|
getListApi?: Function
|
||||||
|
deleteApi?: Function
|
||||||
|
exportListApi?: Function
|
||||||
|
params?: any
|
||||||
|
pagination?: boolean | VxeGridPropTypes.PagerConfig
|
||||||
|
toolBar?: boolean | VxeGridPropTypes.ToolbarConfig
|
||||||
|
afterFetch?: Function
|
||||||
|
}
|
||||||
|
export type XColumns = VxeGridPropTypes.Columns
|
||||||
|
|
||||||
|
export type VxeTableColumn = {
|
||||||
|
field: string
|
||||||
|
title?: string
|
||||||
|
children?: VxeTableColumn[]
|
||||||
|
} & Recordable
|
|
@ -4,6 +4,7 @@ import { Form } from '@/components/Form'
|
||||||
import { Table } from '@/components/Table'
|
import { Table } from '@/components/Table'
|
||||||
import { Search } from '@/components/Search'
|
import { Search } from '@/components/Search'
|
||||||
import { XModal } from '@/components/XModal'
|
import { XModal } from '@/components/XModal'
|
||||||
|
import { XTable } from '@/components/XTable'
|
||||||
import { XButton, XTextButton } from '@/components/XButton'
|
import { XButton, XTextButton } from '@/components/XButton'
|
||||||
import { DictTag } from '@/components/DictTag'
|
import { DictTag } from '@/components/DictTag'
|
||||||
import { ContentWrap } from '@/components/ContentWrap'
|
import { ContentWrap } from '@/components/ContentWrap'
|
||||||
|
@ -15,6 +16,7 @@ export const setupGlobCom = (app: App<Element>): void => {
|
||||||
app.component('Table', Table)
|
app.component('Table', Table)
|
||||||
app.component('Search', Search)
|
app.component('Search', Search)
|
||||||
app.component('XModal', XModal)
|
app.component('XModal', XModal)
|
||||||
|
app.component('XTable', XTable)
|
||||||
app.component('XButton', XButton)
|
app.component('XButton', XButton)
|
||||||
app.component('XTextButton', XTextButton)
|
app.component('XTextButton', XTextButton)
|
||||||
app.component('DictTag', DictTag)
|
app.component('DictTag', DictTag)
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { ref, unref } from 'vue'
|
||||||
|
import { XTableProps } from '@/components/XTable/src/type'
|
||||||
|
|
||||||
|
export interface tableMethod {
|
||||||
|
reload: () => void
|
||||||
|
setProps: (props: XTableProps) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useXTable(props: XTableProps): [Function, tableMethod] {
|
||||||
|
const tableRef = ref<Nullable<tableMethod>>(null)
|
||||||
|
|
||||||
|
function register(instance) {
|
||||||
|
tableRef.value = instance
|
||||||
|
props && instance.setProps(props)
|
||||||
|
}
|
||||||
|
function getInstance(): tableMethod {
|
||||||
|
const table = unref(tableRef)
|
||||||
|
if (!table) {
|
||||||
|
console.error('表格实例不存在')
|
||||||
|
}
|
||||||
|
return table as tableMethod
|
||||||
|
}
|
||||||
|
const methods: tableMethod = {
|
||||||
|
reload: () => getInstance().reload(),
|
||||||
|
setProps: (props) => getInstance().setProps(props)
|
||||||
|
}
|
||||||
|
return [register, methods]
|
||||||
|
}
|
Loading…
Reference in New Issue