Browse Source

Merge remote-tracking branch 'origin/main'

main
wangshaoping 1 year ago
parent
commit
7b41b952f7
  1. 2
      io.sc.platform.core.frontend/src/platform/components/form/WForm.vue
  2. 152
      io.sc.platform.core.frontend/src/platform/components/grid/WGrid.vue
  3. 67
      io.sc.platform.core.frontend/src/platform/components/toolbar/WToolbar.vue

2
io.sc.platform.core.frontend/src/platform/components/form/WForm.vue

@ -100,7 +100,7 @@ const defaultValueHandler = (field) => {
watch( watch(
() => props.fields, () => props.fields,
(newVal, oldVal) => { (newVal, oldVal) => {
if (newVal) { if (newVal.length !== oldVal.length) {
fields_ = ref([...props.fields]); fields_ = ref([...props.fields]);
for (const field of fields_.value as any) { for (const field of fields_.value as any) {
if (field.name) { if (field.name) {

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

@ -24,7 +24,7 @@
<template #top="scope"> <template #top="scope">
<q-resize-observer @resize="onResize" /> <q-resize-observer @resize="onResize" />
<div class="col"> <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 <div
v-if="title || buttons_.length > 0 || configButton || table.queryFormFields.length > 0" v-if="title || buttons_.length > 0 || configButton || table.queryFormFields.length > 0"
class="flex flex-nowrap items-end" class="flex flex-nowrap items-end"
@ -35,7 +35,7 @@
<w-toolbar :dense="denseToolbarComputed" v-bind="toolbarConfigure" :buttons="buttons_" :grid="instance"></w-toolbar> <w-toolbar :dense="denseToolbarComputed" v-bind="toolbarConfigure" :buttons="buttons_" :grid="instance"></w-toolbar>
</div> </div>
<div v-if="configButton" class="flex-none pl-1"> <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"> <q-popup-proxy v-model="table.gridConfig">
<GridConfig :scope="scope" :grid-props="props" :more-column-title-array="columnTitleState.columnTitleArr" :grid="instance"></GridConfig> <GridConfig :scope="scope" :grid-props="props" :more-column-title-array="columnTitleState.columnTitleArr" :grid="instance"></GridConfig>
</q-popup-proxy> </q-popup-proxy>
@ -52,7 +52,7 @@
:rowspan="columnTitleState.columnTitleRowNum" :rowspan="columnTitleState.columnTitleRowNum"
:style="moreColumnTitleTableSelectionStyle" :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>
<q-th v-if="rIndex === 0 && table.sortNo && !props.tree" :rowspan="columnTitleState.columnTitleRowNum" :style="moreColumnTitleTableSortNoStyle"> <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'" :style="props.tree ? '' : 'padding: 0; width: 50px'"
auto-width 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>
<q-th v-else-if="table.checkboxSelection && !props.tree"></q-th> <q-th v-else-if="table.checkboxSelection && !props.tree"></q-th>
<template v-for="col in scope.cols" :key="col.name"> <template v-for="col in scope.cols" :key="col.name">
@ -243,7 +243,7 @@ const props = defineProps({
denseHeader: { type: Boolean, default: undefined }, // denseHeader: { type: Boolean, default: undefined }, //
denseBody: { type: Boolean, default: undefined }, // denseBody: { type: Boolean, default: undefined }, //
denseBottom: { 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 }, // sortNo: { type: Boolean, default: false }, //
stickyNum: { type: Number, default: 0 }, // 1-10el stickyNum: { type: Number, default: 0 }, // 1-10el
checkboxSelection: { type: Boolean, default: true }, // checkbox checkboxSelection: { type: Boolean, default: true }, // checkbox
@ -416,6 +416,7 @@ const table = reactive({
tickedField: props.tickedField, tickedField: props.tickedField,
selectedField: props.selectedField, selectedField: props.selectedField,
spaceHeight: 4, spaceHeight: 4,
allTicked: <null | boolean>false,
gridConfig: false, gridConfig: false,
stickyNum: props.stickyNum, stickyNum: props.stickyNum,
columns: extractTableColumns, columns: extractTableColumns,
@ -427,7 +428,7 @@ const table = reactive({
denseHeader: props.denseHeader !== undefined ? props.denseHeader : false, denseHeader: props.denseHeader !== undefined ? props.denseHeader : false,
denseBody: props.denseBody !== undefined ? props.denseBody : false, denseBody: props.denseBody !== undefined ? props.denseBody : false,
denseBottom: props.denseBottom !== undefined ? props.denseBottom : false, denseBottom: props.denseBottom !== undefined ? props.denseBottom : false,
queryFormFields: [], queryFormFields: <any>[],
moreQueryStatus: false, // moreQueryStatus: false, //
rows: <any>[], rows: <any>[],
inFullscreen: false, // 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 = { const buttonObj = {
separator: 'separator', separator: 'separator',
query: { query: {
@ -578,9 +620,9 @@ const buttonObj = {
} }
return false; return false;
}, },
click: (selected, context) => { click: (tips: boolean = true) => {
if (!selected || selected.length <= 0) { if (!tips) {
NotifyManager.warn('请选择要删除的记录'); remove();
} else { } else {
$q.dialog({ $q.dialog({
title: '询问', title: '询问',
@ -588,19 +630,7 @@ const buttonObj = {
cancel: true, cancel: true,
persistent: true, persistent: true,
}).onOk(() => { }).onOk(() => {
let requestParams: any = { remove();
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('操作失败');
});
}); });
} }
}, },
@ -690,20 +720,19 @@ const buttonObj = {
name: ButtonEnum.resetDefaultValues, name: ButtonEnum.resetDefaultValues,
icon: 'bi-copy', icon: 'bi-copy',
label: '恢复默认值', label: '恢复默认值',
click: (selected, context) => { click: (tips: boolean = true) => {
let requestParams: any = { if (!tips) {
method: 'POST', resetDefaultValues();
url: url.dataUrl + '/resetDefaultValues', } else {
}; $q.dialog({
axios(requestParams) title: '询问',
.then((resp) => { message: '您确认要恢复默认值吗?',
NotifyManager.info('操作成功'); cancel: true,
onRequest({ pagination: state.pagination }); persistent: true,
}) }).onOk(() => {
.catch((error) => { resetDefaultValues();
console.info('error====', error);
NotifyManager.error('操作失败');
}); });
}
}, },
}, },
}; };
@ -737,7 +766,7 @@ const handleChildrenBtn = (arr) => {
} }
return tempArr; return tempArr;
}; };
props.toolbarActions.forEach((btn, index) => { props.toolbarActions.forEach((btn: any, index) => {
if (typeof btn === 'string' && buttonObj[btn]) { if (typeof btn === 'string' && buttonObj[btn]) {
buttons_.push(buttonObj[btn]); buttons_.push(buttonObj[btn]);
} else if (Array.isArray(btn) && btn.length > 0) { } 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({ const dialog = reactive({
dialogTitle: '新增', dialogTitle: '新增',
dialogButtons: [ dialogButtons: [
@ -1084,6 +1144,7 @@ const rowClick = (evt: any, row: any, index: any) => {
} }
row[table.selectedField] = true; row[table.selectedField] = true;
row[table.tickedField] = true; row[table.tickedField] = true;
allTickedStatus();
if (props.onRowClick) { if (props.onRowClick) {
emit('rowClick', evt, row, index); emit('rowClick', evt, row, index);
} }
@ -1097,6 +1158,7 @@ const rowDbClick = (evt, row, index) => {
}; };
const updateTicked = (evt: Event, row: any) => { const updateTicked = (evt: Event, row: any) => {
row[table.selectedField] = row[table.tickedField]; row[table.selectedField] = row[table.tickedField];
allTickedStatus();
if (props.onUpdateTicked) { if (props.onUpdateTicked) {
emit('updateTicked', evt, row); emit('updateTicked', evt, row);
} }
@ -1406,7 +1468,6 @@ const removeRows = (rows) => {
1, 1,
); );
}); });
table.selected.splice(0, table.selected.length);
stickyHeaderColumn(); stickyHeaderColumn();
}; };
// //
@ -1710,7 +1771,7 @@ const thStyleHandler = (c: any, scope: any) => {
for (let tr = 0; tr < trtdIndex.trIndex; tr++) { for (let tr = 0; tr < trtdIndex.trIndex; tr++) {
const tdArr = columnTitleState.columnTitleArr[tr]; const tdArr = columnTitleState.columnTitleArr[tr];
for (let td = 0; td < trtdIndex.tdIndex - 1; td++) { 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 = const result =
tdArr[td].parents.length === c.parents.length && tdArr[td].parents.length === c.parents.length &&
tdArr[td].parents.every((a) => c.parents.some((b) => a === b)) && tdArr[td].parents.every((a) => c.parents.some((b) => a === b)) &&
@ -1933,13 +1994,17 @@ const onDrop = (e, scope) => {
const handlerQueryFormShowField = () => { const handlerQueryFormShowField = () => {
table.queryFormFields = []; table.queryFormFields = [];
if (table.moreQueryStatus) { if (table.moreQueryStatus) {
props.queryFormFields.forEach((item) => { props.queryFormFields.forEach((item: any) => {
table.queryFormFields.push(item); table.queryFormFields.push(item);
item.showIf = () => {
return true;
};
}); });
} else { } else {
//
const rowColsNum = queryFormRef.value.getColsNum() * (props.queryFormRowNum || 1); const rowColsNum = queryFormRef.value.getColsNum() * (props.queryFormRowNum || 1);
let currRowColsNum = 0; let currRowColsNum = 0;
props.queryFormFields.forEach((item) => { props.queryFormFields.forEach((item: any) => {
if (item.hasOwnProperty('colspan')) { if (item.hasOwnProperty('colspan')) {
currRowColsNum += item.colspan; currRowColsNum += item.colspan;
} else { } else {
@ -1947,6 +2012,13 @@ const handlerQueryFormShowField = () => {
} }
if (currRowColsNum <= rowColsNum) { if (currRowColsNum <= rowColsNum) {
table.queryFormFields.push(item); 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-separator v-if="typeof btn.data === 'string' && btn.data === 'separator'" vertical class="class-action-item" />
<q-btn-dropdown <q-btn-dropdown
v-else-if="Array.isArray(btn.data) && btn.data.length > 0" v-else-if="Array.isArray(btn.data) && btn.data.length > 0"
:padding="dense ? '0px 0px' : undefined"
unelevated unelevated
outline outline
:dense="dense"
v-bind="btn.data[0]" 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" :split="btn.data[0].click ? true : false"
:disable="btn.data[0].enableIf ? !btn.data[0].enableIf(selectedComputed, tickedComputed, grid) : false" :disable="btn.data[0].enableIf ? !btn.data[0].enableIf(selectedComputed, tickedComputed, grid) : false"
class="class-action-item" class="class-action-item"
@click="buttonClick(btn.data[0])" @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"> <q-list :dense="dense">
<template v-for="(childrenBtn, childrenIndex) in btn.data" :key="'button_c_' + childrenIndex"> <template v-for="(childrenBtn, childrenIndex) in btn.data" :key="'button_c_' + childrenIndex">
<template v-if="childrenIndex === 0"></template> <template v-if="childrenIndex === 0"></template>
@ -48,18 +56,41 @@
</q-btn-dropdown> </q-btn-dropdown>
<q-btn <q-btn
v-else v-else
:padding="dense ? padding : undefined"
:disable="btn.data.enableIf ? !btn.data.enableIf(selectedComputed, tickedComputed, grid) : false" :disable="btn.data.enableIf ? !btn.data.enableIf(selectedComputed, tickedComputed, grid) : false"
no-wrap no-wrap
no-caps
outline outline
:dense="dense"
v-bind="btn.data" v-bind="btn.data"
align="center"
:icon="dense ? undefined : btn.data.icon"
:label="dense ? '' : btn.data.label"
class="class-action-item" class="class-action-item"
@click="buttonClick(btn.data)" @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> </template>
<!-- moreActions --> <!-- 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"> <q-list :dense="dense">
<template v-for="(childrenBtn, childrenIndex) in moreActions" :key="'moreAction_' + childrenIndex"> <template v-for="(childrenBtn, childrenIndex) in moreActions" :key="'moreAction_' + childrenIndex">
<q-separator v-if="typeof childrenBtn.data === 'string' && childrenBtn.data === 'separator'" /> <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 { Tools } from '@/platform/utils';
import ChildrenBtn from './ChildrenBtn.vue'; import ChildrenBtn from './ChildrenBtn.vue';
const padding = '5px 12px 5px 8px';
const props = defineProps({ const props = defineProps({
xGap: { type: Number, default: 4 }, // x xGap: { type: Number, default: 6 }, // x
noIcon: { type: Boolean, default: false }, // icon noIcon: { type: Boolean, default: false }, // icon
align: { type: String, default: 'right' }, // align: { type: String, default: 'right' }, //
dense: { type: Boolean, default: false }, // dense: { type: Boolean, default: false }, //
@ -169,7 +201,7 @@ extractButton(props.buttons);
const buttons_ = <any>[]; const buttons_ = <any>[];
const handleChildrenSeparator = (arr) => { const handleChildrenSeparator = (arr) => {
const tempArr = []; const tempArr = <any>[];
for (let i = 0; i < arr.length; i++) { for (let i = 0; i < arr.length; i++) {
const btn = arr[i]; const btn = arr[i];
if (i === 0 && typeof btn === 'string' && btn === 'separator') { if (i === 0 && typeof btn === 'string' && btn === 'separator') {
@ -194,7 +226,7 @@ const handleChildrenSeparator = (arr) => {
return tempArr; return tempArr;
}; };
for (let i = 0; i < props.buttons.length; i++) { 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') { if (i === 0 && typeof btn === 'string' && btn === 'separator') {
// //
continue; continue;
@ -212,7 +244,7 @@ for (let i = 0; i < props.buttons.length; i++) {
} }
} }
const baseActions = ref(buttons_); const baseActions = ref(buttons_);
const moreActions = ref([]); const moreActions: any = ref([]);
const isActionWidthInitializedRef = ref(false); const isActionWidthInitializedRef = ref(false);
const moreActionWidth = 100; const moreActionWidth = 100;
const onResize = (size) => { const onResize = (size) => {
@ -228,8 +260,8 @@ const onResize = (size) => {
isActionWidthInitializedRef.value = true; isActionWidthInitializedRef.value = true;
} }
const _baseActions = []; const _baseActions = <any>[];
const _moreActions = []; const _moreActions = <any>[];
const length = buttons_.length; const length = buttons_.length;
let availableWidth = size.width; let availableWidth = size.width;
let width = 0; let width = 0;
@ -263,6 +295,15 @@ const onResize = (size) => {
moreActions.value = _moreActions; 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(() => { const selectedComputed = computed(() => {
return Object.keys(props.grid).length > 0 ? props.grid.getSelectedRows() : []; return Object.keys(props.grid).length > 0 ? props.grid.getSelectedRows() : [];
}); });
@ -273,13 +314,13 @@ const buttonClick = async (button) => {
let beforeResult = true; let beforeResult = true;
const context = {}; const context = {};
if (button.beforeClick) { 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) { 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) { if (button.afterClick) {
nextTick(() => { nextTick(() => {
button.afterClick(selectedComputed.value, tickedComputed.value, context, props.grid); button.afterClick(selectedComputed.value, tickedComputed.value, props.grid, context);
}); });
} }
} }

Loading…
Cancel
Save