统一暗色模式页面/顶栏/Handsontable 选中色,调整下单到仓方式文案与提示,CustomLeftMenu 卡片统一 60px;补充揽收单、问题件处理与 H5 相关页面。 Co-authored-by: Cursor <cursoragent@cursor.com>
997 lines
24 KiB
Vue
997 lines
24 KiB
Vue
<script lang="ts" setup>
|
||
import { useI18n } from 'vue-i18n';
|
||
import {
|
||
computed,
|
||
nextTick,
|
||
onMounted,
|
||
onUnmounted,
|
||
PropType,
|
||
reactive,
|
||
ref,
|
||
unref,
|
||
useAttrs,
|
||
watch,
|
||
} from 'vue';
|
||
import Sortable from 'sortablejs';
|
||
import cloneDeep from 'lodash/cloneDeep';
|
||
import { VxeGridProps, VxeGridPropTypes } from 'vxe-table';
|
||
import useAutoHeight from '@/components/TablePro/autoHeight';
|
||
import { isFunction } from 'lodash';
|
||
import FormPro from '@/components/FormPro/index.vue';
|
||
import { $baseMessage } from '@/utils';
|
||
// import emptyImage from '@/assets/images/empty.png';
|
||
import type { TableProMethods } from './types';
|
||
|
||
const { t } = useI18n();
|
||
|
||
const props = defineProps({
|
||
tableConfig: {
|
||
type: Object,
|
||
default: () => ({}),
|
||
},
|
||
api: {
|
||
type: Function as PropType<(...arg: any[]) => Promise<any>>,
|
||
default: null,
|
||
},
|
||
useForm: {
|
||
type: Boolean,
|
||
default: true,
|
||
},
|
||
formConfig: {
|
||
type: Object,
|
||
default: () => ({}),
|
||
},
|
||
autoHeight: {
|
||
type: Boolean,
|
||
default: true,
|
||
},
|
||
immediate: {
|
||
type: Boolean,
|
||
default: true,
|
||
},
|
||
showPager: {
|
||
type: Boolean,
|
||
default: true,
|
||
},
|
||
searchInfo: {
|
||
type: Object,
|
||
default: () => ({}),
|
||
},
|
||
tableClassName: {
|
||
type: String,
|
||
default: '',
|
||
},
|
||
maxPageSize: {
|
||
type: Number,
|
||
default: null, // null 表示不限制
|
||
},
|
||
defaultPageSize: {
|
||
type: Number,
|
||
default: null, // null 表示使用默认值 300
|
||
},
|
||
});
|
||
const attrs = useAttrs();
|
||
const proOptions = reactive<VxeGridProps>({
|
||
columnConfig: {
|
||
useKey: true,
|
||
resizable: true,
|
||
},
|
||
showOverflow: 'tooltip',
|
||
showHeaderOverflow: 'tooltip',
|
||
toolbarConfig: {
|
||
slots: {
|
||
tools: 'toolbar_right',
|
||
buttons: 'toolbar_buttons',
|
||
},
|
||
enabled: true,
|
||
perfect: true,
|
||
// enable built-in column show/hide configurator
|
||
custom: false, // 禁用自定义工具栏按钮
|
||
...props.tableConfig?.toolbarConfig,
|
||
},
|
||
...props.tableConfig,
|
||
...attrs,
|
||
});
|
||
|
||
// Compute column minWidth based on header title length when width not provided
|
||
const applyAutoHeaderWidth = (columns: any[] = []) => {
|
||
const basePadding = 36; // more space for sort/filters
|
||
const minCell = 110; // avoid 2-line headers
|
||
const charPx = 18; // wider per-char to avoid wrapping
|
||
return columns.map((col: any) => {
|
||
const next = { ...col };
|
||
if (!next.width && !next.minWidth && next.title && !['checkbox', 'seq', 'radio'].includes(next.type)) {
|
||
const textLen = String(next.title).length;
|
||
next.minWidth = Math.max(minCell, textLen * charPx + basePadding);
|
||
}
|
||
if (next.children && Array.isArray(next.children)) {
|
||
next.children = applyAutoHeaderWidth(next.children);
|
||
}
|
||
return next;
|
||
});
|
||
};
|
||
|
||
// apply once on init
|
||
if (props.tableConfig?.columns && Array.isArray(props.tableConfig.columns)) {
|
||
proOptions.columns = applyAutoHeaderWidth(props.tableConfig.columns as any[]);
|
||
}
|
||
|
||
const tableRef = ref();
|
||
const formProRef = ref();
|
||
|
||
// 根据 maxPageSize 限制生成 pageSizes 选项(统一按 10 / 30 / 50 / 100)
|
||
const generatePageSizes = () => {
|
||
const baseSizes = [10, 30, 50, 100];
|
||
if (props.maxPageSize) {
|
||
// 按照统一规则,只保留不超过 maxPageSize 的选项
|
||
return baseSizes.filter((size) => size <= props.maxPageSize);
|
||
}
|
||
return baseSizes;
|
||
};
|
||
|
||
// 确定默认 pageSize(按统一分页规则,默认 30)
|
||
const getDefaultPageSize = () => {
|
||
if (props.defaultPageSize) {
|
||
return props.defaultPageSize;
|
||
}
|
||
if (props.maxPageSize) {
|
||
// 有最大限制时,默认取 30,但不超过 maxPageSize
|
||
return Math.min(30, props.maxPageSize);
|
||
}
|
||
return 30;
|
||
};
|
||
|
||
const tablePage = reactive<VxeGridPropTypes.PagerConfig>({
|
||
currentPage: 1,
|
||
pageSize: getDefaultPageSize(),
|
||
total: 0,
|
||
pagerCount: 5,
|
||
layouts: [
|
||
'Total',
|
||
// 'PrevJump',
|
||
'PrevPage',
|
||
'JumpNumber',
|
||
'NextPage',
|
||
// 'NextJump',
|
||
'Sizes',
|
||
'FullJump',
|
||
],
|
||
size: 'medium',
|
||
pageSizes: generatePageSizes(),
|
||
});
|
||
|
||
// 已选行数量
|
||
const rowsLength = ref(0);
|
||
const { contentHeight, calcContentHeight } = useContentHeight(
|
||
tableRef,
|
||
true,
|
||
12
|
||
);
|
||
|
||
const getData = async () => {
|
||
if (isFunction(props.api)) {
|
||
const formValues = formProRef.value?.getValues() || {};
|
||
|
||
// 限制 pageSize 不超过 maxPageSize
|
||
let pageSize = tablePage.pageSize;
|
||
if (props.maxPageSize && pageSize > props.maxPageSize) {
|
||
pageSize = props.maxPageSize;
|
||
tablePage.pageSize = pageSize;
|
||
}
|
||
|
||
const d = await props.api({
|
||
...formValues,
|
||
...props.searchInfo,
|
||
pageIndex: tablePage.currentPage,
|
||
pageSize: pageSize,
|
||
});
|
||
if (d) {
|
||
if (props.showPager) {
|
||
tablePage.total = Number(d.totalCount) || 0;
|
||
const items = d.items || d?.data?.list || [];
|
||
const dataArray = Array.isArray(items) ? items : [];
|
||
|
||
if (tableRef.value) {
|
||
// 先清空数据,再加载新数据,确保表格更新
|
||
tableRef.value.reloadData([]);
|
||
nextTick(() => {
|
||
tableRef.value.reloadData(dataArray);
|
||
|
||
// 强制刷新表格
|
||
nextTick(() => {
|
||
// 强制触发表格更新
|
||
if (tableRef.value && typeof tableRef.value.updateData === 'function') {
|
||
tableRef.value.updateData();
|
||
}
|
||
validatePage();
|
||
});
|
||
});
|
||
} else {
|
||
console.error('TablePro tableRef 不存在');
|
||
}
|
||
} else {
|
||
const data = d.data || d;
|
||
const items = Array.isArray(data) ? data : [];
|
||
tableRef.value.reloadData(items);
|
||
tablePage.total = Number(items.length) || 0;
|
||
}
|
||
|
||
if (props.autoHeight) {
|
||
proOptions.height = contentHeight.value;
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
const submitFn = () => {
|
||
getData();
|
||
};
|
||
|
||
const resetFn = () => {
|
||
tablePage.currentPage = 1;
|
||
getData();
|
||
};
|
||
|
||
const tableClassName = computed(() => {
|
||
return `px-16px ${props.tableClassName}`;
|
||
});
|
||
|
||
const divRef = ref();
|
||
let sortable: any = null;
|
||
const defaultColumns2 = ref([]);
|
||
const getDefault = () => {
|
||
defaultColumns2.value = cloneDeep(proOptions.columns || props.tableConfig.columns);
|
||
};
|
||
// 使用sortablejs实现aroc table拖拽排序,并且支持固定列不允许拖动,获取拖动完成后的列排序数据
|
||
const handleSortable = () => {
|
||
const $grid = tableRef.value;
|
||
if (!$grid) return;
|
||
sortable = Sortable.create(
|
||
$grid.$el.querySelector(
|
||
'.body--wrapper>.vxe-table--header .vxe-header--row'
|
||
),
|
||
{
|
||
handle: '.vxe-header--column:not(.col--fixed)',
|
||
onEnd: (sortableEvent: any) => {
|
||
// const { showIndex } = props;
|
||
const defaultColumns = cloneDeep(defaultColumns2.value);
|
||
|
||
const targetThElem = sortableEvent.item;
|
||
const newIndex = sortableEvent.newIndex as number;
|
||
const oldIndex = sortableEvent.oldIndex as number;
|
||
const { fullColumn, tableColumn } = $grid.getTableColumn();
|
||
const wrapperElem = targetThElem.parentNode as HTMLElement;
|
||
const newColumn = fullColumn[newIndex];
|
||
const oldColumn = fullColumn[oldIndex];
|
||
if (oldColumn.fixed) {
|
||
// $baseMessage('固定列不允许拖动!', 'error')
|
||
return;
|
||
}
|
||
if (newColumn.fixed) {
|
||
// 错误的移动
|
||
const oldThElem = wrapperElem.children[oldIndex] as HTMLElement;
|
||
if (newIndex > oldIndex) {
|
||
wrapperElem.insertBefore(targetThElem, oldThElem);
|
||
} else {
|
||
wrapperElem.insertBefore(
|
||
targetThElem,
|
||
oldThElem ? oldThElem.nextElementSibling : oldThElem
|
||
);
|
||
}
|
||
// $baseMessage('固定列不允许拖动!', 'error')
|
||
return;
|
||
}
|
||
// 获取列索引 columnIndex > fullColumn
|
||
const oldColumnIndex = $grid.getColumnIndex(tableColumn[oldIndex]);
|
||
const newColumnIndex = $grid.getColumnIndex(tableColumn[newIndex]);
|
||
// 移动到目标列
|
||
const currRow = fullColumn.splice(oldColumnIndex, 1)[0];
|
||
fullColumn.splice(newColumnIndex, 0, currRow);
|
||
$grid.loadColumn(fullColumn);
|
||
|
||
// 保存默认的表格列
|
||
const splielength = 1;
|
||
const dataCurrRow = defaultColumns.splice(
|
||
oldColumnIndex - splielength,
|
||
1
|
||
)[0];
|
||
defaultColumns.splice(newColumnIndex - splielength, 0, dataCurrRow);
|
||
defaultColumns2.value = defaultColumns;
|
||
// setLocalColumns(columnsKey, defaultColumns);
|
||
// columnStorage.value = defaultColumns
|
||
},
|
||
}
|
||
);
|
||
};
|
||
const { height } = useAutoHeight(divRef, {
|
||
subtractHeight: 60, // 为分页组件预留空间
|
||
});
|
||
|
||
watch(
|
||
height,
|
||
() => {
|
||
if (props.autoHeight) {
|
||
proOptions.height = height.value;
|
||
} else {
|
||
proOptions.height = props.tableConfig.height;
|
||
}
|
||
},
|
||
{
|
||
immediate: true,
|
||
deep: true,
|
||
}
|
||
);
|
||
|
||
// 计算最大页码
|
||
const maxPage = computed(() => {
|
||
if (tablePage.total === 0 || tablePage.pageSize === 0) {
|
||
return 1;
|
||
}
|
||
return Math.ceil(tablePage.total / tablePage.pageSize);
|
||
});
|
||
|
||
// 验证并限制页码
|
||
const validatePage = () => {
|
||
const max = maxPage.value;
|
||
if (tablePage.currentPage > max && max > 0) {
|
||
tablePage.currentPage = max;
|
||
$baseMessage(t('pagination.pageExceeded', { max }), 'warning');
|
||
return true; // 返回 true 表示页码被调整了
|
||
}
|
||
if (tablePage.currentPage < 1) {
|
||
tablePage.currentPage = 1;
|
||
return true; // 返回 true 表示页码被调整了
|
||
}
|
||
return false; // 返回 false 表示页码正常
|
||
};
|
||
|
||
watch(
|
||
() => [tablePage.currentPage, tablePage.pageSize],
|
||
() => {
|
||
const pageAdjusted = validatePage();
|
||
// 如果页码被调整了,不需要再次调用 getData,因为调整页码会再次触发这个 watch
|
||
if (!pageAdjusted) {
|
||
getData();
|
||
}
|
||
},
|
||
{ deep: true }
|
||
);
|
||
|
||
// 监听 total 变化,重新验证页码
|
||
watch(
|
||
() => tablePage.total,
|
||
() => {
|
||
const pageAdjusted = validatePage();
|
||
// 如果页码被调整了,会触发上面的 watch,自动调用 getData
|
||
// 如果页码正常,不需要额外操作
|
||
}
|
||
);
|
||
|
||
onMounted(() => {
|
||
getDefault();
|
||
if (props.immediate) {
|
||
getData();
|
||
}
|
||
setTimeout(() => {
|
||
handleSortable();
|
||
}, 500);
|
||
});
|
||
onUnmounted(() => {
|
||
if (sortable) {
|
||
sortable.destroy();
|
||
}
|
||
});
|
||
|
||
// 实现所有方法
|
||
/**
|
||
* 清除选择
|
||
*/
|
||
const clearRowKeys = (): void => {
|
||
if (unref(tableRef)) {
|
||
unref(tableRef).clearCheckboxRow();
|
||
unref(tableRef).clearRadioRow();
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 重新加载数据,可以传入额外的参数
|
||
* @param params 额外的查询参数
|
||
*/
|
||
const reload = (params?: Record<string, any>): void => {
|
||
if (params) {
|
||
tablePage.currentPage = params.page || 1;
|
||
}
|
||
getData();
|
||
};
|
||
|
||
/**
|
||
* 删除勾选行
|
||
*/
|
||
const removeCheckboxRow = async (): Promise<void> => {
|
||
await tableRef.value.removeCheckboxRow();
|
||
const records = unref(tableRef) && unref(tableRef).getCheckboxRecords();
|
||
rowsLength.value = records.length;
|
||
};
|
||
|
||
/**
|
||
* 切换某一行的选择状态
|
||
*/
|
||
const toggleCheckboxRow = (row: any): void => {
|
||
if (unref(tableRef)) {
|
||
unref(tableRef).toggleCheckboxRow(row);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 设置所有行的选中状态
|
||
*/
|
||
const setAllCheckboxRow = (checked: boolean): void => {
|
||
if (unref(tableRef)) {
|
||
unref(tableRef).setAllCheckboxRow(checked);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 设置行为选中状态
|
||
*/
|
||
const setCheckboxRow = (rows: any, checked: boolean): void => {
|
||
if (unref(tableRef)) {
|
||
unref(tableRef).setCheckboxRow(rows, checked);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 设置某一行为选中状态
|
||
*/
|
||
const setRadioRow = (row: any): void => {
|
||
if (unref(tableRef)) {
|
||
unref(tableRef).setRadioRow(row);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 获取当前已选中的行数据
|
||
*/
|
||
const checkAllRows = (isFull?: boolean): any[] => {
|
||
return unref(tableRef)?.getCheckboxRecords(isFull) || [];
|
||
};
|
||
|
||
/**
|
||
* 获取列信息
|
||
*/
|
||
const getColumnByField = (name: string): any => {
|
||
return unref(tableRef).getColumnByField(name);
|
||
};
|
||
|
||
/**
|
||
* 隐藏列
|
||
*/
|
||
const hideColumn = (name: string): void => {
|
||
const field = getColumnByField(name);
|
||
if (unref(tableRef)) {
|
||
unref(tableRef).hideColumn(field || '');
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 显示列
|
||
*/
|
||
const showColumn = (name: string): void => {
|
||
const field = getColumnByField(name);
|
||
if (unref(tableRef)) {
|
||
unref(tableRef).showColumn(field || '');
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 新增行
|
||
*/
|
||
const addRow = async (args: any): Promise<any> => {
|
||
return unref(tableRef)?.insert({ ...args });
|
||
};
|
||
|
||
/**
|
||
* 新增多行到指定位置
|
||
*/
|
||
const addRowsAt = async (record: any | any[], row?: any): Promise<any> => {
|
||
const $table = unref(tableRef);
|
||
return $table.insertAt(record, row || null);
|
||
};
|
||
|
||
/**
|
||
* 激活编辑行
|
||
*/
|
||
const editRowEvent = async (
|
||
row: any,
|
||
fieldOrColumn?: string | any
|
||
): Promise<any> => {
|
||
return unref(tableRef)?.setEditRow(row, fieldOrColumn);
|
||
};
|
||
|
||
/**
|
||
* 设置展开树形节点
|
||
*/
|
||
const setTreeExpand = async (rows: any, checked: boolean): Promise<any> => {
|
||
return unref(tableRef)?.setTreeExpand(rows, checked);
|
||
};
|
||
|
||
/**
|
||
* 选择编辑单元格
|
||
*/
|
||
const editRowCellEvent = (
|
||
row: any,
|
||
fieldOrColumn: string | any
|
||
): Promise<any> => {
|
||
return unref(tableRef)?.setEditCell(row, fieldOrColumn);
|
||
};
|
||
|
||
/**
|
||
* 取消编辑状态
|
||
*/
|
||
const clearEdit = (): Promise<any> => {
|
||
return unref(tableRef)?.clearEdit();
|
||
};
|
||
|
||
/**
|
||
* 取消当前编辑状态并还原数据
|
||
*/
|
||
const cancelRowEvent = (row: any): void => {
|
||
clearEdit().then(() => {
|
||
// 还原行数据
|
||
unref(tableRef)?.revertData(row);
|
||
});
|
||
};
|
||
|
||
/**
|
||
* 获取表格数据集
|
||
*/
|
||
const getActionRows = (): {
|
||
insertRecords: any;
|
||
removeRecords: any;
|
||
updateRecords: any;
|
||
} => {
|
||
const { insertRecords, removeRecords, updateRecords } =
|
||
unref(tableRef)?.getRecordset() || {};
|
||
return {
|
||
insertRecords: insertRecords || [],
|
||
removeRecords: removeRecords || [],
|
||
updateRecords: updateRecords || [],
|
||
};
|
||
};
|
||
|
||
/**
|
||
* 表格验证
|
||
*/
|
||
const validate = async (): Promise<boolean> => {
|
||
const flag = await unref(tableRef).validate(true);
|
||
return !flag;
|
||
};
|
||
|
||
/**
|
||
* 表格完整验证
|
||
*/
|
||
const fullValidate = async (): Promise<boolean> => {
|
||
const flag = await unref(tableRef).fullValidate(true);
|
||
return !flag;
|
||
};
|
||
|
||
/**
|
||
* 获取表格数据
|
||
*/
|
||
const getTableData = (): any => {
|
||
return unref(tableRef).getTableData();
|
||
};
|
||
|
||
/**
|
||
* 获取表格数据 -> table数据
|
||
*/
|
||
const getTableData2 = (): any => {
|
||
return getTableData().tableData;
|
||
};
|
||
|
||
/**
|
||
* 获取表格数据 -> 全部数据
|
||
*/
|
||
const getFullData = (): any => {
|
||
return getTableData().fullData;
|
||
};
|
||
|
||
/**
|
||
* 获取表格数据 -> 显示数据
|
||
*/
|
||
const getVisibleData = (): any => {
|
||
return getTableData().visibleData;
|
||
};
|
||
|
||
/**
|
||
* 获取表格数据 -> 底部数据
|
||
*/
|
||
const getFooterData = (): any => {
|
||
return getTableData().footerData;
|
||
};
|
||
|
||
/**
|
||
* 判断 row 是否为编辑状态
|
||
*/
|
||
const isEditByRow = (row: any): boolean => {
|
||
return unref(tableRef).isEditByRow(row) || false;
|
||
};
|
||
|
||
/**
|
||
* 删除行
|
||
*/
|
||
const removeRow = (row?: any): any => {
|
||
unref(tableRef).remove(row);
|
||
};
|
||
|
||
/**
|
||
* 更改某一行的状态
|
||
*/
|
||
const updateStatus = (row: any): any => {
|
||
unref(tableRef).updateStatus(row);
|
||
};
|
||
|
||
/**
|
||
* 重载表格数据并清除所有状态
|
||
*/
|
||
const reloadData = (data: any[]): void => {
|
||
if (unref(tableRef)) {
|
||
unref(tableRef).reloadData(data);
|
||
}
|
||
rowsLength.value = 0;
|
||
};
|
||
|
||
/**
|
||
* 加载数据
|
||
*/
|
||
const loadData = (data: any[]): void => {
|
||
if (unref(tableRef)) {
|
||
unref(tableRef)?.loadData(data);
|
||
}
|
||
rowsLength.value = 0;
|
||
};
|
||
|
||
/**
|
||
* 获取表格数据编辑
|
||
*/
|
||
const getUpdateRecords = (): any[] => {
|
||
return unref(tableRef).getUpdateRecords() || [];
|
||
};
|
||
|
||
/**
|
||
* 设置某行高亮
|
||
*/
|
||
const setCurrentRow = async (row: any): Promise<void> => {
|
||
if (unref(tableRef)) {
|
||
return unref(tableRef).setCurrentRow(row);
|
||
}
|
||
return Promise.resolve();
|
||
};
|
||
|
||
/**
|
||
* 获取插入数据
|
||
*/
|
||
const getInsertRecords = (): any[] => {
|
||
return unref(tableRef).getInsertRecords() || [];
|
||
};
|
||
|
||
/**
|
||
* 获取某一行数据
|
||
* @param rowIndex 行索引
|
||
*/
|
||
const getRowData = (rowIndex: number): any => {
|
||
return unref(tableRef).getData(rowIndex);
|
||
};
|
||
|
||
/**
|
||
* 清空数据
|
||
*/
|
||
const clearData = async (): Promise<void> => {
|
||
await unref(tableRef).clearData();
|
||
};
|
||
|
||
/**
|
||
* 获取高亮行
|
||
*/
|
||
const getCurrentRecordRow = (): any => {
|
||
return unref(tableRef).getCurrentRecord();
|
||
};
|
||
|
||
/**
|
||
* 获取当前表格的列
|
||
*/
|
||
const getTableColumn = (): {
|
||
collectColumn: any;
|
||
fullColumn: any;
|
||
visibleColumn: any;
|
||
tableColumn: any;
|
||
} => {
|
||
const { collectColumn, fullColumn, visibleColumn, tableColumn } =
|
||
unref(tableRef)?.getTableColumn() || {};
|
||
return {
|
||
collectColumn: collectColumn || [],
|
||
fullColumn: fullColumn || [],
|
||
visibleColumn: visibleColumn || [],
|
||
tableColumn: tableColumn || [],
|
||
};
|
||
};
|
||
|
||
/**
|
||
* 清空高亮
|
||
*/
|
||
const clearCurrentRow = async (): Promise<void> => {
|
||
await unref(tableRef).clearCurrentRow();
|
||
};
|
||
|
||
/**
|
||
* 获取鼠标选择的所有区域
|
||
*/
|
||
const getCellAreas = (): any[] => {
|
||
return unref(tableRef).getCellAreas() || [];
|
||
};
|
||
|
||
/**
|
||
* 获取区域中的活动单元格
|
||
*/
|
||
const getActiveCellArea = (): any => {
|
||
return unref(tableRef).getActiveCellArea();
|
||
};
|
||
|
||
/**
|
||
* 选择指定区域的单元格
|
||
*/
|
||
const setCellAreas = (areaConfigs: any[], activeArea?: any): Promise<any> => {
|
||
return unref(tableRef).setCellAreas(areaConfigs, activeArea);
|
||
};
|
||
|
||
/**
|
||
* 清除鼠标选择的区域
|
||
*/
|
||
const clearCellAreas = (area?: any): Promise<any> => {
|
||
return unref(tableRef).clearCellAreas(area);
|
||
};
|
||
|
||
/**
|
||
* 清除标记为复制粘贴的区域
|
||
*/
|
||
const clearCopyCellArea = (): Promise<any> => {
|
||
return unref(tableRef).clearCopyCellArea();
|
||
};
|
||
|
||
/**
|
||
* 手动关闭查找与替换窗口
|
||
*/
|
||
const closeFNR = (): Promise<any> => {
|
||
return unref(tableRef).closeFNR();
|
||
};
|
||
|
||
/**
|
||
* 打开单元格查找功能
|
||
*/
|
||
const openFind = (): Promise<any> => {
|
||
return unref(tableRef).openFind();
|
||
};
|
||
|
||
/**
|
||
* 打开单元格替换功能
|
||
*/
|
||
const openReplace = (): Promise<any> => {
|
||
return unref(tableRef).openReplace();
|
||
};
|
||
|
||
/**
|
||
* 保存行
|
||
*/
|
||
const saveRow = (row: any): Promise<any> => {
|
||
return unref(tableRef).saveRow(row);
|
||
};
|
||
|
||
const setHeight = (height: number) => {
|
||
proOptions.height = height;
|
||
};
|
||
|
||
// 暴露所有方法
|
||
defineExpose({
|
||
xGrid: tableRef,
|
||
setHeight,
|
||
clearRowKeys,
|
||
removeCheckboxRow,
|
||
toggleCheckboxRow,
|
||
setAllCheckboxRow,
|
||
setCheckboxRow,
|
||
setRadioRow,
|
||
checkAllRows,
|
||
getColumnByField,
|
||
hideColumn,
|
||
showColumn,
|
||
addRow,
|
||
addRowsAt,
|
||
editRowEvent,
|
||
setTreeExpand,
|
||
editRowCellEvent,
|
||
clearEdit,
|
||
cancelRowEvent,
|
||
getActionRows,
|
||
validate,
|
||
fullValidate,
|
||
getTableData,
|
||
getTableData2,
|
||
getFullData,
|
||
getVisibleData,
|
||
getFooterData,
|
||
isEditByRow,
|
||
removeRow,
|
||
updateStatus,
|
||
reloadData,
|
||
loadData,
|
||
getUpdateRecords,
|
||
setCurrentRow,
|
||
getInsertRecords,
|
||
getRowData,
|
||
clearData,
|
||
getCurrentRecordRow,
|
||
getTableColumn,
|
||
clearCurrentRow,
|
||
getCellAreas,
|
||
getActiveCellArea,
|
||
setCellAreas,
|
||
clearCellAreas,
|
||
clearCopyCellArea,
|
||
closeFNR,
|
||
openFind,
|
||
openReplace,
|
||
saveRow,
|
||
reload,
|
||
} as TableProMethods);
|
||
</script>
|
||
|
||
<template>
|
||
<div class="table-pro h-full w-full">
|
||
<div v-if="props.useForm" class="mb-12px table-pro-surface">
|
||
<FormPro
|
||
ref="formProRef"
|
||
:button-config="{
|
||
showBtn: true,
|
||
okText: t('common.search'),
|
||
resetText: t('common.reset'),
|
||
showReset: true,
|
||
showOk: true,
|
||
span: 6,
|
||
}"
|
||
class="px-16px pt-12px"
|
||
v-bind="props.formConfig"
|
||
@reset="resetFn"
|
||
@submit="submitFn"
|
||
/>
|
||
</div>
|
||
<div ref="divRef" class="table-pro-surface">
|
||
<vxe-grid
|
||
ref="tableRef"
|
||
:sort-config="{}"
|
||
border
|
||
:class="tableClassName"
|
||
v-bind="proOptions"
|
||
>
|
||
<template v-for="item in Object.keys($slots)" :key="item" #[item]="row">
|
||
<slot :name="item" v-bind="row" />
|
||
</template>
|
||
<!--
|
||
<template #empty>
|
||
<div class="flex justify-center empty-image">
|
||
<img :src="emptyImage" alt="空数据" class="w-68px mb-17px" />
|
||
</div>
|
||
<div v-if="showText" class="empty-text">
|
||
{{ props.emptyText }}
|
||
</div>
|
||
</template> -->
|
||
|
||
<template #toolbar_buttons>
|
||
<div class="toolbar-buttons">
|
||
<slot name="toolbar_buttons" />
|
||
</div>
|
||
</template>
|
||
<template #toolbar_right>
|
||
<div class="toolbar-right">
|
||
<slot name="toolbar_right" />
|
||
</div>
|
||
</template>
|
||
<template v-if="props.showPager" #pager>
|
||
<vxe-pager
|
||
v-model:current-page="tablePage.currentPage"
|
||
v-model:page-size="tablePage.pageSize"
|
||
:layouts="tablePage.layouts"
|
||
:page-sizes="tablePage.pageSizes"
|
||
:pager-count="tablePage.pagerCount"
|
||
:size="tablePage.size"
|
||
:total="tablePage.total"
|
||
>
|
||
<template #left>
|
||
<!-- <div v class="absolute" style="left: 0">-->
|
||
<!-- {{ $t('已选择') }}-->
|
||
<!-- <span>{{ rowsLength }}</span-->
|
||
<!-- >{{ $t('条') }}-->
|
||
<!-- </div>-->
|
||
<slot name="buttom_left" />
|
||
</template>
|
||
</vxe-pager>
|
||
</template>
|
||
</vxe-grid>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<style lang="less" scoped>
|
||
.table-pro-surface {
|
||
background-color: var(--app-card-bg);
|
||
}
|
||
|
||
.table-pro {
|
||
:deep(.vxe-toolbar) {
|
||
padding: 0;
|
||
background-color: var(--color-bg-2);
|
||
border: 0 !important;
|
||
border-bottom: none;
|
||
}
|
||
|
||
:deep(.vxe-table) {
|
||
border-color: var(--color-neutral-3);
|
||
|
||
.vxe-table--header-wrapper {
|
||
background-color: var(--color-fill-2);
|
||
}
|
||
|
||
.vxe-table--render-default.size--small {
|
||
font-size: 12px;
|
||
}
|
||
|
||
// 全局设置表格行高度为小尺寸
|
||
.vxe-table--render-default {
|
||
font-size: 12px;
|
||
|
||
.vxe-body--row {
|
||
height: 32px !important;
|
||
line-height: 32px !important;
|
||
}
|
||
|
||
.vxe-header--row {
|
||
height: 40px !important;
|
||
line-height: 40px !important;
|
||
}
|
||
}
|
||
|
||
.vxe-body--row {
|
||
background-color: var(--color-bg-2);
|
||
|
||
&:hover {
|
||
background-color: var(--color-fill-2);
|
||
}
|
||
}
|
||
}
|
||
|
||
.empty-image {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding: 20px 0;
|
||
font-size: 12px;
|
||
color: #b8babc;
|
||
|
||
img {
|
||
// width: 180px;
|
||
user-select: none;
|
||
}
|
||
}
|
||
|
||
.toolbar-buttons {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.toolbar-right {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
}
|
||
}
|
||
</style>
|