Browse Source

表格优化提交

main
likunming 1 year ago
parent
commit
2cc6ee14cc
  1. 152
      io.sc.platform.core.frontend/src/platform/components/grid/WGrid.vue
  2. 67
      io.sc.platform.core.frontend/src/platform/components/toolbar/WToolbar.vue

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

@ -24,7 +24,7 @@
<template #top="scope">
<q-resize-observer @resize="onResize" />
<div class="col">
<w-form ref="queryFormRef" v-bind="props.queryFormAttrs" :fields="table.queryFormFields" :cols-num="queryFormColsNum"></w-form>
<w-form ref="queryFormRef" v-bind="props.queryFormAttrs" :fields="props.queryFormFields" :cols-num="queryFormColsNum"></w-form>
<div
v-if="title || buttons_.length > 0 || configButton || table.queryFormFields.length > 0"
class="flex flex-nowrap items-end"
@ -35,7 +35,7 @@
<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>
<q-btn round dense :size="denseToolbarComputed ? '13px' : undefined" icon="manage_accounts" unelevated outline>
<q-popup-proxy v-model="table.gridConfig">
<GridConfig :scope="scope" :grid-props="props" :more-column-title-array="columnTitleState.columnTitleArr" :grid="instance"></GridConfig>
</q-popup-proxy>
@ -52,7 +52,7 @@
:rowspan="columnTitleState.columnTitleRowNum"
:style="moreColumnTitleTableSelectionStyle"
>
<q-checkbox v-model="scope.selected" flat :dense="denseHeaderComputed" />
<q-checkbox v-model="table.allTicked" flat :dense="denseHeaderComputed" @update:model-value="allTickedUpdateFun" />
</q-th>
<q-th v-if="rIndex === 0 && table.sortNo && !props.tree" :rowspan="columnTitleState.columnTitleRowNum" :style="moreColumnTitleTableSortNoStyle">
序号
@ -78,7 +78,7 @@
:style="props.tree ? '' : 'padding: 0; width: 50px'"
auto-width
>
<q-checkbox v-model="scope.selected" flat :dense="denseHeaderComputed"
<q-checkbox v-model="table.allTicked" flat :dense="denseHeaderComputed" @update:model-value="allTickedUpdateFun"
/></q-th>
<q-th v-else-if="table.checkboxSelection && !props.tree"></q-th>
<template v-for="col in scope.cols" :key="col.name">
@ -243,7 +243,7 @@ const props = defineProps({
denseHeader: { type: Boolean, default: undefined }, //
denseBody: { type: Boolean, default: undefined }, //
denseBottom: { type: Boolean, default: undefined }, //
denseToolbar: { type: Boolean, default: undefined }, // toolbar
denseToolbar: { type: Boolean, default: true }, // toolbar
sortNo: { type: Boolean, default: false }, //
stickyNum: { type: Number, default: 0 }, // 1-10el
checkboxSelection: { type: Boolean, default: true }, // checkbox
@ -416,6 +416,7 @@ const table = reactive({
tickedField: props.tickedField,
selectedField: props.selectedField,
spaceHeight: 4,
allTicked: <null | boolean>false,
gridConfig: false,
stickyNum: props.stickyNum,
columns: extractTableColumns,
@ -427,7 +428,7 @@ const table = reactive({
denseHeader: props.denseHeader !== undefined ? props.denseHeader : false,
denseBody: props.denseBody !== undefined ? props.denseBody : false,
denseBottom: props.denseBottom !== undefined ? props.denseBottom : false,
queryFormFields: [],
queryFormFields: <any>[],
moreQueryStatus: false, //
rows: <any>[],
inFullscreen: false, //
@ -464,6 +465,47 @@ enum ButtonEnum {
/**
* 内置按钮
*/
const remove = () => {
const ids = <any>[];
if (getTickedRowsComputed.value && getTickedRowsComputed.value.length > 0) {
getTickedRowsComputed.value.forEach((item) => {
ids.push(item[props.primaryKey]);
});
} else if (getSelectedRowsComputed.value && getSelectedRowsComputed.value.length > 0) {
getSelectedRowsComputed.value.forEach((item) => {
ids.push(item[props.primaryKey]);
});
}
let requestParams: any = {
method: 'DELETE',
url: url.removeDataUrl || url.dataUrl,
data: ids,
};
axios(requestParams)
.then((resp) => {
NotifyManager.info('操作成功');
onRequest({ pagination: state.pagination });
})
.catch((error) => {
console.info('error====', error);
NotifyManager.error('操作失败');
});
};
const resetDefaultValues = () => {
let requestParams: any = {
method: 'POST',
url: url.dataUrl + '/resetDefaultValues',
};
axios(requestParams)
.then((resp) => {
NotifyManager.info('操作成功');
onRequest({ pagination: state.pagination });
})
.catch((error) => {
console.info('error====', error);
NotifyManager.error('操作失败');
});
};
const buttonObj = {
separator: 'separator',
query: {
@ -578,9 +620,9 @@ const buttonObj = {
}
return false;
},
click: (selected, context) => {
if (!selected || selected.length <= 0) {
NotifyManager.warn('请选择要删除的记录');
click: (tips: boolean = true) => {
if (!tips) {
remove();
} else {
$q.dialog({
title: '询问',
@ -588,19 +630,7 @@ const buttonObj = {
cancel: true,
persistent: true,
}).onOk(() => {
let requestParams: any = {
method: 'DELETE',
url: (url.removeDataUrl || url.dataUrl) + '/' + selected[0][props.primaryKey],
};
axios(requestParams)
.then((resp) => {
NotifyManager.info('操作成功');
onRequest({ pagination: state.pagination });
})
.catch((error) => {
console.info('error====', error);
NotifyManager.error('操作失败');
});
remove();
});
}
},
@ -690,20 +720,19 @@ const buttonObj = {
name: ButtonEnum.resetDefaultValues,
icon: 'bi-copy',
label: '恢复默认值',
click: (selected, context) => {
let requestParams: any = {
method: 'POST',
url: url.dataUrl + '/resetDefaultValues',
};
axios(requestParams)
.then((resp) => {
NotifyManager.info('操作成功');
onRequest({ pagination: state.pagination });
})
.catch((error) => {
console.info('error====', error);
NotifyManager.error('操作失败');
click: (tips: boolean = true) => {
if (!tips) {
resetDefaultValues();
} else {
$q.dialog({
title: '询问',
message: '您确认要恢复默认值吗?',
cancel: true,
persistent: true,
}).onOk(() => {
resetDefaultValues();
});
}
},
},
};
@ -737,7 +766,7 @@ const handleChildrenBtn = (arr) => {
}
return tempArr;
};
props.toolbarActions.forEach((btn, index) => {
props.toolbarActions.forEach((btn: any, index) => {
if (typeof btn === 'string' && buttonObj[btn]) {
buttons_.push(buttonObj[btn]);
} else if (Array.isArray(btn) && btn.length > 0) {
@ -830,6 +859,37 @@ const state = reactive({
},
});
const allTickedUpdateFun = (value, evt) => {
if (value) {
table.rows.forEach((item) => {
item[table.tickedField] = true;
});
} else {
table.rows.forEach((item) => {
item[table.tickedField] = false;
});
}
};
//
const allTickedStatus = () => {
// null
// false
// true
const ticked_ = <any>[];
table.rows.forEach((item) => {
if (item[table.tickedField]) {
ticked_.push(item);
}
});
if (ticked_.length === table.rows.length) {
table.allTicked = true;
} else if (ticked_.length > 0) {
table.allTicked = null;
} else {
table.allTicked = false;
}
};
const dialog = reactive({
dialogTitle: '新增',
dialogButtons: [
@ -1084,6 +1144,7 @@ const rowClick = (evt: any, row: any, index: any) => {
}
row[table.selectedField] = true;
row[table.tickedField] = true;
allTickedStatus();
if (props.onRowClick) {
emit('rowClick', evt, row, index);
}
@ -1097,6 +1158,7 @@ const rowDbClick = (evt, row, index) => {
};
const updateTicked = (evt: Event, row: any) => {
row[table.selectedField] = row[table.tickedField];
allTickedStatus();
if (props.onUpdateTicked) {
emit('updateTicked', evt, row);
}
@ -1406,7 +1468,6 @@ const removeRows = (rows) => {
1,
);
});
table.selected.splice(0, table.selected.length);
stickyHeaderColumn();
};
//
@ -1710,7 +1771,7 @@ const thStyleHandler = (c: any, scope: any) => {
for (let tr = 0; tr < trtdIndex.trIndex; tr++) {
const tdArr = columnTitleState.columnTitleArr[tr];
for (let td = 0; td < trtdIndex.tdIndex - 1; td++) {
if (tdArr[td].parents && tdArr[td].parents.length > 0) {
if (tdArr[td] && tdArr[td].parents && tdArr[td].parents.length > 0) {
const result =
tdArr[td].parents.length === c.parents.length &&
tdArr[td].parents.every((a) => c.parents.some((b) => a === b)) &&
@ -1933,13 +1994,17 @@ const onDrop = (e, scope) => {
const handlerQueryFormShowField = () => {
table.queryFormFields = [];
if (table.moreQueryStatus) {
props.queryFormFields.forEach((item) => {
props.queryFormFields.forEach((item: any) => {
table.queryFormFields.push(item);
item.showIf = () => {
return true;
};
});
} else {
//
const rowColsNum = queryFormRef.value.getColsNum() * (props.queryFormRowNum || 1);
let currRowColsNum = 0;
props.queryFormFields.forEach((item) => {
props.queryFormFields.forEach((item: any) => {
if (item.hasOwnProperty('colspan')) {
currRowColsNum += item.colspan;
} else {
@ -1947,6 +2012,13 @@ const handlerQueryFormShowField = () => {
}
if (currRowColsNum <= rowColsNum) {
table.queryFormFields.push(item);
item.showIf = () => {
return true;
};
} else {
item.showIf = () => {
return false;
};
}
});
}

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

@ -9,15 +9,23 @@
<q-separator v-if="typeof btn.data === 'string' && btn.data === 'separator'" vertical class="class-action-item" />
<q-btn-dropdown
v-else-if="Array.isArray(btn.data) && btn.data.length > 0"
:padding="dense ? '0px 0px' : undefined"
unelevated
outline
:dense="dense"
v-bind="btn.data[0]"
:label="dense ? '' : btn.data[0].label"
:icon="dense ? undefined : btn.data[0].icon"
:split="btn.data[0].click ? true : false"
:disable="btn.data[0].enableIf ? !btn.data[0].enableIf(selectedComputed, tickedComputed, grid) : false"
class="class-action-item"
@click="buttonClick(btn.data[0])"
>
<template v-if="dense" #label>
<div :style="btn.data[0].click ? 'padding: 0px 8px' : 'padding: 0px 0px 0px 8px'">
<q-icon v-if="btn.data[0].icon" :name="btn.data[0].icon" size="xs"></q-icon>
<span style="padding-left: 3px">{{ btn.data[0].label }}</span>
</div>
</template>
<q-list :dense="dense">
<template v-for="(childrenBtn, childrenIndex) in btn.data" :key="'button_c_' + childrenIndex">
<template v-if="childrenIndex === 0"></template>
@ -48,18 +56,41 @@
</q-btn-dropdown>
<q-btn
v-else
:padding="dense ? padding : undefined"
:disable="btn.data.enableIf ? !btn.data.enableIf(selectedComputed, tickedComputed, grid) : false"
no-wrap
no-caps
outline
:dense="dense"
v-bind="btn.data"
align="center"
:icon="dense ? undefined : btn.data.icon"
:label="dense ? '' : btn.data.label"
class="class-action-item"
@click="buttonClick(btn.data)"
/>
>
<div v-if="dense">
<q-icon v-if="btn.data.icon" :name="btn.data.icon" size="xs"></q-icon>
<span style="padding-left: 3px">{{ btn.data.label }}</span>
</div>
</q-btn>
</template>
<!-- moreActions -->
<q-btn-dropdown v-if="moreActions && moreActions.length > 0" unelevated outline :label="$t('more')" :dense="dense" class="class-action-item">
<q-btn-dropdown
v-if="moreActions && moreActions.length > 0"
unelevated
outline
label=""
:icon="undefined"
padding="0px 0px"
:dense="dense"
class="class-action-item"
>
<template #label>
<div style="padding: 0px 8px">
<span>{{ $t('more') }}</span>
</div>
</template>
<q-list :dense="dense">
<template v-for="(childrenBtn, childrenIndex) in moreActions" :key="'moreAction_' + childrenIndex">
<q-separator v-if="typeof childrenBtn.data === 'string' && childrenBtn.data === 'separator'" />
@ -96,8 +127,9 @@ import { ref, reactive, computed, nextTick } from 'vue';
import { Tools } from '@/platform/utils';
import ChildrenBtn from './ChildrenBtn.vue';
const padding = '5px 12px 5px 8px';
const props = defineProps({
xGap: { type: Number, default: 4 }, // x
xGap: { type: Number, default: 6 }, // x
noIcon: { type: Boolean, default: false }, // icon
align: { type: String, default: 'right' }, //
dense: { type: Boolean, default: false }, //
@ -169,7 +201,7 @@ extractButton(props.buttons);
const buttons_ = <any>[];
const handleChildrenSeparator = (arr) => {
const tempArr = [];
const tempArr = <any>[];
for (let i = 0; i < arr.length; i++) {
const btn = arr[i];
if (i === 0 && typeof btn === 'string' && btn === 'separator') {
@ -194,7 +226,7 @@ const handleChildrenSeparator = (arr) => {
return tempArr;
};
for (let i = 0; i < props.buttons.length; i++) {
const btn = props.buttons[i];
const btn: any = props.buttons[i];
if (i === 0 && typeof btn === 'string' && btn === 'separator') {
//
continue;
@ -212,7 +244,7 @@ for (let i = 0; i < props.buttons.length; i++) {
}
}
const baseActions = ref(buttons_);
const moreActions = ref([]);
const moreActions: any = ref([]);
const isActionWidthInitializedRef = ref(false);
const moreActionWidth = 100;
const onResize = (size) => {
@ -228,8 +260,8 @@ const onResize = (size) => {
isActionWidthInitializedRef.value = true;
}
const _baseActions = [];
const _moreActions = [];
const _baseActions = <any>[];
const _moreActions = <any>[];
const length = buttons_.length;
let availableWidth = size.width;
let width = 0;
@ -263,6 +295,15 @@ const onResize = (size) => {
moreActions.value = _moreActions;
};
const loadingComputed = computed(() => {
return function (btn) {
if (btn.loadingIf && typeof btn.loadingIf === 'function' && btn.loadingIf(selectedComputed.value, tickedComputed.value, props.grid)) {
return true;
} else {
return false;
}
};
});
const selectedComputed = computed(() => {
return Object.keys(props.grid).length > 0 ? props.grid.getSelectedRows() : [];
});
@ -273,13 +314,13 @@ const buttonClick = async (button) => {
let beforeResult = true;
const context = {};
if (button.beforeClick) {
beforeResult = await button.beforeClick(selectedComputed.value, tickedComputed.value, context, props.grid);
beforeResult = await button.beforeClick(selectedComputed.value, tickedComputed.value, props.grid, context);
}
if (beforeResult && button.click) {
await button.click(selectedComputed.value, tickedComputed.value, context, button._click, props.grid);
await button.click(selectedComputed.value, tickedComputed.value, props.grid, button._click, context);
if (button.afterClick) {
nextTick(() => {
button.afterClick(selectedComputed.value, tickedComputed.value, context, props.grid);
button.afterClick(selectedComputed.value, tickedComputed.value, props.grid, context);
});
}
}

Loading…
Cancel
Save