17 changed files with 2650 additions and 0 deletions
@ -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) { |
||||
|
// 存在父级节点,得到父级节点的列下标 |
||||
|
// 找到parent相同且tdIndex小于其的一共多少列 |
||||
|
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> |
@ -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> |
@ -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> |
@ -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]; |
||||
|
} |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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, |
||||
|
]; |
||||
|
} |
@ -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; |
||||
|
}); |
||||
|
} |
@ -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); |
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
} |
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -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); |
||||
|
} |
@ -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; |
||||
|
} |
||||
|
} |
@ -0,0 +1,10 @@ |
|||||
|
export type ComponentFunctionsType = { |
||||
|
getDialogRef: Function; |
||||
|
getFieldGridRef: Function; |
||||
|
getTemplateConfigFormRef: Function; |
||||
|
getMainConfigFormRef: Function; |
||||
|
getPageSortConfigFormRef: Function; |
||||
|
getQueryConfigFormRef: Function; |
||||
|
getEditConfigFormRef: Function; |
||||
|
setPrimaryKeyOptions: Function; |
||||
|
} |
Loading…
Reference in new issue