Files
vxe-table/examples/views/grid/GridTest.vue
xuliangzhan 9bc4985a4f 重构组件
2024-05-26 12:41:17 +08:00

296 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div>
<vxe-grid ref='xGrid' v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script lang="ts" setup>
import { onMounted, reactive, ref } from 'vue'
import XEUtils from 'xe-utils'
import { VxeUI } from '../../../packages'
import type { VxeGridInstance, VxeGridProps } from '../../../types'
const xGrid = ref({} as VxeGridInstance)
const postMock = (url:string, body: any): Promise<any> => {
return new Promise((resolve) => {
console.log(`模拟提交${url}${JSON.stringify(body)}`)
setTimeout(() => {
resolve({
code: 200,
result: {
insertRows: 0
}
})
}, 300)
})
}
const gridOptions = reactive<VxeGridProps>({
border: true,
resizable: true,
showHeaderOverflow: true,
showOverflow: true,
keepSource: true,
id: 'full_edit_1',
height: 600,
columnConfig: {
useKey: true
},
rowConfig: {
keyField: 'id',
isHover: true
},
customConfig: {
storage: true,
checkMethod ({ column }) {
if (['nickname', 'role'].includes(column.field)) {
return false
}
return true
}
},
printConfig: {
columns: [
{ field: 'name' },
{ field: 'email' },
{ field: 'nickname' },
{ field: 'age' },
{ field: 'amount' }
]
},
sortConfig: {
trigger: 'cell',
remote: true
},
filterConfig: {
remote: true
},
pagerConfig: {
pageSize: 10,
pageSizes: [5, 10, 15, 20, 50, 100, 200, 500, 1000]
},
formConfig: {
titleWidth: 100,
titleAlign: 'right',
items: [
{ field: 'name', title: 'app.body.label.name', span: 8, titlePrefix: { message: 'app.body.valid.rName', icon: 'vxe-icon-question-circle-fill' }, itemRender: { name: '$input', props: { placeholder: '请输入名称' } } },
{ field: 'email', title: '邮件', span: 8, titlePrefix: { useHTML: true, message: '点击链接:<a class="link" href="https://vxetable.cn" target="_blank">vxe-table官网</a>', icon: 'vxe-icon-question-circle-fill' }, itemRender: { name: '$input', props: { placeholder: '请输入邮件' } } },
{ field: 'nickname', title: '昵称', span: 8, itemRender: { name: '$input', props: { placeholder: '请输入昵称' } } },
{ field: 'role', title: '角色', span: 8, folding: true, itemRender: { name: '$input', props: { placeholder: '请输入角色' } } },
{ field: 'sex', title: '性别', span: 8, folding: true, titleSuffix: { message: '注意,必填信息!', icon: 'fa fa-info-circle' }, itemRender: { name: '$select', options: [] } },
{ field: 'age', title: '年龄', span: 8, folding: true, itemRender: { name: '$input', props: { type: 'number', min: 1, max: 120, placeholder: '请输入年龄' } } },
{ span: 24, align: 'center', collapseNode: true, itemRender: { name: '$buttons', children: [{ props: { type: 'submit', content: 'app.body.label.search', status: 'primary' } }, { props: { type: 'reset', content: 'app.body.label.reset' } }] } }
]
},
toolbarConfig: {
buttons: [
{ code: 'insert_actived', name: '新增', icon: 'fa fa-plus' },
{ code: 'delete', name: '直接删除', icon: 'fa fa-trash-o' },
{ code: 'mark_cancel', name: '删除/取消', icon: 'fa fa-trash-o' },
{ code: 'save', name: 'app.body.button.save', icon: 'fa fa-save', status: 'success' }
],
refresh: true,
import: true,
export: true,
print: true,
zoom: true,
custom: true
},
proxyConfig: {
seq: true, // 启用动态序号代理,每一页的序号会根据当前页数变化
sort: true, // 启用排序代理,当点击排序时会自动触发 query 行为
filter: true, // 启用筛选代理,当点击筛选时会自动触发 query 行为
form: true, // 启用表单代理,当点击表单提交按钮时会自动触发 reload 行为
// 对应响应结果 { result: [], page: { total: 100 } }
props: {
result: 'result', // 配置响应结果列表字段
total: 'page.total' // 配置响应结果总页数字段
},
ajax: {
// 接收 Promise
query: ({ page, sorts, filters, form }) => {
const queryParams: any = Object.assign({}, form)
// 处理排序条件
const firstSort = sorts[0]
if (firstSort) {
queryParams.sort = firstSort.property
queryParams.order = firstSort.order
}
// 处理筛选条件
filters.forEach(({ property, values }) => {
queryParams[property] = values.join(',')
})
return fetch(`https://api.vxetable.cn/demo/api/pub/page/list/${page.pageSize}/${page.currentPage}?${XEUtils.serialize(queryParams)}`).then(response => response.json())
},
delete: ({ body }) => {
return postMock('https://api.vxetable.cn/demo/api/pub/save', body)
},
save: ({ body }) => postMock('https://api.vxetable.cn/demo/api/pub/save', body)
}
},
columns: [
{ type: 'checkbox', title: 'ID', width: 120 },
{ field: 'name', title: 'Name', sortable: true, titleHelp: { message: '名称必须填写2' }, titleSuffix: { content: '名称必须填写1' }, editRender: { name: 'input', attrs: { placeholder: '请输入名称' } } },
{
field: 'role',
title: 'Role',
sortable: true,
titlePrefix: { useHTML: true, content: '1点击链接<a class="link" href="https://vxetable.cn" target="_blank">vxe-table官网</a>' },
titleSuffix: { useHTML: true, content: '2点击链接<a class="link" href="https://vxetable.cn" target="_blank">vxe-table官网</a>' },
filters: [
{ label: '前端开发', value: '前端' },
{ label: '后端开发', value: '后端' },
{ label: '测试', value: '测试' },
{ label: '程序员鼓励师', value: '程序员鼓励师' }
],
filterMultiple: false,
editRender: { name: 'input', attrs: { placeholder: '请输入角色' } }
},
{ field: 'email', title: 'Email', width: 160, editRender: { name: '$input', props: { placeholder: '请输入邮件' } } },
{ field: 'nickname', title: 'Nickname', editRender: { name: 'input', attrs: { placeholder: '请输入昵称' } } },
{
field: 'sex',
title: 'Sex',
filters: [
{ label: '男', value: '1' },
{ label: '女', value: '0' }
],
editRender: { name: '$select', options: [], props: { placeholder: '请选择性别' } }
},
{ field: 'age', title: 'Age', visible: false, sortable: true, editRender: { name: '$input', props: { type: 'number', min: 1, max: 120 } } },
{
field: 'amount',
title: 'Amount',
formatter ({ cellValue }) {
return cellValue ? `${XEUtils.commafy(XEUtils.toNumber(cellValue), { digits: 2 })}` : ''
},
editRender:
{ name: '$input', props: { type: 'float', digits: 2, placeholder: '请输入数值' } }
},
{
field: 'updateDate',
title: 'Update Date',
width: 160,
visible: false,
sortable: true,
formatter ({ cellValue }) {
return XEUtils.toDateString(cellValue, 'yyyy-MM-dd HH:ss:mm')
}
},
{
field: 'createDate',
title: 'Create Date',
width: 160,
visible: false,
sortable: true,
formatter ({ cellValue }) {
return XEUtils.toDateString(cellValue, 'yyyy-MM-dd')
}
}
],
importConfig: {
remote: true,
types: ['xlsx'],
modes: ['insert'],
// 自定义服务端导入
importMethod ({ file }) {
const $grid = xGrid.value
const formBody = new FormData()
formBody.append('file', file)
return postMock('https://api.vxetable.cn/demo/api/pub/import', formBody).then(data => {
VxeUI.modal.message({ content: `成功导入 ${data.result.insertRows} 条记录!`, status: 'success' })
// 导入完成,刷新表格
$grid.commitProxy('query')
}).catch(() => {
VxeUI.modal.message({ content: '导入失败,请检查数据是否正确!', status: 'error' })
})
}
},
exportConfig: {
remote: true,
types: ['xlsx'],
modes: ['current', 'selected', 'all'],
// 自定义服务端导出
exportMethod ({ options }) {
const $grid = xGrid.value
const proxyInfo = $grid.getProxyInfo()
// 传给服务端的参数
const body = {
filename: options.filename,
sheetName: options.sheetName,
isHeader: options.isHeader,
original: options.original,
mode: options.mode,
pager: proxyInfo ? proxyInfo.pager : null,
ids: options.mode === 'selected' ? options.data.map((item) => item.id) : [],
fields: options.columns.map((column) => {
return {
field: column.property,
title: column.title
}
})
}
// 开始服务端导出
return postMock('https://api.vxetable.cn/demo/api/pub/export', body).then(data => {
if (data.id) {
VxeUI.modal.message({ content: '导出成功,开始下载', status: 'success' })
// 读取路径,请求文件
fetch(`https://api.vxetable.cn/demo/api/pub/export/download/${data.id}`).then(response => {
response.blob().then(blob => {
// 开始下载
VxeUI.saveFile({ filename: '导出数据', type: 'xlsx', content: blob })
})
})
}
}).catch(() => {
VxeUI.modal.message({ content: '导出失败!', status: 'error' })
})
}
},
checkboxConfig: {
labelField: 'id',
reserve: true,
highlight: true,
range: true
},
editRules: {
name: [
{ required: true, message: 'app.body.valid.rName' },
{ min: 3, max: 50, message: '名称长度在 3 到 50 个字符' }
],
email: [
{ required: true, message: '邮件必须填写' }
],
role: [
{ required: true, message: '角色必须填写' }
]
},
editConfig: {
trigger: 'click',
mode: 'row',
showStatus: true
}
})
onMounted(() => {
const sexList = [
{ label: '女', value: '0' },
{ label: '男', value: '1' }
]
const { formConfig, columns } = gridOptions
if (columns) {
const sexColumn = columns[5]
if (sexColumn && sexColumn.editRender) {
sexColumn.editRender.options = sexList
}
}
if (formConfig && formConfig.items) {
const sexItem = formConfig.items[4]
if (sexItem && sexItem.itemRender) {
sexItem.itemRender.options = sexList
}
}
})
</script>