Browse Source

1、优化低代码模块表单配置功能。

2、w-grid优化。
main
likunming 1 month ago
parent
commit
d4755f195b
  1. 219
      io.sc.platform.core.frontend/src/platform/components/grid/Th.vue
  2. 200
      io.sc.platform.core.frontend/src/platform/components/select/WDictionarySelect.vue
  3. 29
      io.sc.platform.lcdp.frontend/src/views/form/ViewDialog.vue
  4. 44
      io.sc.platform.lcdp.frontend/src/views/form/components/GridToolbar.ts
  5. 256
      io.sc.platform.lcdp.frontend/src/views/form/components/GridToolbarSelect.vue
  6. 427
      io.sc.platform.lcdp.frontend/src/views/form/grid/ColumnTitleConfig.vue
  7. 120
      io.sc.platform.lcdp.frontend/src/views/form/grid/Dialog.vue
  8. 318
      io.sc.platform.lcdp.frontend/src/views/form/grid/FieldEditDialog.vue
  9. 508
      io.sc.platform.lcdp.frontend/src/views/form/grid/Form.vue
  10. 52
      io.sc.platform.lcdp.frontend/src/views/form/grid/ts/ComponentType.ts
  11. 21
      io.sc.platform.lcdp.frontend/src/views/form/grid/ts/ComputedManager.ts
  12. 10
      io.sc.platform.lcdp.frontend/src/views/form/grid/ts/DictionaryType.ts
  13. 51
      io.sc.platform.lcdp.frontend/src/views/form/grid/ts/FormConfig.ts
  14. 204
      io.sc.platform.lcdp.frontend/src/views/form/grid/ts/FunctionManager.ts
  15. 11
      io.sc.platform.lcdp.frontend/src/views/form/grid/ts/JavaType.ts
  16. 170
      io.sc.platform.lcdp.frontend/src/views/form/grid/ts/RequestApi.ts
  17. 10
      io.sc.platform.lcdp.frontend/src/views/form/grid/ts/type/ComponentFunctionsType.ts

219
io.sc.platform.core.frontend/src/platform/components/grid/Th.vue

@ -0,0 +1,219 @@
<template>
<q-th :key="column.name" :rowspan="rowspan" :colspan="colspan" :style="styleComputed" :class="classComputed" style="font-weight: bold" :title="title">
<span v-html="label"></span>
</q-th>
</template>
<script setup lang="ts">
import { Tools, $t } from '@/platform';
import { computed, inject, reactive } from 'vue';
import { Constant, GridTools } from './ts/index';
const tools = <GridTools>inject('tools');
const props = defineProps({
rowspan: { type: Number, default: undefined },
colspan: { type: Number, default: undefined },
title: { type: String, default: '' },
label: { type: String, default: '' },
style: { type: String, default: '' },
class: { type: String, default: '' },
column: {
type: Object,
default: () => {
return {};
},
},
scope: {
//
type: Object,
default: () => {
return {};
},
},
});
const thStickyLastNameComputed = computed(() => {
let result = <any>[];
const stickyColumnArr = tools.titleFM.getStickyColumn();
const lastColumn = tools.titleFM.getMultiTitleIndex(stickyColumnArr[stickyColumnArr.length - 1]['name']);
if (lastColumn.trIndex === 1) {
// 1
result = [stickyColumnArr[stickyColumnArr.length - 1]];
} else {
const map = new Map();
stickyColumnArr.forEach((item) => {
const trtdIndex = tools.titleFM.getMultiTitleIndex(item['name']);
if (map.has(trtdIndex.trIndex) && map.get(trtdIndex.trIndex)[0] < trtdIndex.tdIndex) {
map.set(trtdIndex.trIndex, [trtdIndex.tdIndex, item]);
} else if (!map.has(trtdIndex.trIndex)) {
map.set(trtdIndex.trIndex, [trtdIndex.tdIndex, item]);
}
});
for (let key of map.keys()) {
result.push(map.get(key)[1]);
}
}
return result;
});
const classComputed = computed(() => {
const noBorder = noRightBorder(props.column.name);
if (props.class) {
return props.class + (noBorder ? ' no_border_right' : '');
} else if (noBorder) {
return 'no_border_right';
}
return '';
});
const existYScroll = () => {
let existYScroll = false;
const clientHeight = tools.instance.getHtmlElement()?.getElementsByClassName('q-table__middle')[0]?.clientHeight;
const scrollHeight = tools.instance.getHtmlElement()?.getElementsByClassName('q-table__middle')[0]?.scrollHeight;
if (clientHeight && scrollHeight && scrollHeight > clientHeight) {
//
existYScroll = true;
}
return existYScroll;
};
const noRightBorder = (name) => {
let lastColumn: any = tools.table.originalColumns[tools.table.originalColumns.length - 1];
// for (let i = tools.table.originalColumns.length - 1; i > -1; i--) {
// const column = tools.table.originalColumns[i];
// if (column.showIf) {
// lastColumn = column;
// break;
// }
// }
const flag = existYScroll();
if (lastColumn['name'] === name && !flag) {
return true;
} else if (tools.table.store.multiHeaderLastNames[lastColumn['name']]?.includes(name) && !flag) {
return true;
}
return false;
};
const styleComputed = computed(() => {
let style = '';
if (!Tools.isEmpty(props.style)) {
if (!props.style.endsWith(';')) {
style = props.style + ';';
} else {
style = props.style;
}
}
const stickyColumnArr = tools.titleFM.getStickyColumn();
if (
tools.table.configStore.stickyNum > 0 &&
stickyColumnArr.findIndex((item: any) => {
return item.name === props.column.name;
}) > -1
) {
const stickyThArr = <any>[];
const trtdIndex = tools.titleFM.getMultiTitleIndex(props.column.name);
if (props.column.parents && props.column.parents.length > 0) {
//
// parenttdIndex
for (let tr = 0; tr < trtdIndex.trIndex; tr++) {
const tdArr = tools.titleFM.multiTitles.value[tr];
for (let td = 0; td < trtdIndex.tdIndex - 1; td++) {
if (tdArr[td] && tdArr[td].parents && tdArr[td].parents.length > 0) {
const result =
tdArr[td].parents.length === props.column.parents.length &&
tdArr[td].parents.every((a) => props.column.parents.some((b) => a === b)) &&
props.column.parents.every((_b) => tdArr[td].parents.some((_a) => _a === _b));
if (result) {
if (tr === 0) {
stickyThArr.push({ trIndex: tr + 1, tdIndex: td + tools.cm.extColumnNum.value + 1 });
} else {
stickyThArr.push({ trIndex: tr + 1, tdIndex: td + 1 });
}
}
}
}
}
props.column.parents.forEach((parent) => {
const parentTrtdIndex = tools.titleFM.getMultiTitleIndex(parent);
if (tools.titleFM.multiTitleMap.get(parent)!.parents && tools.titleFM.multiTitleMap.get(parent)!.parents.length > 0) {
const tdArr = tools.titleFM.multiTitles[parentTrtdIndex.trIndex - 1];
for (let td = 0; td < parentTrtdIndex.tdIndex - 1; td++) {
const result =
tdArr[td].parents.length === tools.titleFM.multiTitleMap.get(parent)!.parents.length &&
tdArr[td].parents.every((a) => tools.titleFM.multiTitleMap.get(parent)!.parents.some((b) => a === b)) &&
tools.titleFM.multiTitleMap.get(parent)!.parents.every((_b) => tdArr[td].parents.some((_a) => _a === _b));
if (result) {
stickyThArr.push({ trIndex: parentTrtdIndex.trIndex, tdIndex: td + 1 });
}
}
} else {
const tdArr = tools.titleFM.multiTitles[parentTrtdIndex.trIndex - 1];
for (let td = 0; td < parentTrtdIndex.tdIndex - 1; td++) {
if (
tdArr[td].parents &&
tdArr[td].parents.length > 0 &&
tdArr[td].parents.findIndex((item) => {
return item === parent;
}) > -1
) {
stickyThArr.push({ trIndex: parentTrtdIndex.trIndex, tdIndex: td + tools.cm.extColumnNum.value + 1 });
} else {
stickyThArr.push({ trIndex: parentTrtdIndex.trIndex, tdIndex: td + tools.cm.extColumnNum.value + 1 });
}
}
}
});
if (trtdIndex.tdIndex === 1 && stickyThArr.length === 0) {
stickyThArr.push({ trIndex: 0, tdIndex: 0 });
}
} else {
if (trtdIndex.tdIndex === 1) {
if (tools.cm.extColumnNum.value === 2) {
return thStickyLastNameComputed.value.findIndex((item) => {
return item.name === props.column.name;
}) > -1
? (style += 'z-index: 3;position: sticky;left: calc(var(--columnWidth-1-1) + var(--columnWidth-1-2));')
: (style += 'z-index: 3;position: sticky;left: calc(var(--columnWidth-1-1) + var(--columnWidth-1-2));');
} else if (tools.cm.extColumnNum.value === 1) {
return thStickyLastNameComputed.value.findIndex((item) => {
return item.name === props.column.name;
}) > -1
? (style += 'z-index: 3;position: sticky;left: var(--columnWidth-1-1);')
: (style += 'z-index: 3;position: sticky;left: var(--columnWidth-1-1);');
} else {
return thStickyLastNameComputed.value.findIndex((item) => {
return item.name === props.column.name;
}) > -1
? (style += 'z-index: 3;position: sticky;left: 0px;')
: (style += 'z-index: 3;position: sticky;left: 0px;');
}
} else {
for (let i = 1; i < trtdIndex.tdIndex; i++) {
stickyThArr.push({ trIndex: 1, tdIndex: i + tools.cm.extColumnNum.value });
}
}
}
if (tools.cm.extColumnNum.value === 2) {
stickyThArr.push({ trIndex: 1, tdIndex: 1 });
stickyThArr.push({ trIndex: 1, tdIndex: 2 });
} else if (tools.cm.extColumnNum.value === 1) {
stickyThArr.push({ trIndex: 1, tdIndex: 1 });
}
if (stickyThArr && stickyThArr.length > 0) {
let left = '';
stickyThArr.forEach((item) => {
left += '+ var(--columnWidth-' + item.trIndex + '-' + item.tdIndex + ') ';
});
if (left) {
style += 'z-index: 3;position: sticky;left: calc(' + left.substring(1) + ')' + ';';
}
}
}
// if (c['name'] === tools.table.columns[tools.table.columns.length - 1]['name']) {
// style += 'border-right-width: 0px;';
// }
return style;
});
</script>
<style lang="css"></style>

200
io.sc.platform.core.frontend/src/platform/components/select/WDictionarySelect.vue

@ -0,0 +1,200 @@
<template>
<div v-show="fieldMethodsClass.getShow(props, modelValue)">
<q-input
ref="textSelectRef"
v-model="displayValueComputed"
:hide-bottom-space="true"
:hide-hint="true"
:outlined="true"
:dense="true"
:autogrow="true"
v-bind="attrs"
type="text"
:rules="fieldMethodsClass.getRules(props, { value: modelValue, displayValue: displayValueComputed }, textSelectRef, undefined)"
:readonly="fieldMethodsClass.getReadOnly(props, { value: modelValue, displayValue: displayValueComputed })"
:disable="fieldMethodsClass.getDisable(props, { value: modelValue, displayValue: displayValueComputed })"
:clearable="false"
>
<template #label><w-label :required="fieldMethodsClass.getRequired(props, modelValue)" :label="attrs.label"></w-label></template>
<template v-if="!props['form'] || (props['form'] && props['form'].getStatus() !== 'view')" #append>
<q-btn v-if="!Tools.isEmpty(displayValueComputed)" flat square unelevated dense icon="cancel" @click="fieldMethodsClass.clearValue"></q-btn>
<q-btn flat square unelevated dense icon="pageview">
<q-popup-proxy v-model:model-value="isShow" anchor="bottom right" self="top right" :offset="[0, 10]">
<div style="width: 700px; height: 400px">
<w-grid
ref="dictionaryGridRef"
title="数据字典列表"
:checkbox-selection="false"
:pageable="false"
:dense="true"
:fetch-data-url="dictionaryGridFetchDataUrl"
:config-button="false"
:query-form-cols-num="2"
:toolbar-actions="['query', 'reset']"
:query-form-fields="[{ name: 'code', label: $t('code'), type: 'w-text' }]"
:columns="[
{ name: 'code', label: $t('code') },
{
name: 'name',
label: $t('name'),
format: (value, row) => {
return $t(row.code);
},
},
]"
:ticked-record="{
columnName: valueUseColumnName,
data: typeof modelValue === 'string' ? [modelValue] : modelValue,
}"
db-click-operation="none"
@row-click="rowClick"
>
</w-grid>
</div>
</q-popup-proxy>
</q-btn>
</template>
<template v-for="slotName in fieldMethodsClass.slotNames" :key="slotName" #[slotName]>
<slot v-if="fieldMethodsClass.isTemplateSlot" :name="slotName"></slot>
<FormElementSlot v-else :slot-name="slotName" :slot-content="props['slot'][slotName]"></FormElementSlot>
</template>
</q-input>
</div>
</template>
<script setup lang="ts">
import { $t, axios, Environment, Tools } from '@/platform';
import { FormFieldProps } from '@/platform/components/form/FormField.ts';
import { computed, onMounted, ref, useAttrs, useSlots, watch } from 'vue';
import FormElementSlot from '../form/FormElementSlot.vue';
import { FormFieldMethods } from '../form/FormField';
const textSelectRef = ref();
const attrs = useAttrs();
const slots = useSlots();
const modelValue = defineModel<string>();
const modelObjectValue = ref({}); //
const dictionaryGridRef = ref();
const dictionaryGridFetchDataUrl = Environment.apiContextPath('/api/template/config/dictionaryList');
const isShow = ref(false);
interface FieldProps extends FormFieldProps {}
const props = withDefaults(defineProps<FieldProps>(), {
showIf: true,
});
class FieldMethods extends FormFieldMethods {
isTemplateSlot = this.getSlotType(slots);
slotNames = this.getSlotNames(slots, props);
updateValue = (value_) => {
if (props['onUpdateValue']) {
props['onUpdateValue']({
value: value_,
displayValue: displayValueComputed.value,
form: props['form'],
});
}
};
validate = () => {
return textSelectRef.value.validate();
};
setValue = (value) => {
modelValue.value = value;
setObjectValueByValue(value);
};
getValue = () => {
return modelValue.value;
};
getObjectValue = () => {
return modelObjectValue.value;
};
//
clearValue = () => {
modelValue.value = undefined;
fieldMethodsClass.clearObjectValue();
};
//
clearObjectValue = () => {
modelObjectValue.value = {};
};
}
const fieldMethodsClass = new FieldMethods();
const valueUseColumnName = 'code';
const displayValueComputed = computed(() => {
if (modelObjectValue.value) {
return modelObjectValue.value['displayValue'];
}
return '';
});
const getActualDisplayValue = (row) => {
return row['code'] + '(' + $t(row.code) + ')';
};
const rowClick = (args) => {
const modelValue_ = args.row[valueUseColumnName];
fieldMethodsClass.clearValue();
modelValue.value = modelValue_;
modelObjectValue.value = { value: modelValue_, displayValue: getActualDisplayValue(args.row) };
isShow.value = false;
};
watch(
() => modelValue.value,
(newVal, oldVal) => {
if (newVal !== oldVal) {
fieldMethodsClass.updateValue(newVal);
}
if (Tools.isEmpty(newVal) || (Array.isArray(modelValue.value) && modelValue.value.length === 0)) {
fieldMethodsClass.clearObjectValue();
} else if (newVal !== oldVal) {
setObjectValueByValue(newVal);
}
},
);
//
const setObjectValueByValue = async (value) => {
if ((Array.isArray(value) && value.length > 0) || (typeof value === 'string' && !Tools.isEmpty(value))) {
fieldMethodsClass.clearObjectValue();
const urlSearchParams = new URLSearchParams();
urlSearchParams.append(
'criteria',
JSON.stringify({
fieldName: valueUseColumnName,
operator: 'inSet',
value: Array.isArray(value) ? value : [value],
}),
);
const resp = await axios.get(dictionaryGridFetchDataUrl, { params: urlSearchParams }).catch((error) => {
console.info('error-------------', error);
});
if (resp && resp.data) {
const responseData = resp.data;
if (Array.isArray(responseData) && responseData.length > 0) {
responseData.forEach((item) => {
modelObjectValue.value = { value: item[valueUseColumnName], displayValue: getActualDisplayValue(item) };
});
} else if (typeof responseData === 'object' && responseData.content?.length > 0) {
responseData.content.forEach((item) => {
modelObjectValue.value = { value: item[valueUseColumnName], displayValue: getActualDisplayValue(item) };
});
}
}
}
};
onMounted(() => {
setObjectValueByValue(modelValue.value);
});
defineExpose({
validate: fieldMethodsClass.validate,
setValue: fieldMethodsClass.setValue,
getValue: fieldMethodsClass.getValue,
getObjectValue: fieldMethodsClass.getObjectValue,
clearValue: fieldMethodsClass.clearValue,
});
</script>

29
io.sc.platform.lcdp.frontend/src/views/form/ViewDialog.vue

@ -0,0 +1,29 @@
<template>
<w-dialog ref="dialogRef" title="预览" width="90%" height="90%" body-padding="0px 0px 0px 0px">
<w-grid ref="gridRef" v-bind="config"></w-grid>
</w-dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { Page } from './page';
const dialogRef = ref();
const gridRef = ref();
const config = ref({});
const show = async (data_) => {
const { templateConfig, templateGrid, templateGridFields } = data_;
const page = new Page(templateConfig, templateGrid, templateGridFields);
config.value = await page.buildGridConfig();
dialogRef.value.show();
};
const hide = () => {
dialogRef.value.hide();
};
defineExpose({
show,
hide,
});
</script>

44
io.sc.platform.lcdp.frontend/src/views/form/components/GridToolbar.ts

@ -0,0 +1,44 @@
export class GridToolbar {
static type = {
separator: { label: '分割符', value: 'separator' },
query: { label: '查询', value: 'query' },
reset: { label: '重置', value: 'reset' },
refresh: { label: '刷新', value: 'refresh' },
add: { label: '新增', value: 'add' },
edit: { label: '编辑', value: 'edit' },
clone: { label: '复制', value: 'clone' },
remove: { label: '删除', value: 'remove' },
view: { label: '查看', value: 'view' },
export: { label: '导出', value: 'export' },
addTop: { label: '新增顶级节点', value: 'addTop' },
addChild: { label: '新增子节点', value: 'addChild' },
expand: { label: '展开/收起所有', value: 'expand' },
config: { label: '表格设置', value: 'config' },
};
/**
*
*/
static options: Array<any> = Object.values(this.type);
/**
*
*/
static operatorOptions: Array<any> = Object.values(this.type).filter((item) => item.value !== this.type.separator.value);
/**
*
*/
static tableDefaultOptions: Array<any> = [
this.type.query.value,
this.type.reset.value,
this.type.separator.value,
this.type.add.value,
this.type.edit.value,
this.type.clone.value,
this.type.remove.value,
this.type.config.value,
];
/**
* SQL的默认按钮集合
*/
static sqlDefaultOptions: Array<any> = [this.type.query.value, this.type.reset.value, this.type.config.value];
}

256
io.sc.platform.lcdp.frontend/src/views/form/components/GridToolbarSelect.vue

@ -0,0 +1,256 @@
<template>
<div v-show="fieldMethodsClass.getShow(props, modelValue)">
<q-input
ref="textSelectRef"
v-model="displayValueComputed"
:hide-bottom-space="true"
:hide-hint="true"
:outlined="true"
:dense="true"
:autogrow="true"
v-bind="attrs"
type="text"
:rules="fieldMethodsClass.getRules(props, { value: modelValue, displayValue: displayValueComputed }, textSelectRef, undefined)"
:readonly="fieldMethodsClass.getReadOnly(props, { value: modelValue, displayValue: displayValueComputed })"
:disable="fieldMethodsClass.getDisable(props, { value: modelValue, displayValue: displayValueComputed })"
:clearable="false"
>
<template #label><w-label :required="fieldMethodsClass.getRequired(props, modelValue)" :label="attrs.label"></w-label></template>
<template v-if="!props['form'] || props['form']?.getStatus() !== 'view'" #append>
<q-btn v-if="!Tools.isEmpty(displayValueComputed)" flat square unelevated dense icon="cancel" @click="fieldMethodsClass.clearValue"></q-btn>
<q-btn
flat
square
unelevated
dense
icon="settings_applications"
@click="
() => {
dialogRef.show();
nextTick(() => {
if (modelValue && modelValue.length > 0) {
const rows = <any>[];
modelValue.forEach((item) => {
rows.push(GridToolbar.type[item]);
});
gridRef.setLocalData(rows);
}
});
}
"
></q-btn>
<w-dialog
ref="dialogRef"
title="按钮配置"
width="40%"
height="70%"
:can-maximize="false"
body-padding="5px 5px 5px 5px"
:buttons="[
{
label: '确定',
icon: 'beenhere',
click: () => {
const currRows = gridRef.getRows();
const result = <any>[];
currRows.forEach((row) => {
result.push(row.value);
});
modelValue = result;
dialogRef.hide();
},
},
]"
>
<w-grid
ref="gridRef"
title="按钮列表(拖拽可进行排序)"
:local-mode="true"
:dense="true"
dnd-mode="local"
:config-button="false"
:toolbar-actions="[
[
{
extend: 'add',
label: '引入',
click: () => {
selectDialogRef.show();
nextTick(() => {
const rows = <any>[];
GridToolbar.options.forEach((button) => {
rows.push({ label: button.label, value: button.value });
});
selectGridRef.setLocalData(rows);
});
},
},
{
extend: 'add',
name: 'addAll',
label: '全部引入',
click: () => {
const rows = <any>[];
GridToolbar.operatorOptions.forEach((button) => {
rows.push({ label: button.label, value: button.value });
});
gridRef.setLocalData(rows);
},
},
],
[
{
extend: 'remove',
click: (args: any) => {
args.grid.removeLocalData(args.grid.getTickedRows());
},
},
{
extend: 'remove',
name: 'removeAll',
enableIf: (args: any) => {
const rows = args.grid.getRows();
if (rows.length > 0) {
return true;
}
return false;
},
label: '全部删除',
click: (args: any) => {
args.grid.removeLocalData(args.grid.getRows());
},
},
],
]"
:columns="[
{
name: 'label',
label: '按钮',
sortable: false,
},
]"
>
</w-grid>
<w-dialog
ref="selectDialogRef"
title="引入按钮"
width="30%"
height="65%"
:can-maximize="false"
body-padding="5px 5px 5px 5px"
:buttons="[
{
label: '确定',
icon: 'beenhere',
click: () => {
const rows = selectGridRef.getTickedRows();
const currRows = gridRef.getRows();
rows.forEach((row) => {
if (
row.value === GridToolbar.type.separator.value ||
(row.value !== GridToolbar.type.separator.value && currRows.findIndex((item) => item.value === row.value) < 0)
) {
gridRef.addLocalData({ label: row.label, value: row.value });
}
});
selectDialogRef.hide();
},
},
]"
>
<w-grid
ref="selectGridRef"
:local-mode="true"
:dense="true"
:config-button="false"
:columns="[
{
name: 'label',
label: '按钮',
sortable: false,
},
]"
>
</w-grid>
</w-dialog>
</w-dialog>
</template>
</q-input>
</div>
</template>
<script setup lang="ts">
import { ref, computed, useAttrs, watch, nextTick } from 'vue';
import { Tools, FormFieldProps, FormFieldMethods } from 'platform-core';
import { GridToolbar } from './GridToolbar';
const dialogRef = ref();
const gridRef = ref();
const selectDialogRef = ref();
const selectGridRef = ref();
const textSelectRef = ref();
const attrs = useAttrs();
const modelValue = defineModel<Array<string>>();
interface FieldProps extends FormFieldProps {
multiple?: boolean;
}
const props = withDefaults(defineProps<FieldProps>(), {
showIf: true,
multiple: false, //
});
class FieldMethods extends FormFieldMethods {
updateValue = (value_) => {
if (props['onUpdateValue']) {
props['onUpdateValue']({
value: value_,
displayValue: displayValueComputed.value,
form: props['form'],
});
}
};
validate = () => {
return textSelectRef.value.validate();
};
setValue = (value) => {
modelValue.value = value;
};
getValue = () => {
return modelValue.value;
};
clearValue = () => {
modelValue.value = [];
};
}
const fieldMethodsClass = new FieldMethods();
const displayValueComputed = computed(() => {
let result = '';
if (modelValue.value && modelValue.value.length > 0) {
result = '[';
modelValue.value.forEach((item) => {
result = result + GridToolbar.type[item].label + ',';
});
result = result.substring(0, result.length - 1);
result += ']';
}
return result;
});
watch(
() => modelValue.value,
(newVal, oldVal) => {
if (newVal !== oldVal) {
fieldMethodsClass.updateValue(newVal);
}
},
);
defineExpose({
validate: fieldMethodsClass.validate,
setValue: fieldMethodsClass.setValue,
getValue: fieldMethodsClass.getValue,
clearValue: fieldMethodsClass.clearValue,
});
</script>

427
io.sc.platform.lcdp.frontend/src/views/form/grid/ColumnTitleConfig.vue

@ -0,0 +1,427 @@
<template>
<div v-show="fieldMethodsClass.getShow(props, modelValue)">
<q-input
ref="textSelectRef"
v-model="displayValueComputed"
:hide-bottom-space="true"
:hide-hint="true"
:outlined="true"
:dense="true"
:autogrow="true"
v-bind="attrs"
type="text"
:rules="fieldMethodsClass.getRules(props, { value: modelValue, displayValue: displayValueComputed }, textSelectRef, undefined)"
:readonly="fieldMethodsClass.getReadOnly(props, { value: modelValue, displayValue: displayValueComputed })"
:disable="fieldMethodsClass.getDisable(props, { value: modelValue, displayValue: displayValueComputed })"
:clearable="false"
>
<template #label><w-label :required="fieldMethodsClass.getRequired(props, modelValue)" :label="attrs.label"></w-label></template>
<template v-if="!props['form'] || props['form']?.getStatus() !== 'view'" #append>
<q-btn v-if="!Tools.isEmpty(displayValueComputed)" flat square unelevated dense icon="cancel" @click="fieldMethodsClass.clearValue"></q-btn>
<q-btn
flat
square
unelevated
dense
icon="settings_applications"
@click="
() => {
const fields = getFields();
if (fields.length > 0) {
dialogRef.show();
nextTick(() => {
if (modelValue && modelValue.length > 0) {
const rows = <any>[];
modelValue.forEach((item) => {
rows.push({ name: item['name'], label: item['label'], children: toRaw(item['columns']), isGroup: item['isGroup'] });
});
gridRef.setLocalData(rows);
}
});
} else {
NotifyManager.warn('字段列表为空,无法进行多表头配置');
}
}
"
></q-btn>
<w-dialog
ref="dialogRef"
title="多表头配置"
width="80%"
height="80%"
:can-maximize="false"
body-padding="5px 5px 5px 5px"
:buttons="[
{
label: '确定',
icon: 'beenhere',
click: () => {
const currRows = gridRef.getRows();
const result = <any>[];
currRows.forEach((row) => {
let children = [];
if (row['children']) {
children = toRaw(row['children']);
removeExtraField(children);
}
const tmp = { name: row['name'], label: row['label'], isGroup: row['isGroup'] };
if (children.length > 0) {
tmp['columns'] = children;
}
result.push(tmp);
});
modelValue = result;
dialogRef.hide();
},
},
]"
>
<w-grid
ref="gridRef"
title="表头列表(拖拽可移动)"
:local-mode="true"
:dense="true"
:tree="true"
primary-key="name"
:tree-icon="
(row) => {
if (row.isGroup) {
return {
name: 'bi-folder-fill',
color: 'amber',
};
}
return {
name: 'note',
};
}
"
dnd-mode="local"
:config-button="false"
:toolbar-actions="[
{
extend: 'add',
label: '新增',
},
[
{
extend: 'remove',
click: (args: any) => {
const tickedRows = args.grid.getTickedRows();
const selectedRows = args.grid.getSelectedRow();
if (tickedRows.length > 0) {
args.grid.removeLocalData(tickedRows);
} else {
args.grid.removeLocalData(selectedRows);
}
},
},
{
extend: 'remove',
name: 'removeAll',
enableIf: (args: any) => {
const rows = args.grid.getRows();
if (rows.length > 0) {
return true;
}
return false;
},
label: '全部删除',
click: (args: any) => {
args.grid.removeLocalData(args.grid.getRows());
},
},
],
'separator',
[
{
extend: 'add',
name: 'importColumn',
label: '引入',
click: () => {
selectDialogRef.show();
nextTick(() => {
const result = getFields();
selectGridRef.setLocalData(result);
});
},
},
{
extend: 'add',
name: 'importColumnAll',
label: '全部引入',
click: () => {
const result = getFields();
importColumn(result);
},
},
],
'separator',
'expand',
]"
:columns="[
{
name: 'name',
label: '表头名称',
sortable: false,
},
{
name: 'label',
label: '页面显示名称',
sortable: false,
},
{
name: 'isGroup',
label: '是否分组表头',
showIf: false,
},
]"
:editor="{
dialog: {
title: '新增表头',
width: '30%',
height: '30%',
},
form: {
colsNum: 1,
fields: [
{ label: '字段名称', name: 'name', requiredIf: true, type: 'w-text' },
{ label: '页面显示名称', name: 'label', requiredIf: true, type: 'w-text' },
{ label: '是否分组表头', name: 'isGroup', showIf: false, defaultValue: true, type: 'w-checkbox' },
],
},
}"
@after-editor-open="
(args) => {
const row = args.grid.getSelectedRow();
if (row && row['isGroup']) {
//
args.grid.getEditorForm().setStatus('addChild');
}
}
"
>
</w-grid>
<w-dialog
ref="selectDialogRef"
title="引入字段"
width="70%"
height="70%"
:can-maximize="false"
body-padding="5px 5px 5px 5px"
:buttons="[
{
label: '确定',
icon: 'beenhere',
click: () => {
const rows = selectGridRef.getTickedRows();
importColumn(rows);
selectDialogRef.hide();
},
},
]"
>
<w-grid
ref="selectGridRef"
:local-mode="true"
:dense="true"
:config-button="false"
:columns="[
{
name: 'fieldName',
label: '字段名称',
sortable: false,
},
{
name: 'fieldLabel',
label: '页面显示名称',
sortable: false,
},
]"
>
</w-grid>
</w-dialog>
</w-dialog>
</template>
</q-input>
</div>
</template>
<script setup lang="ts">
import { ref, computed, useAttrs, watch, nextTick, inject, toRaw } from 'vue';
import { Tools, FormFieldProps, FormFieldMethods, NotifyManager } from 'platform-core';
import { FormConfig } from './ts/FormConfig';
const dialogRef = ref();
const gridRef = ref();
const selectDialogRef = ref();
const selectGridRef = ref();
const textSelectRef = ref();
const attrs = useAttrs();
const modelValue = defineModel<Array<any>>();
const formConfig = <FormConfig>inject('formConfig');
interface FieldProps extends FormFieldProps {
multiple?: boolean;
}
const props = withDefaults(defineProps<FieldProps>(), {
showIf: true,
multiple: false, //
});
class FieldMethods extends FormFieldMethods {
updateValue = (value_) => {
if (props['onUpdateValue']) {
props['onUpdateValue']({
value: value_,
displayValue: displayValueComputed.value,
form: props['form'],
});
}
};
validate = () => {
return textSelectRef.value.validate();
};
setValue = (value) => {
modelValue.value = value;
};
getValue = () => {
return modelValue.value;
};
clearValue = () => {
modelValue.value = [];
};
}
const fieldMethodsClass = new FieldMethods();
const displayValueComputed = computed(() => {
let result = '';
if (modelValue.value && modelValue.value.length > 0) {
result = `已配置${modelValue.value.length}`;
}
return result;
});
watch(
() => modelValue.value,
(newVal, oldVal) => {
if (newVal !== oldVal) {
fieldMethodsClass.updateValue(newVal);
}
},
);
const removeExtraField = (arr: Array<any>) => {
if (arr && arr.length > 0) {
arr.forEach((item: any) => {
if (item.children && item.children.length > 0) {
removeExtraField(item.children);
} else {
removeFields(item);
}
});
}
};
const removeFields = (target: any) => {
if (Tools.hasOwnProperty(target, '_rowKey_')) {
delete target['_rowKey_'];
}
if (Tools.hasOwnProperty(target, 'expand')) {
delete target['expand'];
}
if (Tools.hasOwnProperty(target, '_tickedCount')) {
delete target['_tickedCount'];
}
if (Tools.hasOwnProperty(target, '_childrenTickedCount')) {
delete target['_childrenTickedCount'];
}
if (Tools.hasOwnProperty(target, '_rowOldValue')) {
delete target['_rowOldValue'];
}
if (Tools.hasOwnProperty(target, '_rowIndex')) {
delete target['_rowIndex'];
}
if (Tools.hasOwnProperty(target, '_lazyloadNoChildren')) {
delete target['_lazyloadNoChildren'];
}
if (Tools.hasOwnProperty(target, '_selectable')) {
delete target['_selectable'];
}
if (Tools.hasOwnProperty(target, '_treeTickable')) {
delete target['_treeTickable'];
}
if (Tools.hasOwnProperty(target, 'ticked')) {
delete target['ticked'];
}
if (Tools.hasOwnProperty(target, 'selected')) {
delete target['selected'];
}
};
//
const getFields = () => {
const rows = formConfig.cf.getFieldGridRef().getRows();
const result = <any>[];
rows.forEach((row) => {
result.push({ fieldName: row['fieldName'], fieldLabel: row['fieldLabel'] });
});
return result;
};
const importColumn = (rows: Array<any>) => {
const row = gridRef.value.getSelectedRow();
const result = <any>[];
if (rows.length > 0) {
const currRows = gridRef.value.getRows();
const columns = getColumn(currRows);
rows.forEach((item) => {
if (columns.findIndex((tmp) => tmp['name'] === item['fieldName']) < 0) {
const tmp = { name: item['fieldName'], label: item['fieldLabel'] };
if (row && row['isGroup']) {
tmp['parent'] = row['name'];
}
result.push(tmp);
}
});
}
if (result.length > 0) {
gridRef.value.addLocalData(result);
} else {
NotifyManager.info('列表中已经存在的字段已被忽略');
}
};
/**
* 获取将父子列全部平铺后的表格列数据
* @param columns
*/
const getColumn = (columns: Array<any>) => {
const gridColumns = <any>[];
if (columns && columns.length > 0) {
columns.forEach((item: any) => {
childrenHandler(item, gridColumns);
});
return gridColumns;
}
return [];
};
//
const childrenHandler = (item: any, gridColumns: any) => {
if (item.children && item.children.length > 0) {
item.children.forEach((column) => {
childrenHandler(column, gridColumns);
});
} else {
gridColumns.push({ name: item.name, label: item.label });
}
};
defineExpose({
validate: fieldMethodsClass.validate,
setValue: fieldMethodsClass.setValue,
getValue: fieldMethodsClass.getValue,
clearValue: fieldMethodsClass.clearValue,
});
</script>

120
io.sc.platform.lcdp.frontend/src/views/form/grid/Dialog.vue

@ -0,0 +1,120 @@
<template>
<w-dialog ref="dialogRef" :title="title" :maximized="true" :can-maximize="false" body-padding="5px 5px 0px 5px" :buttons="buttonsComputed">
<w-splitter :model-value="20">
<template #before>
<Form></Form>
</template>
<template #after>
<FieldGrid class="pl-1"> </FieldGrid>
</template>
</w-splitter>
<ViewDialog ref="viewDialogRef"></ViewDialog>
</w-dialog>
</template>
<script setup lang="ts">
import { ref, provide, getCurrentInstance, nextTick, computed } from 'vue';
import { Tools, NotifyManager, VueTools } from 'platform-core';
import { FormConfig } from './ts/FormConfig';
import Form from './Form.vue';
import FieldGrid from './FieldGrid.vue';
import ViewDialog from '../ViewDialog.vue';
const dialogRef = ref();
const viewDialogRef = ref();
const emit = defineEmits(['refresh-grid']);
const formConfig = new FormConfig();
const title = ref('新增');
const editFlag = ref(false);
const saveButton = {
icon: 'save',
label: '保存',
loading: false,
click: () => {
formConfig.api.save();
},
};
const viewButton = {
icon: 'visibility',
label: '预览',
click: () => {
view();
},
};
const buttonsComputed = computed(() => {
if (!editFlag.value) {
return [saveButton];
} else {
return [saveButton, viewButton];
}
});
const view = () => {
const rows = formConfig.cf.getFieldGridRef().getRows();
if (!rows || rows.length === 0) {
NotifyManager.warn('字段列表为空');
return;
}
if (Tools.isEmpty(formConfig.editId) || Tools.isEmpty(formConfig.editGridId)) {
NotifyManager.warn('保存后才可预览');
return;
}
const data = formConfig.api.buildSaveData();
viewDialogRef.value.show(data);
};
const show = async (selected: any) => {
dialogRef.value.show();
if (selected) {
editFlag.value = true;
title.value = '编辑';
formConfig.editId = selected.id;
const data = await formConfig.api.fetchFormConfigData();
formConfig.editGridId = data['templateGrid'].id;
nextTick(() => {
const gridConfigData = data['templateGrid'];
const fields = data['templateGridFields'];
formConfig.cf.getTemplateConfigFormRef().setData({ ...data['templateConfig'], ...gridConfigData });
if (gridConfigData.columnTitles) {
const titles = JSON.parse(gridConfigData.columnTitles);
if (Tools.hasOwnProperty(titles, 'value')) {
gridConfigData.columnTitles = titles.value;
} else {
gridConfigData.columnTitles = [];
}
} else {
gridConfigData.columnTitles = [];
}
formConfig.cf.getMainConfigFormRef().setData(gridConfigData);
formConfig.cf.getPageSortConfigFormRef().setData(gridConfigData);
formConfig.cf.getQueryConfigFormRef().setData(gridConfigData);
formConfig.cf.getEditConfigFormRef().setData(gridConfigData);
console.info('222fields=========', fields);
formConfig.cf.getFieldGridRef().setLocalData(fields);
const names = fields.map((item) => item.fieldName);
formConfig.cf.setPrimaryKeyOptions(names);
});
}
};
const hide = () => {
dialogRef.value.hide();
};
defineExpose({
show,
hide,
});
//
const instance = getCurrentInstance();
// API
VueTools.expose2Instance(instance);
const getDialogRef = () => {
return instance;
};
formConfig.cf.getDialogRef = getDialogRef;
provide('formConfig', formConfig);
</script>

318
io.sc.platform.lcdp.frontend/src/views/form/grid/FieldEditDialog.vue

@ -0,0 +1,318 @@
<template>
<w-dialog
ref="dialogRef"
title="字段属性编辑"
width="80%"
height="80%"
body-padding="5px 5px 5px 5px"
:buttons="[
{
label: '确定',
icon: 'beenhere',
click: () => {
save();
},
},
]"
>
<w-form
ref="formRef"
:cols-num="3"
:fields="[
{
type: 'w-form-group',
mode: 'card',
layout: 'form',
headerBgColor: 'green',
colsNum: 2,
colSpan: 'full',
label: '基础属性',
fields: [
{ name: 'fieldName', label: '字段名称', type: 'w-text', readOnlyIf: true },
{
name: 'sqlType',
label: '数据库类型',
type: 'w-text',
readOnlyIf: true,
showIf: () => {
if (formConfig.cm.fieldComeFromValueComputed.value === 'table') {
return true;
}
return false;
},
},
{ name: 'fieldLabel', label: '页面显示名称', type: 'w-text' },
{ name: 'editorFormType', label: '前端组件', type: 'w-select', options: ComponentType.options },
{ name: 'fieldType', label: 'Java类型', type: 'w-select', options: JavaType.options },
{
name: 'fieldLength',
label: '字段长度',
type: 'w-integer',
showIf: (args: any) => {
if (args.form?.getFieldValue('fieldType') === JavaType.type.String.value && formConfig.cm.fieldComeFromValueComputed.value === 'table') {
return true;
}
return false;
},
},
{
name: 'fieldPrecision',
label: '字段精度',
type: 'w-integer',
showIf: (args: any) => {
if (args.form?.getFieldValue('fieldType') === JavaType.type.BigDecimal.value && formConfig.cm.fieldComeFromValueComputed.value === 'table') {
return true;
}
return false;
},
},
{ name: 'optionComeFrom', label: '码值类型', type: 'w-select', options: DictionaryType.options },
{
label: '码值',
name: 'dictionaryOptionValue',
type: 'w-select',
options: [
{ label: 'XX状态', value: 'xx' },
{ label: 'AA类型', value: 'aa' },
],
showIf: (args) => {
if (args.form?.getFieldValue('optionComeFrom') === DictionaryType.type.dictionary.value) {
return true;
}
return false;
},
},
{
label: '码值',
name: 'otherOptionValue',
type: 'w-text',
hideHint: true,
showIf: (args) => {
if (
args.form?.getFieldValue('optionComeFrom') === DictionaryType.type.array.value ||
args.form?.getFieldValue('optionComeFrom') === DictionaryType.type.sql.value
) {
return true;
}
return false;
},
},
],
},
{
type: 'q-space',
colSpan: 'full',
},
{
type: 'q-space',
colSpan: 'full',
},
{
type: 'q-space',
colSpan: 'full',
},
{
type: 'w-form-group',
mode: 'card',
headerBgColor: 'red',
layout: 'form',
colsNum: 1,
label: '查询面板',
fields: [
{
label: '查询面板中显示',
name: 'queryShow',
type: 'w-checkbox',
},
{
label: '默认值',
name: 'queryDefaultValue',
type: 'w-text',
showIf: (args) => {
if (args.form?.getFieldValue('queryShow') === true) {
return true;
}
return false;
},
},
{
label: '是否为必填项',
name: 'queryIsRequired',
type: 'w-select',
defaultValue: false,
options: [
{ label: '是', value: true },
{ label: '否', value: false },
],
showIf: (args) => {
if (args.form?.getFieldValue('queryShow') === true) {
return true;
}
return false;
},
},
{
label: '匹配模式',
name: 'queryOperator',
type: 'w-select',
defaultValue: 'contains',
options: [
{ label: '模糊匹配', value: 'contains' },
{ label: '完全匹配', value: 'equals' },
],
showIf: (args) => {
if (args.form?.getFieldValue('queryShow') === true) {
return true;
}
return false;
},
},
],
},
{
type: 'w-form-group',
mode: 'card',
headerBgColor: 'orange',
layout: 'form',
colsNum: 1,
label: '列表',
fields: [
{
label: '列表中显示',
name: 'tableShow',
type: 'w-checkbox',
},
{
label: '是否支持排序',
name: 'tableSort',
defaultValue: true,
type: 'w-select',
options: [
{ label: '是', value: true },
{ label: '否', value: false },
],
showIf: (args) => {
if (args.form?.getFieldValue('tableShow') === true) {
return true;
}
return false;
},
},
{
label: '列对齐方式',
name: 'tableColumnAlign',
defaultValue: 'left',
type: 'w-select',
options: [
{ label: '居左', value: 'left' },
{ label: '居中', value: 'center' },
{ label: '居右', value: 'right' },
],
showIf: (args) => {
if (args.form?.getFieldValue('tableShow') === true) {
return true;
}
return false;
},
},
{
label: '列宽',
name: 'tableColumnWidth',
type: 'w-integer',
showIf: (args) => {
if (args.form?.getFieldValue('tableShow') === true) {
return true;
}
return false;
},
},
],
},
{
type: 'w-form-group',
mode: 'card',
headerBgColor: 'teal',
layout: 'form',
colsNum: 1,
label: '编辑页面',
fields: [
{
label: '编辑页面中显示',
name: 'editorShow',
type: 'w-checkbox',
disableIf: () => {
return formConfig.cm.fieldComeFromValueComputed.value === 'sql';
},
},
{
label: '默认值',
name: 'editorDefaultValue',
type: 'w-text',
showIf: (args) => {
if (args.form?.getFieldValue('editorShow') === true) {
return true;
}
return false;
},
},
{
label: '是否为必填项',
name: 'editorIsRequired',
type: 'w-select',
options: [
{ label: '是', value: true },
{ label: '否', value: false },
],
showIf: (args) => {
if (args.form?.getFieldValue('editorShow') === true) {
return true;
}
return false;
},
},
],
},
]"
>
</w-form>
</w-dialog>
</template>
<script setup lang="ts">
import { ref, inject, nextTick } from 'vue';
import { FormConfig } from './ts/FormConfig';
import { JavaType } from './ts/JavaType';
import { DictionaryType } from './ts/DictionaryType';
import { ComponentType } from './ts/ComponentType';
const dialogRef = ref();
const formRef = ref();
const formConfig = <FormConfig>inject('formConfig');
const data = ref({});
const save = async () => {
const validate = await formRef.value.validate();
if (validate) {
const formData = formRef.value.getData();
data.value = { ...data.value, ...formData };
formConfig.cf.getFieldGridRef().updateLocalData(data.value);
dialogRef.value.hide();
}
};
const show = (data_) => {
data.value = data_;
dialogRef.value.show();
nextTick(() => {
formRef.value.setData(data_);
});
};
const hide = () => {
dialogRef.value.hide();
};
defineExpose({
show,
hide,
});
</script>

508
io.sc.platform.lcdp.frontend/src/views/form/grid/Form.vue

@ -0,0 +1,508 @@
<template>
<div class="pr-1">
<q-list bordered class="rounded-borders">
<q-expansion-item default-opened expand-separator icon="settings" label="模板配置" header-class="text-green">
<div class="p-1">
<w-form
ref="templateRef"
:cols-num="1"
:fields="[
{
label: '模板名称',
name: 'templateName',
type: 'w-text',
requiredIf: true,
},
{
label: '模板类型',
name: 'templateType',
type: 'w-select',
requiredIf: true,
showIf: false,
defaultValue: 'GRID',
options: [{ label: '表格页面模板', value: 'GRID' }],
},
{
label: '页面加载类型',
name: 'pageLoadType',
type: 'w-select',
requiredIf: true,
showIf: false,
defaultValue: 'CONFIG',
options: [
{ label: '配置加载', value: 'CONFIG' },
{ label: 'JSON字符串加载', value: 'JSON' },
],
},
{
label: '字段来源',
name: 'fieldComeFrom',
type: 'w-select',
requiredIf: true,
defaultValue: 'table',
options: [
{ label: '数据库单表', value: 'table' },
{ label: 'SQL语句', value: 'sql' },
],
onUpdateValue: (args) => {
if (args.value === 'table') {
formConfig.cf.getMainConfigFormRef().getFieldComponent('buttons').setValue(GridToolbar.tableDefaultOptions);
} else if (args.value === 'sql') {
formConfig.cf.getMainConfigFormRef().getFieldComponent('buttons').setValue(GridToolbar.sqlDefaultOptions);
}
},
},
{
label: '数据库表',
name: 'databaseTable',
type: 'w-db-table-select',
requiredIf: true,
showIf: (args) => {
if (args.form?.getFieldValue('fieldComeFrom') === 'sql') {
return false;
}
return true;
},
onUpdateValue: (args) => {
const fields = args.form.getFieldComponent('databaseTable').getFields();
if (fields && fields.length > 0) {
formConfig.fm.setFieldGridData(fields);
const names = fields.map((item) => item.name);
formConfig.cf.setPrimaryKeyOptions(names);
}
},
},
{
label: 'SQL',
name: 'sql',
type: 'w-code-mirror',
lang: 'sql',
toolbar: false,
requiredIf: true,
hint: `当查询面板配置了字段时,需要把查询条件通过占位符放到sql中,在页面中真正查询数据时才能带上用户输入的查询条件,示例:select u.loginname_,r.name_ from sys_user_role ur join sys_user u on ur.user_id_=u.id_ join sys_role r on ur.role_id_=r.id_ where u.loginname_='#{loginname_}' and r.name_ like '%#{name_}%'`,
hideHint: true,
showIf: (args) => {
if (args.form?.getFieldValue('fieldComeFrom') === 'sql') {
return true;
}
return false;
},
slot: {
append: {
componentType: 'q-btn',
attrs: {
dense: true,
label: '查询',
icon: 'search',
color: 'primary',
onClick: () => {
const sql = templateRef.getFieldValue('sql');
formConfig.api.loadFields(sql);
},
},
},
},
},
]"
>
</w-form>
</div>
</q-expansion-item>
<q-expansion-item default-opened expand-separator icon="grid_on" label="表格配置" header-class="text-light-blue">
<div class="p-1">
<div class="flex justify-end p-2">
<q-toggle v-model="mainConfigToggleModelValue" dense label="全部配置" />
</div>
<w-form
ref="mainConfigFormRef"
:cols-num="1"
:fields="[
{ label: '表格标题', name: 'title', type: 'w-text' },
{
label: '数据主键',
name: 'primaryKey',
type: 'w-select',
options: primaryKeyOptions,
},
{
label: '表格按钮',
name: 'buttons',
defaultValue: GridToolbar.tableDefaultOptions,
type: markRawGridToolbarSelect,
},
{
type: 'w-form-group',
layout: 'form',
colsNum: 2,
fields: [
{
label: '显示序号',
name: 'sortNo',
type: 'w-checkbox',
defaultValue: true,
},
{
label: '显示复选框',
name: 'checkboxSelection',
type: 'w-checkbox',
defaultValue: true,
},
],
},
{
label: '多表头',
name: 'moreColumnTitle',
type: 'w-select',
defaultValue: false,
options: [
{ label: '启用', value: true },
{ label: '禁用', value: false },
],
},
{
label: '多表头配置',
name: 'columnTitles',
requiredIf: true,
type: markRawColumnTitleConfig,
showIf: (args) => {
if (args.form?.getFieldValue('moreColumnTitle')) {
return true;
}
return false;
},
},
{
label: '紧凑模式',
name: 'dense',
type: 'w-checkbox-group',
defaultValue: ['denseToolbar'],
simple: false,
showIf: () => {
if (mainConfigToggleModelValue) {
return true;
}
return false;
},
options: [
{ label: '整体紧凑', value: 'dense' },
{ label: '按钮栏紧凑', value: 'denseToolbar' },
{ label: '标题紧凑', value: 'denseHeader' },
{ label: '内容紧凑', value: 'denseBody' },
{ label: '分页栏紧凑', value: 'denseBottom' },
],
},
{
label: '冻结列数',
name: 'stickyNum',
type: 'w-select',
defaultValue: 0,
showIf: () => {
if (mainConfigToggleModelValue) {
return true;
}
return false;
},
options: [
{ label: '不冻结', value: 0 },
{ label: '冻结1列', value: 1 },
{ label: '冻结2列', value: 2 },
{ label: '冻结3列', value: 3 },
{ label: '冻结4列', value: 4 },
{ label: '冻结5列', value: 5 },
{ label: '冻结6列', value: 6 },
{ label: '冻结7列', value: 7 },
{ label: '冻结8列', value: 8 },
{ label: '冻结8列', value: 9 },
{ label: '冻结10列', value: 10 },
],
},
{
label: '表格模式',
name: 'tree',
type: 'w-select',
defaultValue: false,
showIf: () => {
if (mainConfigToggleModelValue) {
return true;
}
return false;
},
options: [
{ label: '普通表格', value: false },
{ label: '树形表格', value: true },
],
},
{
label: '数据外键',
name: 'foreignKey',
type: 'w-text',
showIf: (args) => {
if (mainConfigToggleModelValue && args.form?.getFieldValue('tree')) {
return true;
}
return false;
},
defaultValue: 'parent',
hint: `树形表格模式时,该字段为构建树数据的关系字段`,
},
{
label: '树形表格数据关系',
name: 'treeRelationship',
type: 'w-select',
defaultValue: 'parent',
showIf: (args) => {
if (mainConfigToggleModelValue && args.form?.getFieldValue('tree')) {
return true;
}
return false;
},
options: [
{ label: 'parent', value: 'parent' },
{ label: 'children', value: 'children' },
],
},
{
label: '树形表格默认全部展开',
name: 'treeDefaultExpandAll',
type: 'w-checkbox',
showIf: (args) => {
if (mainConfigToggleModelValue && args.form?.getFieldValue('tree')) {
return true;
}
return false;
},
},
{
label: '数据操作URL前缀',
name: 'dataUrl',
type: 'w-text',
showIf: false,
defaultValue: '',
},
{
label: '查询URL',
name: 'fetchDataUrl',
type: 'w-text',
showIf: false,
defaultValue: 'api/jdbc/list',
},
{
label: '新增URL',
name: 'addDataUrl',
type: 'w-text',
showIf: false,
defaultValue: 'api/jdbc/add',
},
{
label: '编辑URL',
name: 'editDataUrl',
type: 'w-text',
showIf: false,
defaultValue: 'api/jdbc/edit',
},
{
label: '删除URL',
name: 'removeDataUrl',
type: 'w-text',
showIf: false,
defaultValue: 'api/jdbc/delete',
},
{
label: '自动加载数据',
name: 'autoFetchData',
type: 'w-checkbox',
showIf: false,
defaultValue: true,
},
]"
>
</w-form>
</div>
</q-expansion-item>
<q-expansion-item expand-separator icon="auto_stories" label="分页排序" header-class="text-purple">
<div class="p-1">
<w-form
ref="pageSortConfigFormRef"
:cols-num="1"
:fields="[
{
label: '默认排序字段',
name: 'defaultSortBy',
type: 'w-text',
hint: `示例:单字段默认排序:['username'],多字段默认排序:['username', '-date'],其中'-date'的中'-'代表倒序`,
},
{
label: '排序方式',
name: 'descending',
type: 'w-select',
defaultValue: false,
options: [
{ label: '正序', value: false },
{ label: '倒序', value: true },
],
},
{
label: '是否分页',
name: 'pageable',
type: 'w-select',
defaultValue: true,
options: [
{ label: '是', value: true },
{ label: '否', value: false },
],
},
{
label: '每页显示行数',
name: 'rowsPerPage',
type: 'w-number',
defaultValue: 10,
showIf: (args) => {
if (args.form?.getFieldValue('pageable')) {
return true;
}
return false;
},
},
{
label: '后端使用的初始页码',
name: 'reqPageStart',
type: 'w-select',
defaultValue: 1,
options: [
{ label: '从1开始', value: 1 },
{ label: '从0开始', value: 0 },
],
showIf: (args) => {
// if (
// args.form?.getFieldValue('pageable')
// ) {
// return true;
// }
return false;
},
},
]"
>
</w-form>
</div>
</q-expansion-item>
<q-expansion-item expand-separator icon="find_in_page" label="查询面板" header-class="text-teal">
<div class="p-1">
<w-form
ref="queryConfigFormRef"
:cols-num="1"
:fields="[
{
label: '一行显示条件个数',
name: 'queryFormColsNum',
type: 'w-select',
defaultValue: 0,
options: [
{ label: '自适应', value: 0 },
{ label: '1个', value: 1 },
{ label: '2个', value: 2 },
{ label: '3个', value: 3 },
{ label: '4个', value: 4 },
{ label: '5个', value: 5 },
{ label: '6个', value: 6 },
],
},
{
label: '查询条件默认行数',
name: 'queryFormRowNum',
type: 'w-number',
defaultValue: 1,
},
]"
>
</w-form>
</div>
</q-expansion-item>
<q-expansion-item expand-separator icon="edit_document" label="编辑页面" header-class="text-orange">
<div class="p-1">
<w-form
ref="editConfigFormRef"
:cols-num="1"
:fields="[
{
label: '窗口宽度',
name: 'editorWidth',
type: 'w-text',
hint: '不设置根据内容自动撑;支持设置百分比,示例:80%;也支持设置像素点,示例:500px',
},
{
label: '窗口高度',
name: 'editorHeight',
type: 'w-text',
hint: '不设置根据内容自动撑;支持设置百分比,示例:80%;也支持设置像素点,示例:500px',
},
{
label: '一行显示元素个数',
name: 'editorFormColsNum',
type: 'w-select',
defaultValue: 1,
options: [
{ label: '自适应', value: 0 },
{ label: '1个', value: 1 },
{ label: '2个', value: 2 },
{ label: '3个', value: 3 },
{ label: '4个', value: 4 },
{ label: '5个', value: 5 },
{ label: '6个', value: 6 },
],
},
]"
>
</w-form>
</div>
</q-expansion-item>
</q-list>
</div>
</template>
<script setup lang="ts">
import { inject, ref, computed, markRaw } from 'vue';
import { Options } from 'platform-core';
import { FormConfig } from './ts/FormConfig';
import GridToolbarSelect from '../components/GridToolbarSelect.vue';
import { GridToolbar } from '@/views/form/components/GridToolbar';
import ColumnTitleConfig from './ColumnTitleConfig.vue';
const markRawGridToolbarSelect = markRaw(GridToolbarSelect);
const markRawColumnTitleConfig = markRaw(ColumnTitleConfig);
const templateRef = ref();
const mainConfigFormRef = ref();
const pageSortConfigFormRef = ref();
const queryConfigFormRef = ref();
const editConfigFormRef = ref();
const mainConfigToggleModelValue = ref(false);
const primaryKeyOptions = ref(<any>[]);
const formConfig = <FormConfig>inject('formConfig');
const getTemplateConfigFormRef = () => {
return templateRef.value;
};
const getMainConfigFormRef = () => {
return mainConfigFormRef.value;
};
const getPageSortConfigFormRef = () => {
return pageSortConfigFormRef.value;
};
const getQueryConfigFormRef = () => {
return queryConfigFormRef.value;
};
const getEditConfigFormRef = () => {
return editConfigFormRef.value;
};
const setPrimaryKeyOptions = (options: Array<any>) => {
primaryKeyOptions.value = options;
};
formConfig.cf.getTemplateConfigFormRef = getTemplateConfigFormRef;
formConfig.cf.getMainConfigFormRef = getMainConfigFormRef;
formConfig.cf.getPageSortConfigFormRef = getPageSortConfigFormRef;
formConfig.cf.getQueryConfigFormRef = getQueryConfigFormRef;
formConfig.cf.getEditConfigFormRef = getEditConfigFormRef;
formConfig.cf.setPrimaryKeyOptions = setPrimaryKeyOptions;
</script>

52
io.sc.platform.lcdp.frontend/src/views/form/grid/ts/ComponentType.ts

@ -0,0 +1,52 @@
export class ComponentType {
static type = {
text: { label: '文本框', value: 'text', component: 'w-text' },
textarea: { label: '文本域', value: 'textarea', component: 'w-textarea' },
checkbox: { label: '复选框', value: 'checkbox', component: 'w-checkbox' },
codeMirror: { label: '代码编辑器', value: 'codeMirror', component: 'w-code-mirror' },
date: { label: '日期', value: 'date', component: 'w-date' },
dateRange: { label: '日期范围', value: 'dateRange', component: 'w-date-range' },
icon: { label: '图标选择', value: 'icon', component: 'w-icon' },
number: { label: '数字框', value: 'number', component: 'w-number' },
integer: { label: '整数框', value: 'integer', component: 'w-integer' },
radio: { label: '单选按钮', value: 'radio', component: 'w-radio' },
select: { label: '下拉框', value: 'select', component: 'w-select' },
multipleSelect: { label: '多选下拉框', value: 'multipleSelect', component: 'w-select' },
userSelect: { label: '用户选择', value: 'userSelect', component: 'w-user-select' },
mulitpleUserSelect: { label: '用户选择(多选)', value: 'mulitpleUserSelect', component: 'w-user-select' },
orgSelect: { label: '机构选择', value: 'orgSelect', component: 'w-org-select' },
mulitpleOrgSelect: { label: '机构选择(多选)', value: 'mulitpleOrgSelect', component: 'w-org-select' },
roleSelect: { label: '角色选择', value: 'roleSelect', component: 'w-role-select' },
mulitpleRoleSelect: { label: '角色选择(多选)', value: 'mulitpleRoleSelect', type: 'w-role-select' },
dbTableSelect: { label: '数据表选择', value: 'dbTableSelect', component: 'w-db-table-select' },
mulitpleDbTableSelect: { label: '数据表选择(多选)', value: 'mulitpleDbTableSelect', component: 'w-db-table-select' },
};
/**
*
*/
static options: Array<any> = Object.values(this.type);
/**
*
*/
static multipleSelectTypes: Array<any> = [
this.type.multipleSelect,
this.type.mulitpleUserSelect,
this.type.mulitpleOrgSelect,
this.type.mulitpleRoleSelect,
this.type.mulitpleDbTableSelect,
];
/**
*
*/
static selectTypes: Array<any> = [
this.type.select,
this.type.userSelect,
this.type.orgSelect,
this.type.roleSelect,
this.type.dbTableSelect,
...this.multipleSelectTypes,
];
}

21
io.sc.platform.lcdp.frontend/src/views/form/grid/ts/ComputedManager.ts

@ -0,0 +1,21 @@
import { computed } from 'vue';
import { Tools } from 'platform-core';
import { FormConfig } from './FormConfig';
export class ComputedManager {
form: FormConfig;
constructor(form_: FormConfig) {
this.form = form_;
}
fieldComeFromValueComputed = computed(() => {
if (this.form.cf.getTemplateConfigFormRef) {
const ref = this.form.cf.getTemplateConfigFormRef();
if (ref && !Tools.isEmpty(ref.getFieldValue('fieldComeFrom'))) {
return ref.getFieldValue('fieldComeFrom');
}
}
return undefined;
});
}

10
io.sc.platform.lcdp.frontend/src/views/form/grid/ts/DictionaryType.ts

@ -0,0 +1,10 @@
export class DictionaryType {
static type = {
none: { label: '无', value: 'none' },
dictionary: { label: '数据字典', value: 'dictionary' },
array: { label: '自定义数组', value: 'array' },
sql: { label: 'Sql', value: 'sql' },
};
static options: Array<any> = Object.values(this.type);
}

51
io.sc.platform.lcdp.frontend/src/views/form/grid/ts/FormConfig.ts

@ -0,0 +1,51 @@
import type { ComponentFunctionsType } from './type/ComponentFunctionsType';
import { RequestApi } from './RequestApi';
import { ComputedManager } from './ComputedManager';
import { FunctionManager } from './FunctionManager';
export class FormConfig {
/**
* ID
*/
editId: string = '';
/**
* ID
*/
editGridId: string = '';
/**
*
*/
schemas: Array<any> = [];
/**
*
*/
cm: ComputedManager;
/**
*
*/
fm: FunctionManager;
/**
* API管理器
*/
api: RequestApi;
/**
* vue文件中定义的函数管理器
*/
cf: ComponentFunctionsType = {
getDialogRef: () => {},
getFieldGridRef: () => {},
getTemplateConfigFormRef: () => {},
getMainConfigFormRef: () => {},
getPageSortConfigFormRef: () => {},
getQueryConfigFormRef: () => {},
getEditConfigFormRef: () => {},
setPrimaryKeyOptions: () => {},
};
constructor() {
this.api = new RequestApi(this);
this.cm = new ComputedManager(this);
this.fm = new FunctionManager(this);
this.api.getSchemas();
}
}

204
io.sc.platform.lcdp.frontend/src/views/form/grid/ts/FunctionManager.ts

@ -0,0 +1,204 @@
import { Tools } from 'platform-core';
import { FormConfig } from './FormConfig';
import { ComponentType } from './ComponentType';
import { JavaType } from './JavaType';
export class FunctionManager {
form: FormConfig;
constructor(form_: FormConfig) {
this.form = form_;
}
/**
*
* @param fields
*/
setFieldGridData(fields: Array<any>) {
if (this.form.cf.getFieldGridRef) {
if (this.form.cm.fieldComeFromValueComputed.value === 'table') {
const data = this.buildTableTypeFields(fields);
this.form.cf.getFieldGridRef().setLocalData(data);
} else if (this.form.cm.fieldComeFromValueComputed.value === 'sql') {
const data = this.buildSqlTypeFields(fields);
this.form.cf.getFieldGridRef().setLocalData(data);
}
}
}
private buildSqlTypeFields(fields: Array<any>) {
const result = <any>[];
fields.forEach((item: any) => {
const javaType = this.getFieldType(item['javaType']);
const autoData = this.buildAutoData(item['name']);
const componentType = this.getComponentType(item['javaType']);
const field = {
tableName: undefined,
fieldName: item['name'],
fieldLabel: undefined,
fieldType: javaType, // 字段类型
fieldLength: javaType === 'String' ? item['size'] : undefined, // 字段长度
fieldPrecision: undefined, // 字段精度
fieldIsSelect: false, // 字段为选项值
optionComeFrom: 'none', // 选项值来源
dictionaryOptionValue: '', // 数据字典选项值
otherOptionValue: '', // 其他类型选项值
addValueType: 'NONE', // 新增时系统自动填充类型
editOverride: undefined, // 修改时覆盖系统自动填充值
// 查询面板
queryShow: false, // 查询面板中显示
queryFormType: componentType, // 使用的表单类型
queryDefaultValue: '', // 默认值
queryIsrequiredIf: false, // 必填项
queryOperator: '', // 匹配模式
// 列表
tableShow: true, // 列表中显示
tableSort: false, // 支持排序
tableColumnAlign: '', // 列对齐方式
tableColumnWidth: undefined, // 列宽
// 新增页面
editorShow: false, // 新增编辑页面中显示
editorFormType: componentType, // 使用的表单类型
editorDefaultValue: '', // 默认值
editorIsRequired: false, // 必填项
};
result.push({ ...field, ...autoData });
});
return result;
}
private buildTableTypeFields(fields: Array<any>) {
const result = <any>[];
fields.forEach((item: any) => {
// 设置主键
if (item['partOfPrimaryKey'] && this.form.cf.getMainConfigFormRef) {
this.form.cf.getMainConfigFormRef().setFieldValue('primaryKey', item['name']);
}
const javaType = this.getFieldType(item['javaType']);
const autoData = this.buildAutoData(item['name']);
const componentType = this.getComponentType(item['javaType']);
const field = {
tableName: this.form.cf.getTemplateConfigFormRef ? this.form.cf.getTemplateConfigFormRef().getFieldValue('databaseTable') : undefined,
fieldName: item['name'],
fieldLabel: item['remarks'],
sqlType: item['sqlType'],
width: item['width'],
fieldType: javaType, // 字段类型
fieldLength: javaType === 'String' ? item['size'] : undefined, // 字段长度
fieldPrecision: undefined, // 字段精度
fieldIsSelect: false, // 字段为选项值
optionComeFrom: 'none', // 选项值来源
dictionaryOptionValue: '', // 数据字典选项值
otherOptionValue: '', // 其他类型选项值
addValueType: 'NONE', // 新增时系统自动填充类型
editOverride: undefined, // 修改时覆盖系统自动填充值
// 查询面板
queryShow: false, // 查询面板中显示
queryFormType: componentType, // 使用的表单类型
queryDefaultValue: '', // 默认值
queryIsrequiredIf: false, // 必填项
queryOperator: '', // 匹配模式
// 列表
tableShow: true, // 列表中显示
tableSort: false, // 支持排序
tableColumnAlign: '', // 列对齐方式
tableColumnWidth: undefined, // 列宽
// 新增页面
editorShow: true, // 新增编辑页面中显示
editorFormType: componentType, // 使用的表单类型
editorDefaultValue: '', // 默认值
editorIsRequired: false, // 必填项
};
result.push({ ...field, ...autoData });
});
return result;
}
private buildAutoData(name: string) {
if (name.toUpperCase() === 'ID' || name.toUpperCase() === 'ID_') {
return {
addValueType: 'UUID',
editOverride: false,
tableShow: false,
editorShow: false,
};
} else if (name.toUpperCase() === 'JPA_VERSION' || name.toUpperCase() === 'JPA_VERSION_') {
return {
editOverride: false,
tableShow: false,
editorShow: false,
};
} else if (name.toUpperCase() === 'DATA_COME_FROM' || name.toUpperCase() === 'DATA_COME_FROM_') {
return {
addValueType: 'DCF_INPUT',
editOverride: false,
tableShow: false,
editorShow: false,
};
} else if (name.toUpperCase() === 'CREATOR' || name.toUpperCase() === 'CREATOR_') {
return {
addValueType: 'CURR_USER',
editOverride: false,
tableShow: false,
editorShow: false,
};
} else if (name.toUpperCase() === 'CREATE_DATE' || name.toUpperCase() === 'CREATE_DATE_') {
return {
addValueType: 'CURR_DATE',
editOverride: false,
tableShow: false,
editorShow: false,
};
} else if (name.toUpperCase() === 'LAST_MODIFIER' || name.toUpperCase() === 'LAST_MODIFIER_') {
return {
addValueType: 'CURR_USER',
editOverride: true,
tableShow: false,
editorShow: false,
};
} else if (name.toUpperCase() === 'LAST_MODIFYDATE' || name.toUpperCase() === 'LAST_MODIFYDATE_') {
return {
addValueType: 'CURR_DATE',
editOverride: true,
tableShow: false,
editorShow: false,
};
} else if (name.toUpperCase() === 'CORP_CODE' || name.toUpperCase() === 'CORP_CODE_') {
return {
addValueType: 'CURR_CORP',
editOverride: true,
tableShow: false,
editorShow: false,
};
}
return {};
}
private getFieldType(javaType: string) {
if (javaType === 'java.lang.Integer' || javaType === 'java.lang.Long') {
return JavaType.type.Integer.value;
} else if (javaType === 'java.sql.Timestamp') {
return JavaType.type.Date.value;
} else if (javaType === 'java.lang.Boolean') {
return JavaType.type.Boolean.value;
} else if (javaType === 'java.math.BigDecimal') {
return JavaType.type.BigDecimal.value;
} else {
return JavaType.type.String.value;
}
}
private getComponentType(javaType: string) {
if (javaType === 'java.lang.Integer' || javaType === 'java.lang.Long') {
return ComponentType.type.integer.value;
} else if (javaType === 'java.sql.Timestamp') {
return ComponentType.type.date.value;
} else if (javaType === 'java.lang.Boolean') {
return ComponentType.type.select.value;
} else if (javaType === 'java.math.BigDecimal') {
return ComponentType.type.number.value;
} else {
return ComponentType.type.text.value;
}
}
}

11
io.sc.platform.lcdp.frontend/src/views/form/grid/ts/JavaType.ts

@ -0,0 +1,11 @@
export class JavaType {
static type = {
String: { label: '字符串', value: 'String' },
Integer: { label: '整数', value: 'Integer' },
BigDecimal: { label: '小数', value: 'BigDecimal' },
Date: { label: '日期', value: 'Date' },
Boolean: { label: '布尔', value: 'Boolean' },
};
static options: Array<any> = Object.values(this.type);
}

170
io.sc.platform.lcdp.frontend/src/views/form/grid/ts/RequestApi.ts

@ -0,0 +1,170 @@
import { toRaw } from 'vue';
import { axios, Environment, NotifyManager } from 'platform-core';
import { FormConfig } from './FormConfig';
import { ComponentType } from './ComponentType';
export class RequestApi {
form: FormConfig;
constructor(form_: FormConfig) {
this.form = form_;
}
getSchemas() {
axios({
method: 'GET',
url: Environment.apiContextPath('api/template/config/schemas'),
}).then((resp) => {
this.form.schemas = [];
resp.data.forEach((item: any) => {
this.form.schemas.push({ label: item.name, value: item.name });
});
});
}
loadFields(sql: string) {
const requestParams = {
method: 'POST',
headers: { 'content-type': 'text/plain;charset=utf-8;' },
data: sql,
url: Environment.apiContextPath('api/jdbc/fetchMetaDataBySql'),
};
axios(requestParams)
.then((resp: any) => {
const columns = <any>[];
const gridRef = this.form.cf.getFieldGridRef();
const oldColumns = gridRef.getRows();
// if (oldColumns.length > 0) {
// resp.data.forEach((item) => {
// const column = oldColumns.find((oldColumn) => {
// return oldColumn.fieldName === item.columnName;
// });
// if (!Tools.isEmpty(column)) {
// columns.push({
// id: item.id,
// parent: item.parent,
// name: item.columnName,
// fieldName: item.columnName,
// queryShow: item.queryShow || false,
// tableShow: item.tableShow || false,
// ...column,
// });
// } else {
// columns.push({
// id: item.id,
// parent: item.parent,
// name: item.columnName,
// fieldName: item.columnName,
// queryShow: item.queryShow || false,
// tableShow: item.tableShow || false,
// });
// }
// });
// gridRef.setLocalData(columns, 'sql');
// } else {
resp.data.forEach((item) => {
columns.push({
id: item.id,
parent: item.parent,
name: item.columnName,
fieldName: item.columnName,
queryShow: item.parent === 'where_field' || false,
optionComeFrom: 'none', // 选项值来源
addValueType: 'NONE', // 新增时系统自动填充类型
// 查询表单
queryFormtype: ComponentType.type.text.value, // 使用的表单类型
queryDefaultValue: '', // 默认值
queryIsrequiredIf: false, // 必填项
queryOperator: '', // 匹配模式
// 列表
tableShow: true, // 列表中显示
tableSort: false, // 支持排序
tableColumnAlign: '', // 列对齐方式
tableColumnWidth: undefined, // 列宽
// 新增页面
editorShow: false, // 新增编辑页面中显示
editorFormType: ComponentType.type.text.value, // 使用的表单类型
editorDefaultValue: '', // 默认值
editorIsRequired: false, // 必填项
});
});
gridRef.setLocalData(columns);
const names = columns.map((item) => item.fieldName);
this.form.cf.setPrimaryKeyOptions(names);
// }
})
.catch((error: any) => {
NotifyManager.error('SQL执行报错');
});
}
async fetchFormConfigData() {
const resp = await axios.get(Environment.apiContextPath('api/template/config/fetch/') + this.form.editId);
if (resp && resp.data) {
return resp.data;
}
return undefined;
}
buildSaveData() {
const templateFormData = this.form.cf.getTemplateConfigFormRef().getData();
const mainFormData = this.form.cf.getMainConfigFormRef().getData();
const pageSortFormData = this.form.cf.getPageSortConfigFormRef().getData();
const queryFormData = this.form.cf.getQueryConfigFormRef().getData();
const editFormData = this.form.cf.getEditConfigFormRef().getData();
const rows = this.form.cf.getFieldGridRef().getRows();
rows.forEach((item: any, index: number) => {
item['sortNo'] = index + 1;
if (item['editorFormType'] === ComponentType.type.date.value) {
// 当前端组件为日期类型时,查询面板的组件替换为日期范围
item['queryFormType'] = ComponentType.type.dateRange.value;
} else {
// 其他组件通用
item['queryFormType'] = item['editorFormType'];
}
});
const requestData = {
templateConfig: { ...templateFormData, ...{ id: this.form.editId } },
templateGrid: { ...templateFormData, ...mainFormData, ...pageSortFormData, ...queryFormData, ...editFormData, id: this.form.editGridId },
templateGridFields: toRaw(rows),
};
requestData.templateGrid['columnTitles'] = JSON.stringify({ value: mainFormData['columnTitles'] });
return requestData;
}
async save() {
const rows = this.form.cf.getFieldGridRef().getRows();
if (!rows || rows.length === 0) {
NotifyManager.warn('字段列表为空');
return;
}
if (!(await this.formValidate())) {
return;
}
const requestData = this.buildSaveData();
axios({
method: 'POST',
url: Environment.apiContextPath('api/template/config') + (this.form.editId ? '/edit' : '/add'),
data: requestData,
})
.then((resp) => {
// 关闭窗口,刷新表格
this.form.cf.getDialogRef().hide();
this.form.cf.getDialogRef().emit('refresh-grid');
NotifyManager.info('保存成功');
})
.catch((error) => {
console.info('error====', error);
NotifyManager.error('保存失败');
});
}
private async formValidate() {
const templateConfigFormValidate = await this.form.cf.getTemplateConfigFormRef().validate();
const mainConfigFormValidate = await this.form.cf.getMainConfigFormRef().validate();
const pageSortFormValidate = await this.form.cf.getPageSortConfigFormRef().validate();
const queryFormValidate = await this.form.cf.getQueryConfigFormRef().validate();
const editFormValidate = await this.form.cf.getEditConfigFormRef().validate();
return templateConfigFormValidate && mainConfigFormValidate && pageSortFormValidate && queryFormValidate && editFormValidate;
}
}

10
io.sc.platform.lcdp.frontend/src/views/form/grid/ts/type/ComponentFunctionsType.ts

@ -0,0 +1,10 @@
export type ComponentFunctionsType = {
getDialogRef: Function;
getFieldGridRef: Function;
getTemplateConfigFormRef: Function;
getMainConfigFormRef: Function;
getPageSortConfigFormRef: Function;
getQueryConfigFormRef: Function;
getEditConfigFormRef: Function;
setPrimaryKeyOptions: Function;
}
Loading…
Cancel
Save