vxe-pc-ui
Version:
A vue based PC component library
438 lines (437 loc) • 16.9 kB
JavaScript
import { defineComponent, ref, h, reactive, provide, watch, nextTick, computed, createCommentVNode } from 'vue';
import { VxeUI, getConfig, createEvent, getI18n, renderer, useSize } from '../../ui';
import { errLog } from '../../ui/src/log';
import { toCssUnit } from '../../ui/src/dom';
import { getSlotVNs } from '../../ui/src/vn';
import { createListDesignActionButton } from '../render/util';
import VxeLoadingComponent from '../../loading/src/loading';
import XEUtils from 'xe-utils';
export default defineComponent({
name: 'VxeListView',
props: {
size: {
type: String,
default: () => getConfig().listView.size || getConfig().size
},
config: Object,
height: {
type: [String, Number],
default: () => getConfig().listView.height
},
loading: Boolean,
formData: Object,
actionButtons: Array,
gridOptions: Object,
gridEvents: Object,
viewRender: Object
},
emits: [
'cell-action',
'update:formData',
'update:actionButtons'
],
setup(props, context) {
const VxeTableGridComponent = VxeUI.getComponent('VxeGrid');
const { emit, slots } = context;
const xID = XEUtils.uniqueId();
const refElem = ref();
const refGrid = ref();
const { computeSize } = useSize(props);
const reactData = reactive({
formConfig: {},
searchFormData: {},
searchFormItems: [],
listTableColumns: [],
tableColumns: [],
footerData: [
{} // 默认一行合计
]
});
const computeGridOptions = computed(() => {
const { gridOptions } = props;
const { formConfig, tableColumns, searchFormData, searchFormItems, footerData } = reactData;
const { showStatistics } = formConfig;
const gridOpts = gridOptions || {};
const columnOpts = Object.assign({
minWidth: 120
}, gridOpts.columnConfig);
let proxyOpts;
if (gridOpts.proxyConfig) {
proxyOpts = Object.assign({ autoLoad: false }, gridOpts.proxyConfig);
}
return Object.assign({}, gridOpts, {
columns: tableColumns,
columnConfig: columnOpts,
showFooter: showStatistics,
footerData: showStatistics ? footerData : null,
formConfig: {
data: searchFormData,
items: searchFormItems
},
proxyConfig: proxyOpts
});
});
const computeGridEvents = computed(() => {
const { gridEvents } = props;
const ons = {};
XEUtils.each(gridEvents, (fn, key) => {
ons[XEUtils.camelCase(`on-${key}`)] = fn;
});
return ons;
});
const refMaps = {
refElem,
refGrid
};
const computeMaps = {
computeSize
};
const $xeListView = {
xID,
props,
context,
reactData,
getRefMaps: () => refMaps,
getComputeMaps: () => computeMaps
};
const systemConfigList = [];
const customConfigList = [];
renderer.forEach((item, name) => {
const { createListDesignSettingActionButtonConfig } = item;
if (createListDesignSettingActionButtonConfig) {
const params = { name };
const btnConfig = Object.assign(createListDesignActionButton({ code: name }), createListDesignSettingActionButtonConfig(params));
if (btnConfig.type === 'custom') {
customConfigList.push(btnConfig);
}
else {
systemConfigList.push(btnConfig);
}
}
});
const configToSearchItems = (searchItems) => {
if (searchItems && searchItems.length) {
const data = {};
const items = searchItems.map(item => {
data[item.field] = null;
return {
field: item.field,
title: item.title,
folding: item.folding,
itemRender: item.itemRender
};
});
items.push({
field: 'active',
title: '',
folding: false,
collapseNode: searchItems.some(item => item.folding),
itemRender: {
name: 'VxeButtonGroup',
options: [
{ content: '查询', icon: 'vxe-icon-search', status: 'primary', type: 'submit' },
{ content: '重置', icon: 'vxe-icon-repeat', type: 'reset' }
]
}
});
return {
items,
data
};
}
return { items: [], data: {} };
};
const configToListColumns = (listColumns) => {
if (listColumns) {
return listColumns.map(item => {
return {
field: item.field,
title: item.title,
visible: !!item.visible,
width: item.width,
cellRender: XEUtils.clone(item.cellRender)
};
});
}
return [];
};
const clearConfig = () => {
emit('update:formData', {});
Object.assign(reactData, {
formConfig: {},
searchFormData: {},
searchFormItems: [],
listTableColumns: [],
tableColumns: [],
footerData: [
{} // 默认一行合计
]
});
return nextTick();
};
const loadConfig = (config) => {
if (config) {
const { formConfig, searchItems, listColumns } = config;
reactData.formConfig = formConfig || {};
setSearchItems(searchItems || []);
loadListColumns(listColumns || []);
}
return nextTick();
};
const parseForm = (searchItems) => {
return configToSearchItems(searchItems || []);
};
const parseTableColumn = (listColumns, formConfig) => {
const formOpts = Object.assign({}, formConfig);
const { showSeq, actionButtonList } = formOpts;
const columns = [];
const rowRecord = {};
const cellActionSlot = slots.cellAction;
const footerCellSlot = slots.footerCell;
if (showSeq) {
columns.push({
type: 'seq',
field: '_seq',
fixed: 'left',
width: 70
});
}
configToListColumns(listColumns || []).forEach(conf => {
const columnConf = Object.assign({}, conf);
if (formOpts.showStatistics && footerCellSlot) {
columnConf.slots = {
footer: (params) => {
return footerCellSlot(Object.assign({}, params));
}
};
}
if (columnConf.field) {
rowRecord[columnConf.field] = null;
}
columns.push(columnConf);
});
if (actionButtonList && actionButtonList.length) {
const actionColumn = {
field: '_active',
title: getI18n('vxe.table.actionTitle'),
fixed: 'right',
width: 'auto'
};
const btnOptions = [];
actionButtonList.forEach(btnItem => {
if (btnItem.type === 'custom') {
return {
content: btnItem.name,
name: btnItem.code,
icon: btnItem.icon
};
}
const btnConfig = systemConfigList.find(item => item.code === btnItem.code);
let btnName = btnItem.name;
let btnIcon = btnItem.icon;
let btnStatus = btnItem.status;
let btnPermissionCode = btnItem.permissionCode;
let btnClassify = btnItem.classify;
if (btnConfig) {
const nameConfig = btnConfig.name;
btnIcon = btnConfig.icon || '';
btnStatus = btnConfig.status || '';
btnPermissionCode = btnConfig.permissionCode || '';
btnClassify = btnConfig.classify || '';
btnName = XEUtils.toValueString(XEUtils.isFunction(nameConfig) ? nameConfig({ name: btnConfig.code || '' }) : nameConfig);
}
if (!btnClassify || btnClassify === 'cellButton') {
btnOptions.push({
content: btnName,
name: btnItem.code,
icon: btnIcon,
status: btnStatus,
permissionCode: btnPermissionCode
});
}
});
if (cellActionSlot) {
actionColumn.slots = {
default(params) {
return cellActionSlot(Object.assign(Object.assign({}, params), { buttons: btnOptions }));
}
};
}
else {
actionColumn.cellRender = {
name: 'VxeButtonGroup',
props: {
mode: 'text'
},
options: btnOptions,
events: {
click(params, btnParams) {
const { option } = btnParams;
dispatchEvent('cell-action', Object.assign(Object.assign({}, params), { button: option }), btnParams.$event);
}
}
};
}
columns.push(actionColumn);
}
return { rowRecord, columns, actionButtons: actionButtonList };
};
const parseConfig = (config) => {
const { formConfig, searchItems, listColumns } = config || {};
const { columns, rowRecord, actionButtons } = parseTableColumn(listColumns || [], formConfig || reactData.formConfig);
const { data, items } = parseForm(searchItems || []);
return {
formData: data,
formItems: items,
tableColumns: columns,
tableRecord: rowRecord,
actionButtons
};
};
const getTableRecord = (configOrListColumns) => {
if (XEUtils.isArray(configOrListColumns)) {
const { rowRecord } = parseTableColumn(configOrListColumns, reactData.formConfig);
return rowRecord;
}
if (configOrListColumns) {
const { formConfig, listColumns } = configOrListColumns;
const { rowRecord } = parseTableColumn(listColumns || [], formConfig || reactData.formConfig);
return rowRecord;
}
return {};
};
const getQueryFilter = () => {
const { searchFormData, searchFormItems } = reactData;
const items = [];
const rest = {
items,
type: 'and'
};
const $grid = refGrid.value;
if (!$grid) {
return rest;
}
searchFormItems.forEach(item => {
const { field } = item;
const itemValue = searchFormData[field];
if (itemValue) {
const condition = [];
condition.push({
field,
value: itemValue,
match: 'exact',
type: XEUtils.isArray(itemValue) ? 'array' : ''
});
items.push({
condition,
type: 'and'
});
}
});
return rest;
};
const commitProxy = (code, ...args) => {
const $grid = refGrid.value;
if ($grid) {
return $grid.commitProxy(code, ...args);
}
return Promise.resolve();
};
const loadListColumns = (listColumns) => {
const { formConfig } = reactData;
const listTableColumns = listColumns || [];
const { columns, actionButtons } = parseTableColumn(listTableColumns, formConfig);
reactData.listTableColumns = listTableColumns;
reactData.tableColumns = columns;
emit('update:actionButtons', actionButtons);
nextTick(() => {
const gridOptions = computeGridOptions.value;
if (gridOptions.proxyConfig) {
commitProxy('reload');
}
});
};
const setSearchItems = (searchItems) => {
const { data, items } = configToSearchItems(searchItems);
reactData.searchFormData = data;
reactData.searchFormItems = items;
emit('update:formData', data);
return nextTick();
};
const dispatchEvent = (type, params, evnt) => {
emit(type, createEvent(evnt, { $listView: $xeListView }, params));
};
const listViewMethods = {
dispatchEvent,
clearConfig,
loadConfig,
parseConfig,
getTableRecord,
getQueryFilter,
commitProxy
};
const listViewPrivateMethods = {};
Object.assign($xeListView, listViewMethods, listViewPrivateMethods);
const renderVN = () => {
const { height, loading } = props;
const vSize = computeSize.value;
const gridSlot = slots.grid;
const gridOptions = computeGridOptions.value;
const gridEvents = computeGridEvents.value;
return h('div', {
ref: refElem,
class: ['vxe-list-view', {
[`size--${vSize}`]: vSize,
'is--loading': loading
}],
style: height
? {
height: toCssUnit(height)
}
: null
}, [
h('div', {
class: 'vxe-list-view--body'
}, [
gridSlot
? h('div', {
class: 'vxe-list-view--grid-wrapper'
}, getSlotVNs(gridSlot({ $listView: $xeListView })))
: (VxeTableGridComponent
? h(VxeTableGridComponent, Object.assign({}, gridOptions, gridEvents, {
ref: refGrid
}), Object.assign({}, slots, {
default: undefined
}))
: createCommentVNode())
]),
/**
* 加载中
*/
h(VxeLoadingComponent, {
class: 'vxe-list-view--loading',
modelValue: loading
})
]);
};
watch(() => props.config, (value) => {
loadConfig(value || {});
});
if (props.config) {
loadConfig(props.config);
}
provide('$xeListView', $xeListView);
if (process.env.NODE_ENV === 'development') {
nextTick(() => {
if (!VxeTableGridComponent) {
errLog('vxe.error.reqComp', ['vxe-grid']);
}
});
}
$xeListView.renderVN = renderVN;
return $xeListView;
},
render() {
return this.renderVN();
}
});