---初始化后台管理web页面项目
This commit is contained in:
589
src/views/form/design/components/BasicConfigStep.vue
Normal file
589
src/views/form/design/components/BasicConfigStep.vue
Normal file
@ -0,0 +1,589 @@
|
||||
<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>
|
||||
298
src/views/form/design/components/CodeGeneratorModal.vue
Normal file
298
src/views/form/design/components/CodeGeneratorModal.vue
Normal file
@ -0,0 +1,298 @@
|
||||
<template>
|
||||
<BasicModal @register="registerModal" v-bind="$attrs" wrapClassName="form-modal">
|
||||
<template #title>
|
||||
<div class="step-form-form">
|
||||
<a href="https://fcdma.gdyditc.com/" target="_blank">
|
||||
<DesignLogo />
|
||||
</a>
|
||||
<span>•</span>
|
||||
<span>{{ t('表单生成代码配置') }}</span>
|
||||
<a-steps :current="current">
|
||||
<a-step :title="t('基本信息')" />
|
||||
<a-step :title="t('界面设计')" />
|
||||
<a-step :title="t('代码预览')" />
|
||||
<a-step :title="t('菜单设置')" />
|
||||
</a-steps>
|
||||
<div class="btn-box">
|
||||
<a-button type="primary" @click="handleStepPrev" v-show="current !== 0">{{
|
||||
t('上一步')
|
||||
}}</a-button>
|
||||
<a-button type="primary" @click="handleStepNext" v-show="current < 3">{{
|
||||
t('下一步')
|
||||
}}</a-button>
|
||||
<a-button type="primary" @click="handleSave" v-show="current === 3">{{
|
||||
t('保存')
|
||||
}}</a-button>
|
||||
<a-button type="primary" danger @click="handleClose">{{ t('关闭') }}</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="step-container">
|
||||
<StructureConfigStep
|
||||
ref="structureConfigStepRef"
|
||||
v-show="current === 0"
|
||||
:isFormGenerator="true"
|
||||
/>
|
||||
<ViewDesignStep ref="viewDesignStepRef" v-show="current === 1" :isFormGenerator="true" />
|
||||
<PreviewCodeStep ref="previewCodeStepRef" v-show="current === 2" :isFormGenerator="true" />
|
||||
<MenuConfigStep ref="menuConfigStepRef" v-show="current === 3" />
|
||||
</div>
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, provide, watch, Ref } from 'vue';
|
||||
import PreviewCodeStep from '/@/views/generator/dev/components/PreviewCodeStep.vue';
|
||||
import {
|
||||
StructureConfigStep,
|
||||
ViewDesignStep,
|
||||
MenuConfigStep,
|
||||
} from '/@/components/CreateCodeStep';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { GeneratorModel } from '/@/api/system/generator/model';
|
||||
import { FormProps } from '/@/components/Form';
|
||||
import { buildOption } from '/@/utils/helper/designHelper';
|
||||
import { buildCode } from '/@/utils/helper/generatorHelper';
|
||||
import { CustomFormConfig, GeneratorConfig } from '/@/model/generator/generatorConfig';
|
||||
import { TableInfo } from '/@/components/Designer';
|
||||
import { getFormTemplate } from '/@/api/form/design';
|
||||
import { dataFirstGeneratorCode } from '/@/api/system/generator';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
import { FormTypeEnum } from '/@/enums/formtypeEnum';
|
||||
import * as antd from '/@/components/Designer/src/types';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import DesignLogo from '/@/components/ModalPanel/src/DesignLogo.vue';
|
||||
const { t } = useI18n();
|
||||
const userStore = useUserStore();
|
||||
const current = ref(0);
|
||||
|
||||
const structureConfigStepRef = ref();
|
||||
const viewDesignStepRef = ref();
|
||||
const previewCodeStepRef = ref();
|
||||
const menuConfigStepRef = ref();
|
||||
|
||||
const tableInfo = ref<TableInfo[]>([]);
|
||||
const widgetForm = JSON.parse(JSON.stringify(antd.widgetForm));
|
||||
|
||||
const emits = defineEmits(['success', 'register', 'close']);
|
||||
const isGetInfo = ref<boolean>(false);
|
||||
|
||||
// const templateInfo = inject('getTemplateInfo');
|
||||
|
||||
let generatorConfig = reactive<GeneratorConfig>({
|
||||
databaseId: '', //数据库id
|
||||
tableConfigs: [],
|
||||
tableStructureConfigs: [],
|
||||
formJson: {},
|
||||
formEventConfig: {},
|
||||
listConfig: {
|
||||
isLeftMenu: false,
|
||||
queryConfigs: [],
|
||||
leftMenuConfig: {
|
||||
datasourceType: 'static',
|
||||
listFieldName: undefined,
|
||||
apiConfig: {},
|
||||
dictionaryItemId: undefined,
|
||||
menuName: '',
|
||||
parentIcon: '',
|
||||
childIcon: '',
|
||||
staticData: [],
|
||||
},
|
||||
columnConfigs: [],
|
||||
buttonConfigs: [],
|
||||
defaultOrder: true,
|
||||
isPage: true,
|
||||
},
|
||||
menuConfig: {},
|
||||
outputConfig: {
|
||||
creator: userStore.getUserInfo.name,
|
||||
isMenu: true,
|
||||
},
|
||||
});
|
||||
let customFormConfig = reactive<CustomFormConfig>({
|
||||
name: '',
|
||||
category: '',
|
||||
formDesignType: 0,
|
||||
formType: FormTypeEnum.CUSTOM_FORM,
|
||||
formJson: generatorConfig,
|
||||
remark: '',
|
||||
});
|
||||
|
||||
provide<GeneratorConfig>('generatorConfig', generatorConfig);
|
||||
provide<CustomFormConfig>('customFormConfig', customFormConfig);
|
||||
provide<Ref<TableInfo[]>>('tableInfo', tableInfo);
|
||||
provide('widgetForm', widgetForm);
|
||||
provide<Ref<number>>('current', current); //当前步骤
|
||||
watch(
|
||||
() => generatorConfig,
|
||||
() => {
|
||||
console.log(generatorConfig, 'generatorConfig:>>watch');
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
() => customFormConfig,
|
||||
() => {
|
||||
console.log(customFormConfig, 'customFormConfig:>>watch');
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
},
|
||||
);
|
||||
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
setModalProps({
|
||||
confirmLoading: false,
|
||||
defaultFullscreen: true,
|
||||
destroyOnClose: true,
|
||||
draggable: false,
|
||||
showOkBtn: false,
|
||||
showCancelBtn: false,
|
||||
footer: null,
|
||||
closable: false,
|
||||
});
|
||||
const res = await getFormTemplate(data.formId);
|
||||
const formJson = JSON.parse(res.formJson);
|
||||
generatorConfig.databaseId = formJson.databaseId;
|
||||
generatorConfig.formJson = formJson.formJson;
|
||||
generatorConfig.tableConfigs = formJson.tableConfigs;
|
||||
generatorConfig.tableStructureConfigs = formJson.tableStructureConfigs;
|
||||
generatorConfig.formEventConfig = formJson.formEventConfig;
|
||||
generatorConfig.outputConfig.dataAuthList = formJson.dataAuthList;
|
||||
generatorConfig.outputConfig.type =res.formDesignType
|
||||
generatorConfig.outputConfig.isDataAuth = formJson.isDataAuth;
|
||||
isGetInfo.value = true;
|
||||
});
|
||||
|
||||
function handleClose() {
|
||||
closeModal();
|
||||
emits('close');
|
||||
}
|
||||
//上一步
|
||||
function handleStepPrev() {
|
||||
current.value--;
|
||||
}
|
||||
//下一步
|
||||
async function handleStepNext() {
|
||||
const isOk = await stepValidate[current.value]();
|
||||
if (!isOk) {
|
||||
return;
|
||||
}
|
||||
current.value++;
|
||||
}
|
||||
|
||||
async function handleSave() {
|
||||
const isOk = await stepValidate[3]();
|
||||
if (
|
||||
generatorConfig.formJson?.hiddenComponent &&
|
||||
generatorConfig.formJson?.hiddenComponent.length
|
||||
) {
|
||||
generatorConfig.formJson.list.push(...generatorConfig.formJson.hiddenComponent);
|
||||
}
|
||||
|
||||
if (!isOk) {
|
||||
return;
|
||||
}
|
||||
const data = generatorConfig as GeneratorModel;
|
||||
data.frontCode = buildCode(
|
||||
generatorConfig,
|
||||
tableInfo.value,
|
||||
buildOption(generatorConfig.formJson) as FormProps,
|
||||
);
|
||||
await dataFirstGeneratorCode(data);
|
||||
closeModal();
|
||||
emits('success');
|
||||
emits('close');
|
||||
}
|
||||
|
||||
const stepValidate = {
|
||||
//数据表配置 验证
|
||||
0: () => structureConfigStepRef.value.validateStep(),
|
||||
1: () => viewDesignStepRef.value.validateStep(),
|
||||
2: () => previewCodeStepRef.value.validateStep(),
|
||||
3: () => menuConfigStepRef.value.validateStep(),
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@keyframes rotation {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes rotationReverse {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(-360deg);
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-steps-item-process) {
|
||||
.ant-steps-item-icon {
|
||||
border: 2px solid #fff;
|
||||
outline: 2px dashed #1890ff !important;
|
||||
line-height: 30px;
|
||||
animation: rotation 4s linear infinite;
|
||||
|
||||
.ant-steps-icon {
|
||||
display: inline-block;
|
||||
animation: rotationReverse 4s linear infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.step-form-content {
|
||||
padding: 24px;
|
||||
background-color: @component-background;
|
||||
}
|
||||
|
||||
.step-form-form {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 400;
|
||||
|
||||
a {
|
||||
margin-left: -16px;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 16px;
|
||||
margin: 0 20px 0 -5px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
:deep(.ant-steps) {
|
||||
width: calc(100% - 750px);
|
||||
}
|
||||
|
||||
:deep(.ant-steps-item-container) {
|
||||
padding: 2px 0 2px 2px;
|
||||
}
|
||||
|
||||
.btn-box {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
|
||||
:deep(.ant-btn) {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.step-container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.step1 {
|
||||
padding: 14px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
112
src/views/form/design/components/DesignModal.vue
Normal file
112
src/views/form/design/components/DesignModal.vue
Normal file
@ -0,0 +1,112 @@
|
||||
// 自定义表单
|
||||
<template>
|
||||
<BasicModal @register="registerModal" v-bind="$attrs">
|
||||
<GroupCard :growCardList="items" />
|
||||
<DataFirstModal
|
||||
v-if="state.isShowDataFirst"
|
||||
@register="registerDataFirst"
|
||||
@success="handleSuccess"
|
||||
@close="handleClose('isShowDataFirst')"
|
||||
/>
|
||||
<CodeFirstModal
|
||||
v-if="state.isShowCodeFirst"
|
||||
@register="registerCodeFirst"
|
||||
@success="handleSuccess"
|
||||
@close="handleClose('isShowCodeFirst')"
|
||||
/>
|
||||
<SimpleTemplateModal
|
||||
v-if="state.isShowSimpleTemplate"
|
||||
@register="registerSimpleTemplate"
|
||||
@success="handleSuccess"
|
||||
@close="handleClose('isShowSimpleTemplate')"
|
||||
/>
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue';
|
||||
import { BasicModal, useModal, useModalInner } from '/@/components/Modal';
|
||||
import GroupCard from '/@/views/generator/dev/components/GroupCard.vue';
|
||||
import DataFirstModal from './components/DataFirstModal.vue';
|
||||
import CodeFirstModal from './components/CodeFirstModal.vue';
|
||||
import SimpleTemplateModal from './components/SimpleTemplateModal.vue';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
import interfaceFirstPng from '/@/assets/images/design/interfaceFirst.png';
|
||||
import dataFirst from '/@/assets/images/design/dataFirst.png';
|
||||
import simpleTemplate from '/@/assets/images/design/simpleTemplate.png';
|
||||
import quickDevelop from '/@/assets/images/design/quickDevelop.png';
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
const [registerDataFirst, { openModal: openDataFirstModal }] = useModal();
|
||||
const [registerCodeFirst, { openModal: openCodeFirstModal }] = useModal();
|
||||
const [registerSimpleTemplate, { openModal: openSimpleTemplateModal }] = useModal();
|
||||
|
||||
const emits = defineEmits(['success', 'register']);
|
||||
|
||||
const items = [
|
||||
{
|
||||
name: t('界面优先'),
|
||||
content: t('以界面为基础设计并生成单表或多表的基础功能'),
|
||||
btnName: t('设计功能'),
|
||||
image: interfaceFirstPng,
|
||||
func: () => {
|
||||
openCodeFirstModal(true, { undoAble: true });
|
||||
},
|
||||
},
|
||||
{
|
||||
name: t('数据优先'),
|
||||
content: t('以数据为基础设置生成单表或多表的基础功能'),
|
||||
btnName: t('设计功能'),
|
||||
image: dataFirst,
|
||||
func: () => {
|
||||
openDataFirstModal(true, { undoAble: true });
|
||||
},
|
||||
},
|
||||
{
|
||||
name: t('简易模板'),
|
||||
content: t('通过简单操作生成不需要考虑数据库的基础功能'),
|
||||
btnName: t('设计功能'),
|
||||
image: simpleTemplate,
|
||||
func: () => {
|
||||
openSimpleTemplateModal(true, { undoAble: true });
|
||||
},
|
||||
},
|
||||
{
|
||||
name: t('快速生成代码'),
|
||||
content: t('根据数据表结构自动快速生成功能代码'),
|
||||
btnName: t('设计功能'),
|
||||
image: quickDevelop,
|
||||
func: () => {
|
||||
router.push({ path: '/dataconfig/database' });
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
setModalProps({
|
||||
confirmLoading: false,
|
||||
canFullscreen: false,
|
||||
defaultFullscreen: true,
|
||||
draggable: false,
|
||||
title: data.title,
|
||||
showOkBtn: false,
|
||||
showCancelBtn: false,
|
||||
});
|
||||
});
|
||||
const state = reactive({
|
||||
isShowDataFirst: true,
|
||||
isShowCodeFirst: true,
|
||||
isShowSimpleTemplate: true,
|
||||
});
|
||||
const handleClose = (modal) => {
|
||||
state[modal] = !state[modal];
|
||||
setTimeout(() => {
|
||||
state[modal] = !state[modal];
|
||||
}, 100);
|
||||
};
|
||||
|
||||
const handleSuccess = () => {
|
||||
emits('success');
|
||||
closeModal();
|
||||
};
|
||||
</script>
|
||||
128
src/views/form/design/components/HistoryModal.vue
Normal file
128
src/views/form/design/components/HistoryModal.vue
Normal file
@ -0,0 +1,128 @@
|
||||
<template>
|
||||
<BasicModal @register="registerCategoryModal" v-bind="$attrs">
|
||||
<BasicTable @register="registerTable">
|
||||
<template #action="{ record }">
|
||||
<a-button type="link" v-if="record.activityFlag === 1" @click="handlePreview(record.id)"
|
||||
>{{ t('预览') }}
|
||||
</a-button>
|
||||
<div v-else class="flex justify-around">
|
||||
<a-button type="link" @click="handlePreview(record.id)">{{ t('预览') }} </a-button>
|
||||
<a-popconfirm
|
||||
:title="t('确认要将当前表单更新到此历史版本吗?')"
|
||||
:ok-text="t('确定')"
|
||||
:cancel-text="t('取消')"
|
||||
@confirm="handleVersion(record)"
|
||||
>
|
||||
<a-button type="link">{{ t('更新到此版本') }} </a-button>
|
||||
</a-popconfirm>
|
||||
</div>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</BasicModal>
|
||||
<PreviewModal @register="registerPreviewModal" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { BasicModal, useModal, useModalInner } from '/@/components/Modal';
|
||||
import PreviewModal from './PreviewModal.vue';
|
||||
import { BasicTable, useTable, BasicColumn } from '/@/components/Table';
|
||||
import { getFormHistoryInfo, setFormHistoryVersion } from '/@/api/form/design';
|
||||
import { getFormHistory } from '/@/api/form/design';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
const { t } = useI18n();
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
dataIndex: 'activityFlag',
|
||||
title: t('状态'),
|
||||
customRender: ({ record }) =>
|
||||
`${record.activityFlag === 1 ? t('当前版本') : t('非当前版本')}`, //1-当前版本 0-非当前版本
|
||||
},
|
||||
{
|
||||
dataIndex: 'version',
|
||||
title: t('版本'),
|
||||
},
|
||||
|
||||
{
|
||||
dataIndex: 'createUserName',
|
||||
title: t('创建人'),
|
||||
},
|
||||
{
|
||||
dataIndex: 'createDate',
|
||||
title: t('创建时间'),
|
||||
},
|
||||
];
|
||||
|
||||
const formId = ref<string>('');
|
||||
const { notification } = useMessage();
|
||||
|
||||
const [registerPreviewModal, { openModal }] = useModal();
|
||||
|
||||
const [registerCategoryModal, { setModalProps }] = useModalInner(async (data) => {
|
||||
formId.value = data.formId;
|
||||
setModalProps({
|
||||
confirmLoading: false,
|
||||
draggable: false,
|
||||
title: data.title,
|
||||
showOkBtn: false,
|
||||
showCancelBtn: false,
|
||||
destroyOnClose: true,
|
||||
width: 800,
|
||||
});
|
||||
});
|
||||
const [registerTable, { reload }] = useTable({
|
||||
api: getFormHistory,
|
||||
beforeFetch: () => {
|
||||
return formId.value;
|
||||
},
|
||||
rowKey: 'id',
|
||||
columns,
|
||||
showTableSetting: false,
|
||||
bordered: true,
|
||||
maxHeight: 200,
|
||||
actionColumn: {
|
||||
width: 180,
|
||||
title: t('操作'),
|
||||
dataIndex: 'action',
|
||||
slots: { customRender: 'action' },
|
||||
},
|
||||
});
|
||||
|
||||
const handlePreview = async (id) => {
|
||||
if (!id) {
|
||||
notification.warning({
|
||||
message: t('提示'),
|
||||
description: t('请先选择要预览的数据项'),
|
||||
}); //提示消息
|
||||
return;
|
||||
}
|
||||
const templateJson = await getFormHistoryInfo(id);
|
||||
openModal(true, { title: t('预览'), formJson: templateJson.formJson });
|
||||
};
|
||||
|
||||
const handleVersion = (data) => {
|
||||
setFormHistoryVersion({ formId: data.formId, id: data.id }).then((res) => {
|
||||
if (res) {
|
||||
notification.success({
|
||||
message: t('提示'),
|
||||
description: t('更新版本成功'),
|
||||
});
|
||||
reload();
|
||||
} else {
|
||||
notification.error({
|
||||
message: t('提示'),
|
||||
description: t('更新版本失败'),
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
:deep(.vben-basic-table-header__toolbar) {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
:deep(.current-row) td {
|
||||
background: #e6f2ff !important;
|
||||
}
|
||||
</style>
|
||||
44
src/views/form/design/components/PreviewModal.vue
Normal file
44
src/views/form/design/components/PreviewModal.vue
Normal file
@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div>
|
||||
<BasicModal @register="registerModal" v-bind="$attrs" title="预览">
|
||||
<SimpleForm
|
||||
ref="formRef"
|
||||
:key="show"
|
||||
:formProps="state.formProps"
|
||||
:formModel="state.formModel"
|
||||
/>
|
||||
</BasicModal>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, provide } from 'vue';
|
||||
import SimpleForm from '/@/components/SimpleForm/src/SimpleForm.vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { buildOption } from '/@/utils/helper/designHelper';
|
||||
|
||||
const state = reactive({
|
||||
formProps: {},
|
||||
formModel: {},
|
||||
});
|
||||
provide<boolean>('isCustomForm', true);
|
||||
const show = ref(1);
|
||||
const formRef = ref();
|
||||
|
||||
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
|
||||
state.formProps = buildOption(JSON.parse(data.formJson).formJson, false);
|
||||
show.value += 1;
|
||||
|
||||
await formRef.value.setDefaultValue();
|
||||
formRef.value.resetFields();
|
||||
|
||||
setModalProps({
|
||||
confirmLoading: false,
|
||||
draggable: false,
|
||||
title: data.title,
|
||||
destroyOnClose: true,
|
||||
showOkBtn: false,
|
||||
showCancelBtn: false,
|
||||
width: 800,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
371
src/views/form/design/components/components/CodeFirstModal.vue
Normal file
371
src/views/form/design/components/components/CodeFirstModal.vue
Normal file
@ -0,0 +1,371 @@
|
||||
<template>
|
||||
<BasicModal @register="registerModal" v-bind="$attrs" wrapClassName="form-modal">
|
||||
<template #title>
|
||||
<div class="step-form-form">
|
||||
<a href="https://fcdma.gdyditc.com/" target="_blank">
|
||||
<DesignLogo />
|
||||
</a>
|
||||
<span>•</span>
|
||||
<span>{{ t('表单设计') }} - {{ t('界面优先') }}</span>
|
||||
<a-steps :current="current" size="mini">
|
||||
<a-step :title="t('基础信息')" />
|
||||
<a-step :title="t('表单设计')" />
|
||||
<a-step :title="t('表单事件')" />
|
||||
<a-step :title="t('完整配置')" />
|
||||
<a-step :title="t('结构配置')" />
|
||||
</a-steps>
|
||||
<div class="btn-box">
|
||||
<a-button @click="handleStepPrev" v-show="current !== 0">{{ t('上一步') }}</a-button>
|
||||
<a-button type="primary" @click="handleStepNext" v-show="current < 4">
|
||||
{{ t('下一步') }}
|
||||
</a-button>
|
||||
<a-button type="primary" @click="handleSave" v-show="current === 4">
|
||||
{{ t('保存') }}
|
||||
</a-button>
|
||||
<a-button type="primary" danger @click="handleClose">{{ t('关闭') }}</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="step-container">
|
||||
<BasicConfigStep ref="basicConfigStepRef" v-show="current === 0" />
|
||||
<FormDesignStep ref="formDesignStepRef" v-show="current === 1" />
|
||||
<FormEventStep ref="formEventStepRef" v-show="current === 2" />
|
||||
<EntireConfigStep ref="entireConfigStepRef" v-show="current === 3"/>
|
||||
<StructureConfigStep
|
||||
ref="structureConfigStepRef"
|
||||
v-show="current === 4"
|
||||
:isUpdate="isUpdate"
|
||||
:beforeTableNames="beforeTableNames"
|
||||
@validate-table="handleSave"
|
||||
/>
|
||||
|
||||
</div>
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, provide, inject, Ref, toRaw, watch } from 'vue';
|
||||
import { FormDesignStep, FormEventStep, StructureConfigStep,EntireConfigStep} from '/@/components/CreateCodeStep';
|
||||
import BasicConfigStep from '../BasicConfigStep.vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import {
|
||||
CustomFormConfig,
|
||||
CustomFormJson,
|
||||
GeneratorConfig,
|
||||
} from '/@/model/generator/generatorConfig';
|
||||
import { TableInfo } from '/@/components/Designer';
|
||||
import {
|
||||
addCodeFirstFormTemplate,
|
||||
updateCodeFirstFormTemplate,
|
||||
getFormTemplate,
|
||||
} from '/@/api/form/design';
|
||||
import { noHaveTableAndField } from '/@/components/Designer';
|
||||
import * as antd from '/@/components/Designer/src/types';
|
||||
import { FormTypeEnum } from '/@/enums/formtypeEnum';
|
||||
import DesignLogo from '/@/components/ModalPanel/src/DesignLogo.vue';
|
||||
import { random } from 'lodash-es';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { FormJson } from '/@/model/generator/codeGenerator';
|
||||
import { FormEventColumnConfig } from '/@/model/generator/formEventConfig';
|
||||
import { changeCompsApiConfig, changeEventApiConfig, getMainTable } from '/@/utils/event/design';
|
||||
import {ListConfig} from "/@/model/generator/listConfig";
|
||||
|
||||
const { t } = useI18n();
|
||||
const current = ref(0);
|
||||
|
||||
const basicConfigStepRef = ref();
|
||||
const formDesignStepRef = ref();
|
||||
const formEventStepRef = ref();
|
||||
const entireConfigStepRef = ref();
|
||||
const structureConfigStepRef = ref();
|
||||
const widgetForm = ref(JSON.parse(JSON.stringify(antd.widgetForm))); //FormDesignStep -> designer和StructureConfigStep页面使用
|
||||
const isUpdate = ref<boolean>(false);
|
||||
const tableInfo = ref<TableInfo[]>([]);
|
||||
const formId = ref<string>('');
|
||||
const beforeTableNames = ref<string[]>([]);
|
||||
const mainTableName = ref('table_' + random(10000, 99999));
|
||||
|
||||
let generatorConfig = reactive<CustomFormJson>({
|
||||
databaseId: '', //数据库id
|
||||
formJson: {} as FormJson,
|
||||
tableStructureConfigs: [],
|
||||
formEventConfig: {} as FormEventColumnConfig,
|
||||
isDataAuth: false,
|
||||
dataAuthList: [],
|
||||
});
|
||||
|
||||
let customFormConfig = reactive<CustomFormConfig>({
|
||||
name: '',
|
||||
category: '',
|
||||
formDesignType: 1,
|
||||
formType:'',
|
||||
formJson: generatorConfig,
|
||||
remark: '',
|
||||
isChange: false,
|
||||
});
|
||||
|
||||
provide<GeneratorConfig>('generatorConfig', generatorConfig as GeneratorConfig);
|
||||
provide<CustomFormConfig>('customFormConfig', customFormConfig);
|
||||
provide<Ref<TableInfo[]>>('tableInfo', tableInfo);
|
||||
provide<Ref<number>>('current', current); //当前步骤
|
||||
provide<string>('designType', 'code');
|
||||
provide('widgetForm', widgetForm);
|
||||
provide<Ref<string>>('mainTableName', mainTableName);
|
||||
provide<boolean>('isCustomForm', true); //是自定义表单
|
||||
provide<Ref<boolean>>('isFieldUpper', ref(false));
|
||||
|
||||
watch(
|
||||
() => generatorConfig,
|
||||
(val) => {
|
||||
customFormConfig.formJson = val;
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
},
|
||||
);
|
||||
const emits = defineEmits(['success', 'register', 'close']);
|
||||
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
isUpdate.value = !!data.isUpdate;
|
||||
formId.value = data.id;
|
||||
customFormConfig.isChange = isUpdate.value;
|
||||
if (formId.value) {
|
||||
getFormTemplateInfo();
|
||||
}
|
||||
setModalProps({
|
||||
confirmLoading: false,
|
||||
canFullscreen: false,
|
||||
defaultFullscreen: true,
|
||||
destroyOnClose: true,
|
||||
draggable: false,
|
||||
showOkBtn: false,
|
||||
showCancelBtn: false,
|
||||
footer: null,
|
||||
closable: false,
|
||||
});
|
||||
});
|
||||
|
||||
async function getFormTemplateInfo() {
|
||||
const data = await getFormTemplate(formId.value);
|
||||
customFormConfig.name = data.name;
|
||||
customFormConfig.category = data.category;
|
||||
customFormConfig.formDesignType = data.formDesignType;
|
||||
customFormConfig.formJson = JSON.parse(data.formJson);
|
||||
customFormConfig.listConfig = JSON.parse(data.listConfig)||{} as ListConfig;
|
||||
customFormConfig.renderConfig =data.renderConfig;
|
||||
customFormConfig.remark = data.remark;
|
||||
|
||||
const { formJson,listConfig,renderConfig } = customFormConfig;
|
||||
|
||||
generatorConfig.databaseId = formJson.databaseId;
|
||||
generatorConfig.isDataAuth = formJson.isDataAuth;
|
||||
generatorConfig.dataAuthList = formJson.dataAuthList;
|
||||
generatorConfig.tableStructureConfigs = formJson.tableStructureConfigs;
|
||||
generatorConfig.formJson = formJson.formJson;
|
||||
generatorConfig.listConfig = listConfig;
|
||||
generatorConfig.renderConfig = renderConfig;
|
||||
generatorConfig.formEventConfig = formJson.formEventConfig!;
|
||||
generatorConfig.formJson.list = generatorConfig.formJson.list.filter(
|
||||
(x) => x.type !== 'hiddenComponent',
|
||||
);
|
||||
|
||||
getMainTableFirst(generatorConfig.formJson.list);
|
||||
widgetForm.value = generatorConfig.formJson;
|
||||
|
||||
basicConfigStepRef.value.setFieldsValue({
|
||||
name: customFormConfig?.name,
|
||||
category: customFormConfig?.category,
|
||||
remark: customFormConfig?.remark,
|
||||
databaseId: generatorConfig.databaseId,
|
||||
isDataAuth: generatorConfig.isDataAuth,
|
||||
dataAuthList: generatorConfig.dataAuthList,
|
||||
});
|
||||
|
||||
beforeTableNames.value = generatorConfig.tableStructureConfigs!.map((x) => x.tableName);
|
||||
}
|
||||
|
||||
function getMainTableFirst(list) {
|
||||
list.some((x) => {
|
||||
if (['tab', 'grid', 'card'].includes(x.type)) {
|
||||
for (const child of x.layout!) {
|
||||
return getMainTableFirst(child.list);
|
||||
}
|
||||
} else if (x.type === 'table-layout') {
|
||||
for (const child of x.layout!) {
|
||||
for (const el of child.list!) {
|
||||
return getMainTableFirst(el.children);
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
x.type !== 'form' &&
|
||||
x.type !== 'one-for-one' &&
|
||||
!noHaveTableAndField.includes(x.type)
|
||||
) {
|
||||
mainTableName.value = x.bindTable;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleClose() {
|
||||
closeModal();
|
||||
emits('close');
|
||||
}
|
||||
|
||||
//上一步
|
||||
async function handleStepPrev() {
|
||||
current.value--;
|
||||
if(current.value==1){
|
||||
widgetForm.value = generatorConfig.formJson;
|
||||
}
|
||||
}
|
||||
//下一步
|
||||
async function handleStepNext() {
|
||||
if (current.value === 2) {
|
||||
entireConfigStepRef.value.initStep();
|
||||
current.value++;
|
||||
return;
|
||||
}
|
||||
|
||||
const isOk = await stepValidate[current.value]();
|
||||
if (!isOk) {
|
||||
return;
|
||||
}
|
||||
current.value++;
|
||||
}
|
||||
|
||||
async function handleSave() {
|
||||
const isOk = await stepValidate[4]();
|
||||
if (!isOk) {
|
||||
return;
|
||||
}
|
||||
|
||||
let tableFieldConfigs = getMainTable(generatorConfig.tableStructureConfigs);
|
||||
changeCompsApiConfig(generatorConfig!.formJson.list, 'code', tableFieldConfigs);
|
||||
changeEventApiConfig(generatorConfig!.formEventConfig, 'code', tableFieldConfigs);
|
||||
|
||||
if (
|
||||
generatorConfig.formJson?.hiddenComponent &&
|
||||
generatorConfig.formJson?.hiddenComponent.length
|
||||
) {
|
||||
generatorConfig.formJson.list.push(...generatorConfig.formJson.hiddenComponent);
|
||||
}
|
||||
if (isUpdate.value) {
|
||||
handleEditSuccess();
|
||||
} else {
|
||||
await addCodeFirstFormTemplate(toRaw(customFormConfig));
|
||||
closeModal();
|
||||
emits('success');
|
||||
emits('close');
|
||||
}
|
||||
}
|
||||
|
||||
async function handleEditSuccess() {
|
||||
await updateCodeFirstFormTemplate({ id: formId.value, ...toRaw(customFormConfig) });
|
||||
closeModal();
|
||||
emits('success');
|
||||
emits('close');
|
||||
}
|
||||
|
||||
const stepValidate = {
|
||||
//数据表配置 验证
|
||||
0: () => basicConfigStepRef.value.validateStep(),
|
||||
1: () => formDesignStepRef.value.validateStep(),
|
||||
2: () => formEventStepRef.value.validateStep(),
|
||||
3: () => entireConfigStepRef.value.validateStep(),
|
||||
4: () => structureConfigStepRef.value.validateStep(),
|
||||
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@keyframes rotation {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes rotationReverse {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(-360deg);
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-steps-item-process) {
|
||||
.ant-steps-item-icon {
|
||||
border: 2px solid #fff;
|
||||
line-height: 30px;
|
||||
animation: rotation 4s linear infinite;
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
border: 2px dashed #1890ff;
|
||||
content: '';
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
display: block;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
left: -4px;
|
||||
top: -4px;
|
||||
}
|
||||
|
||||
.ant-steps-icon {
|
||||
display: inline-block;
|
||||
animation: rotationReverse 4s linear infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.step-form-content {
|
||||
padding: 24px;
|
||||
background-color: @component-background;
|
||||
}
|
||||
|
||||
.step-form-form {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 400;
|
||||
|
||||
a {
|
||||
margin-left: -16px;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 16px;
|
||||
margin: 0 20px 0 -5px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
:deep(.ant-steps) {
|
||||
width: calc(100% - 750px);
|
||||
}
|
||||
|
||||
:deep(.ant-steps-item-container) {
|
||||
padding: 3px 0 3px 3px;
|
||||
}
|
||||
|
||||
.btn-box {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
|
||||
:deep(.ant-btn) {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.step-container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.step1 {
|
||||
padding: 0 14px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
317
src/views/form/design/components/components/DataFirstModal.vue
Normal file
317
src/views/form/design/components/components/DataFirstModal.vue
Normal file
@ -0,0 +1,317 @@
|
||||
<template>
|
||||
<BasicModal @register="registerModal" v-bind="$attrs" wrapClassName="form-modal">
|
||||
<template #title>
|
||||
<div class="step-form-form">
|
||||
<a href="https://fcdma.gdyditc.com/" target="_blank">
|
||||
<DesignLogo />
|
||||
</a>
|
||||
<span>•</span>
|
||||
<span>{{ t('表单设计') }} - {{ t('数据优先') }}</span>
|
||||
<a-steps :current="current">
|
||||
<a-step :title="t('基础信息')" />
|
||||
<a-step :title="t('表单设计')" />
|
||||
<a-step :title="t('表单事件')" />
|
||||
<a-step :title="t('完整配置')" />
|
||||
</a-steps>
|
||||
<div class="btn-box">
|
||||
<ajax-error-icon />
|
||||
<a-button type="primary" @click="handleStepPrev" v-show="current !== 0">{{
|
||||
t('上一步')
|
||||
}}</a-button>
|
||||
<a-button type="primary" @click="handleStepNext" v-show="current < 3">{{
|
||||
t('下一步')
|
||||
}}</a-button>
|
||||
<a-button type="primary" @click="handleSave" v-show="current === 3">{{
|
||||
t('保存')
|
||||
}}</a-button>
|
||||
<a-button type="primary" danger @click="handleClose">{{ t('关闭') }}</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="step-container">
|
||||
<BasicConfigStep ref="basicConfigStepRef" v-show="current === 0" />
|
||||
<FormDesignStep ref="formDesignStepRef" v-show="current === 1" />
|
||||
<FormEventStep ref="formEventStepRef" v-show="current === 2" />
|
||||
<EntireConfigStep ref="entireConfigStepRef" v-show="current === 3"/>
|
||||
</div>
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, provide, watch, Ref, toRaw, onUnmounted } from 'vue';
|
||||
import BasicConfigStep from '../BasicConfigStep.vue';
|
||||
import { FormDesignStep, FormEventStep,EntireConfigStep } from '/@/components/CreateCodeStep';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { CustomFormConfig, GeneratorConfig } from '/@/model/generator/generatorConfig';
|
||||
import { TableInfo } from '/@/components/Designer';
|
||||
import AjaxErrorIcon from '/@/components/SecondDev/AjaxErrorIcon.vue';
|
||||
import {
|
||||
addDataFirstFormTemplate,
|
||||
updateDataFirstFormTemplate,
|
||||
getFormTemplate,
|
||||
} from '/@/api/form/design';
|
||||
import { FormTypeEnum } from '/@/enums/formtypeEnum';
|
||||
import * as antd from '/@/components/Designer/src/types';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import DesignLogo from '/@/components/ModalPanel/src/DesignLogo.vue';
|
||||
import useGlobalFlag from '/@/hooks/core/useGlobalFlag';
|
||||
import {ListConfig} from "/@/model/generator/listConfig";
|
||||
|
||||
const { t } = useI18n();
|
||||
const current = ref(0);
|
||||
|
||||
const basicConfigStepRef = ref();
|
||||
const formDesignStepRef = ref();
|
||||
const formEventStepRef = ref();
|
||||
const entireConfigStepRef = ref();
|
||||
|
||||
const tableInfo = ref<TableInfo[]>([]);
|
||||
const widgetForm = ref(JSON.parse(JSON.stringify(antd.widgetForm)));
|
||||
const isUpdate = ref<boolean>(false);
|
||||
const formId = ref<string>('');
|
||||
const emits = defineEmits(['success', 'register', 'close']);
|
||||
const globalFlag = useGlobalFlag();
|
||||
const { isEditorOpen } = globalFlag;
|
||||
|
||||
watch(current, () => {
|
||||
isEditorOpen.value = current.value === 1;
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
isEditorOpen.value = false;
|
||||
});
|
||||
|
||||
let generatorConfig = reactive<GeneratorConfig>({
|
||||
databaseId: '', //数据库id
|
||||
tableConfigs: [],
|
||||
formJson: {},
|
||||
formEventConfig: {},
|
||||
isDataAuth: false,
|
||||
dataAuthList: [],
|
||||
});
|
||||
let customFormConfig = reactive<CustomFormConfig>({
|
||||
name: '',
|
||||
category: '',
|
||||
formDesignType: 0,
|
||||
formType: '',
|
||||
formJson: generatorConfig,
|
||||
remark: '',
|
||||
});
|
||||
|
||||
provide<GeneratorConfig>('generatorConfig', generatorConfig);
|
||||
provide<CustomFormConfig>('customFormConfig', customFormConfig);
|
||||
provide<Ref<TableInfo[]>>('tableInfo', tableInfo);
|
||||
provide<string>('designType', 'data');
|
||||
provide('widgetForm', widgetForm);
|
||||
provide<Ref<number>>('current', current); //当前步骤
|
||||
provide<boolean>('isCustomForm', true); //是自定义表单
|
||||
|
||||
watch(
|
||||
() => generatorConfig,
|
||||
(val) => {
|
||||
customFormConfig.formJson = val;
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
},
|
||||
);
|
||||
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner((data) => {
|
||||
isUpdate.value = !!data.isUpdate;
|
||||
formId.value = data.id;
|
||||
if (formId.value) getFormTemplateInfo();
|
||||
setModalProps({
|
||||
confirmLoading: false,
|
||||
canFullscreen: false,
|
||||
defaultFullscreen: true,
|
||||
destroyOnClose: true,
|
||||
draggable: false,
|
||||
showOkBtn: false,
|
||||
showCancelBtn: false,
|
||||
footer: null,
|
||||
closable: false,
|
||||
});
|
||||
});
|
||||
|
||||
async function getFormTemplateInfo() {
|
||||
const data = await getFormTemplate(formId.value);
|
||||
customFormConfig.name = data.name;
|
||||
customFormConfig.category = data.category;
|
||||
customFormConfig.formDesignType = data.formDesignType;
|
||||
customFormConfig.formJson = JSON.parse(data.formJson);
|
||||
customFormConfig.listConfig = JSON.parse(data.listConfig)||{} as ListConfig;
|
||||
customFormConfig.renderConfig =data.renderConfig;
|
||||
customFormConfig.remark = data.remark;
|
||||
|
||||
const { formJson,listConfig,renderConfig } = customFormConfig;
|
||||
|
||||
generatorConfig.databaseId = formJson.databaseId;
|
||||
generatorConfig.isDataAuth = formJson.isDataAuth;
|
||||
generatorConfig.dataAuthList = formJson.dataAuthList;
|
||||
generatorConfig.tableConfigs = formJson.tableConfigs;
|
||||
generatorConfig.formJson = formJson.formJson;
|
||||
generatorConfig.listConfig = listConfig;
|
||||
generatorConfig.renderConfig = renderConfig;
|
||||
generatorConfig.formEventConfig = formJson.formEventConfig!;
|
||||
generatorConfig.formJson.list = generatorConfig.formJson.list.filter(
|
||||
(x) => x.type !== 'hiddenComponent',
|
||||
);
|
||||
widgetForm.value = generatorConfig.formJson;
|
||||
basicConfigStepRef.value.setFieldsValue({
|
||||
name: customFormConfig?.name,
|
||||
category: customFormConfig?.category,
|
||||
remark: customFormConfig?.remark,
|
||||
databaseId: generatorConfig.databaseId,
|
||||
isDataAuth: generatorConfig.isDataAuth,
|
||||
dataAuthList: generatorConfig.dataAuthList,
|
||||
});
|
||||
}
|
||||
|
||||
function handleClose() {
|
||||
closeModal();
|
||||
emits('close');
|
||||
}
|
||||
|
||||
//上一步
|
||||
function handleStepPrev() {
|
||||
current.value--;
|
||||
if(current.value==1){
|
||||
widgetForm.value = generatorConfig.formJson;
|
||||
}
|
||||
}
|
||||
//下一步
|
||||
async function handleStepNext() {
|
||||
const isOk = await stepValidate[current.value]();
|
||||
if (!isOk) {
|
||||
return;
|
||||
}
|
||||
current.value++;
|
||||
|
||||
if(current.value === 3){
|
||||
entireConfigStepRef.value.initStep();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function handleSave() {
|
||||
const isOk = await stepValidate[3]();
|
||||
if (!isOk) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
generatorConfig.formJson?.hiddenComponent &&
|
||||
generatorConfig.formJson?.hiddenComponent.length
|
||||
) {
|
||||
generatorConfig.formJson.list.push(...generatorConfig.formJson.hiddenComponent);
|
||||
}
|
||||
if (isUpdate.value) {
|
||||
await updateDataFirstFormTemplate({ id: formId.value, ...toRaw(customFormConfig) });
|
||||
} else {
|
||||
await addDataFirstFormTemplate(toRaw(customFormConfig));
|
||||
}
|
||||
|
||||
closeModal();
|
||||
emits('close');
|
||||
emits('success');
|
||||
}
|
||||
|
||||
const stepValidate = {
|
||||
//数据表配置 验证
|
||||
0: () => basicConfigStepRef.value.validateStep(),
|
||||
1: () => formDesignStepRef.value.validateStep(),
|
||||
2: () => formEventStepRef.value.validateStep(),
|
||||
3: () => entireConfigStepRef.value.validateStep(),
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@keyframes rotation {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes rotationReverse {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(-360deg);
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-steps-item-process) {
|
||||
.ant-steps-item-icon {
|
||||
border: 2px solid #fff;
|
||||
line-height: 30px;
|
||||
animation: rotation 4s linear infinite;
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
border: 2px dashed #1890ff;
|
||||
content: '';
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
display: block;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
left: -4px;
|
||||
top: -4px;
|
||||
}
|
||||
|
||||
.ant-steps-icon {
|
||||
display: inline-block;
|
||||
animation: rotationReverse 4s linear infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.step-form-content {
|
||||
padding: 24px;
|
||||
background-color: @component-background;
|
||||
}
|
||||
|
||||
.step-form-form {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 400;
|
||||
|
||||
a {
|
||||
margin-left: -16px;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 16px;
|
||||
margin: 0 20px 0 -5px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
:deep(.ant-steps) {
|
||||
width: calc(100% - 750px);
|
||||
}
|
||||
|
||||
:deep(.ant-steps-item-container) {
|
||||
padding: 3px 0 3px 3px;
|
||||
}
|
||||
|
||||
.btn-box {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
|
||||
:deep(.ant-btn) {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.step-container {
|
||||
height: calc(100% - 50px);
|
||||
}
|
||||
|
||||
.step1 {
|
||||
padding: 14px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,411 @@
|
||||
<template>
|
||||
<BasicModal @register="registerModal" v-bind="$attrs" wrapClassName="form-modal">
|
||||
<template #title>
|
||||
<div class="step-form-form">
|
||||
<a href="https://fcdma.gdyditc.com/" target="_blank">
|
||||
<DesignLogo />
|
||||
</a>
|
||||
<span>•</span>
|
||||
<span>{{ t('表单设计') }} - {{ t('简易模板') }}</span>
|
||||
<a-steps :current="current" size="mini">
|
||||
<a-step :title="t('基础信息')" />
|
||||
<a-step :title="t('表单设计')" />
|
||||
<a-step :title="t('表单事件')" />
|
||||
<a-step :title="t('完整配置')" />
|
||||
</a-steps>
|
||||
<div class="btn-box">
|
||||
<a-button @click="handleStepPrev" v-show="current !== 0">{{ t('上一步') }}</a-button>
|
||||
<a-button type="primary" @click="handleStepNext" v-show="current < 3">
|
||||
{{ t('下一步') }}
|
||||
</a-button>
|
||||
<a-button type="primary" @click="handleSave" v-show="current === 3">
|
||||
{{ t('保存') }}
|
||||
</a-button>
|
||||
<a-button type="primary" danger @click="handleClose">{{ t('关闭') }}</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="step-container">
|
||||
<BasicConfigStep ref="basicConfigStepRef" v-show="current === 0" />
|
||||
<FormDesignStep ref="formDesignStepRef" v-show="current === 1" />
|
||||
<FormEventStep ref="formEventStepRef" v-show="current === 2" />
|
||||
<EntireConfigStep ref="entireConfigStepRef" v-show="current === 3"/>
|
||||
</div>
|
||||
</BasicModal>
|
||||
<TableNameModal @register="registerTableName" @success="handleEditSuccess" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, provide, Ref, toRaw, watch, onMounted } from 'vue';
|
||||
import { FormDesignStep, FormEventStep,EntireConfigStep,TableNameModal } from '/@/components/CreateCodeStep';
|
||||
import BasicConfigStep from '../BasicConfigStep.vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { GeneratorConfig, CustomFormConfig } from '/@/model/generator/generatorConfig';
|
||||
import { TableInfo, upperFieldDb } from '/@/components/Designer';
|
||||
import { validateTableName, getMasterInfo } from '/@/api/system/generator';
|
||||
import {
|
||||
addCodeFirstFormTemplate,
|
||||
updateCodeFirstFormTemplate,
|
||||
getFormTemplate,
|
||||
} from '/@/api/form/design';
|
||||
import { FormTypeEnum } from '/@/enums/formtypeEnum';
|
||||
import * as antd from '/@/components/Designer/src/types';
|
||||
import { random } from 'lodash-es';
|
||||
import { noHaveTableAndField } from '/@/components/Designer';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import DesignLogo from '/@/components/ModalPanel/src/DesignLogo.vue';
|
||||
import {ListConfig} from "/@/model/generator/listConfig";
|
||||
|
||||
const { t } = useI18n();
|
||||
const current = ref(0);
|
||||
|
||||
const basicConfigStepRef = ref();
|
||||
const formDesignStepRef = ref();
|
||||
const formEventStepRef = ref();
|
||||
const entireConfigStepRef = ref();
|
||||
|
||||
const widgetForm = ref(JSON.parse(JSON.stringify(antd.widgetForm))); //FormDesignStep -> designer和StructureConfigStep页面使用
|
||||
const mainTableName = ref('table_' + random(10000, 99999));
|
||||
|
||||
const tableInfo = ref<TableInfo[]>([]);
|
||||
const isUpdate = ref<boolean>(false);
|
||||
const formId = ref<string>('');
|
||||
const beforeTableNames = ref<string[]>([]);
|
||||
const isFieldUpper = ref<boolean>(false);
|
||||
|
||||
let generatorConfig = reactive<GeneratorConfig>({
|
||||
databaseId: 'master',
|
||||
formJson: {},
|
||||
tableStructureConfigs: [],
|
||||
formEventConfig: {},
|
||||
isDataAuth: false,
|
||||
dataAuthList: [],
|
||||
});
|
||||
|
||||
let customFormConfig = reactive<CustomFormConfig>({
|
||||
name: '',
|
||||
category: '',
|
||||
formDesignType: 2,
|
||||
formType:'',
|
||||
formJson: generatorConfig,
|
||||
remark: '',
|
||||
isChange: false,
|
||||
});
|
||||
|
||||
const [registerTableName, { openModal }] = useModal();
|
||||
|
||||
provide<GeneratorConfig>('generatorConfig', generatorConfig);
|
||||
provide<Ref<TableInfo[]>>('tableInfo', tableInfo);
|
||||
provide<CustomFormConfig>('customFormConfig', customFormConfig);
|
||||
provide<Ref<number>>('current', current); //当前步骤
|
||||
provide<string>('designType', 'template');
|
||||
provide('widgetForm', widgetForm);
|
||||
provide<Ref<string>>('mainTableName', mainTableName);
|
||||
provide<boolean>('isCustomForm', true); //是自定义表单
|
||||
provide<Ref<boolean>>('isFieldUpper', isFieldUpper);
|
||||
|
||||
watch(
|
||||
() => generatorConfig,
|
||||
(val) => {
|
||||
customFormConfig.formJson = val;
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
},
|
||||
);
|
||||
const emits = defineEmits(['success', 'register', 'close']);
|
||||
|
||||
onMounted(async () => {
|
||||
const res = await getMasterInfo();
|
||||
isFieldUpper.value = upperFieldDb.includes(res?.dbType || '');
|
||||
mainTableName.value = isFieldUpper.value
|
||||
? mainTableName.value.toUpperCase()
|
||||
: mainTableName.value;
|
||||
});
|
||||
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
isUpdate.value = !!data.isUpdate;
|
||||
formId.value = data.id;
|
||||
customFormConfig.isChange = isUpdate.value;
|
||||
if (formId.value) {
|
||||
getFormTemplateInfo();
|
||||
}
|
||||
setModalProps({
|
||||
confirmLoading: false,
|
||||
canFullscreen: false,
|
||||
defaultFullscreen: true,
|
||||
destroyOnClose: true,
|
||||
draggable: false,
|
||||
showOkBtn: false,
|
||||
showCancelBtn: false,
|
||||
footer: null,
|
||||
closable: false,
|
||||
});
|
||||
});
|
||||
|
||||
async function getFormTemplateInfo() {
|
||||
const data = await getFormTemplate(formId.value);
|
||||
customFormConfig.name = data.name;
|
||||
customFormConfig.category = data.category;
|
||||
customFormConfig.formDesignType = data.formDesignType;
|
||||
customFormConfig.formJson = JSON.parse(data.formJson);
|
||||
customFormConfig.listConfig = JSON.parse(data.listConfig)||{} as ListConfig;
|
||||
customFormConfig.renderConfig =data.renderConfig;
|
||||
customFormConfig.remark = data.remark;
|
||||
|
||||
const { formJson,listConfig,renderConfig } = customFormConfig;
|
||||
|
||||
generatorConfig.databaseId = formJson.databaseId;
|
||||
generatorConfig.isDataAuth = formJson.isDataAuth;
|
||||
generatorConfig.dataAuthList = formJson.dataAuthList;
|
||||
generatorConfig.tableStructureConfigs = formJson.tableStructureConfigs;
|
||||
generatorConfig.formJson = formJson.formJson;
|
||||
generatorConfig.listConfig = listConfig;
|
||||
generatorConfig.renderConfig = renderConfig;
|
||||
generatorConfig.formEventConfig = formJson.formEventConfig!;
|
||||
generatorConfig.formJson.list = generatorConfig.formJson.list.filter(
|
||||
(x) => x.type !== 'hiddenComponent',
|
||||
);
|
||||
beforeTableNames.value = generatorConfig.tableStructureConfigs?.map((x) => x.tableName) || [];
|
||||
getMainTableFirst(generatorConfig.formJson.list);
|
||||
|
||||
widgetForm.value = generatorConfig.formJson;
|
||||
|
||||
basicConfigStepRef.value.setFieldsValue({
|
||||
name: customFormConfig?.name,
|
||||
category: customFormConfig?.category,
|
||||
remark: customFormConfig?.remark,
|
||||
databaseId: generatorConfig.databaseId,
|
||||
isDataAuth: generatorConfig.isDataAuth,
|
||||
dataAuthList: generatorConfig.dataAuthList,
|
||||
});
|
||||
}
|
||||
|
||||
function getMainTableFirst(list) {
|
||||
list.some((x) => {
|
||||
if (['tab', 'grid', 'card'].includes(x.type)) {
|
||||
for (const child of x.layout!) {
|
||||
return getMainTableFirst(child.list);
|
||||
}
|
||||
} else if (x.type === 'table-layout') {
|
||||
for (const child of x.layout!) {
|
||||
for (const el of child.list!) {
|
||||
return getMainTableFirst(el.children);
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
x.type !== 'form' &&
|
||||
x.type !== 'one-for-one' &&
|
||||
!noHaveTableAndField.includes(x.type)
|
||||
) {
|
||||
mainTableName.value = x.bindTable;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleClose() {
|
||||
closeModal();
|
||||
emits('close');
|
||||
}
|
||||
|
||||
//上一步
|
||||
function handleStepPrev() {
|
||||
current.value--;
|
||||
if(current.value==1){
|
||||
widgetForm.value = generatorConfig.formJson;
|
||||
}
|
||||
}
|
||||
//下一步
|
||||
async function handleStepNext() {
|
||||
const isOk = await stepValidate[current.value]();
|
||||
if (!isOk) {
|
||||
return;
|
||||
}
|
||||
current.value++;
|
||||
|
||||
if(current.value === 3){
|
||||
entireConfigStepRef.value.initStep();
|
||||
}
|
||||
}
|
||||
async function handleSave() {
|
||||
const isOk = await stepValidate[3]();
|
||||
|
||||
if (!isOk) {
|
||||
return;
|
||||
}
|
||||
const tableNames: string[] = generatorConfig.tableStructureConfigs!.map((x) => x.tableName);
|
||||
|
||||
const testTableNames = tableNames.filter((x) => {
|
||||
return !beforeTableNames.value.includes(x);
|
||||
});
|
||||
|
||||
if (!isUpdate.value || (isUpdate.value && testTableNames.length)) {
|
||||
const names = isUpdate.value ? testTableNames.toString() : tableNames.toString();
|
||||
validateName(names);
|
||||
} else {
|
||||
submitTemplate();
|
||||
}
|
||||
}
|
||||
|
||||
const validateName = (tableNames) => {
|
||||
const params = {
|
||||
id: 'master',
|
||||
tableNames,
|
||||
};
|
||||
validateTableName(params, 'none')
|
||||
.then(() => {
|
||||
submitTemplate();
|
||||
})
|
||||
.catch((err) => {
|
||||
if (!err) return;
|
||||
const info = err.message.split('[')[1];
|
||||
const existTableName = info.substring(0, info.length - 1).split(',');
|
||||
const newTableName: string[] = [];
|
||||
generatorConfig?.tableStructureConfigs!.map((table) => {
|
||||
const tableName = 'table_' + random(10000, 99999);
|
||||
if (existTableName.includes(table.tableName)) {
|
||||
table.tableName = tableName;
|
||||
}
|
||||
newTableName.push(tableName);
|
||||
generatorConfig.formJson.list.map((component) => {
|
||||
editTableName(component, existTableName, tableName);
|
||||
});
|
||||
});
|
||||
validateName(newTableName.toString());
|
||||
});
|
||||
};
|
||||
const editTableName = (component, existTableName, tableName) => {
|
||||
if (existTableName.includes(component.bindTable)) {
|
||||
component.bindTable = tableName;
|
||||
if (component.children || component.layout || component.list) {
|
||||
editTableName(component.children, existTableName, tableName);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const submitTemplate = async () => {
|
||||
if (
|
||||
generatorConfig.formJson?.hiddenComponent &&
|
||||
generatorConfig.formJson?.hiddenComponent.length
|
||||
) {
|
||||
generatorConfig.formJson.list.push(...generatorConfig.formJson.hiddenComponent);
|
||||
}
|
||||
if (isUpdate.value) {
|
||||
openModal();
|
||||
} else {
|
||||
await addCodeFirstFormTemplate(toRaw(customFormConfig));
|
||||
closeModal();
|
||||
emits('success');
|
||||
emits('close');
|
||||
}
|
||||
};
|
||||
|
||||
async function handleEditSuccess() {
|
||||
await updateCodeFirstFormTemplate({ id: formId.value, ...toRaw(customFormConfig) });
|
||||
closeModal();
|
||||
emits('success');
|
||||
emits('close');
|
||||
}
|
||||
|
||||
const stepValidate = {
|
||||
//数据表配置 验证
|
||||
0: () => basicConfigStepRef.value.validateStep(),
|
||||
1: () => formDesignStepRef.value.validateStep(),
|
||||
2: () => formEventStepRef.value.validateStep(),
|
||||
3: () => entireConfigStepRef.value.validateStep(),
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@keyframes rotation {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes rotationReverse {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(-360deg);
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-steps-item-process) {
|
||||
.ant-steps-item-icon {
|
||||
border: 2px solid #fff;
|
||||
line-height: 30px;
|
||||
animation: rotation 4s linear infinite;
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
border: 2px dashed #1890ff;
|
||||
content: '';
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
display: block;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
left: -4px;
|
||||
top: -4px;
|
||||
}
|
||||
|
||||
.ant-steps-icon {
|
||||
display: inline-block;
|
||||
animation: rotationReverse 4s linear infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.step-form-content {
|
||||
padding: 24px;
|
||||
background-color: @component-background;
|
||||
}
|
||||
|
||||
.step-form-form {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 400;
|
||||
|
||||
a {
|
||||
margin-left: -16px;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 16px;
|
||||
margin: 0 20px 0 -5px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
:deep(.ant-steps) {
|
||||
width: calc(100% - 750px);
|
||||
}
|
||||
|
||||
:deep(.ant-steps-item-container) {
|
||||
padding: 3px 0 3px 3px;
|
||||
}
|
||||
|
||||
.btn-box {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
|
||||
:deep(.ant-btn) {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.step-container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.step1 {
|
||||
padding: 0 14px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user