mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2026-02-05 01:55:29 +08:00
3.7.1版本发布
This commit is contained in:
@ -5,15 +5,15 @@
|
||||
<template #buttons>
|
||||
<div :class="`${prefixCls}-button div`" :size="btnSize">
|
||||
<slot v-if="showPrefix" name="toolbarPrefix" :size="btnSize" />
|
||||
<a-button v-if="showAdd" type="primary" preIcon="ant-design:plus-outlined" :disabled="disabled" @click="trigger('add')">
|
||||
<a-button v-if="showAdd" type="primary" preIcon="ant-design:plus-outlined" :disabled="disabled" :loading="deleting" @click="trigger('add')">
|
||||
<span>新增</span>
|
||||
</a-button>
|
||||
<a-button v-if="showSave" preIcon="ant-design:save-outlined" :disabled="disabled" @click="trigger('save')">
|
||||
<span>保存</span>
|
||||
</a-button>
|
||||
<template v-if="selectedRowIds.length > 0">
|
||||
<Popconfirm v-if="showRemove" :title="`确定要删除这 ${selectedRowIds.length} 项吗?`" @confirm="trigger('remove')">
|
||||
<a-button preIcon="ant-design:minus-outlined" :disabled="disabled">删除</a-button>
|
||||
<template v-if="deleting || selectedRowIds.length > 0">
|
||||
<Popconfirm v-if="showRemove" :title="`确定要删除这 ${selectedRowIds.length} 项吗?`" :disabled="deleting" @confirm="onRemove">
|
||||
<a-button preIcon="ant-design:minus-outlined" :disabled="disabled" :loading="deleting">删除</a-button>
|
||||
</Popconfirm>
|
||||
<template v-if="showClearSelection">
|
||||
<a-button preIcon="ant-design:delete-outlined" @click="trigger('clearSelection')">清空选择</a-button>
|
||||
@ -115,4 +115,19 @@
|
||||
function toggleCollapse() {
|
||||
collapsed.value = !collapsed.value;
|
||||
}
|
||||
|
||||
// 【TV360X-1975】在Online设计中,当字段多时,由于会同步删除其他表格导致删除时间变长,所以增加删除loading,防止以为点击删除按钮无效
|
||||
const deleting = ref(false);
|
||||
|
||||
let deleteTimer: any = null
|
||||
|
||||
function onRemove() {
|
||||
trigger('remove')
|
||||
deleting.value = true;
|
||||
if (deleteTimer) {
|
||||
clearTimeout(deleteTimer)
|
||||
}
|
||||
deleteTimer = setTimeout(() => deleting.value = false, 300);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@ -183,7 +183,9 @@ function handleSeqColumn({ props, col, columns }: HandleArgs) {
|
||||
*/
|
||||
function handleSelectionColumn({ props, data, col, columns }: HandleArgs) {
|
||||
// 判断是否开启了可选择行
|
||||
if (props.rowSelection) {
|
||||
// -update-begin--author:liaozhiyang---date:20240617---for:【TV360X-1002】详情页面行编辑不显示checkbox
|
||||
if (props.rowSelection && props.disabled == false) {
|
||||
// -update-end--author:liaozhiyang---date:20240617---for:【TV360X-1002】详情页面行编辑不显示checkbox
|
||||
let width = 45;
|
||||
if (data.statistics.has && !props.rowExpand && !props.dragSort) {
|
||||
width = 60;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { onMounted, onUnmounted, nextTick } from 'vue';
|
||||
import { JVxeTableMethods, JVxeTableProps } from '/@/components/jeecg/JVxeTable/src/types';
|
||||
import Sortable from 'sortablejs';
|
||||
import { isEnabledVirtualYScroll } from '/@/components/jeecg/JVxeTable/utils';
|
||||
|
||||
export function useDragSort(props: JVxeTableProps, methods: JVxeTableMethods) {
|
||||
if (props.dragSort) {
|
||||
@ -37,40 +38,73 @@ export function useDragSort(props: JVxeTableProps, methods: JVxeTableMethods) {
|
||||
// @ts-ignore
|
||||
startChildren = [...from.children];
|
||||
},
|
||||
onEnd(e) {
|
||||
let oldIndex = e.oldIndex as number;
|
||||
let newIndex = e.newIndex as number;
|
||||
if (oldIndex === newIndex) {
|
||||
return;
|
||||
}
|
||||
// 【VUEN-2505】获取当前行数据
|
||||
let rowNode = xTable.getRowNode(e.item);
|
||||
if (!rowNode) {
|
||||
return;
|
||||
}
|
||||
let from = e.from;
|
||||
let element = startChildren[oldIndex];
|
||||
let target = null;
|
||||
if (oldIndex > newIndex) {
|
||||
// 向上移动
|
||||
if (oldIndex + 1 < startChildren.length) {
|
||||
target = startChildren[oldIndex + 1];
|
||||
onEnd(e: any) {
|
||||
// -update-begin--author:liaozhiyang---date:20240619---for:【TV360X-585】拖动字段虚拟滚动不好使
|
||||
const isRealEnabledVirtual = isEnabledVirtualYScroll(props, xTable);
|
||||
let newIndex;
|
||||
let oldIndex;
|
||||
// 滚动排序需要区分当前行编辑是否启动了虚拟滚动(底层loadData方法对是否真实开启了虚拟滚动处理不一样导致需要区分)
|
||||
if (isRealEnabledVirtual) {
|
||||
// e.clone的元素才是真实拖动的元素(虚拟滚动也不会变)
|
||||
const dragNode = e.clone;
|
||||
const dragRowInfo = xTable.getRowNode(dragNode);
|
||||
// e.item的元素只有没虚拟滚动时才是拖动的元素(如果虚拟滚动了则会变)
|
||||
const itemNode = e.item;
|
||||
const itemRowInfo = xTable.getRowNode(itemNode);
|
||||
// e.newIndex是当前可视区内元素的索引(不是数据实际的索引)、e.oldIndex 是拖动时可视区内元素的索引(不是数据实际的索引)
|
||||
if (dragRowInfo!.rowid === itemRowInfo!.rowid) {
|
||||
// e.clone和e.item相同说明拖拽的元素在DOM中,没被虚拟滚动给remove掉。
|
||||
if (e.newIndex === e.oldIndex) {
|
||||
// 此时新旧index一样就可认为没拖动
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
// 此时真实DOM元素顺序已排(通过拖拽元素的前后元素确定拖拽元素在真实数据中是往前还是往后拖)
|
||||
oldIndex = dragRowInfo!.index;
|
||||
const len = e.from.childNodes.length;
|
||||
let referenceIndex;
|
||||
let referenceNode;
|
||||
if (e.newIndex + 1 < len) {
|
||||
// 拖拽DOM交换之后,后面还有元素(参考物是后面的元素)
|
||||
referenceNode = e.from.childNodes[e.newIndex + 1];
|
||||
referenceIndex = xTable.getRowNode(referenceNode)!.index;
|
||||
if (oldIndex > referenceIndex) {
|
||||
newIndex = referenceIndex;
|
||||
} else {
|
||||
newIndex = referenceIndex - 1;
|
||||
}
|
||||
} else {
|
||||
// 拖拽DOM交换之后,后面没有元素了(参考物是前面的元素)
|
||||
referenceNode = e.from.childNodes[e.newIndex - 1];
|
||||
referenceIndex = xTable.getRowNode(referenceNode)!.index;
|
||||
newIndex = referenceIndex;
|
||||
}
|
||||
} else {
|
||||
// 向下移动
|
||||
target = startChildren[oldIndex + 1];
|
||||
}
|
||||
from.removeChild(element);
|
||||
from.insertBefore(element, target);
|
||||
nextTick(() => {
|
||||
// 【VUEN-2505】算出因虚拟滚动导致的偏移量
|
||||
let diffIndex = rowNode!.index - oldIndex;
|
||||
if (diffIndex > 0) {
|
||||
oldIndex = oldIndex + diffIndex;
|
||||
newIndex = newIndex + diffIndex;
|
||||
oldIndex = e.oldIndex;
|
||||
newIndex = e.newIndex;
|
||||
if (oldIndex === newIndex) {
|
||||
return;
|
||||
}
|
||||
const from = e.from;
|
||||
const element = startChildren[oldIndex];
|
||||
let target = null;
|
||||
if (oldIndex > newIndex) {
|
||||
// 向上移动
|
||||
if (oldIndex + 1 < startChildren.length) {
|
||||
target = startChildren[oldIndex + 1];
|
||||
}
|
||||
} else {
|
||||
// 向下移动
|
||||
target = startChildren[oldIndex + 1];
|
||||
}
|
||||
from.removeChild(element);
|
||||
from.insertBefore(element, target);
|
||||
}
|
||||
// -update-end--author:liaozhiyang---date:20240620---for:【TV360X-585】拖动字段虚拟滚动不好使
|
||||
nextTick(() => {
|
||||
methods.doSort(oldIndex, newIndex);
|
||||
methods.trigger('dragged', { oldIndex, newIndex });
|
||||
methods.trigger('dragged', { oldIndex: oldIndex, newIndex: newIndex });
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@ -11,6 +11,7 @@ import { useWebSocket } from './useWebSocket';
|
||||
import { getPrefix, getJVxeAuths } from '../utils/authUtils';
|
||||
import { excludeKeywords } from '../componentMap';
|
||||
import { useColumnsCache } from './useColumnsCache';
|
||||
import { isEnabledVirtualYScroll } from '/@/components/jeecg/JVxeTable/utils';
|
||||
|
||||
export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps, refs: JVxeRefs, instanceRef: Ref) {
|
||||
let xTableTemp: VxeTableInstance & VxeTablePrivateMethods;
|
||||
@ -195,7 +196,9 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
|
||||
return getEnhanced(column.params.type).aopEvents.activeMethod!.apply(instanceRef.value, arguments as any) ?? true;
|
||||
})();
|
||||
if (!flag) {
|
||||
getXTable().clearActived();
|
||||
// -update-begin--author:liaozhiyang---date:20240619---for:【TV360X-1404】vxetable警告
|
||||
getXTable().clearEdit();
|
||||
// -update-end--author:liaozhiyang---date:20240619---for:【TV360X-1404】vxetable警告
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
@ -424,8 +427,10 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
|
||||
// 插入行
|
||||
let result = await xTable.insertAt(rows, index);
|
||||
if (setActive) {
|
||||
// -update-begin--author:liaozhiyang---date:20240619---for:【TV360X-1404】vxetable警告
|
||||
// 激活最后一行的编辑模式
|
||||
xTable.setActiveRow(result.rows[result.rows.length - 1]);
|
||||
xTable.setEditRow(result.rows[result.rows.length - 1]);
|
||||
// -update-end--author:liaozhiyang---date:20240619---for:【TV360X-1404】vxetable警告
|
||||
}
|
||||
await recalcSortNumber();
|
||||
return result;
|
||||
@ -453,8 +458,14 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
|
||||
callback('', tableData);
|
||||
}
|
||||
|
||||
type getTableDataOptions = {
|
||||
rowIds?: string[];
|
||||
// 是否保留新行的id
|
||||
keepNewId?: boolean;
|
||||
}
|
||||
|
||||
/** 获取表格数据 */
|
||||
function getTableData(options: any = {}) {
|
||||
function getTableData(options: getTableDataOptions = {}) {
|
||||
let { rowIds } = options;
|
||||
let tableData;
|
||||
// 仅查询指定id的行
|
||||
@ -470,7 +481,10 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
|
||||
// 查询所有行
|
||||
tableData = getXTable().getTableData().fullData;
|
||||
}
|
||||
return filterNewRows(tableData, false);
|
||||
return filterNewRows(tableData, {
|
||||
keepNewId: options.keepNewId ?? false,
|
||||
removeNewLine: false,
|
||||
});
|
||||
}
|
||||
|
||||
/** 仅获取新增的数据 */
|
||||
@ -513,23 +527,33 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
|
||||
return null;
|
||||
}
|
||||
|
||||
type filterNewRowsOptions = {
|
||||
keepNewId?: boolean;
|
||||
removeNewLine?: boolean;
|
||||
} | boolean
|
||||
|
||||
/**
|
||||
* 过滤添加的行
|
||||
* @param rows 要筛选的行数据
|
||||
* @param remove true = 删除新增,false=只删除id
|
||||
* @param optOrRm 如果传 boolean 则是 removeNewLine 参数(true = 删除新增,false=只删除id),如果传对象则是配置参数
|
||||
* @param handler function
|
||||
*/
|
||||
function filterNewRows(rows, remove = true, handler?: Fn) {
|
||||
function filterNewRows(rows, optOrRm:filterNewRowsOptions = true, handler?: Fn) {
|
||||
let insertRecords = getXTable().getInsertRecords();
|
||||
let records: Recordable[] = [];
|
||||
optOrRm = typeof optOrRm === 'boolean' ? { removeNewLine: optOrRm } : optOrRm;
|
||||
// true = 删除新增,false=只删除id
|
||||
let removeNewLine = optOrRm?.removeNewLine ?? true;
|
||||
for (let row of rows) {
|
||||
let item = cloneDeep(row);
|
||||
if (insertRecords.includes(row)) {
|
||||
handler ? handler({ item, row, insertRecords }) : null;
|
||||
if (remove) {
|
||||
if (removeNewLine) {
|
||||
continue;
|
||||
}
|
||||
delete item.id;
|
||||
if (!optOrRm?.keepNewId) {
|
||||
delete item.id;
|
||||
}
|
||||
}
|
||||
records.push(item);
|
||||
}
|
||||
@ -762,6 +786,11 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
|
||||
if (xTable.keepSource) {
|
||||
sort(xTable.internalData.tableSourceData);
|
||||
}
|
||||
// -update-begin--author:liaozhiyang---date:20240620---for:【TV360X-585】拖动字段虚拟滚动不好使
|
||||
if (isEnabledVirtualYScroll(props, xTable)) {
|
||||
await xTable.loadData(xTable.internalData.tableFullData);
|
||||
}
|
||||
// -update-end--author:liaozhiyang---date:20240620---for:【TV360X-585】拖动字段虚拟滚动不好使
|
||||
return await recalcSortNumber(force);
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,3 +107,26 @@ export function vModel(value, row, column: Ref<any> | string) {
|
||||
let property = isRef(column) ? column.value.property : column;
|
||||
unref(row)[property] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* liaozhiyang
|
||||
* 2024-06-20
|
||||
* 判断当前行编辑是否使用了虚拟滚动(并不是开启了就是,还得满足数据数量大于gt值)
|
||||
*/
|
||||
export function isEnabledVirtualYScroll(props, xTable): boolean {
|
||||
let isRealEnabledVirtual = false;
|
||||
const isEnabledVScroll = props?.scrollY?.enabled;
|
||||
// 100是底层的默认值
|
||||
const gtYNum = props?.scrollY?.gt || 100;
|
||||
if (isEnabledVScroll) {
|
||||
const tableFullData = xTable.internalData.tableFullData;
|
||||
if (gtYNum === 0) {
|
||||
isRealEnabledVirtual = true;
|
||||
} else {
|
||||
if (tableFullData.length > gtYNum) {
|
||||
isRealEnabledVirtual = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return isRealEnabledVirtual;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user