Browse Source

表格优化提交

main
likunming 1 year ago
parent
commit
e2315d4bac
  1. 1
      io.sc.platform.core.frontend/src/platform/components/form/WForm.vue
  2. 2
      io.sc.platform.core.frontend/src/platform/components/form/elements/WCodeMirror.vue
  3. 100
      io.sc.platform.core.frontend/src/platform/components/form/elements/WIcon.vue
  4. 2
      io.sc.platform.core.frontend/src/platform/components/grid/TreeGridRow.vue
  5. 99
      io.sc.platform.core.frontend/src/platform/components/grid/WGrid.vue

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

@ -80,6 +80,7 @@ const fiedType = {
codeMirror: 'w-code-mirror', codeMirror: 'w-code-mirror',
position: 'w-position', position: 'w-position',
date: 'w-date', date: 'w-date',
icon: 'w-icon',
number: 'w-number', number: 'w-number',
select: 'w-select', select: 'w-select',
text: 'w-text', text: 'w-text',

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

@ -21,7 +21,7 @@
<template #control> <template #control>
<div ref="codemirrorRef" style="width: 100%" @focus.stop.prevent="() => {}" @click.stop.prevent="() => {}"></div> <div ref="codemirrorRef" style="width: 100%" @focus.stop.prevent="() => {}" @click.stop.prevent="() => {}"></div>
</template> </template>
<template v-if="!Tools.isEmpty(codeMirrorValue)" #append> <template v-if="!Tools.isEmpty(codeMirrorValue) && attrs.button" #append>
<q-btn <q-btn
round round
dense dense

100
io.sc.platform.core.frontend/src/platform/components/form/elements/WIcon.vue

@ -1,7 +1,21 @@
<template> <template>
<q-input v-model="valueRef" @update:model-value="valueChanged"> <div v-show="showIfComputed">
<q-input
ref="iconRef"
v-model="valueRef"
:hide-bottom-space="true"
:hide-hint="true"
:outlined="true"
:dense="true"
v-bind="attrs"
:rules="rulesComputed"
:readonly="readonlyIfComputed"
:disable="disableIfComputed"
@update:model-value="valueChanged"
>
<template #label> <span v-if="requiredIfComputed" style="color: red">*</span> {{ attrs.label }} </template>
<template #append> <template #append>
<q-btn icon="bi-suit-heart" size="10px" padding="2px" flat square unelevated :title="$t('select')"> <q-btn :icon="Tools.isEmpty(valueRef) ? 'bi-suit-heart' : valueRef" size="10px" padding="2px" flat square unelevated :title="$t('select')">
<q-popup-proxy v-model:model-value="isShow" anchor="bottom right" self="top right" :offset="[0, 10]" @show="show"> <q-popup-proxy v-model:model-value="isShow" anchor="bottom right" self="top right" :offset="[0, 10]" @show="show">
<q-splitter v-model="leftWidthRef" style="width: 800px; height: 300px; position: relative"> <q-splitter v-model="leftWidthRef" style="width: 800px; height: 300px; position: relative">
<template #before> <template #before>
@ -71,10 +85,12 @@
></q-btn> ></q-btn>
</template> </template>
</q-input> </q-input>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, toRaw, onMounted } from 'vue'; import { ref, toRaw, onMounted, computed, useAttrs, watch } from 'vue';
import { Tools } from '@/platform'; import { Tools } from '@/platform';
import { FormValidators } from '@/platform/components';
import bootstrap from './icons/bootstrap.json'; import bootstrap from './icons/bootstrap.json';
import materialIcons from './icons/material-icons.json'; import materialIcons from './icons/material-icons.json';
import materialSymbolsOutlined from './icons/material-symbols-outlined.json'; import materialSymbolsOutlined from './icons/material-symbols-outlined.json';
@ -83,9 +99,42 @@ import fontawesomeBrands from './icons/fontawesome-v6-icons-brands.json';
import fontawesomeRegular from './icons/fontawesome-v6-icons-regular.json'; import fontawesomeRegular from './icons/fontawesome-v6-icons-regular.json';
import fontawesomeSolid from './icons/fontawesome-v6-icons-solid.json'; import fontawesomeSolid from './icons/fontawesome-v6-icons-solid.json';
const attrs = useAttrs();
const rules = attrs.rules;
const iconRef = ref();
const props = defineProps({ const props = defineProps({
modelValue: { type: String, default: '' }, modelValue: { type: String, default: '' },
restore: { type: Boolean, default: false }, restore: { type: Boolean, default: false },
showIf: {
type: Function,
default: () => {
return true;
},
},
required: {
type: Boolean,
default: false,
},
requiredIf: {
type: Function,
default: undefined,
},
readonlyIf: {
type: Function,
default: () => {
return false;
},
},
disableIf: {
type: Function,
default: () => {
return false;
},
},
form: {
type: Object,
default: undefined,
},
}); });
const emit = defineEmits(['update:modelValue']); const emit = defineEmits(['update:modelValue']);
@ -104,8 +153,53 @@ const selectedTab = ref('bootstrap');
const isShow = ref(false); const isShow = ref(false);
const searchRef = ref(''); const searchRef = ref('');
const valueRef = ref(props.modelValue || 'bi-arrow-up-left-square'); const valueRef = ref(props.modelValue || 'bi-arrow-up-left-square');
watch(
() => props.modelValue,
(newVal, oldVal) => {
valueRef.value = newVal;
},
);
const restoreValue = toRaw(props.modelValue || ''); const restoreValue = toRaw(props.modelValue || '');
const rulesComputed = computed(() => {
let result = rules || <any>[];
if (showIfComputed.value && requiredIfComputed.value) {
result.push(FormValidators.required());
} else if (!showIfComputed.value) {
result = [];
}
if (iconRef?.value) {
iconRef.value.resetValidation();
}
return result;
});
const showIfComputed = computed(() => {
return props.showIf(props.form);
});
const requiredIfComputed = computed(() => {
if (props.requiredIf) {
return props.requiredIf(props.form) || false;
} else if (props.required) {
return true;
}
return false;
});
const readonlyIfComputed = computed(() => {
return props.readonlyIf(props.form);
});
const disableIfComputed = computed(() => {
return props.disableIf(props.form);
});
const computedStoreBackgroundColorValue = computed(() => {
const color: string = restoreValue;
if (color.toLowerCase() === 'white' || color.toLowerCase() === '#ffffff' || color.toLowerCase() === '#fff') {
return '#eee';
}
return undefined;
});
if (Tools.isEmpty(valueRef.value)) { if (Tools.isEmpty(valueRef.value)) {
selectedTab.value = 'bootstrap'; selectedTab.value = 'bootstrap';
} else if (valueRef.value.startsWith('bi')) { } else if (valueRef.value.startsWith('bi')) {

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

@ -190,9 +190,9 @@ const selectedParent = (row, value) => {
parent[table.tickedField] = false; parent[table.tickedField] = false;
} }
} }
}
selectedParent(parent, value); selectedParent(parent, value);
} }
}
}; };
// //

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

@ -218,11 +218,11 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed, onMounted, nextTick, toRaw, useAttrs, getCurrentInstance, provide, watchEffect } from 'vue'; import { ref, reactive, computed, onMounted, nextTick, toRaw, useAttrs, getCurrentInstance, provide, watchEffect, watch } from 'vue';
import { axios, Environment, NotifyManager, TreeBuilder, VueTools, Tools } from '@/platform'; import { axios, Environment, NotifyManager, TreeBuilder, VueTools, Tools } from '@/platform';
import { useQuasar, getCssVar, exportFile } from 'quasar'; import { useQuasar, getCssVar, exportFile } from 'quasar';
import { IconEnum } from '@/platform/enums'; import { IconEnum } from '@/platform/enums';
import { extractTableColumnsProps, arrayToMap, OperatorTypeEnum, isEmpty, PageStatusEnum } from '@/platform/components/utils'; import { arrayToMap, OperatorTypeEnum, isEmpty, PageStatusEnum } from '@/platform/components/utils';
import TreeGridRow from './TreeGridRow.vue'; import TreeGridRow from './TreeGridRow.vue';
import GridConfig from './GridConfig.vue'; import GridConfig from './GridConfig.vue';
@ -395,7 +395,61 @@ const dialogRef = ref();
const drawerRef = ref(); const drawerRef = ref();
const dialogFormRef = ref(); const dialogFormRef = ref();
const infoRef = ref(); const infoRef = ref();
const tableColumnsMap = arrayToMap('name', props.columns); const tableColumns = ref(props.columns);
const tableColumnsMap = ref(arrayToMap('name', tableColumns.value));
const columnStyle = (item: any) => {
let style = '';
if (item.hasOwnProperty('style')) {
style = item.style;
}
if (item.hasOwnProperty('width')) {
if (typeof item.width === 'number') {
item.style = `min-width: ` + item.width + `px; width: ` + item.width + `px;max-width: ` + item.width + `px;` + style;
} else {
item.style = `min-width: ` + item.width + `; width: ` + item.width + `;max-width: ` + item.width + `;` + style;
}
delete item.width;
if (item.hasOwnProperty('classes')) {
item.classes = item.classes + ' truncate';
} else {
item.classes = 'truncate';
}
}
};
const columnChildrenHandler = (item: any, gridColumns: any) => {
if (item.columns && item.columns.length > 0) {
item.columns.forEach((column) => {
columnChildrenHandler(column, gridColumns);
});
} else {
columnStyle(item);
gridColumns.push({
...{ align: 'left', label: item.name, field: item.name, sortable: true, hidden: false },
...item,
});
}
};
const extractTableColumnsProps = () => {
const gridColumns = <any>[];
if (tableColumns.value && tableColumns.value.length > 0) {
gridColumns.push({ name: '_sortNo_', align: 'center', label: '序号', field: '_sortNo_', hidden: props.sortNo ? false : true });
tableColumns.value.forEach((item: any) => {
columnChildrenHandler(item, gridColumns);
});
return gridColumns;
}
return [];
};
const extractTableColumns = ref(extractTableColumnsProps());
watch(
() => props.columns,
(newVal, oldVal) => {
tableColumns.value = newVal;
tableColumnsMap.value = arrayToMap('name', tableColumns.value);
extractTableColumns.value = extractTableColumnsProps();
},
);
const queryFormFieldsMap = arrayToMap('name', props.queryFormFields); const queryFormFieldsMap = arrayToMap('name', props.queryFormFields);
const rowKey_ = '_rowKey_'; // UUID const rowKey_ = '_rowKey_'; // UUID
const url = { const url = {
@ -406,11 +460,10 @@ const url = {
removeDataUrl: props.removeDataUrl, removeDataUrl: props.removeDataUrl,
}; };
const extractTableColumns = extractTableColumnsProps(props);
// props // props
const titleScopeHandler = (column: any, scope: any) => { const titleScopeHandler = (column: any, scope: any) => {
if (extractTableColumns && extractTableColumns.length > 0) { if (extractTableColumns.value && extractTableColumns.value.length > 0) {
const i = extractTableColumns.findIndex((item) => item.name === column.name); const i = extractTableColumns.value.findIndex((item) => item.name === column.name);
if (i > -1) { if (i > -1) {
return scope; return scope;
} }
@ -425,7 +478,7 @@ const table = reactive({
allTicked: <null | boolean>false, allTicked: <null | boolean>false,
gridConfig: false, gridConfig: false,
stickyNum: props.stickyNum, stickyNum: props.stickyNum,
columns: extractTableColumns, columns: extractTableColumns.value,
treeExpand: props.treeDefaultExpandAll, treeExpand: props.treeDefaultExpandAll,
checkboxSelection: props.checkboxSelection, checkboxSelection: props.checkboxSelection,
sortNo: props.sortNo, sortNo: props.sortNo,
@ -660,10 +713,10 @@ const buttonObj = {
icon: 'file_download', icon: 'file_download',
label: '导出', label: '导出',
click: (selected, context) => { click: (selected, context) => {
const content = [props.columns.map((col) => wrapCsvValue(col.label))] const content = [tableColumns.value.map((col) => wrapCsvValue(col.label))]
.concat( .concat(
table.rows.map((row) => table.rows.map((row) =>
props.columns tableColumns.value
.map((col) => wrapCsvValue(typeof col.field === 'function' ? col.field(row) : row[col.field === void 0 ? col.name : col.field], col.format, row)) .map((col) => wrapCsvValue(typeof col.field === 'function' ? col.field(row) : row[col.field === void 0 ? col.name : col.field], col.format, row))
.join(','), .join(','),
), ),
@ -1004,7 +1057,7 @@ function findParents(arrData: any, name: any) {
} }
const handlerMoreRowColumnTitle = () => { const handlerMoreRowColumnTitle = () => {
props.columns.forEach((tableColumn: any) => { tableColumns.value.forEach((tableColumn: any) => {
columnToMap(tableColumn); columnToMap(tableColumn);
}); });
let maxColumnChildrenLevel = 0; let maxColumnChildrenLevel = 0;
@ -1024,7 +1077,7 @@ const handlerMoreRowColumnTitle = () => {
tmpColspan = 0; tmpColspan = 0;
// parent // parent
const parent = findParents(props.columns, key); const parent = findParents(tableColumns.value, key);
moreColumnTitleMap.get(key)!.parents = parent; moreColumnTitleMap.get(key)!.parents = parent;
// parentLevel // parentLevel
@ -1076,7 +1129,7 @@ const tableHeightComputed = computed(() => {
// //
const screenHeight = $q.screen.height; const screenHeight = $q.screen.height;
// XX // XX
const footerHeight = gc.theme.footer.enable ? gc.theme.footer.height : 0; const footerHeight = gc.theme.footer.show ? gc.theme.footer.height : 0;
// //
const mainPaddingBottom = gc.theme.main.paddingBottom || 0; const mainPaddingBottom = gc.theme.main.paddingBottom || 0;
// //
@ -1107,7 +1160,7 @@ const noDataBottomHeightComputed = computed(() => {
// //
const screenHeight = $q.screen.height; const screenHeight = $q.screen.height;
// XX // XX
const footerHeight = gc.theme.footer.enable ? gc.theme.footer.height : 0; const footerHeight = gc.theme.footer.show ? gc.theme.footer.height : 0;
// 4px // 4px
const otherHeight = table.spaceHeight || 4; const otherHeight = table.spaceHeight || 4;
// //
@ -1404,10 +1457,10 @@ const view = () => {
viewInfo.infoArray.push({ label: item.label, value: value, originalValue: getSelectedRowsComputed.value[0][item.name] }); viewInfo.infoArray.push({ label: item.label, value: value, originalValue: getSelectedRowsComputed.value[0][item.name] });
} else { } else {
let value = null; let value = null;
if (tableColumnsMap.get(item.name) && tableColumnsMap.get(item.name).format) { if (tableColumnsMap.value.get(item.name) && tableColumnsMap.value.get(item.name).format) {
value = getSelectedRowsComputed.value[0][item.name]; value = getSelectedRowsComputed.value[0][item.name];
try { try {
value = tableColumnsMap.get(item.name).format(getSelectedRowsComputed.value[0][item.name], getSelectedRowsComputed.value[0]); value = tableColumnsMap.value.get(item.name).format(getSelectedRowsComputed.value[0][item.name], getSelectedRowsComputed.value[0]);
} catch (error) { } catch (error) {
console.error('format error!'); console.error('format error!');
} }
@ -1418,7 +1471,7 @@ const view = () => {
} }
} }
} else { } else {
for (let item of tableColumnsMap) { for (let item of tableColumnsMap.value) {
if (item[1].format) { if (item[1].format) {
let value = getSelectedRowsComputed.value[0][item[0]]; let value = getSelectedRowsComputed.value[0][item[0]];
try { try {
@ -1455,8 +1508,14 @@ const wrapCsvValue = (val, formatFn, row) => {
// //
const setLocalData = (rows: any) => { const setLocalData = (rows: any) => {
if (props.tree && props.treeRelationship === 'parent') {
const treeRows = TreeBuilder.build(rows, props.foreignKey, props.primaryKey);
table.rows = treeRows;
} else {
table.rows = rows; table.rows = rows;
}
addRowKey(table.rows); addRowKey(table.rows);
state.pagination.rowsNumber = table.rows.length;
stickyHeaderColumn(); stickyHeaderColumn();
}; };
// //
@ -1478,6 +1537,7 @@ const removeRows = (rows) => {
1, 1,
); );
}); });
state.pagination.rowsNumber = table.rows.length;
stickyHeaderColumn(); stickyHeaderColumn();
}; };
// //
@ -1488,6 +1548,7 @@ const addRow = (row, index) => {
table.rows.splice(index, 0, row); table.rows.splice(index, 0, row);
} }
addRowKey(table.rows); addRowKey(table.rows);
state.pagination.rowsNumber = table.rows.length;
stickyHeaderColumn(); stickyHeaderColumn();
}; };
@ -1705,7 +1766,7 @@ const handlerStickyChildrenColumn = (item, columns) => {
} }
}; };
const getStickyColumn = () => { const getStickyColumn = () => {
const columns = props.columns.filter((item, index) => { const columns = tableColumns.value.filter((item, index) => {
return index < table.stickyNum; return index < table.stickyNum;
}); });
const arr = []; const arr = [];
@ -1880,7 +1941,7 @@ const tableClassComputed = computed(() => {
if (table.stickyNum && table.stickyNum > 0) { if (table.stickyNum && table.stickyNum > 0) {
if (columnTitleState.columnTitleRowNum > 1) { if (columnTitleState.columnTitleRowNum > 1) {
// //
const stickyColumn = props.columns.filter((item, index) => { const stickyColumn = tableColumns.value.filter((item, index) => {
return index < table.stickyNum; return index < table.stickyNum;
}); });
let tdNum = excludeColumnNum.value; let tdNum = excludeColumnNum.value;
@ -2035,7 +2096,7 @@ const handlerQueryFormShowField = () => {
}; };
onMounted(() => { onMounted(() => {
if (extractTableColumns && extractTableColumns.length > props.columns.length) { if (extractTableColumns.value && extractTableColumns.value > tableColumns.value.length) {
handlerMoreRowColumnTitle(); handlerMoreRowColumnTitle();
} }
handlerQueryFormShowField(); handlerQueryFormShowField();

Loading…
Cancel
Save