Files
geg-gas-web/src/views/form/design/components/BasicConfigStep.vue
suguangxu 202022a3a5 优化、改造部分代码:
1.登录时是否输入租户码默认是需要输入。
2.切换租户的部分逻辑抽取成独立工具类。
3.表单编辑模块整合部分代码,将两个tabpane抽出来成独立文件。
4.修正bug-表单的列表配置为空时编辑页面报错,现改成为空时赋值{}。
5.系统数据迁移复制功能:去掉一些无用的代码;改成多租户时才允许以租户模式导入。
2025-06-13 15:12:51 +08:00

590 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="step1">
<div class="step1-form">
<BasicForm @register="register" />
</div>
<template v-if="designType === 'data'">
<Divider />
<p>{{ t('添加数据库表(请先选择数据库-第一个选择的为主库)') }}</p>
<div>
<a-table
:columns="columns"
:data-source="generatorConfig?.tableConfigs"
:pagination="false"
>
<template #bodyCell="{ column, record, index }">
<template v-if="column.key === 'order'">
<span>
{{ index + 1 }}
</span>
</template>
<template v-if="column.key === 'isMain'">
<span>
<a-tag :color="record.isMain ? 'blue' : 'orange'">
{{ record.isMain ? t('主表') : t('附表') }}
</a-tag>
</span>
</template>
<template v-else-if="column.key === 'relationField'">
<template v-if="index > 0">
<Select
style="width: 200px"
v-model:value="record[column.key]"
:placeholder="t('请选择附表关联主表字段')"
>
<SelectOption
v-for="(name, idx) in selectOptions[record.tableName]"
:key="idx"
:value="name"
>
{{ name }}
</SelectOption>
</Select>
</template>
</template>
<template v-else-if="column.key === 'relationTableField'">
<template v-if="index > 0">
<Select
style="width: 200px"
v-model:value="record[column.key]"
:placeholder="t('请选择主表字段')"
>
<SelectOption
v-for="(name, idx) in selectOptions[mainTable]"
:key="idx"
:value="name"
>
{{ name }}
</SelectOption>
</Select>
</template>
</template>
<template v-else-if="column.key === 'action'">
<DeleteTwoTone two-tone-color="#ff8080" @click="remove(index)" />
</template>
</template>
</a-table>
<a-button type="dashed" block @click="add">
<PlusOutlined />
{{ t('新增') }}
</a-button>
</div>
<SelectDatabase @register="registerModal" @success="handleSelectSuccess" />
</template>
</div>
</template>
<script lang="ts" setup>
import { computed, inject, Ref, ref, toRaw, watch } from 'vue';
import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
import { getDatabaselinkMultiTableColumns } from '/@/api/system/databaselink';
import { getAuthList } from '/@/api/system/authorize';
import { Divider } from 'ant-design-vue';
import { PlusOutlined, DeleteTwoTone } from '@ant-design/icons-vue';
import { useModal } from '/@/components/Modal';
import { SelectDatabase } from '/@/components/CreateCodeStep';
import { Select } from 'ant-design-vue';
import { debounce, uniqBy } from 'lodash-es';
import { TableConfig } from '/@/model/generator/tableConfig';
import { CustomFormConfig, GeneratorConfig } from '/@/model/generator/generatorConfig';
import { useMessage } from '/@/hooks/web/useMessage';
import { TableInfo, FieldInfo, upperFieldDb } from '/@/components/Designer';
import { JavaTypeConvertTsType } from '/@/utils/helper/designHelper';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();
const SelectOption = Select.Option;
const { notification } = useMessage();
const dataAuthPlaceholder = computed(() => {
return generatorConfig!.isDataAuth ? t('请选择已有通用数据权限') : t('请先启用数据权限');
});
const dataAuthHelpMessage = `
1.启用数据权限会判断主表是否包含RuleUserlD字段如果存在则不进行表结构修改如果不存在则会对主表进行字段添加。
2.RuleUserlD主要用来控制每一条记录的权限所属人新增时默认将当前登录认作为权限所属人。
3.在表单设计中会添加“批量设置权限所属人”功能启用后,拥有该按钮权限的人员可以设置每一条记录的权限所属人。
`;
const formSchemaData: FormSchema[] = [
{
field: 'name',
label: t('表单名称'),
required: true,
component: 'Input',
colProps: {
span: 12,
},
componentProps: {
placeholder: t('请输入表单名称'),
onChange: debounce((val: ChangeEvent) => {
customFormConfig!.name = val.target.value;
}, 200),
},
},
{
field: 'category',
label: t('表单分类'),
component: 'DicSelect',
required: true,
componentProps: {
placeholder: t('请选择表单分类'),
itemId: '1419276800524424444',
isShowAdd: false,
onChange: debounce((id) => {
customFormConfig!.category = id;
}, 200),
},
colProps: { span: 12 },
},
{
field: 'remark',
label: t('功能描述'),
component: 'Input',
colProps: { span: 12 },
componentProps: {
placeholder: t('请输入功能描述'),
onChange: debounce((val: ChangeEvent) => {
customFormConfig!.remark = val.target.value;
}, 200),
},
},
{
field: 'databaseId',
label: t('数据库'),
component: 'DbSelect',
required: true,
colProps: { span: 12 },
componentProps: {
placeholder: t('请选择数据库'),
onChange: debounce((val, option) => {
generatorConfig!.databaseId = val;
if (option) isFieldUpper.value = upperFieldDb.includes(option.dbType);
mainTableName.value = isFieldUpper.value
? mainTableName.value.toUpperCase()
: mainTableName.value;
}, 200),
},
},
{
field: 'isDataAuth',
label: t('数据权限'),
component: 'Switch',
required: false,
colProps: { span: 12 },
helpMessage: dataAuthHelpMessage,
helpComponentProps: { maxWidth: '400px' },
componentProps: {
checkedValue: true,
unCheckedValue: false,
onChange: (val) => {
if (!val) {
setFieldsValue({ dataAuthList: [] });
generatorConfig!.dataAuthList = [];
}
generatorConfig!.isDataAuth = val;
},
},
},
{
field: 'dataAuthList',
label: t('权限选择'),
component: 'ApiSelect',
required: false,
colProps: { span: 12 },
componentProps: {
mode: 'multiple',
placeholder: dataAuthPlaceholder,
api: getAuthList,
labelField: 'name',
valueField: 'id',
getPopupContainer: () => document.body,
onChange: (val) => {
generatorConfig!.dataAuthList = val;
},
},
dynamicDisabled: ({ values }) => {
return !values.isDataAuth;
},
},
];
const formSchema: FormSchema[] = [
{
field: 'name',
label: t('表单名称'),
required: true,
component: 'Input',
colProps: {
span: 12,
},
componentProps: {
placeholder: t('请输入表单名称'),
onChange: debounce((val: ChangeEvent) => {
customFormConfig!.name = val.target.value;
}, 200),
},
},
{
field: 'category',
label: t('表单分类'),
component: 'DicSelect',
required: true,
componentProps: {
placeholder: t('请选择表单分类'),
itemId: '1419276800524424444',
isShowAdd: false,
onChange: debounce((id) => {
customFormConfig!.category = id;
}, 200),
},
colProps: { span: 12 },
},
{
field: 'remark',
label: t('功能描述'),
component: 'Input',
colProps: { span: 12 },
componentProps: {
placeholder: t('请输入功能描述'),
onChange: debounce((val: ChangeEvent) => {
customFormConfig!.remark = val.target.value;
}, 200),
},
},
{
field: 'isDataAuth',
label: t('数据权限'),
component: 'Switch',
required: false,
colProps: { span: 12 },
helpMessage: dataAuthHelpMessage,
helpComponentProps: { maxWidth: '400px' },
componentProps: {
checkedValue: true,
unCheckedValue: false,
onChange: (val) => {
if (!val) {
setFieldsValue({ dataAuthList: [] });
generatorConfig!.dataAuthList = [];
}
generatorConfig!.isDataAuth = val;
},
},
},
{
field: 'dataAuthList',
label: t('权限选择'),
component: 'ApiSelect',
required: false,
colProps: { span: 12 },
componentProps: {
mode: 'multiple',
placeholder: dataAuthPlaceholder,
api: getAuthList,
labelField: 'name',
valueField: 'id',
getPopupContainer: () => document.body,
onChange: (val) => {
generatorConfig!.dataAuthList = val;
},
},
dynamicDisabled: ({ values }) => {
return !values.isDataAuth;
},
},
];
const columns = [
{
title: t('序号'),
dataIndex: 'order',
key: 'order',
width: 80,
},
{
title: t('类别'),
dataIndex: 'isMain',
key: 'isMain',
width: 80,
},
{
title: t('表名'),
dataIndex: 'tableName',
key: 'tableName',
},
{
title: t('关联字段'),
dataIndex: 'relationField',
key: 'relationField',
},
{
title: t('关联表字段'),
key: 'relationTableField',
dataIndex: 'relationTableField',
},
{
title: t('操作'),
key: 'action',
align: 'center',
},
];
const selectOptions = ref({});
const selectTableName = computed(() =>
generatorConfig!.tableConfigs!.map((item) => item.tableName),
);
const mainTable = computed(
() => generatorConfig!.tableConfigs!.find((item) => item.isMain)!.tableName,
);
const generatorConfig = inject<GeneratorConfig>('generatorConfig');
const customFormConfig = inject<CustomFormConfig>('customFormConfig');
const tableInfo = inject<Ref<TableInfo[]>>('tableInfo');
const designType = inject<string>('designType');
const isFieldUpper = inject<Ref<boolean>>('isFieldUpper', ref(false));
let mainTableName = inject<Ref<string>>('mainTableName', ref(''));
const formType = inject<Ref<number>>('formType');
watch(
() => generatorConfig?.databaseId,
(val, oldVal) => {
const { tableConfigs } = generatorConfig!;
if (
designType === 'data' &&
val &&
val !== oldVal &&
tableConfigs &&
tableConfigs.length > 0
) {
getDatabaselinkColumns(val);
}
},
);
watch(
() => generatorConfig?.formJson,
(val) => {
if (!val) return;
if (val.list.length > 0 || val.hiddenComponent.length > 0) {
updateSchema({
field: 'databaseId',
componentProps: {
disabled: true,
},
});
} else {
updateSchema({
field: 'databaseId',
componentProps: {
disabled: false,
},
});
}
},
{
deep: true,
},
);
const filterFormSchema=(formSchema:FormSchema[])=>{
customFormConfig.formType=formType.value;
const rtSchema=[];
for(let i=0;i<formSchema.length;i++){
let item=formSchema[i];
if(item.field=='category'){
if(formType.value==1){
rtSchema.push(item);
}
}else{
rtSchema.push(item);
}
}
return rtSchema;
};
const [registerModal, { openModal }] = useModal();
const [register, { validate, getFieldsValue, setFieldsValue, updateSchema }] = useForm({
labelWidth: 100,
schemas: designType === 'data' ? filterFormSchema(formSchemaData) : filterFormSchema(formSchema),
showActionButtonGroup: false,
});
const add = async () => {
try {
const values = await validate();
openModal(true, { databaseId: values.databaseId, selectTableName: selectTableName.value });
} catch (error) {}
};
const handleSelectSuccess = (selectRows: TableConfig[]) => {
if (generatorConfig?.tableConfigs && generatorConfig?.tableConfigs.length === 0) {
generatorConfig!.tableConfigs = [...toRaw(selectRows)];
} else {
generatorConfig!.tableConfigs = uniqBy(
generatorConfig!.tableConfigs!.concat([...selectRows]),
'tableName',
);
}
const formData = getFieldsValue();
getDatabaselinkColumns(formData.databaseId);
};
const remove = (index) => {
// TODO 这里删除 可能会引起 表单设计步骤所有的设计 出错。3个解决方案
//1 删除后提示用户 表单设计全部清空!
//2 删除之后根据所删除的表名 去表单设计Json匹配 所绑定的组件 全部将绑定表置空!
//3 表单设计后 不允许删除表配置!
//如果删除的数据是主表 并且还有其他表 默认顺序 找下一张表 将其设为主表
if (generatorConfig!.tableConfigs![index].isMain && generatorConfig!.tableConfigs!.length > 1) {
const nextObj = generatorConfig!.tableConfigs![index + 1];
nextObj.isMain = true;
nextObj.relationField = '';
nextObj.relationTableField = '';
const nextTable = tableInfo!.value![index + 1];
nextTable.isMain = true;
generatorConfig!.tableConfigs!.splice(index, 1);
tableInfo?.value.splice(index, 1);
} else {
generatorConfig!.tableConfigs!.splice(index, 1);
tableInfo?.value.splice(index, 1);
}
};
const getDatabaselinkColumns = (databaseId) => {
getDatabaselinkMultiTableColumns({
id: databaseId,
tableNames: selectTableName.value.join(','),
}).then((result) => {
for (const key in result) {
const columnInfo = result[key];
//如果已经写入过的表格 不再添加
if (!tableInfo?.value.find((x) => x.name === key)) {
const fields = columnInfo.map((field) => {
const filedInfo: FieldInfo = {
name: field.column,
length: field.dataLength,
type: JavaTypeConvertTsType(field.dataType),
isPk: field.primaryKey,
isNullable: field.nullable,
};
return filedInfo;
});
tableInfo?.value.push({
name: key,
isMain: generatorConfig!.tableConfigs!.find((x) => x.tableName === key)
?.isMain as boolean,
fields: fields,
});
const thisTableConfig = generatorConfig!.tableConfigs!.find((x) => x.tableName === key);
const col = columnInfo.find((x) => x.primaryKey);
thisTableConfig!.pkField = col.column;
thisTableConfig!.pkType = col.dataType;
}
selectOptions.value[key] = columnInfo.map((x) => x.column);
}
});
};
//验证当前步骤的数据
const validateStep = async (): Promise<boolean> => {
try {
await validate();
if (designType !== 'data') {
return true;
}
const { tableConfigs } = generatorConfig as GeneratorConfig;
//判断tableconfig 是否为空 或者 一条数据都没有
if (!tableConfigs || tableConfigs!.length === 0) {
notification.error({
message: t('提示'),
description: t('数据表配置不能为空!'),
}); //提示消息
return false;
}
for (const config of tableConfigs!) {
//如果是主表 可以不需要关联字段等
if (config.isMain) {
if (!config.tableName) {
notification.error({
message: t('提示'),
description: t('主表表名未能配置成功!'),
}); //提示消息
return false;
}
} else {
//子表需要验证关联字段 已经关联表 是否选择好
if (!config.tableName) {
notification.error({
message: t('提示'),
description: t('子表表名未能配置成功!'),
}); //提示消息
return false;
}
if (!config.relationField) {
notification.error({
message: t('提示'),
description: t(`{name} 表 关联字段未选中`, { name: config.tableName }),
}); //提示消息
return false;
}
if (!config.relationTableField) {
notification.error({
message: t('提示'),
description: t(`{name} 表 关联表字段未选中`, { name: config.tableName }),
}); //提示消息
return false;
}
}
}
} catch (error) {
return false;
}
return true;
};
defineExpose({ validateStep, setFieldsValue });
</script>
<style lang="less" scoped>
.step1 {
h3 {
margin: 0 0 12px;
font-size: 16px;
line-height: 32px;
color: @text-color;
}
h4 {
margin: 0 0 4px;
font-size: 14px;
line-height: 22px;
color: @text-color;
}
p {
color: @text-color;
}
}
.pay-select {
width: 20%;
}
.pay-input {
width: 70%;
}
:deep(.ant-table-tbody > tr > td) {
padding: 16px 8px;
}
</style>