正式移除 VXE 表格
This commit is contained in:
parent
fd447dc7a3
commit
ebbf47f509
@ -42,7 +42,6 @@
|
|||||||
| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 的超集 | 4.9.5 |
|
| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 的超集 | 4.9.5 |
|
||||||
| [pinia](https://pinia.vuejs.org/) | Vue 存储库 替代 vuex5 | 2.0.33 |
|
| [pinia](https://pinia.vuejs.org/) | Vue 存储库 替代 vuex5 | 2.0.33 |
|
||||||
| [vueuse](https://vueuse.org/) | 常用工具集 | 9.13.0 |
|
| [vueuse](https://vueuse.org/) | 常用工具集 | 9.13.0 |
|
||||||
| [vxe-table](https://vxetable.cn/) | Vue 最强表单 | 4.3.10 |
|
|
||||||
| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.2.2 |
|
| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.2.2 |
|
||||||
| [vue-router](https://router.vuejs.org/) | Vue 路由 | 4.1.6 |
|
| [vue-router](https://router.vuejs.org/) | Vue 路由 | 4.1.6 |
|
||||||
| [windicss](https://cn.windicss.org/) | 下一代工具优先的 CSS 框架 | 3.5.6 |
|
| [windicss](https://cn.windicss.org/) | 下一代工具优先的 CSS 框架 | 3.5.6 |
|
||||||
|
@ -18,10 +18,6 @@ const include = [
|
|||||||
'lodash-es',
|
'lodash-es',
|
||||||
'nprogress',
|
'nprogress',
|
||||||
'animate.css',
|
'animate.css',
|
||||||
'vxe-table',
|
|
||||||
'vxe-table/es/style',
|
|
||||||
'vxe-table/lib/locale/lang/zh-CN',
|
|
||||||
'vxe-table/lib/locale/lang/en-US',
|
|
||||||
'web-storage-cache',
|
'web-storage-cache',
|
||||||
'@iconify/iconify',
|
'@iconify/iconify',
|
||||||
'@vueuse/core',
|
'@vueuse/core',
|
||||||
|
@ -69,7 +69,6 @@
|
|||||||
"vue-router": "^4.1.6",
|
"vue-router": "^4.1.6",
|
||||||
"vue-types": "^5.0.2",
|
"vue-types": "^5.0.2",
|
||||||
"vuedraggable": "^4.1.0",
|
"vuedraggable": "^4.1.0",
|
||||||
"vxe-table": "^4.3.11",
|
|
||||||
"web-storage-cache": "^1.1.1",
|
"web-storage-cache": "^1.1.1",
|
||||||
"xe-utils": "^3.5.7",
|
"xe-utils": "^3.5.7",
|
||||||
"xml-js": "^1.6.11"
|
"xml-js": "^1.6.11"
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
import XModal from './src/XModal.vue'
|
|
||||||
|
|
||||||
export { XModal }
|
|
@ -1,44 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { propTypes } from '@/utils/propTypes'
|
|
||||||
const slots = useSlots()
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
id: propTypes.string.def('model_1'),
|
|
||||||
modelValue: propTypes.bool.def(false),
|
|
||||||
fullscreen: propTypes.bool.def(false),
|
|
||||||
loading: propTypes.bool.def(false),
|
|
||||||
title: propTypes.string.def('弹窗'),
|
|
||||||
width: propTypes.string.def('40%'),
|
|
||||||
height: propTypes.string,
|
|
||||||
minWidth: propTypes.string.def('460'),
|
|
||||||
minHeight: propTypes.string.def('320'),
|
|
||||||
showFooter: propTypes.bool.def(true),
|
|
||||||
maskClosable: propTypes.bool.def(false),
|
|
||||||
escClosable: propTypes.bool.def(false)
|
|
||||||
})
|
|
||||||
|
|
||||||
const getBindValue = computed(() => {
|
|
||||||
const attrs = useAttrs()
|
|
||||||
const obj = { ...attrs, ...props }
|
|
||||||
return obj
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<vxe-modal v-bind="getBindValue" destroy-on-close show-zoom resize transfer>
|
|
||||||
<template v-if="slots.header" #header>
|
|
||||||
<slot name="header"></slot>
|
|
||||||
</template>
|
|
||||||
<ElScrollbar>
|
|
||||||
<template v-if="slots.default" #default>
|
|
||||||
<slot name="default"></slot>
|
|
||||||
</template>
|
|
||||||
</ElScrollbar>
|
|
||||||
<template v-if="slots.corner" #corner>
|
|
||||||
<slot name="corner"></slot>
|
|
||||||
</template>
|
|
||||||
<template v-if="slots.footer" #footer>
|
|
||||||
<slot name="footer"></slot>
|
|
||||||
</template>
|
|
||||||
</vxe-modal>
|
|
||||||
</template>
|
|
@ -1,3 +0,0 @@
|
|||||||
import XTable from './src/XTable.vue'
|
|
||||||
|
|
||||||
export { XTable }
|
|
@ -1,442 +0,0 @@
|
|||||||
<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 setup lang="ts" name="XTable">
|
|
||||||
import { PropType } 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'
|
|
||||||
import styleCss from './style/dark.scss?inline'
|
|
||||||
import download from '@/utils/download'
|
|
||||||
|
|
||||||
const { t } = useI18n()
|
|
||||||
const message = useMessage() // 消息弹窗
|
|
||||||
|
|
||||||
const appStore = useAppStore()
|
|
||||||
|
|
||||||
const { getPrefixCls } = useDesign()
|
|
||||||
const prefixCls = getPrefixCls('x-vxe-table')
|
|
||||||
|
|
||||||
const attrs = useAttrs()
|
|
||||||
const emit = defineEmits(['register'])
|
|
||||||
const removeStyles = () => {
|
|
||||||
const filename = 'cssTheme'
|
|
||||||
//移除引入的文件名
|
|
||||||
const targetelement = 'style'
|
|
||||||
const targetattr = 'id'
|
|
||||||
const allsuspects = document.getElementsByTagName(targetelement)
|
|
||||||
for (let i = allsuspects.length; i >= 0; i--) {
|
|
||||||
if (
|
|
||||||
allsuspects[i] &&
|
|
||||||
allsuspects[i].getAttribute(targetattr) != null &&
|
|
||||||
allsuspects[i].getAttribute(targetattr)?.indexOf(filename) != -1
|
|
||||||
) {
|
|
||||||
console.log(allsuspects[i], 'node')
|
|
||||||
allsuspects[i].parentNode?.removeChild(allsuspects[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const reImport = () => {
|
|
||||||
const head = document.getElementsByTagName('head')[0]
|
|
||||||
const style = document.createElement('style')
|
|
||||||
style.innerText = styleCss
|
|
||||||
style.id = 'cssTheme'
|
|
||||||
head.appendChild(style)
|
|
||||||
}
|
|
||||||
watch(
|
|
||||||
() => appStore.getIsDark,
|
|
||||||
() => {
|
|
||||||
if (appStore.getIsDark) {
|
|
||||||
reImport()
|
|
||||||
}
|
|
||||||
if (!appStore.getIsDark) {
|
|
||||||
removeStyles()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ 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 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
|
|
||||||
getOptionInitConfig(options)
|
|
||||||
getColumnsConfig(options)
|
|
||||||
getProxyConfig(options)
|
|
||||||
getPageConfig(options)
|
|
||||||
getToolBarConfig(options)
|
|
||||||
// console.log(options);
|
|
||||||
return {
|
|
||||||
...options,
|
|
||||||
...attrs
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
|
|
||||||
|
|
||||||
let proxyForm = false
|
|
||||||
|
|
||||||
const getOptionInitConfig = (options: XTableProps) => {
|
|
||||||
options.size = currentSize as any
|
|
||||||
options.rowConfig = {
|
|
||||||
isCurrent: true, // 当鼠标点击行时,是否要高亮当前行
|
|
||||||
isHover: true // 当鼠标移到行时,是否要高亮当前行
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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: 110,
|
|
||||||
titleAlign: 'right',
|
|
||||||
items: allSchemas.searchSchema
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (allSchemas.tableSchema) {
|
|
||||||
options.columns = allSchemas.tableSchema
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 动态请求
|
|
||||||
const getProxyConfig = (options: XTableProps) => {
|
|
||||||
const { getListApi, proxyConfig, data, isList } = options
|
|
||||||
if (proxyConfig || data) return
|
|
||||||
if (getListApi && isFunction(getListApi)) {
|
|
||||||
if (!isList) {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
if (!options?.treeConfig) {
|
|
||||||
queryParams.pageSize = page.pageSize
|
|
||||||
queryParams.pageNo = page.currentPage
|
|
||||||
}
|
|
||||||
return new Promise(async (resolve) => {
|
|
||||||
resolve(await getListApi(queryParams))
|
|
||||||
})
|
|
||||||
},
|
|
||||||
delete: ({ body }) => {
|
|
||||||
return new Promise(async (resolve) => {
|
|
||||||
if (options.deleteApi) {
|
|
||||||
resolve(await options.deleteApi(JSON.stringify(body)))
|
|
||||||
} else {
|
|
||||||
Promise.reject('未设置deleteApi')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
queryAll: ({ form }) => {
|
|
||||||
const queryParams = Object.assign({}, JSON.parse(JSON.stringify(form)))
|
|
||||||
return new Promise(async (resolve) => {
|
|
||||||
if (options.getAllListApi) {
|
|
||||||
resolve(await options.getAllListApi(queryParams))
|
|
||||||
} else {
|
|
||||||
resolve(await getListApi(queryParams))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
options.proxyConfig = {
|
|
||||||
seq: true, // 启用动态序号代理(分页之后索引自动计算为当前页的起始序号)
|
|
||||||
form: true, // 启用表单代理,当点击表单提交按钮时会自动触发 reload 行为
|
|
||||||
props: { result: 'data' },
|
|
||||||
ajax: {
|
|
||||||
query: ({ form }) => {
|
|
||||||
let queryParams: any = Object.assign({}, JSON.parse(JSON.stringify(form)))
|
|
||||||
if (options?.params) {
|
|
||||||
queryParams = Object.assign(queryParams, options.params)
|
|
||||||
}
|
|
||||||
return new Promise(async (resolve) => {
|
|
||||||
resolve(await getListApi(queryParams))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (options.exportListApi) {
|
|
||||||
options.exportConfig = {
|
|
||||||
filename: options?.exportName,
|
|
||||||
// 默认选中类型
|
|
||||||
type: 'csv',
|
|
||||||
// 自定义数据量列表
|
|
||||||
modes: options?.getAllListApi ? ['current', 'all'] : ['current'],
|
|
||||||
columns: options?.allSchemas?.printSchema
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
const getPageConfig = (options: XTableProps) => {
|
|
||||||
const { pagination, pagerConfig, treeConfig, isList } = options
|
|
||||||
if (isList) return
|
|
||||||
if (treeConfig) {
|
|
||||||
options.treeConfig = options.treeConfig
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (pagerConfig) return
|
|
||||||
if (pagination) {
|
|
||||||
if (isBoolean(pagination)) {
|
|
||||||
options.pagerConfig = {
|
|
||||||
border: false, // 带边框
|
|
||||||
background: false, // 带背景颜色
|
|
||||||
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
|
|
||||||
} else {
|
|
||||||
if (pagination != false) {
|
|
||||||
options.pagerConfig = {
|
|
||||||
border: false, // 带边框
|
|
||||||
background: false, // 带背景颜色
|
|
||||||
perfect: false, // 配套的样式
|
|
||||||
pageSize: 10, // 每页大小
|
|
||||||
pagerCount: 7, // 显示页码按钮的数量
|
|
||||||
autoHidden: false, // 当只有一页时自动隐藏
|
|
||||||
pageSizes: [5, 10, 20, 30, 50, 100], // 每页大小选项列表
|
|
||||||
layouts: [
|
|
||||||
'Sizes',
|
|
||||||
'PrevJump',
|
|
||||||
'PrevPage',
|
|
||||||
'Number',
|
|
||||||
'NextPage',
|
|
||||||
'NextJump',
|
|
||||||
'FullJump',
|
|
||||||
'Total'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// tool bar
|
|
||||||
const getToolBarConfig = (options: XTableProps) => {
|
|
||||||
const { toolBar, toolbarConfig, topActionSlots } = options
|
|
||||||
if (toolbarConfig) return
|
|
||||||
if (toolBar) {
|
|
||||||
if (!isBoolean(toolBar)) {
|
|
||||||
console.info(2)
|
|
||||||
options.toolbarConfig = toolBar
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else if (topActionSlots != false) {
|
|
||||||
options.toolbarConfig = {
|
|
||||||
slots: { buttons: 'toolbar_buttons' }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
options.toolbarConfig = {
|
|
||||||
enabled: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 刷新列表
|
|
||||||
const reload = () => {
|
|
||||||
const g = unref(xGrid)
|
|
||||||
if (!g) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
g.commitProxy('query')
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除
|
|
||||||
const deleteData = async (id: string | number) => {
|
|
||||||
const g = unref(xGrid)
|
|
||||||
if (!g) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const options = innerProps.value || props.options
|
|
||||||
if (!options.deleteApi) {
|
|
||||||
console.error('未传入delListApi')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return new Promise(async () => {
|
|
||||||
message.delConfirm().then(async () => {
|
|
||||||
await (options?.deleteApi && options?.deleteApi(id))
|
|
||||||
message.success(t('common.delSuccess'))
|
|
||||||
// 刷新列表
|
|
||||||
reload()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 批量删除
|
|
||||||
const deleteBatch = async () => {
|
|
||||||
const g = unref(xGrid)
|
|
||||||
if (!g) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const rows = g.getCheckboxRecords() || g.getRadioRecord()
|
|
||||||
let ids: any[] = []
|
|
||||||
if (rows.length == 0) {
|
|
||||||
message.error('请选择数据')
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
rows.forEach((row) => {
|
|
||||||
ids.push(row.id)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const options = innerProps.value || props.options
|
|
||||||
if (options.deleteListApi) {
|
|
||||||
return new Promise(async () => {
|
|
||||||
message.delConfirm().then(async () => {
|
|
||||||
await (options?.deleteListApi && options?.deleteListApi(ids))
|
|
||||||
message.success(t('common.delSuccess'))
|
|
||||||
// 刷新列表
|
|
||||||
reload()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else if (options.deleteApi) {
|
|
||||||
return new Promise(async () => {
|
|
||||||
message.delConfirm().then(async () => {
|
|
||||||
ids.forEach(async (id) => {
|
|
||||||
await (options?.deleteApi && options?.deleteApi(id))
|
|
||||||
})
|
|
||||||
message.success(t('common.delSuccess'))
|
|
||||||
// 刷新列表
|
|
||||||
reload()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
console.error('未传入delListApi')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 导出
|
|
||||||
const exportList = async (fileName?: string) => {
|
|
||||||
const g = unref(xGrid)
|
|
||||||
if (!g) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const options = innerProps.value || props.options
|
|
||||||
if (!options?.exportListApi) {
|
|
||||||
console.error('未传入exportListApi')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const queryParams = Object.assign({}, JSON.parse(JSON.stringify(g.getProxyInfo()?.form)))
|
|
||||||
message.exportConfirm().then(async () => {
|
|
||||||
const res = await (options?.exportListApi && options?.exportListApi(queryParams))
|
|
||||||
download.excel(res as unknown as Blob, fileName ? fileName : 'excel.xls')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取查询参数
|
|
||||||
const getSearchData = () => {
|
|
||||||
const g = unref(xGrid)
|
|
||||||
if (!g) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const queryParams = Object.assign({}, JSON.parse(JSON.stringify(g.getProxyInfo()?.form)))
|
|
||||||
return queryParams
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取当前列
|
|
||||||
const getCurrentColumn = () => {
|
|
||||||
const g = unref(xGrid)
|
|
||||||
if (!g) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return g.getCurrentColumn()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取当前选中列,redio
|
|
||||||
const getRadioRecord = () => {
|
|
||||||
const g = unref(xGrid)
|
|
||||||
if (!g) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return g.getRadioRecord(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取当前选中列,checkbox
|
|
||||||
const getCheckboxRecords = () => {
|
|
||||||
const g = unref(xGrid)
|
|
||||||
if (!g) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return g.getCheckboxRecords(false)
|
|
||||||
}
|
|
||||||
const setProps = (prop: Partial<XTableProps>) => {
|
|
||||||
innerProps.value = { ...unref(innerProps), ...prop }
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({ reload, Ref: xGrid, getSearchData, deleteData, exportList })
|
|
||||||
emit('register', {
|
|
||||||
reload,
|
|
||||||
getSearchData,
|
|
||||||
setProps,
|
|
||||||
deleteData,
|
|
||||||
deleteBatch,
|
|
||||||
exportList,
|
|
||||||
getCurrentColumn,
|
|
||||||
getRadioRecord,
|
|
||||||
getCheckboxRecords
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<style lang="scss">
|
|
||||||
@import './style/index.scss';
|
|
||||||
</style>
|
|
@ -1,81 +0,0 @@
|
|||||||
// 修改样式变量
|
|
||||||
//@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.scss';
|
|
@ -1,6 +0,0 @@
|
|||||||
// @import 'vxe-table/styles/variable.scss';
|
|
||||||
// @import 'vxe-table/styles/modules.scss';
|
|
||||||
// @import './theme/light.scss';
|
|
||||||
i {
|
|
||||||
border-color: initial;
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
// 修改样式变量
|
|
||||||
// /*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';
|
|
@ -1,26 +0,0 @@
|
|||||||
import { CrudSchema } from '@/hooks/web/useCrudSchemas'
|
|
||||||
import type { VxeGridProps, VxeGridPropTypes, VxeTablePropTypes } from 'vxe-table'
|
|
||||||
|
|
||||||
export type XTableProps<D = any> = VxeGridProps<D> & {
|
|
||||||
allSchemas?: CrudSchema
|
|
||||||
height?: number // 高度 默认730
|
|
||||||
topActionSlots?: boolean // 是否开启表格内顶部操作栏插槽
|
|
||||||
treeConfig?: VxeTablePropTypes.TreeConfig // 树形表单配置
|
|
||||||
isList?: boolean // 是否不带分页的list
|
|
||||||
getListApi?: Function // 获取列表接口
|
|
||||||
getAllListApi?: Function // 获取全部数据接口 用于 vxe 导出
|
|
||||||
deleteApi?: Function // 删除接口
|
|
||||||
deleteListApi?: Function // 批量删除接口
|
|
||||||
exportListApi?: Function // 导出接口
|
|
||||||
exportName?: string // 导出文件夹名称
|
|
||||||
params?: any // 其他查询参数
|
|
||||||
pagination?: boolean | VxeGridPropTypes.PagerConfig // 分页配置参数
|
|
||||||
toolBar?: boolean | VxeGridPropTypes.ToolbarConfig // 右侧工具栏配置参数
|
|
||||||
}
|
|
||||||
export type XColumns = VxeGridPropTypes.Columns
|
|
||||||
|
|
||||||
export type VxeTableColumn = {
|
|
||||||
field: string
|
|
||||||
title?: string
|
|
||||||
children?: VxeTableColumn[]
|
|
||||||
} & Recordable
|
|
@ -3,8 +3,6 @@ import { Icon } from './Icon'
|
|||||||
import { Form } from '@/components/Form'
|
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 { 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,8 +13,6 @@ export const setupGlobCom = (app: App<Element>): void => {
|
|||||||
app.component('Form', Form)
|
app.component('Form', Form)
|
||||||
app.component('Table', Table)
|
app.component('Table', Table)
|
||||||
app.component('Search', Search)
|
app.component('Search', Search)
|
||||||
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)
|
||||||
|
@ -1,354 +0,0 @@
|
|||||||
import {
|
|
||||||
FormItemRenderOptions,
|
|
||||||
VxeColumnPropTypes,
|
|
||||||
VxeFormItemProps,
|
|
||||||
VxeGridPropTypes,
|
|
||||||
VxeTableDefines
|
|
||||||
} from 'vxe-table'
|
|
||||||
import { eachTree } from 'xe-utils'
|
|
||||||
|
|
||||||
import { getBoolDictOptions, getDictOptions, getIntDictOptions } from '@/utils/dict'
|
|
||||||
import { FormSchema } from '@/types/form'
|
|
||||||
import { VxeTableColumn } from '@/types/table'
|
|
||||||
import { ComponentOptions } from '@/types/components'
|
|
||||||
import { DescriptionsSchema } from '@/types/descriptions'
|
|
||||||
|
|
||||||
export type VxeCrudSchema = {
|
|
||||||
primaryKey?: string // 主键ID
|
|
||||||
primaryTitle?: string // 主键标题 默认为序号
|
|
||||||
primaryType?: VxeColumnPropTypes.Type | 'id' // 还支持 "id" | "seq" | "radio" | "checkbox" | "expand" | "html" | null
|
|
||||||
firstColumn?: VxeColumnPropTypes.Type // 第一列显示类型
|
|
||||||
action?: boolean // 是否开启表格内右侧操作栏插槽
|
|
||||||
actionTitle?: string // 操作栏标题 默认为操作
|
|
||||||
actionWidth?: string // 操作栏插槽宽度,一般2个字带图标 text 类型按钮 50-70
|
|
||||||
columns: VxeCrudColumns[]
|
|
||||||
searchSpan?: number
|
|
||||||
}
|
|
||||||
type VxeCrudColumns = Omit<VxeTableColumn, 'children'> & {
|
|
||||||
field: string // 字段名
|
|
||||||
title?: string // 标题名
|
|
||||||
formatter?: VxeColumnPropTypes.Formatter // vxe formatter格式化
|
|
||||||
isSearch?: boolean // 是否在查询显示
|
|
||||||
search?: CrudSearchParams // 查询的详细配置
|
|
||||||
isTable?: boolean // 是否在列表显示
|
|
||||||
table?: CrudTableParams // 列表的详细配置
|
|
||||||
isForm?: boolean // 是否在表单显示
|
|
||||||
form?: CrudFormParams // 表单的详细配置
|
|
||||||
isDetail?: boolean // 是否在详情显示
|
|
||||||
detail?: CrudDescriptionsParams // 详情的详细配置
|
|
||||||
print?: CrudPrintParams // vxe 打印的字段
|
|
||||||
children?: VxeCrudColumns[] // 子级
|
|
||||||
dictType?: string // 字典类型
|
|
||||||
dictClass?: 'string' | 'number' | 'boolean' // 字典数据类型 string | number | boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
type CrudSearchParams = {
|
|
||||||
// 是否显示在查询项
|
|
||||||
show?: boolean
|
|
||||||
} & Omit<VxeFormItemProps, 'field'>
|
|
||||||
|
|
||||||
type CrudTableParams = {
|
|
||||||
// 是否显示表头
|
|
||||||
show?: boolean
|
|
||||||
} & Omit<VxeTableDefines.ColumnOptions, 'field'>
|
|
||||||
|
|
||||||
type CrudFormParams = {
|
|
||||||
// 是否显示表单项
|
|
||||||
show?: boolean
|
|
||||||
} & Omit<FormSchema, 'field'>
|
|
||||||
|
|
||||||
type CrudDescriptionsParams = {
|
|
||||||
// 是否显示表单项
|
|
||||||
show?: boolean
|
|
||||||
} & Omit<DescriptionsSchema, 'field'>
|
|
||||||
|
|
||||||
type CrudPrintParams = {
|
|
||||||
// 是否显示打印项
|
|
||||||
show?: boolean
|
|
||||||
} & Omit<VxeTableDefines.ColumnInfo[], 'field'>
|
|
||||||
|
|
||||||
export type VxeAllSchemas = {
|
|
||||||
searchSchema: VxeFormItemProps[]
|
|
||||||
tableSchema: VxeGridPropTypes.Columns
|
|
||||||
formSchema: FormSchema[]
|
|
||||||
detailSchema: DescriptionsSchema[]
|
|
||||||
printSchema: VxeTableDefines.ColumnInfo[]
|
|
||||||
}
|
|
||||||
|
|
||||||
// 过滤所有结构
|
|
||||||
export const useVxeCrudSchemas = (
|
|
||||||
crudSchema: VxeCrudSchema
|
|
||||||
): {
|
|
||||||
allSchemas: VxeAllSchemas
|
|
||||||
} => {
|
|
||||||
// 所有结构数据
|
|
||||||
const allSchemas = reactive<VxeAllSchemas>({
|
|
||||||
searchSchema: [],
|
|
||||||
tableSchema: [],
|
|
||||||
formSchema: [],
|
|
||||||
detailSchema: [],
|
|
||||||
printSchema: []
|
|
||||||
})
|
|
||||||
|
|
||||||
const searchSchema = filterSearchSchema(crudSchema)
|
|
||||||
allSchemas.searchSchema = searchSchema || []
|
|
||||||
|
|
||||||
const tableSchema = filterTableSchema(crudSchema)
|
|
||||||
allSchemas.tableSchema = tableSchema || []
|
|
||||||
|
|
||||||
const formSchema = filterFormSchema(crudSchema)
|
|
||||||
allSchemas.formSchema = formSchema
|
|
||||||
|
|
||||||
const detailSchema = filterDescriptionsSchema(crudSchema)
|
|
||||||
allSchemas.detailSchema = detailSchema
|
|
||||||
|
|
||||||
const printSchema = filterPrintSchema(crudSchema)
|
|
||||||
allSchemas.printSchema = printSchema
|
|
||||||
|
|
||||||
return {
|
|
||||||
allSchemas
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 过滤 Search 结构
|
|
||||||
const filterSearchSchema = (crudSchema: VxeCrudSchema): VxeFormItemProps[] => {
|
|
||||||
const { t } = useI18n()
|
|
||||||
const span = crudSchema.searchSpan ? crudSchema.searchSpan : 6
|
|
||||||
const spanLength = 24 / span
|
|
||||||
const searchSchema: VxeFormItemProps[] = []
|
|
||||||
eachTree(crudSchema.columns, (schemaItem: VxeCrudColumns) => {
|
|
||||||
// 判断是否显示
|
|
||||||
if (schemaItem?.isSearch || schemaItem.search?.show) {
|
|
||||||
let itemRenderName = schemaItem?.search?.itemRender?.name || '$input'
|
|
||||||
const options: any[] = []
|
|
||||||
let itemRender: FormItemRenderOptions = {}
|
|
||||||
|
|
||||||
if (schemaItem.dictType) {
|
|
||||||
const allOptions = { label: '全部', value: '' }
|
|
||||||
options.push(allOptions)
|
|
||||||
getDictOptions(schemaItem.dictType).forEach((dict) => {
|
|
||||||
options.push(dict)
|
|
||||||
})
|
|
||||||
itemRender.options = options
|
|
||||||
if (!schemaItem?.search?.itemRender?.name) itemRenderName = '$select'
|
|
||||||
itemRender = {
|
|
||||||
name: itemRenderName,
|
|
||||||
options: options,
|
|
||||||
props: { placeholder: t('common.selectText') }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (schemaItem.search?.itemRender) {
|
|
||||||
itemRender = schemaItem.search.itemRender
|
|
||||||
} else {
|
|
||||||
itemRender = {
|
|
||||||
name: itemRenderName,
|
|
||||||
props:
|
|
||||||
itemRenderName == '$input'
|
|
||||||
? { placeholder: t('common.inputText') }
|
|
||||||
: { placeholder: t('common.selectText') }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const searchSchemaItem = {
|
|
||||||
// 默认为 input
|
|
||||||
folding: searchSchema.length > spanLength - 1,
|
|
||||||
itemRender: schemaItem.itemRender ? schemaItem.itemRender : itemRender,
|
|
||||||
field: schemaItem.field,
|
|
||||||
title: schemaItem.search?.title || schemaItem.title,
|
|
||||||
slots: schemaItem.search?.slots,
|
|
||||||
span: span
|
|
||||||
}
|
|
||||||
searchSchema.push(searchSchemaItem)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (searchSchema.length > 0) {
|
|
||||||
// 添加搜索按钮
|
|
||||||
const buttons: VxeFormItemProps = {
|
|
||||||
span: 24,
|
|
||||||
align: 'right',
|
|
||||||
collapseNode: searchSchema.length > spanLength,
|
|
||||||
itemRender: {
|
|
||||||
name: '$buttons',
|
|
||||||
children: [
|
|
||||||
{ props: { type: 'submit', content: t('common.query'), status: 'primary' } },
|
|
||||||
{ props: { type: 'reset', content: t('common.reset') } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
searchSchema.push(buttons)
|
|
||||||
}
|
|
||||||
return searchSchema
|
|
||||||
}
|
|
||||||
|
|
||||||
// 过滤 table 结构
|
|
||||||
const filterTableSchema = (crudSchema: VxeCrudSchema): VxeGridPropTypes.Columns => {
|
|
||||||
const { t } = useI18n()
|
|
||||||
const tableSchema: VxeGridPropTypes.Columns = []
|
|
||||||
// 第一列
|
|
||||||
if (crudSchema.firstColumn) {
|
|
||||||
const tableSchemaItem = {
|
|
||||||
type: crudSchema.firstColumn,
|
|
||||||
width: '50px'
|
|
||||||
}
|
|
||||||
tableSchema.push(tableSchemaItem)
|
|
||||||
}
|
|
||||||
// 主键ID
|
|
||||||
if (crudSchema.primaryKey && crudSchema.primaryType) {
|
|
||||||
const primaryTitle = crudSchema.primaryTitle ? crudSchema.primaryTitle : t('common.index')
|
|
||||||
const primaryWidth = primaryTitle.length * 30 + 'px'
|
|
||||||
|
|
||||||
let tableSchemaItem: { [x: string]: any } = {
|
|
||||||
title: primaryTitle,
|
|
||||||
field: crudSchema.primaryKey,
|
|
||||||
width: primaryWidth
|
|
||||||
}
|
|
||||||
if (crudSchema.primaryType != 'id') {
|
|
||||||
tableSchemaItem = {
|
|
||||||
...tableSchemaItem,
|
|
||||||
type: crudSchema.primaryType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tableSchema.push(tableSchemaItem)
|
|
||||||
}
|
|
||||||
|
|
||||||
eachTree(crudSchema.columns, (schemaItem: VxeCrudColumns) => {
|
|
||||||
// 判断是否显示
|
|
||||||
if (schemaItem?.isTable !== false && schemaItem?.table?.show !== false) {
|
|
||||||
const tableSchemaItem = {
|
|
||||||
...schemaItem.table,
|
|
||||||
field: schemaItem.field,
|
|
||||||
title: schemaItem.table?.title || schemaItem.title,
|
|
||||||
minWidth: '80px'
|
|
||||||
}
|
|
||||||
tableSchemaItem.showOverflow = 'tooltip'
|
|
||||||
if (schemaItem?.formatter) {
|
|
||||||
tableSchemaItem.formatter = schemaItem.formatter
|
|
||||||
tableSchemaItem.width = tableSchemaItem.width ? tableSchemaItem.width : 160
|
|
||||||
}
|
|
||||||
if (schemaItem?.dictType) {
|
|
||||||
tableSchemaItem.cellRender = {
|
|
||||||
name: 'XDict',
|
|
||||||
content: schemaItem.dictType
|
|
||||||
}
|
|
||||||
tableSchemaItem.width = tableSchemaItem.width ? tableSchemaItem.width : 160
|
|
||||||
}
|
|
||||||
|
|
||||||
tableSchema.push(tableSchemaItem)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// 操作栏插槽
|
|
||||||
if (crudSchema.action && crudSchema.action == true) {
|
|
||||||
const tableSchemaItem = {
|
|
||||||
title: crudSchema.actionTitle ? crudSchema.actionTitle : t('table.action'),
|
|
||||||
field: 'actionbtns',
|
|
||||||
fixed: 'right' as unknown as VxeColumnPropTypes.Fixed,
|
|
||||||
width: crudSchema.actionWidth ? crudSchema.actionWidth : '200px',
|
|
||||||
slots: {
|
|
||||||
default: 'actionbtns_default'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tableSchema.push(tableSchemaItem)
|
|
||||||
}
|
|
||||||
return tableSchema
|
|
||||||
}
|
|
||||||
|
|
||||||
// 过滤 form 结构
|
|
||||||
const filterFormSchema = (crudSchema: VxeCrudSchema): FormSchema[] => {
|
|
||||||
const formSchema: FormSchema[] = []
|
|
||||||
|
|
||||||
eachTree(crudSchema.columns, (schemaItem: VxeCrudColumns) => {
|
|
||||||
// 判断是否显示
|
|
||||||
if (schemaItem?.isForm !== false && schemaItem?.form?.show !== false) {
|
|
||||||
// 默认为 input
|
|
||||||
let component = schemaItem?.form?.component || 'Input'
|
|
||||||
let defaultValue: any = ''
|
|
||||||
if (schemaItem.form?.value) {
|
|
||||||
defaultValue = schemaItem.form?.value
|
|
||||||
} else {
|
|
||||||
if (component === 'InputNumber') {
|
|
||||||
defaultValue = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let comonentProps = {}
|
|
||||||
if (schemaItem.dictType) {
|
|
||||||
const options: ComponentOptions[] = []
|
|
||||||
if (schemaItem.dictClass && schemaItem.dictClass === 'number') {
|
|
||||||
getIntDictOptions(schemaItem.dictType).forEach((dict) => {
|
|
||||||
options.push(dict)
|
|
||||||
})
|
|
||||||
} else if (schemaItem.dictClass && schemaItem.dictClass === 'boolean') {
|
|
||||||
getBoolDictOptions(schemaItem.dictType).forEach((dict) => {
|
|
||||||
options.push(dict)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
getDictOptions(schemaItem.dictType).forEach((dict) => {
|
|
||||||
options.push(dict)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
comonentProps = {
|
|
||||||
options: options
|
|
||||||
}
|
|
||||||
if (!(schemaItem.form && schemaItem.form.component)) component = 'Select'
|
|
||||||
}
|
|
||||||
const formSchemaItem = {
|
|
||||||
component: component,
|
|
||||||
componentProps: comonentProps,
|
|
||||||
value: defaultValue,
|
|
||||||
...schemaItem.form,
|
|
||||||
field: schemaItem.field,
|
|
||||||
label: schemaItem.form?.label || schemaItem.title
|
|
||||||
}
|
|
||||||
|
|
||||||
formSchema.push(formSchemaItem)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return formSchema
|
|
||||||
}
|
|
||||||
|
|
||||||
// 过滤 descriptions 结构
|
|
||||||
const filterDescriptionsSchema = (crudSchema: VxeCrudSchema): DescriptionsSchema[] => {
|
|
||||||
const descriptionsSchema: DescriptionsSchema[] = []
|
|
||||||
|
|
||||||
eachTree(crudSchema.columns, (schemaItem: VxeCrudColumns) => {
|
|
||||||
// 判断是否显示
|
|
||||||
if (schemaItem?.isDetail !== false && schemaItem.detail?.show !== false) {
|
|
||||||
const descriptionsSchemaItem = {
|
|
||||||
...schemaItem.detail,
|
|
||||||
field: schemaItem.field,
|
|
||||||
label: schemaItem.detail?.label || schemaItem.title
|
|
||||||
}
|
|
||||||
if (schemaItem.dictType) {
|
|
||||||
descriptionsSchemaItem.dictType = schemaItem.dictType
|
|
||||||
}
|
|
||||||
if (schemaItem.detail?.dateFormat || schemaItem.formatter == 'formatDate') {
|
|
||||||
// 优先使用 detail 下的配置,如果没有默认为 YYYY-MM-DD HH:mm:ss
|
|
||||||
descriptionsSchemaItem.dateFormat = schemaItem?.detail?.dateFormat
|
|
||||||
? schemaItem?.detail?.dateFormat
|
|
||||||
: 'YYYY-MM-DD HH:mm:ss'
|
|
||||||
}
|
|
||||||
|
|
||||||
descriptionsSchema.push(descriptionsSchemaItem)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return descriptionsSchema
|
|
||||||
}
|
|
||||||
|
|
||||||
// 过滤 打印 结构
|
|
||||||
const filterPrintSchema = (crudSchema: VxeCrudSchema): any[] => {
|
|
||||||
const printSchema: any[] = []
|
|
||||||
|
|
||||||
eachTree(crudSchema.columns, (schemaItem: VxeCrudColumns) => {
|
|
||||||
// 判断是否显示
|
|
||||||
if (schemaItem?.print?.show !== false) {
|
|
||||||
const printSchemaItem = {
|
|
||||||
field: schemaItem.field
|
|
||||||
}
|
|
||||||
|
|
||||||
printSchema.push(printSchemaItem)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return printSchema
|
|
||||||
}
|
|
@ -1,264 +0,0 @@
|
|||||||
import { computed, nextTick, reactive } from 'vue'
|
|
||||||
import { SizeType, VxeGridProps, VxeTablePropTypes } from 'vxe-table'
|
|
||||||
import { useAppStore } from '@/store/modules/app'
|
|
||||||
import { VxeAllSchemas } from './useVxeCrudSchemas'
|
|
||||||
|
|
||||||
import download from '@/utils/download'
|
|
||||||
|
|
||||||
const { t } = useI18n()
|
|
||||||
const message = useMessage() // 消息弹窗
|
|
||||||
|
|
||||||
interface UseVxeGridConfig<T = any> {
|
|
||||||
allSchemas: VxeAllSchemas
|
|
||||||
height?: number // 高度 默认730
|
|
||||||
topActionSlots?: boolean // 是否开启表格内顶部操作栏插槽
|
|
||||||
treeConfig?: VxeTablePropTypes.TreeConfig // 树形表单配置
|
|
||||||
isList?: boolean // 是否不带分页的list
|
|
||||||
getListApi: (option: any) => Promise<T> // 获取列表接口
|
|
||||||
getAllListApi?: (option: any) => Promise<T> // 获取全部数据接口 用于VXE导出
|
|
||||||
deleteApi?: (option: any) => Promise<T> // 删除接口
|
|
||||||
exportListApi?: (option: any) => Promise<T> // 导出接口
|
|
||||||
exportName?: string // 导出文件夹名称
|
|
||||||
queryParams?: any // 其他查询参数
|
|
||||||
}
|
|
||||||
|
|
||||||
const appStore = useAppStore()
|
|
||||||
|
|
||||||
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
|
|
||||||
})
|
|
||||||
|
|
||||||
export const useVxeGrid = <T = any>(config?: UseVxeGridConfig<T>) => {
|
|
||||||
/**
|
|
||||||
* grid options 初始化
|
|
||||||
*/
|
|
||||||
const gridOptions = reactive<VxeGridProps<any>>({
|
|
||||||
loading: true,
|
|
||||||
size: currentSize as any,
|
|
||||||
height: config?.height ? config.height : 730,
|
|
||||||
rowConfig: {
|
|
||||||
isCurrent: true, // 当鼠标点击行时,是否要高亮当前行
|
|
||||||
isHover: true // 当鼠标移到行时,是否要高亮当前行
|
|
||||||
},
|
|
||||||
toolbarConfig: {
|
|
||||||
slots:
|
|
||||||
!config?.topActionSlots && config?.topActionSlots != false
|
|
||||||
? { buttons: 'toolbar_buttons' }
|
|
||||||
: {}
|
|
||||||
},
|
|
||||||
printConfig: {
|
|
||||||
columns: config?.allSchemas.printSchema
|
|
||||||
},
|
|
||||||
formConfig: {
|
|
||||||
enabled: true,
|
|
||||||
titleWidth: 100,
|
|
||||||
titleAlign: 'right',
|
|
||||||
items: config?.allSchemas.searchSchema
|
|
||||||
},
|
|
||||||
columns: config?.allSchemas.tableSchema,
|
|
||||||
proxyConfig: {
|
|
||||||
seq: true, // 启用动态序号代理(分页之后索引自动计算为当前页的起始序号)
|
|
||||||
form: true, // 启用表单代理,当点击表单提交按钮时会自动触发 reload 行为
|
|
||||||
props: { result: 'list', total: 'total' },
|
|
||||||
ajax: {
|
|
||||||
query: ({ page, form }) => {
|
|
||||||
let queryParams: any = Object.assign({}, JSON.parse(JSON.stringify(form)))
|
|
||||||
if (config?.queryParams) {
|
|
||||||
queryParams = Object.assign(queryParams, config.queryParams)
|
|
||||||
}
|
|
||||||
if (!config?.treeConfig) {
|
|
||||||
queryParams.pageSize = page.pageSize
|
|
||||||
queryParams.pageNo = page.currentPage
|
|
||||||
}
|
|
||||||
gridOptions.loading = false
|
|
||||||
return new Promise(async (resolve) => {
|
|
||||||
resolve(await config?.getListApi(queryParams))
|
|
||||||
})
|
|
||||||
},
|
|
||||||
delete: ({ body }) => {
|
|
||||||
return new Promise(async (resolve) => {
|
|
||||||
if (config?.deleteApi) {
|
|
||||||
resolve(await config?.deleteApi(JSON.stringify(body)))
|
|
||||||
} else {
|
|
||||||
Promise.reject('未设置deleteApi')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
queryAll: ({ form }) => {
|
|
||||||
const queryParams = Object.assign({}, JSON.parse(JSON.stringify(form)))
|
|
||||||
return new Promise(async (resolve) => {
|
|
||||||
if (config?.getAllListApi) {
|
|
||||||
resolve(await config?.getAllListApi(queryParams))
|
|
||||||
} else {
|
|
||||||
resolve(await config?.getListApi(queryParams))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
exportConfig: {
|
|
||||||
filename: config?.exportName,
|
|
||||||
// 默认选中类型
|
|
||||||
type: 'csv',
|
|
||||||
// 自定义数据量列表
|
|
||||||
modes: config?.getAllListApi ? ['current', 'all'] : ['current'],
|
|
||||||
columns: config?.allSchemas.printSchema
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (config?.treeConfig) {
|
|
||||||
gridOptions.treeConfig = config.treeConfig
|
|
||||||
} else if (config?.isList) {
|
|
||||||
gridOptions.proxyConfig = {
|
|
||||||
seq: true, // 启用动态序号代理(分页之后索引自动计算为当前页的起始序号)
|
|
||||||
form: true, // 启用表单代理,当点击表单提交按钮时会自动触发 reload 行为
|
|
||||||
props: { result: 'data' },
|
|
||||||
ajax: {
|
|
||||||
query: ({ form }) => {
|
|
||||||
let queryParams: any = Object.assign({}, JSON.parse(JSON.stringify(form)))
|
|
||||||
if (config?.queryParams) {
|
|
||||||
queryParams = Object.assign(queryParams, config.queryParams)
|
|
||||||
}
|
|
||||||
gridOptions.loading = false
|
|
||||||
return new Promise(async (resolve) => {
|
|
||||||
resolve(await config?.getListApi(queryParams))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gridOptions.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'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 刷新列表
|
|
||||||
* @param ref
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
const getList = async (ref) => {
|
|
||||||
if (!ref) {
|
|
||||||
console.error('未传入gridRef')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await nextTick()
|
|
||||||
ref.value.commitProxy('query')
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取查询参数
|
|
||||||
const getSearchData = async (ref) => {
|
|
||||||
if (!ref) {
|
|
||||||
console.error('未传入gridRef')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await nextTick()
|
|
||||||
const queryParams = Object.assign(
|
|
||||||
{},
|
|
||||||
JSON.parse(JSON.stringify(ref.value.getProxyInfo()?.form))
|
|
||||||
)
|
|
||||||
return queryParams
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除
|
|
||||||
* @param ref
|
|
||||||
* @param ids rowid
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
const deleteData = async (ref, ids: string | number) => {
|
|
||||||
if (!ref) {
|
|
||||||
console.error('未传入gridRef')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!config?.deleteApi) {
|
|
||||||
console.error('未传入delListApi')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await nextTick()
|
|
||||||
return new Promise(async () => {
|
|
||||||
message.delConfirm().then(async () => {
|
|
||||||
await (config?.deleteApi && config?.deleteApi(ids))
|
|
||||||
message.success(t('common.delSuccess'))
|
|
||||||
// 刷新列表
|
|
||||||
ref.value.commitProxy('query')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 导出
|
|
||||||
* @param ref
|
|
||||||
* @param fileName 文件名,默认excel.xls
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
const exportList = async (ref, fileName?: string) => {
|
|
||||||
if (!ref) {
|
|
||||||
console.error('未传入gridRef')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!config?.exportListApi) {
|
|
||||||
console.error('未传入exportListApi')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await nextTick()
|
|
||||||
const queryParams = Object.assign(
|
|
||||||
{},
|
|
||||||
JSON.parse(JSON.stringify(ref.value?.getProxyInfo()?.form))
|
|
||||||
)
|
|
||||||
message.exportConfirm().then(async () => {
|
|
||||||
const res = await (config?.exportListApi && config?.exportListApi(queryParams))
|
|
||||||
download.excel(res as unknown as Blob, fileName ? fileName : 'excel.xls')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 表格最大/最小化
|
|
||||||
* @param ref
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
const zoom = async (ref) => {
|
|
||||||
if (!ref) {
|
|
||||||
console.error('未传入gridRef')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await nextTick()
|
|
||||||
ref.value.zoom(!ref.value.isMaximized())
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
gridOptions,
|
|
||||||
getList,
|
|
||||||
getSearchData,
|
|
||||||
deleteData,
|
|
||||||
exportList,
|
|
||||||
zoom
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
import { XTableProps } from '@/components/XTable/src/type'
|
|
||||||
|
|
||||||
export interface tableMethod {
|
|
||||||
reload: () => void // 刷新表格
|
|
||||||
setProps: (props: XTableProps) => void
|
|
||||||
deleteData: (id: string | number) => void // 删除数据
|
|
||||||
deleteBatch: () => void // 批量删除
|
|
||||||
exportList: (fileName?: string) => void // 导出列表
|
|
||||||
getCurrentColumn: () => void // 获取当前列
|
|
||||||
getRadioRecord: () => void // 获取当前选中列,radio
|
|
||||||
getCheckboxRecords: () => void //获取当前选中列, checkbox
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useXTable = (props: XTableProps): [Function, tableMethod] => {
|
|
||||||
const tableRef = ref<Nullable<tableMethod>>(null)
|
|
||||||
|
|
||||||
const register = (instance) => {
|
|
||||||
tableRef.value = instance
|
|
||||||
props && instance.setProps(props)
|
|
||||||
}
|
|
||||||
const 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),
|
|
||||||
deleteData: (id: string | number) => getInstance().deleteData(id),
|
|
||||||
deleteBatch: () => getInstance().deleteBatch(),
|
|
||||||
exportList: (fileName?: string) => getInstance().exportList(fileName),
|
|
||||||
getCurrentColumn: () => getInstance().getCheckboxRecords(),
|
|
||||||
getRadioRecord: () => getInstance().getRadioRecord(),
|
|
||||||
getCheckboxRecords: () => getInstance().getCheckboxRecords()
|
|
||||||
}
|
|
||||||
return [register, methods]
|
|
||||||
}
|
|
@ -16,9 +16,6 @@ import { setupGlobCom } from '@/components'
|
|||||||
// 引入 element-plus
|
// 引入 element-plus
|
||||||
import { setupElementPlus } from '@/plugins/elementPlus'
|
import { setupElementPlus } from '@/plugins/elementPlus'
|
||||||
|
|
||||||
// 引入 vxe-table
|
|
||||||
import { setupVxeTable } from '@/plugins/vxeTable'
|
|
||||||
|
|
||||||
// 引入 form-create
|
// 引入 form-create
|
||||||
import { setupFormCreate } from '@/plugins/formCreate'
|
import { setupFormCreate } from '@/plugins/formCreate'
|
||||||
|
|
||||||
@ -83,8 +80,6 @@ const setupAll = async () => {
|
|||||||
|
|
||||||
setupElementPlus(app)
|
setupElementPlus(app)
|
||||||
|
|
||||||
setupVxeTable(app)
|
|
||||||
|
|
||||||
setupFormCreate(app)
|
setupFormCreate(app)
|
||||||
|
|
||||||
setupRouter(app)
|
setupRouter(app)
|
||||||
|
@ -1,223 +0,0 @@
|
|||||||
import { App } from 'vue'
|
|
||||||
import XEUtils from 'xe-utils'
|
|
||||||
import './renderer'
|
|
||||||
import 'vxe-table/lib/style.css'
|
|
||||||
import { i18n } from '@/plugins/vueI18n'
|
|
||||||
import zhCN from 'vxe-table/lib/locale/lang/zh-CN'
|
|
||||||
import enUS from 'vxe-table/lib/locale/lang/en-US'
|
|
||||||
import {
|
|
||||||
// 全局对象
|
|
||||||
VXETable,
|
|
||||||
// 表格功能
|
|
||||||
Filter,
|
|
||||||
Edit,
|
|
||||||
Menu,
|
|
||||||
Export,
|
|
||||||
Keyboard,
|
|
||||||
Validator,
|
|
||||||
// 可选组件
|
|
||||||
Icon,
|
|
||||||
Column,
|
|
||||||
Colgroup,
|
|
||||||
Grid,
|
|
||||||
Tooltip,
|
|
||||||
Toolbar,
|
|
||||||
Pager,
|
|
||||||
Form,
|
|
||||||
FormItem,
|
|
||||||
FormGather,
|
|
||||||
Checkbox,
|
|
||||||
CheckboxGroup,
|
|
||||||
Radio,
|
|
||||||
RadioGroup,
|
|
||||||
RadioButton,
|
|
||||||
Switch,
|
|
||||||
Input,
|
|
||||||
Select,
|
|
||||||
Optgroup,
|
|
||||||
Option,
|
|
||||||
Textarea,
|
|
||||||
Button,
|
|
||||||
Modal,
|
|
||||||
List,
|
|
||||||
Pulldown,
|
|
||||||
// 表格
|
|
||||||
Table
|
|
||||||
} from 'vxe-table'
|
|
||||||
|
|
||||||
// 全局默认参数
|
|
||||||
VXETable.setup({
|
|
||||||
size: 'medium', // 全局尺寸
|
|
||||||
version: 0, // 版本号,对于某些带数据缓存的功能有用到,上升版本号可以用于重置数据
|
|
||||||
zIndex: 1008, // 全局 zIndex 起始值,如果项目的的 z-index 样式值过大时就需要跟随设置更大,避免被遮挡
|
|
||||||
loadingText: '加载中...', // 全局loading提示内容,如果为null则不显示文本
|
|
||||||
height: 600,
|
|
||||||
table: {
|
|
||||||
border: 'inner', // default(默认), full(完整边框), outer(外边框), inner(内边框), none(无边框)
|
|
||||||
align: 'center', // eft(左对齐), center(居中对齐), right(右对齐)
|
|
||||||
autoResize: true, // 自动监听父元素的变化去重新计算表格
|
|
||||||
resizable: true, // 列是否允许拖动列宽调整大小
|
|
||||||
emptyText: '暂无数据', // 空表单
|
|
||||||
highlightHoverRow: true, // 自动监听父元素的变化去重新计算表格
|
|
||||||
treeConfig: {
|
|
||||||
rowField: 'id',
|
|
||||||
parentField: 'parentId',
|
|
||||||
children: 'children',
|
|
||||||
indent: 20,
|
|
||||||
showIcon: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
toolbarConfig: {
|
|
||||||
refresh: true,
|
|
||||||
export: true,
|
|
||||||
print: true,
|
|
||||||
zoom: true,
|
|
||||||
custom: true
|
|
||||||
},
|
|
||||||
pagerConfig: {
|
|
||||||
border: false,
|
|
||||||
background: false,
|
|
||||||
autoHidden: true,
|
|
||||||
perfect: true,
|
|
||||||
pageSize: 10,
|
|
||||||
pagerCount: 7,
|
|
||||||
pageSizes: [5, 10, 15, 20, 50, 100, 200, 500],
|
|
||||||
layouts: [
|
|
||||||
'Sizes',
|
|
||||||
'PrevJump',
|
|
||||||
'PrevPage',
|
|
||||||
'Number',
|
|
||||||
'NextPage',
|
|
||||||
'NextJump',
|
|
||||||
'FullJump',
|
|
||||||
'Total'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
pager: {
|
|
||||||
background: false,
|
|
||||||
autoHidden: false,
|
|
||||||
perfect: true,
|
|
||||||
pageSize: 10,
|
|
||||||
pagerCount: 7,
|
|
||||||
pageSizes: [10, 15, 20, 50, 100],
|
|
||||||
layouts: ['PrevJump', 'PrevPage', 'Jump', 'PageCount', 'NextPage', 'NextJump', 'Sizes', 'Total']
|
|
||||||
},
|
|
||||||
input: {
|
|
||||||
clearable: true
|
|
||||||
},
|
|
||||||
form: {
|
|
||||||
titleColon: true // 是否显示标题冒号
|
|
||||||
},
|
|
||||||
modal: {
|
|
||||||
width: 800, // 窗口的宽度
|
|
||||||
height: 600, // 窗口的高度
|
|
||||||
minWidth: 460,
|
|
||||||
minHeight: 320,
|
|
||||||
showZoom: true, // 标题是否标显示最大化与还原按钮
|
|
||||||
resize: true, // 是否允许窗口边缘拖动调整窗口大小
|
|
||||||
marginSize: 0, // 只对 resize 启用后有效,用于设置可拖动界限范围,如果为负数则允许拖动超出屏幕边界
|
|
||||||
remember: false, // 记忆功能,会记住最后操作状态,再次打开窗口时还原窗口状态
|
|
||||||
destroyOnClose: true, // 在窗口关闭时销毁内容
|
|
||||||
storage: false, // 是否启用 localStorage 本地保存,会将窗口拖动的状态保存到本地
|
|
||||||
transfer: true, // 是否将弹框容器插入于 body 内
|
|
||||||
showFooter: true, // 是否显示底部
|
|
||||||
mask: true, // 是否显示遮罩层
|
|
||||||
maskClosable: true, // 是否允许点击遮罩层关闭窗口
|
|
||||||
escClosable: true // 是否允许按 Esc 键关闭窗口
|
|
||||||
},
|
|
||||||
i18n: (key, args) => {
|
|
||||||
return unref(i18n.global.locale) === 'zh-CN'
|
|
||||||
? XEUtils.toFormatString(XEUtils.get(zhCN, key), args)
|
|
||||||
: XEUtils.toFormatString(XEUtils.get(enUS, key), args)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// 自定义全局的格式化处理函数
|
|
||||||
VXETable.formats.mixin({
|
|
||||||
// 格式精简日期,默认 yyyy-MM-dd HH:mm:ss
|
|
||||||
formatDay({ cellValue }, format) {
|
|
||||||
if (cellValue != null) {
|
|
||||||
return XEUtils.toDateString(cellValue, format || 'yyyy-MM-dd')
|
|
||||||
} else {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 格式完整日期,默认 yyyy-MM-dd HH:mm:ss
|
|
||||||
formatDate({ cellValue }, format) {
|
|
||||||
if (cellValue != null) {
|
|
||||||
return XEUtils.toDateString(cellValue, format || 'yyyy-MM-dd HH:mm:ss')
|
|
||||||
} else {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 四舍五入金额,每隔3位逗号分隔,默认2位数
|
|
||||||
formatAmount({ cellValue }, digits = 2) {
|
|
||||||
return XEUtils.commafy(Number(cellValue), { digits })
|
|
||||||
},
|
|
||||||
// 格式化银行卡,默认每4位空格隔开
|
|
||||||
formatBankcard({ cellValue }) {
|
|
||||||
return XEUtils.commafy(XEUtils.toValueString(cellValue), { spaceNumber: 4, separator: ' ' })
|
|
||||||
},
|
|
||||||
// 四舍五入,默认两位数
|
|
||||||
formatFixedNumber({ cellValue }, digits = 2) {
|
|
||||||
return XEUtils.toFixed(XEUtils.round(cellValue, digits), digits)
|
|
||||||
},
|
|
||||||
// 向下舍入,默认两位数
|
|
||||||
formatCutNumber({ cellValue }, digits = 2) {
|
|
||||||
return XEUtils.toFixed(XEUtils.floor(cellValue, digits), digits)
|
|
||||||
},
|
|
||||||
// 格式化图片,将图片链接转换为html标签
|
|
||||||
formatImg({ cellValue }) {
|
|
||||||
return '<img height="40" src="' + cellValue + '"> '
|
|
||||||
},
|
|
||||||
// 格式化文件大小
|
|
||||||
formatSize({ cellValue }, digits = 0) {
|
|
||||||
const unitArr = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
|
||||||
const srcSize = parseFloat(cellValue)
|
|
||||||
const index = Math.floor(Math.log(srcSize) / Math.log(1024))
|
|
||||||
const size = srcSize / Math.pow(1024, index)
|
|
||||||
return XEUtils.toFixed(XEUtils.floor(size, 2), 2) + ' ' + unitArr[digits]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
export const setupVxeTable = (app: App<Element>) => {
|
|
||||||
// 表格功能
|
|
||||||
app.use(Filter).use(Edit).use(Menu).use(Export).use(Keyboard).use(Validator)
|
|
||||||
|
|
||||||
// 可选组件
|
|
||||||
app
|
|
||||||
.use(Icon)
|
|
||||||
.use(Column)
|
|
||||||
.use(Colgroup)
|
|
||||||
.use(Grid)
|
|
||||||
.use(Tooltip)
|
|
||||||
.use(Toolbar)
|
|
||||||
.use(Pager)
|
|
||||||
.use(Form)
|
|
||||||
.use(FormItem)
|
|
||||||
.use(FormGather)
|
|
||||||
.use(Checkbox)
|
|
||||||
.use(CheckboxGroup)
|
|
||||||
.use(Radio)
|
|
||||||
.use(RadioGroup)
|
|
||||||
.use(RadioButton)
|
|
||||||
.use(Switch)
|
|
||||||
.use(Input)
|
|
||||||
.use(Select)
|
|
||||||
.use(Optgroup)
|
|
||||||
.use(Option)
|
|
||||||
.use(Textarea)
|
|
||||||
.use(Button)
|
|
||||||
.use(Modal)
|
|
||||||
.use(List)
|
|
||||||
.use(Pulldown)
|
|
||||||
|
|
||||||
// 安装表格
|
|
||||||
.use(Table)
|
|
||||||
|
|
||||||
// 给 vue 实例挂载内部对象,例如:
|
|
||||||
// app.config.globalProperties.$XModal = VXETable.modal
|
|
||||||
// app.config.globalProperties.$XPrint = VXETable.print
|
|
||||||
// app.config.globalProperties.$XSaveFile = VXETable.saveFile
|
|
||||||
// app.config.globalProperties.$XReadFile = VXETable.readFile
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
import { ElDatePicker } from 'element-plus'
|
|
||||||
import { VXETable } from 'vxe-table'
|
|
||||||
|
|
||||||
// 日期区间选择渲染
|
|
||||||
VXETable.renderer.add('XDataPicker', {
|
|
||||||
// 默认显示模板
|
|
||||||
renderItemContent(renderOpts, params) {
|
|
||||||
const { data, field } = params
|
|
||||||
const { content } = renderOpts
|
|
||||||
return (
|
|
||||||
<ElDatePicker
|
|
||||||
v-model={data[field]}
|
|
||||||
style="width: 100%"
|
|
||||||
type={content ? (content as any) : 'datetime'}
|
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
clearable
|
|
||||||
></ElDatePicker>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
@ -1,23 +0,0 @@
|
|||||||
import { ElDatePicker } from 'element-plus'
|
|
||||||
import { VXETable } from 'vxe-table'
|
|
||||||
|
|
||||||
// 日期区间选择渲染
|
|
||||||
VXETable.renderer.add('XDataTimePicker', {
|
|
||||||
// 默认显示模板
|
|
||||||
renderItemContent(renderOpts, params) {
|
|
||||||
const { t } = useI18n()
|
|
||||||
const { data, field } = params
|
|
||||||
const { content } = renderOpts
|
|
||||||
return (
|
|
||||||
<ElDatePicker
|
|
||||||
v-model={data[field]}
|
|
||||||
style="width: 100%"
|
|
||||||
type={content ? (content as any) : 'datetimerange'}
|
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder={t('common.startTimeText')}
|
|
||||||
end-placeholder={t('common.endTimeText')}
|
|
||||||
></ElDatePicker>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
@ -1,12 +0,0 @@
|
|||||||
import { DictTag } from '@/components/DictTag'
|
|
||||||
import { VXETable } from 'vxe-table'
|
|
||||||
|
|
||||||
// 字典渲染
|
|
||||||
VXETable.renderer.add('XDict', {
|
|
||||||
// 默认显示模板
|
|
||||||
renderDefault(renderOpts, params) {
|
|
||||||
const { row, column } = params
|
|
||||||
const { content } = renderOpts
|
|
||||||
return <DictTag type={content as unknown as string} value={row[column.field]}></DictTag>
|
|
||||||
}
|
|
||||||
})
|
|
@ -1,10 +0,0 @@
|
|||||||
import { VXETable } from 'vxe-table'
|
|
||||||
|
|
||||||
// 图片渲染
|
|
||||||
VXETable.renderer.add('XHtml', {
|
|
||||||
// 默认显示模板
|
|
||||||
renderDefault(_renderOpts, params) {
|
|
||||||
const { row, column } = params
|
|
||||||
return <span v-html={row[column.field]}></span>
|
|
||||||
}
|
|
||||||
})
|
|
@ -1,20 +0,0 @@
|
|||||||
import { VXETable } from 'vxe-table'
|
|
||||||
import { ElImage } from 'element-plus'
|
|
||||||
|
|
||||||
// 图片渲染
|
|
||||||
VXETable.renderer.add('XImg', {
|
|
||||||
// 默认显示模板
|
|
||||||
renderDefault(_renderOpts, params) {
|
|
||||||
const { row, column } = params
|
|
||||||
return (
|
|
||||||
<ElImage
|
|
||||||
style="width: 80px; height: 50px"
|
|
||||||
src={row[column.field]}
|
|
||||||
key={row[column.field]}
|
|
||||||
preview-src-list={[row[column.field]]}
|
|
||||||
fit="contain"
|
|
||||||
lazy
|
|
||||||
></ElImage>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
@ -1,7 +0,0 @@
|
|||||||
import './dataPicker'
|
|
||||||
import './dataTimeRangePicker'
|
|
||||||
import './dict'
|
|
||||||
import './html'
|
|
||||||
import './link'
|
|
||||||
import './img'
|
|
||||||
import './preview'
|
|
@ -1,15 +0,0 @@
|
|||||||
import { VXETable } from 'vxe-table'
|
|
||||||
|
|
||||||
// 超链接渲染
|
|
||||||
VXETable.renderer.add('XLink', {
|
|
||||||
// 默认显示模板
|
|
||||||
renderDefault(renderOpts, params) {
|
|
||||||
const { row, column } = params
|
|
||||||
const { events = {} } = renderOpts
|
|
||||||
return (
|
|
||||||
<a class="link" onClick={() => events.click(params)}>
|
|
||||||
{row[column.field]}
|
|
||||||
</a>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
@ -1,35 +0,0 @@
|
|||||||
import { VXETable } from 'vxe-table'
|
|
||||||
import { ElImage, ElLink } from 'element-plus'
|
|
||||||
|
|
||||||
// 图片渲染
|
|
||||||
VXETable.renderer.add('XPreview', {
|
|
||||||
// 默认显示模板
|
|
||||||
renderDefault(_renderOpts, params) {
|
|
||||||
const { row, column } = params
|
|
||||||
if (row.type.indexOf('image/') === 0) {
|
|
||||||
return (
|
|
||||||
<ElImage
|
|
||||||
style="width: 80px; height: 50px"
|
|
||||||
src={row[column.field]}
|
|
||||||
key={row[column.field]}
|
|
||||||
preview-src-list={[row[column.field]]}
|
|
||||||
fit="contain"
|
|
||||||
lazy
|
|
||||||
></ElImage>
|
|
||||||
)
|
|
||||||
} else if (row.type.indexOf('video/') === 0) {
|
|
||||||
return (
|
|
||||||
<video>
|
|
||||||
<source src={row[column.field]}></source>
|
|
||||||
</video>
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
// @ts-ignore
|
|
||||||
<ElLink href={row[column.field]} target="_blank">
|
|
||||||
{row[column.field]}
|
|
||||||
</ElLink>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
2
src/types/auto-components.d.ts
vendored
2
src/types/auto-components.d.ts
vendored
@ -120,8 +120,6 @@ declare module '@vue/runtime-core' {
|
|||||||
VerifyPoints: typeof import('./../components/Verifition/src/Verify/VerifyPoints.vue')['default']
|
VerifyPoints: typeof import('./../components/Verifition/src/Verify/VerifyPoints.vue')['default']
|
||||||
VerifySlide: typeof import('./../components/Verifition/src/Verify/VerifySlide.vue')['default']
|
VerifySlide: typeof import('./../components/Verifition/src/Verify/VerifySlide.vue')['default']
|
||||||
XButton: typeof import('./../components/XButton/src/XButton.vue')['default']
|
XButton: typeof import('./../components/XButton/src/XButton.vue')['default']
|
||||||
XModal: typeof import('./../components/XModal/src/XModal.vue')['default']
|
|
||||||
XTable: typeof import('./../components/XTable/src/XTable.vue')['default']
|
|
||||||
XTextButton: typeof import('./../components/XButton/src/XTextButton.vue')['default']
|
XTextButton: typeof import('./../components/XButton/src/XTextButton.vue')['default']
|
||||||
}
|
}
|
||||||
export interface ComponentCustomProperties {
|
export interface ComponentCustomProperties {
|
||||||
|
2
src/types/auto-imports.d.ts
vendored
2
src/types/auto-imports.d.ts
vendored
@ -62,8 +62,6 @@ declare global {
|
|||||||
const useRouter: typeof import('vue-router')['useRouter']
|
const useRouter: typeof import('vue-router')['useRouter']
|
||||||
const useSlots: typeof import('vue')['useSlots']
|
const useSlots: typeof import('vue')['useSlots']
|
||||||
const useTable: typeof import('@/hooks/web/useTable')['useTable']
|
const useTable: typeof import('@/hooks/web/useTable')['useTable']
|
||||||
const useVxeCrudSchemas: typeof import('@/hooks/web/useVxeCrudSchemas')['useVxeCrudSchemas']
|
|
||||||
const useXTable: typeof import('@/hooks/web/useXTable')['useXTable']
|
|
||||||
const watch: typeof import('vue')['watch']
|
const watch: typeof import('vue')['watch']
|
||||||
const watchEffect: typeof import('vue')['watchEffect']
|
const watchEffect: typeof import('vue')['watchEffect']
|
||||||
const watchPostEffect: typeof import('vue')['watchPostEffect']
|
const watchPostEffect: typeof import('vue')['watchPostEffect']
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
</ContentWrap>
|
</ContentWrap>
|
||||||
|
|
||||||
<!-- 添加/修改的弹窗 -->
|
<!-- 添加/修改的弹窗 -->
|
||||||
<XModal id="templateModel" :loading="modelLoading" v-model="dialogVisible" :title="dialogTitle">
|
<Dialog id="templateModel" :loading="modelLoading" v-model="dialogVisible" :title="dialogTitle">
|
||||||
<!-- 表单:添加/修改 -->
|
<!-- 表单:添加/修改 -->
|
||||||
<Form
|
<Form
|
||||||
ref="formRef"
|
ref="formRef"
|
||||||
@ -72,10 +72,10 @@
|
|||||||
<!-- 按钮:关闭 -->
|
<!-- 按钮:关闭 -->
|
||||||
<XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" />
|
<XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" />
|
||||||
</template>
|
</template>
|
||||||
</XModal>
|
</Dialog>
|
||||||
|
|
||||||
<!-- 测试站内信的弹窗 -->
|
<!-- 测试站内信的弹窗 -->
|
||||||
<XModal id="sendTest" v-model="sendVisible" title="测试">
|
<Dialog id="sendTest" v-model="sendVisible" title="测试">
|
||||||
<el-form :model="sendForm" :rules="sendRules" label-width="200px" label-position="top">
|
<el-form :model="sendForm" :rules="sendRules" label-width="200px" label-position="top">
|
||||||
<el-form-item label="模板内容" prop="content">
|
<el-form-item label="模板内容" prop="content">
|
||||||
<el-input type="textarea" v-model="sendForm.content" readonly />
|
<el-input type="textarea" v-model="sendForm.content" readonly />
|
||||||
@ -112,7 +112,7 @@
|
|||||||
/>
|
/>
|
||||||
<XButton :title="t('dialog.close')" @click="sendVisible = false" />
|
<XButton :title="t('dialog.close')" @click="sendVisible = false" />
|
||||||
</template>
|
</template>
|
||||||
</XModal>
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts" name="SystemNotifyTemplate">
|
<script setup lang="ts" name="SystemNotifyTemplate">
|
||||||
import { FormExpose } from '@/components/Form'
|
import { FormExpose } from '@/components/Form'
|
||||||
|
Loading…
Reference in New Issue
Block a user