Browse Source

表格优化提交

main
likunming 1 year ago
parent
commit
7d80acd15b
  1. 143
      io.sc.platform.core.frontend/src/platform/components/grid/TreeGridRow.vue
  2. 303
      io.sc.platform.core.frontend/src/platform/components/grid/WGrid.vue
  3. 21
      io.sc.platform.core.frontend/src/platform/components/toolbar/ChildrenBtn.vue
  4. 33
      io.sc.platform.core.frontend/src/platform/components/toolbar/WToolbar.vue
  5. 106
      io.sc.platform.core.frontend/src/views/likm/Grid.vue
  6. 47
      io.sc.platform.core.frontend/src/views/likm/TreeGrid.vue
  7. 2
      io.sc.platform.system/src/main/java/io/sc/platform/system/menu/jpa/entity/MenuEntity.java

143
io.sc.platform.core.frontend/src/platform/components/grid/TreeGridRow.vue

@ -1,5 +1,9 @@
<template>
<q-tr :class="row.selected ? 'selected' : ''" @click="click($event, row, row.rowIndex)">
<q-tr
:class="row[table.selectedField] ? 'selected' : ''"
@click.stop.prevent="click($event, row, row.rowIndex)"
@dblclick.stop.prevent="dbClick($event, row, row.rowIndex)"
>
<q-td class="nowrap text-nowrap">
<div class="flex flex-nowrap items-center">
<!--层级占位符-->
@ -10,13 +14,21 @@
flat
dense
padding="0px 0px"
:icon="state.currRow.expand ? 'bi-dash' : 'bi-plus'"
@click.stop="expandFun"
:icon="row.expand ? 'bi-dash' : 'bi-plus'"
@click.stop="expandFun(row)"
@dblclick.stop="() => {}"
/>
<!--展开按钮占位符-->
<span v-else style="width: 27px"></span>
<!--选择框-->
<q-checkbox v-if="table.checkboxSelection" v-model="state.currRow.selected" flat dense @update:model-value="selectedFun(state.currRow.selected, row)" />
<q-checkbox
v-if="table.checkboxSelection"
v-model="getRow(table.rows, row[props.rowKey], false)[table.tickedField]"
flat
dense
@dblclick.stop="() => {}"
@update:model-value="selectedFun(row[table.tickedField], row, $event)"
/>
<!--图标-->
<q-icon v-if="typeof iconComputed === 'string'" :name="iconComputed" size="20px" class="px-1"></q-icon>
<q-icon v-else-if="typeof iconComputed === 'object'" size="20px" v-bind="iconComputed" class="px-1"></q-icon>
@ -32,11 +44,7 @@
</div>
</q-td>
<template v-for="(col, index) in cols" :key="col.name">
<q-td
v-if="index > 0"
:title="col.classes?.indexOf('truncate') > -1 && col.value && typeof col.value !== 'object' ? col.value : ''"
@click="click($event, row, row.rowIndex)"
>
<q-td v-if="index > 0" :title="col.classes?.indexOf('truncate') > -1 && col.value && typeof col.value !== 'object' ? col.value : ''">
<div :class="col.__thClass">
<template v-if="col.value && typeof col.value === 'object' && col.value.componentType">
<component :is="col.value.componentType" v-bind="col.value.attrs"></component>
@ -50,13 +58,14 @@
</q-tr>
<template v-for="child in row.children" :key="child[rowKey]">
<TreeGridRow
v-if="state.currRow.expand"
v-if="row.expand"
:columns-map="props.columnsMap"
:row="child"
:cols="childColsHandler(child)"
:level="props.level + 1"
:grid-props="gridProps"
:row-key="props.rowKey"
:grid="props.grid"
></TreeGridRow>
</template>
</template>
@ -89,19 +98,14 @@ const props = defineProps({
},
},
rowKey: { type: String, default: '_rowKey_' },
grid: {
type: Object,
default: () => {
return {};
},
},
});
const table = inject('table');
const state = reactive({
currRow: {},
});
watch(
() => props.row.selected,
(newVal, oldVal) => {
state.currRow.selected = newVal;
},
);
const iconComputed = computed(() => {
if (props.gridProps.treeIcon) {
@ -118,20 +122,6 @@ const iconComputed = computed(() => {
}
});
//
const getCurrRow = (arr) => {
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
if (item[props.rowKey] === props.row[props.rowKey]) {
state.currRow = { expand: false, selected: false, ...item };
break;
} else if (item.children && item.children.length > 0) {
getCurrRow(item.children);
}
}
};
getCurrRow(table.rows);
// key
const getRow = (arr, key, parent) => {
let result = undefined;
@ -151,60 +141,54 @@ const getRow = (arr, key, parent) => {
};
// /
const expandFun = () => {
if (state.currRow) {
state.currRow.expand = !state.currRow.expand;
}
const expandFun = (row) => {
row.expand = !row.expand;
};
// checkbox
const selectedFun = (value, row) => {
const selectedFun = (value, row, event) => {
if (value) {
selectedPush(row);
getRow(table.rows, row[props.rowKey], false).selected = true;
getRow(table.rows, row[props.rowKey], false)[table.tickedField] = true;
} else {
selectedRemove(row);
getRow(table.rows, row[props.rowKey], false).selected = false;
getRow(table.rows, row[props.rowKey], false)[table.tickedField] = false;
}
selectedChildren(row, value);
selectedParent(row, value);
if (props.gridProps.onUpdateTicked) {
props.gridProps.onUpdateTicked(event, row);
}
};
//
const selectedChildren = (row, selected) => {
const selectedChildren = (row, value) => {
if (row.children && row.children.length > 0) {
for (let child of row.children) {
child['selected'] = selected;
if (selected) {
selectedPush(child);
} else {
selectedRemove(child);
}
selectedChildren(child, selected);
child[table.tickedField] = value;
selectedChildren(child, value);
}
}
};
//
const selectedParent = (row, selected) => {
const selectedParent = (row, value) => {
if (row.parent) {
const parent = getRow(table.rows, row.parent, true);
if (parent) {
if (selected && childrenSelectedStatus(parent).allSelected) {
parent.selected = true;
selectedPush(parent);
} else if (selected) {
parent.selected = null;
if (value && childrenSelectedStatus(parent).allSelected) {
parent[table.tickedField] = true;
// selectedPush(parent);
} else if (value) {
parent[table.tickedField] = null;
} else {
selectedRemove(parent);
// selectedRemove(parent);
if (childrenSelectedStatus(parent).partSelected) {
parent.selected = null;
parent[table.tickedField] = null;
} else {
parent.selected = false;
parent[table.tickedField] = false;
}
}
}
selectedParent(parent, selected);
selectedParent(parent, value);
}
};
@ -216,7 +200,7 @@ const childrenSelectedStatus = (row) => {
};
if (row.children && row.children.length > 0) {
for (let i = 0; i < row.children.length; i++) {
if (!row.children[i].selected) {
if (!row.children[i][table.tickedField]) {
result.allSelected = false;
} else {
result.partSelected = true;
@ -233,23 +217,6 @@ const childrenSelectedStatus = (row) => {
return result;
};
//
const selectedPush = (row) => {
// push
if (table.selected.findIndex((item) => item[props.rowKey] === row[props.rowKey]) < 0) {
table.selected.push(row);
}
};
const selectedRemove = (row) => {
// remove
if (table.selected.findIndex((item) => item[props.rowKey] === row[props.rowKey]) > -1) {
table.selected.splice(
table.selected.findIndex((item) => item[props.rowKey] === row[props.rowKey]),
1,
);
}
};
// cols
const childColsHandler = (child) => {
const cols = <any>[];
@ -270,13 +237,19 @@ const childColsHandler = (child) => {
};
const click = (evt, row, rowIndex) => {
table.rows.forEach((item) => {
selectedFun(false, item);
});
table.selected.splice(0, table.selected.length);
selectedFun(true, row);
if (!evt.ctrlKey) {
props.grid.cleanSelected();
}
row[table.selectedField] = true;
if (props.gridProps.onRowClick) {
props.gridProps.onRowClick(evt, row, rowIndex);
}
};
const dbClick = (evt, row, rowIndex) => {
if (props.gridProps.onRowDbClick) {
props.gridProps.onRowDbClick(evt, row, rowIndex);
} else {
props.grid.view();
}
};
</script>

303
io.sc.platform.core.frontend/src/platform/components/grid/WGrid.vue

@ -3,7 +3,6 @@
<q-table
ref="tableRef"
v-model:pagination="state.pagination"
v-model:selected="table.selected"
flat
binary-state-sort
:no-data-label="state.noDataLabel"
@ -29,15 +28,7 @@
<div class="pt-2.5 flex flex-nowrap items-end">
<div class="flex-none">{{ title }}</div>
<div class="flex-1">
<w-toolbar
:dense="denseToolbarComputed"
v-bind="toolbarConfigure"
:buttons="buttons_"
:grid-props="{
selected: getSelectedRowsComputed,
grid: instance,
}"
></w-toolbar>
<w-toolbar :dense="denseToolbarComputed" v-bind="toolbarConfigure" :buttons="buttons_" :grid="instance"></w-toolbar>
</div>
<div v-if="configButton" class="flex-none pl-1">
<q-btn round dense :size="denseToolbarComputed ? '13px' : '14px'" :icon="IconEnum.设置" unelevated outline>
@ -102,11 +93,17 @@
</template>
<template #body="scope">
<template v-if="tree">
<TreeGridRow :columns-map="tableColumnsMap" :row="scope.row" :cols="scope.cols" :grid-props="props" :row-key="rowKey_"></TreeGridRow>
<TreeGridRow :columns-map="tableColumnsMap" :row="scope.row" :cols="scope.cols" :grid-props="props" :row-key="rowKey_" :grid="instance"></TreeGridRow>
</template>
<q-tr v-else :props="scope" @click="rowClick($event, scope.row, scope.rowIndex)" @dblclick="rowDbClick($el, scope.row, scope.rowIndex)">
<q-tr
v-else
:class="scope.row[table.selectedField] ? 'selected' : ''"
:props="scope"
@click.stop="rowClick($event, scope.row, scope.rowIndex)"
@dblclick.stop="rowDbClick($event, scope.row, scope.rowIndex)"
>
<q-td v-if="table.checkboxSelection" class="text-center" style="padding: 0; width: 50px">
<q-checkbox v-model="scope.selected" flat :dense="denseBodyComputed" />
<q-checkbox v-model="scope.row[table.tickedField]" flat :dense="denseBodyComputed" @update:model-value="updateTicked($event, scope.row)" />
</q-td>
<template v-if="draggable">
<q-td
@ -247,10 +244,12 @@ const props = defineProps({
sortNo: { type: Boolean, default: false }, //
stickyNum: { type: Number, default: 0 }, // 1-10el
checkboxSelection: { type: Boolean, default: true }, // checkbox
tickedField: { type: String, default: 'ticked' }, // checkbox
selectedField: { type: String, default: 'selected' }, //
tree: { type: Boolean, default: false }, //
treeIcon: { type: Function, default: undefined }, //
treeExpand: { type: Boolean, default: false }, //
treeExpandChildren: { type: Boolean, default: false }, //
treeDefaultExpandAll: { type: Boolean, default: false }, //
treeTickStrategy: { type: String, default: 'leaf' }, // strictleaf
treeRelationship: { type: String, default: 'parent' }, // parent, childrenparentchildren
primaryKey: { type: String, default: 'id' }, // APIRestCrudControllerupdate
foreignKey: { type: String, default: 'parent' }, //
@ -327,26 +326,24 @@ const props = defineProps({
},
onRowClick: {
type: Function,
default: null,
}, // 使
default: undefined,
},
onRowDbClick: {
type: Function,
default: null,
}, // 使
default: undefined,
},
onUpdateTicked: {
type: Function,
default: undefined,
},
});
const emit = defineEmits<{
(
e: 'rowClick', //
evt: Event, // JS
row: any, // ,
index: number, // ,
): void;
(
e: 'rowDbClick', //
evt: Event, // JS
row: any, // ,
index: number, // ,
): void;
//
(e: 'rowClick', evt: Event, row: any, index: number): void;
//
(e: 'rowDbClick', evt: Event, row: any, index: number): void;
// checkbox
(e: 'updateTicked', evt: Event, row: any): void;
(
e: 'requestDataBefore', //
requestParams: URLSearchParams | any, //
@ -395,9 +392,7 @@ const dialogFormRef = ref();
const infoRef = ref();
const tableColumnsMap = arrayToMap('name', props.columns);
const queryFormFieldsMap = arrayToMap('name', props.queryFormFields);
const rowKey_ = '_rowKey_';
const selected_ = '_selected_';
const ticked_ = '_ticked_';
const rowKey_ = '_rowKey_'; // UUID
const url = {
dataUrl: props.dataUrl,
fetchDataUrl: props.fetchDataUrl,
@ -406,6 +401,47 @@ const url = {
removeDataUrl: props.removeDataUrl,
};
const extractTableColumns = extractTableColumnsProps(props);
// props
const titleScopeHandler = (column: any, scope: any) => {
if (extractTableColumns && extractTableColumns.length > 0) {
const i = extractTableColumns.findIndex((item) => item.name === column.name);
if (i > -1) {
return scope;
}
}
return undefined;
};
const table = reactive({
tickedField: props.tickedField,
selectedField: props.selectedField,
spaceHeight: 4,
gridConfig: false,
stickyNum: props.stickyNum,
columns: extractTableColumns,
treeExpand: props.treeDefaultExpandAll,
checkboxSelection: props.checkboxSelection,
sortNo: props.sortNo,
dense: props.dense !== undefined ? props.dense : false,
denseToolbar: props.denseToolbar !== undefined ? props.denseToolbar : false,
denseHeader: props.denseHeader !== undefined ? props.denseHeader : false,
denseBody: props.denseBody !== undefined ? props.denseBody : false,
denseBottom: props.denseBottom !== undefined ? props.denseBottom : false,
queryFormFields: [],
moreQueryStatus: false, //
rows: <any>[],
inFullscreen: false, //
});
provide('table', table);
const expandIcon = computed(() => {
return table.treeExpand ? 'expand_less' : 'expand_more';
});
const expandLabel = computed(() => {
return table.treeExpand ? '收起所有节点' : '展开所有节点';
});
/**
* 内置按钮枚举
*/
@ -421,6 +457,9 @@ enum ButtonEnum {
removeAll = 'removeAll', //
view = 'view', //
export = 'export', //
addTop = 'addTop', //
addChild = 'addChild', //
expand = 'expand', // ?
}
/**
* 内置按钮
@ -431,7 +470,7 @@ const buttonObj = {
name: ButtonEnum.query,
icon: IconEnum.查询,
label: '查询',
click: (selected, context) => {
click: () => {
refresh();
},
},
@ -446,7 +485,7 @@ const buttonObj = {
return true;
}
},
click: (selected, context) => {
click: () => {
table.moreQueryStatus = !table.moreQueryStatus;
handlerQueryFormShowField();
},
@ -455,7 +494,7 @@ const buttonObj = {
name: ButtonEnum.reset,
icon: IconEnum.重置,
label: '重置',
click: (selected, context) => {
click: () => {
queryFormRef.value.reset();
},
},
@ -463,7 +502,7 @@ const buttonObj = {
name: ButtonEnum.refresh,
icon: IconEnum.刷新,
label: '刷新',
click: (selected, context) => {
click: () => {
refresh();
},
},
@ -471,7 +510,7 @@ const buttonObj = {
name: ButtonEnum.add,
icon: IconEnum.新增,
label: '新增',
click: (selected, context) => {
click: () => {
dialog.dialogTitle = '新增';
dialogRef.value.show();
nextTick(() => {
@ -484,13 +523,13 @@ const buttonObj = {
name: ButtonEnum.edit,
icon: IconEnum.编辑,
label: '编辑',
enableIf: (selected) => {
enableIf: (selected, ticked, grid) => {
if (selected && selected.length > 0) {
return true;
}
return false;
},
click: (selected, context) => {
click: (selected) => {
if (!selected || selected.length <= 0) {
NotifyManager.warn('请选择要编辑的记录');
} else {
@ -514,7 +553,7 @@ const buttonObj = {
}
return false;
},
click: (selected, context) => {
click: (selected) => {
if (!selected || selected.length <= 0) {
NotifyManager.warn('请选择要复制的记录');
} else {
@ -531,8 +570,10 @@ const buttonObj = {
name: ButtonEnum.remove,
icon: IconEnum.删除,
label: '删除',
enableIf: (selected) => {
if (selected && selected.length > 0) {
enableIf: (selected, ticked, grid) => {
if (ticked && ticked.length > 0) {
return true;
} else if (selected && selected.length > 0) {
return true;
}
return false;
@ -553,7 +594,6 @@ const buttonObj = {
};
axios(requestParams)
.then((resp) => {
table.selected = [];
NotifyManager.info('操作成功');
onRequest({ pagination: state.pagination });
})
@ -576,7 +616,7 @@ const buttonObj = {
return false;
},
click: (selected, context) => {
onView();
view();
},
},
export: {
@ -605,6 +645,55 @@ const buttonObj = {
}
},
},
addTop: {
name: ButtonEnum.addTop,
icon: IconEnum.新增,
label: '新增顶级节点',
click: (selected, context) => {
dialog.dialogTitle = '新增顶级节点';
dialogRef.value.show();
nextTick(() => {
dialogFormRef.value.setStatus('addTop');
emit('addDialogOpenAfter');
});
},
},
addChild: {
name: ButtonEnum.addChild,
icon: 'playlist_add',
label: '新增子节点',
enableIf: (selected) => {
if (selected && selected.length > 0) {
return true;
}
return false;
},
click: (selected, context) => {
dialog.dialogTitle = '新增子节点';
dialogRef.value.show();
nextTick(() => {
dialogFormRef.value.setStatus('addChild');
emit('addDialogOpenAfter');
});
},
},
expand: {
name: ButtonEnum.expand,
icon: expandIcon.value,
label: expandLabel.value,
click: (selected, context) => {
expandFun(table.rows, table.treeExpand);
table.treeExpand = !table.treeExpand;
},
},
};
const expandFun = (arr, treeExpand) => {
arr.forEach((item) => {
if (props.tree && item.children && item.children.length > 0) {
item.expand = !treeExpand;
expandFun(item.children, treeExpand);
}
});
};
// toobar
@ -641,39 +730,6 @@ props.toolbarActions.forEach((btn, index) => {
}
});
const extractTableColumns = extractTableColumnsProps(props);
// props
const titleScopeHandler = (column: any, scope: any) => {
if (extractTableColumns && extractTableColumns.length > 0) {
const i = extractTableColumns.findIndex((item) => item.name === column.name);
if (i > -1) {
return scope;
}
}
return undefined;
};
const table = reactive({
selected: <any>[],
ticked: <any>[],
spaceHeight: 4,
gridConfig: false,
stickyNum: props.stickyNum,
columns: extractTableColumns,
checkboxSelection: props.checkboxSelection,
sortNo: props.sortNo,
dense: props.dense !== undefined ? props.dense : false,
denseToolbar: props.denseToolbar !== undefined ? props.denseToolbar : false,
denseHeader: props.denseHeader !== undefined ? props.denseHeader : false,
denseBody: props.denseBody !== undefined ? props.denseBody : false,
denseBottom: props.denseBottom !== undefined ? props.denseBottom : false,
queryFormFields: [],
moreQueryStatus: false, //
rows: <any>[],
inFullscreen: false, //
});
provide('table', table);
const denseToolbarComputed = computed(() => {
if (table.denseToolbar) {
return true;
@ -996,20 +1052,28 @@ const tableFullscreenFun = (value) => {
};
const rowClick = (evt: any, row: any, index: any) => {
// checkboxcheckboxcheckbox
if (!evt.ctrlKey) {
table.selected = [];
cleanSelected();
cleanTicked();
}
table.selected.push(row);
row[table.selectedField] = true;
row[table.tickedField] = true;
if (props.onRowClick) {
emit('rowClick', evt, row, index);
}
};
const rowDbClick = (evt, row, index) => {
if (props.onRowDbClick) {
emit('rowDbClick', evt, row, index);
} else {
onView();
view();
}
};
const updateTicked = (evt: Event, row: any) => {
row[table.selectedField] = row[table.tickedField];
if (props.onUpdateTicked) {
emit('updateTicked', evt, row);
}
};
@ -1158,9 +1222,13 @@ const onRequest = async (ops: any) => {
const addRowKey = (rows: []) => {
if (rows && rows.length > 0) {
rows.forEach((item) => {
rows.forEach((item: any) => {
item[rowKey_] = Tools.uuid();
item['_'];
item[table.tickedField] = item[table.tickedField] || false;
item[table.selectedField] = item[table.selectedField] || false;
if (props.tree) {
item['expand'] = false;
}
if (props.tree && item.children && item.children.length > 0) {
addRowKey(item.children);
}
@ -1174,7 +1242,7 @@ const save = async () => {
const validate = await dialogFormRef.value.validate();
if (validate) {
let dialogFormData = dialogFormRef.value.getData();
if (getSelectedRowsComputed.value && getSelectedRowsComputed.value.length > 0) {
if (formStatus === PageStatusEnum.编辑 && getSelectedRowsComputed.value && getSelectedRowsComputed.value.length > 0) {
dialogFormData[props.primaryKey] = getSelectedRowsComputed.value[0][props.primaryKey];
}
let submitFlag = true;
@ -1186,12 +1254,17 @@ const save = async () => {
}
});
if (submitFlag) {
if (formStatus === 'addTop') {
dialogFormData[props.foreignKey] = null;
} else if (formStatus === 'addChild') {
dialogFormData[props.foreignKey] = getSelectedRowsComputed.value[0][props.primaryKey];
}
let requestParams = {
method: formStatus === PageStatusEnum.新增 ? 'POST' : 'PUT',
method: formStatus === PageStatusEnum.新增 || formStatus === 'addTop' || formStatus === 'addChild' ? 'POST' : 'PUT',
headers: { 'content-type': 'application/json;charset=utf-8;' },
data: dialogFormData,
url:
formStatus === PageStatusEnum.新增
formStatus === PageStatusEnum.新增 || formStatus === 'addTop' || formStatus === 'addChild'
? url.addDataUrl
? url.addDataUrl
: url.dataUrl
@ -1205,7 +1278,6 @@ const save = async () => {
NotifyManager.info('操作成功');
dialogRef.value.hide();
onRequest({ pagination: state.pagination });
table.selected = [];
})
.catch((error) => {
console.info('error====', error);
@ -1219,7 +1291,7 @@ const save = async () => {
dialog.dialogButtons[0].loading = false;
}
};
const onView = () => {
const view = () => {
if (!getSelectedRowsComputed.value || getSelectedRowsComputed.value.length <= 0) {
NotifyManager.warn('请选择要查看的记录');
} else {
@ -1320,34 +1392,34 @@ const addRow = (row, index) => {
stickyHeaderColumn();
};
const getSelectedRowsHandler = (arr, selectedRows) => {
const getSelectRowsByFieldName = (arr, selectedRows, fieldName) => {
arr.forEach((item) => {
if (table.selected.findIndex((tmp) => tmp[rowKey_] === item[rowKey_]) > -1) {
if (item[fieldName]) {
selectedRows.push(item);
}
if (props.tree && item.children && item.children.length > 0) {
getSelectedRowsHandler(item.children, selectedRows);
getSelectRowsByFieldName(item.children, selectedRows, fieldName);
}
});
};
const getSelectedRowsComputed = computed(() => {
const selectedRows = <any>[];
getSelectedRowsHandler(table.rows, selectedRows);
return selectedRows;
return getSelectedRows();
});
//
const getTickedRowsComputed = computed(() => {
return getTickedRows();
});
//
const getSelectedRows = () => {
if (props.tree) {
return getSelectedRowsComputed.value;
} else {
return getSelectedRowsComputed.value;
}
const selectedRows = [];
getSelectRowsByFieldName(table.rows, selectedRows, table.selectedField);
return toRaw(selectedRows);
};
//
// checkbox
const getTickedRows = () => {
return getSelectedRowsComputed.value;
const tickedRows = [];
getSelectRowsByFieldName(table.rows, tickedRows, table.tickedField);
return toRaw(tickedRows);
};
const getRows = () => {
@ -1915,6 +1987,24 @@ const setEditDataUrl = (url_) => {
const setRemoveDataUrl = (url_) => {
url.removeDataUrl = url_;
};
//
const cleanSelected = (arr = table.rows) => {
arr.forEach((item) => {
item[table.selectedField] = false;
if (props.tree && item.children && item.children.length > 0) {
cleanSelected(item.children);
}
});
};
// checkbox
const cleanTicked = (arr = table.rows) => {
arr.forEach((item) => {
item[table.tickedField] = false;
if (props.tree && item.children && item.children.length > 0) {
cleanTicked(item.children);
}
});
};
defineExpose({
getSelectedRows,
@ -1938,6 +2028,9 @@ defineExpose({
setEditDataUrl,
setRemoveDataUrl,
stickyHeaderColumn,
cleanSelected,
cleanTicked,
view,
});
const instance = getCurrentInstance();

21
io.sc.platform.core.frontend/src/platform/components/toolbar/ChildrenBtn.vue

@ -1,5 +1,5 @@
<template>
<q-item clickable :dense="dense" :disable="button[0].enableIf ? !button[0].enableIf(gridProps.selected, gridProps.grid) : false">
<q-item clickable :dense="dense" :disable="button[0].enableIf ? !button[0].enableIf(selectedComputed, tickedComputed, grid) : false">
<q-item-section>
<q-item-label><q-icon v-if="button[0].icon" :name="button[0].icon" left size="20px"></q-icon> {{ button[0].label }}</q-item-label>
</q-item-section>
@ -16,14 +16,14 @@
v-else-if="Array.isArray(childrenBtn) && childrenBtn.length > 0"
:dense="dense"
:button="childrenBtn"
:grid-props="gridProps"
:grid="grid"
:button-click="buttonClick"
></ChildrenBtn>
<template v-else>
<q-item
v-close-popup
clickable
:disable="childrenBtn.enableIf ? !childrenBtn.enableIf(gridProps.selected, gridProps.grid) : false"
:disable="childrenBtn.enableIf ? !childrenBtn.enableIf(selectedComputed, tickedComputed, grid) : false"
:dense="dense"
@click="buttonClick(childrenBtn)"
>
@ -38,6 +38,7 @@
</q-item>
</template>
<script setup lang="ts">
import { computed } from 'vue';
const props = defineProps({
button: {
type: Object,
@ -45,13 +46,10 @@ const props = defineProps({
return [];
},
},
gridProps: {
grid: {
type: Object,
default: () => {
return {
selected: [],
grid: undefined,
};
return {};
},
},
buttonClick: {
@ -62,4 +60,11 @@ const props = defineProps({
},
dense: { type: Boolean, default: false },
});
const selectedComputed = computed(() => {
return props.grid.getSelectedRows();
});
const tickedComputed = computed(() => {
return props.grid.getTickedRows();
});
</script>

33
io.sc.platform.core.frontend/src/platform/components/toolbar/WToolbar.vue

@ -14,7 +14,7 @@
:dense="dense"
v-bind="btn.data[0]"
:split="btn.data[0].click ? true : false"
:disable="btn.data[0].enableIf ? !btn.data[0].enableIf(gridProps.selected, gridProps.grid) : false"
:disable="btn.data[0].enableIf ? !btn.data[0].enableIf(selectedComputed, tickedComputed, grid) : false"
class="class-action-item"
@click="buttonClick(btn.data[0])"
>
@ -26,7 +26,7 @@
<ChildrenBtn
v-else-if="Array.isArray(childrenBtn) && childrenBtn.length > 0"
:button="childrenBtn"
:grid-props="gridProps"
:grid="grid"
:button-click="buttonClick"
:dense="dense"
></ChildrenBtn>
@ -35,7 +35,7 @@
v-close-popup
clickable
:dense="dense"
:disable="childrenBtn.enableIf ? !childrenBtn.enableIf(gridProps.selected) : false"
:disable="childrenBtn.enableIf ? !childrenBtn.enableIf(selectedComputed, tickedComputed, grid) : false"
@click="buttonClick(childrenBtn)"
>
<q-item-section>
@ -48,7 +48,7 @@
</q-btn-dropdown>
<q-btn
v-else
:disable="btn.data.enableIf ? !btn.data.enableIf(gridProps.selected, gridProps.grid) : false"
:disable="btn.data.enableIf ? !btn.data.enableIf(selectedComputed, tickedComputed, grid) : false"
no-wrap
outline
:dense="dense"
@ -66,7 +66,7 @@
<ChildrenBtn
v-else-if="Array.isArray(childrenBtn.data) && childrenBtn.data.length > 0"
:button="childrenBtn.data"
:grid-props="gridProps"
:grid="grid"
:button-click="buttonClick"
:dense="dense"
></ChildrenBtn>
@ -75,7 +75,7 @@
v-close-popup
clickable
:dense="dense"
:disable="childrenBtn.data.enableIf ? !childrenBtn.data.enableIf(gridProps.selected, gridProps.grid) : false"
:disable="childrenBtn.data.enableIf ? !childrenBtn.data.enableIf(selectedComputed, tickedComputed, grid) : false"
@click="buttonClick(childrenBtn.data)"
>
<q-item-section>
@ -92,7 +92,7 @@
</div>
</template>
<script setup lang="ts">
import { ref, reactive, nextTick } from 'vue';
import { ref, reactive, computed, nextTick } from 'vue';
import { Tools } from '@/platform/utils';
import ChildrenBtn from './ChildrenBtn.vue';
@ -107,13 +107,10 @@ const props = defineProps({
return [];
},
},
gridProps: {
grid: {
type: Object,
default: () => {
return {
selected: [],
grid: undefined,
};
return {};
},
},
});
@ -266,17 +263,23 @@ const onResize = (size) => {
moreActions.value = _moreActions;
};
const selectedComputed = computed(() => {
return props.grid.getSelectedRows();
});
const tickedComputed = computed(() => {
return props.grid.getTickedRows();
});
const buttonClick = async (button) => {
let beforeResult = true;
const context = {};
if (button.beforeClick) {
beforeResult = await button.beforeClick(props.gridProps.selected, context, props.gridProps.grid);
beforeResult = await button.beforeClick(selectedComputed.value, tickedComputed.value, context, props.grid);
}
if (beforeResult && button.click) {
await button.click(props.gridProps.selected, context, button._click, props.gridProps.grid);
await button.click(selectedComputed.value, tickedComputed.value, context, button._click, props.grid);
if (button.afterClick) {
nextTick(() => {
button.afterClick(props.gridProps.selected, context, props.gridProps.grid);
button.afterClick(selectedComputed.value, tickedComputed.value, context, props.grid);
});
}
}

106
io.sc.platform.core.frontend/src/views/likm/Grid.vue

@ -4,16 +4,16 @@
:title="testGrid.title"
draggable
:data-url="testGrid.tableDataUrl"
:checkbox-selection="false"
:checkbox-selection="true"
selection="multiple"
:columns="testGrid.tableColumns"
:toolbar-actions="testGrid.toolbar"
:query-form-fields="testGrid.queryForm"
:editor="testGrid.addEdit"
:viewer="testGrid.view"
@selection="selection"
@update:selected="aaa"
@update-ticked="updateTicked"
@row-click="rowClick"
@row-db-click="rowDbClick"
></w-grid>
</div>
</template>
@ -24,36 +24,34 @@ import { axios, Environment } from '@/platform';
import EnableIcon from '@/platform/components/grid/EnableIcon.vue';
import { IconEnum } from '@/platform/enums';
const selection = (details) => {
// console.info('details====', details);
};
const aaa = (newSelected) => {
console.info('newSelected========', newSelected);
const updateTicked = (event, row) => {
console.info('grid.updateTicked.event====', event);
console.info('grid.updateTicked.row====', row);
};
const startY = ref(0);
const endY = ref(0);
const rowClick = (evt, row, index) => {
if (startY.value === 0) {
startY.value = evt.clientY;
} else if (evt.shiftKey && endY.value === 0) {
endY.value = evt.clientY;
}
console.info('startY====', startY.value);
console.info('endY====', endY.value);
// startY endY
if (startY.value > 0 && endY.value > 0) {
console.info('添加到选择中,同时清空 startY 与 endY');
startY.value = 0;
endY.value = 0;
}
// if (startY.value === 0) {
// startY.value = evt.clientY;
// } else if (evt.shiftKey && endY.value === 0) {
// endY.value = evt.clientY;
// }
// console.info('startY====', startY.value);
// console.info('endY====', endY.value);
// // startY endY
// if (startY.value > 0 && endY.value > 0) {
// console.info(' startY endY');
// startY.value = 0;
// endY.value = 0;
// }
// startY.value = 0;
// endY.value = 0;
console.info('grid.rowClick.row====', row);
};
const rowDbClick = (evt, row, index) => {
// console.info('row1====', row);
console.info('grid.rowDbClick.row====', row);
};
const testGrid = reactive({
@ -130,37 +128,37 @@ const testGrid = reactive({
// { label: '', name: 'lastModifyDate', type: 'w-date' },
],
tableColumns: [
{
name: 'info',
label: '用户信息',
hidden: true,
childrenColumns: [
{ name: 'loginName', label: '登录名', align: 'right' },
{ name: 'userName', label: '用户名' },
],
},
{
name: 'lxxx',
label: '联系方式',
childrenColumns: [
{ name: 'email', label: '邮箱地址' },
{
name: 'tx',
label: '通讯',
childrenColumns: [
{ name: 'phone', label: '电话' },
{ name: 'mobile', label: '手机号' },
],
},
{ name: 'qq', label: 'QQ' },
],
},
// { name: 'loginName', label: '', align: 'right' },
// { name: 'userName', label: '' },
// { name: 'email', label: '' },
// { name: 'phone', label: '' },
// { name: 'mobile', label: '' },
// { name: 'qq', label: 'QQ' },
// {
// name: 'info',
// label: '',
// hidden: true,
// childrenColumns: [
// { name: 'loginName', label: '', align: 'right' },
// { name: 'userName', label: '' },
// ],
// },
// {
// name: 'lxxx',
// label: '',
// childrenColumns: [
// { name: 'email', label: '' },
// {
// name: 'tx',
// label: '',
// childrenColumns: [
// { name: 'phone', label: '' },
// { name: 'mobile', label: '' },
// ],
// },
// { name: 'qq', label: 'QQ' },
// ],
// },
{ name: 'loginName', label: '登录名', align: 'right' },
{ name: 'userName', label: '用户名' },
{ name: 'email', label: '邮箱地址' },
{ name: 'phone', label: '电话' },
{ name: 'mobile', label: '手机号' },
{ name: 'qq', label: 'QQ' },
{ name: 'description', label: '描述', width: 400 },
{
name: 'enable',

47
io.sc.platform.core.frontend/src/views/likm/TreeGrid.vue

@ -11,11 +11,11 @@
:data-url="testGrid.dataUrl"
:fetch-data-url="testGrid.fetchDataUrl"
:columns="testGrid.tableColumns"
:editor="testGrid.editor"
:toolbar-actions="testGrid.toolbar"
:query-form-fields="testGrid.queryFormFields"
:query-form-cols-num="3"
@selection="selection"
@row-click="rowClick"
@update-ticked="updateTicked"
></w-grid>
</div>
</template>
@ -29,15 +29,22 @@ import { IconEnum } from '@/platform/enums';
const { t } = useI18n();
const gridRef = ref();
const rowClick = (evt, row, rowIndex) => {
// console.info('evt========', evt);
// console.info('row========', row);
// console.info('rowIndex========', rowIndex);
const updateTicked = (event, row) => {
console.info('treeGrid.updateTicked.event====', event);
console.info('treeGrid.updateTicked.row====', row);
};
const selection = (details) => {
// console.info('details====', details);
const startY = ref(0);
const endY = ref(0);
const rowClick = (evt, row, index) => {
console.info('grid.rowClick.row====', row);
};
const rowDbClick = (evt, row, index) => {
console.info('grid.rowDbClick.row====', index);
};
const gridRef = ref();
const testGrid = {
title: '菜单列表',
dataUrl: Environment.apiContextPath('api/system/menu'),
@ -70,6 +77,9 @@ const testGrid = {
// gridRefs.addEditFormRef.setFieldValue('userName', '');
},
},
'addTop',
'addChild',
'expand',
[
{
name: 'op',
@ -95,7 +105,7 @@ const testGrid = {
{
name: 'name',
label: '菜单名称',
width: 500,
// width: 500,
format: (val, row) => {
return t(row.name);
},
@ -139,7 +149,11 @@ const testGrid = {
// { name: 'lastModifyDate', label: '' },
// ],
// },
{ name: 'type', label: '菜单类型', width: 500 },
{
name: 'type',
label: '菜单类型',
// , width: 500
},
{ name: 'order', label: '排序号' },
{
name: 'enable',
@ -160,6 +174,17 @@ const testGrid = {
{ name: 'lastModifier', label: '最后修改人' },
{ name: 'lastModifyDate', label: '最后修改时间' },
],
editor: {
form: {
fields: [
{ label: '菜单名称', name: 'name', type: 'text' },
{ label: '菜单类型', name: 'type', type: 'text' },
{ label: '菜单图标', name: 'icon', type: 'text' },
{ label: '排序号', name: 'order', type: 'number' },
{ label: '是否可用', name: 'enable', type: 'checkbox' },
],
},
},
};
onMounted(() => {

2
io.sc.platform.system/src/main/java/io/sc/platform/system/menu/jpa/entity/MenuEntity.java

@ -30,7 +30,7 @@ import java.util.Objects;
@DiscriminatorColumn(name="TYPE_",discriminatorType=DiscriminatorType.STRING,length=20)
@Table(name="SYS_MENU")
@JsonIgnoreProperties(ignoreUnknown=true)
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type",visible=true)
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type",visible=true,defaultImpl =MenuGroupEntity.class )
@JsonSubTypes({
@JsonSubTypes.Type(value = MenuGroupEntity.class, name = "GROUP"),
@JsonSubTypes.Type(value = MenuRouteEntity.class, name = "ROUTE"),

Loading…
Cancel
Save