style: lint格式化文件

This commit is contained in:
2025-10-21 18:04:02 +08:00
parent f9ca969fec
commit 7629120548
1092 changed files with 148218 additions and 157907 deletions

View File

@ -1,118 +1,120 @@
<template>
<div class="entireConfigStep">
<a-tabs v-model:activeKey="activeKey" size="large" class="tab-list">
<a-tab-pane key="1" tab="列表配置">
<CodeEditor v-model:value="listConfigObject" @change="handleListConfigChange" language="json" />
</a-tab-pane>
<a-tab-pane key="2" tab="表单配置">
<CodeEditor v-model:value="formConfigObject" @change="handleFormConfigChange" language="json" />
</a-tab-pane>
<a-tab-pane key="3" tab="渲染覆盖配置">
<CodeEditor v-model:value="renderConfigObject" @change="handleRenderConfigChange" :mode="MODE.JS" />
</a-tab-pane>
</a-tabs>
</div>
<div class="entireConfigStep">
<a-tabs v-model:activeKey="activeKey" size="large" class="tab-list">
<a-tab-pane key="1" tab="列表配置">
<CodeEditor v-model:value="listConfigObject" @change="handleListConfigChange" language="json" />
</a-tab-pane>
<a-tab-pane key="2" tab="表单配置">
<CodeEditor v-model:value="formConfigObject" @change="handleFormConfigChange" language="json" />
</a-tab-pane>
<a-tab-pane key="3" tab="渲染覆盖配置">
<CodeEditor v-model:value="renderConfigObject" @change="handleRenderConfigChange" :mode="MODE.JS" />
</a-tab-pane>
</a-tabs>
</div>
</template>
<script lang="ts" setup>
import { onMounted, inject,watch,computed, ref,unref} from 'vue';
import { onMounted, inject, watch, computed, ref, unref } from 'vue';
import { useI18n } from '/@/hooks/web/useI18n';
import { useMessage } from '/@/hooks/web/useMessage';
import { debounce} from 'lodash-es';
import {CustomFormConfig, GeneratorConfig} from '/@/model/generator/generatorConfig';
import { CodeEditor,MODE } from '/@/components/CodeEditor';
import {ListConfig} from "/@/model/generator/listConfig";
import { debounce } from 'lodash-es';
import { CustomFormConfig, GeneratorConfig } from '/@/model/generator/generatorConfig';
import { CodeEditor, MODE } from '/@/components/CodeEditor';
import { ListConfig } from '/@/model/generator/listConfig';
const { t } = useI18n();
const { notification } = useMessage();
const generatorConfig = inject<GeneratorConfig>('generatorConfig');
const customFormConfig = inject<CustomFormConfig>('customFormConfig');
const listConfigObject=ref();
const formConfigObject=ref();
const renderConfigObject=ref();
const listConfigObject = ref();
const formConfigObject = ref();
const renderConfigObject = ref();
const activeKey = ref('1');
onMounted(() => {
});
const handleListConfigChange=debounce((v)=>{
try{
let jsonObject = JSON.parse(v);
generatorConfig.listConfig.queryConfigs= jsonObject.queryConfigs;
generatorConfig.listConfig.columnConfigs= jsonObject.columnConfigs;
generatorConfig.listConfig.buttonConfigs= jsonObject.buttonConfigs;
}catch(e){
console.log(e);
notification.error({
message: t('提示'),
description: t('列表配置json格式有误'),
});
}
},1000);
onMounted(() => {});
const handleFormConfigChange=debounce((v)=>{
try{
generatorConfig.formJson= JSON.parse(v);
}catch(e){
console.error(e);
notification.error({
message: t('提示'),
description: t('表单配置json格式有误'),
});
}
},1000);
const handleListConfigChange = debounce((v) => {
try {
let jsonObject = JSON.parse(v);
generatorConfig.listConfig.queryConfigs = jsonObject.queryConfigs;
generatorConfig.listConfig.columnConfigs = jsonObject.columnConfigs;
generatorConfig.listConfig.buttonConfigs = jsonObject.buttonConfigs;
} catch (e) {
console.log(e);
notification.error({
message: t('提示'),
description: t('列表配置json格式有误')
});
}
}, 1000);
const handleRenderConfigChange=debounce((v)=>{
customFormConfig.renderConfig=v;
},1000);
const handleFormConfigChange = debounce((v) => {
try {
generatorConfig.formJson = JSON.parse(v);
} catch (e) {
console.error(e);
notification.error({
message: t('提示'),
description: t('表单配置json格式有误')
});
}
}, 1000);
const initStep =()=> {
listConfigObject.value=JSON.stringify({
queryConfigs:generatorConfig.listConfig.queryConfigs||[],
columnConfigs:generatorConfig.listConfig.columnConfigs||[],
buttonConfigs:generatorConfig.listConfig.buttonConfigs||[]
}, null, 2);
const handleRenderConfigChange = debounce((v) => {
customFormConfig.renderConfig = v;
}, 1000);
formConfigObject.value=JSON.stringify(generatorConfig.formJson, null, 2);
renderConfigObject.value= customFormConfig.renderConfig||'';
}
const validateStep = async (): Promise<boolean> => {
try{
let jsonObject = JSON.parse(listConfigObject.value);
generatorConfig.listConfig.queryConfigs= jsonObject.queryConfigs;
generatorConfig.listConfig.columnConfigs= jsonObject.columnConfigs;
generatorConfig.listConfig.buttonConfigs= jsonObject.buttonConfigs;
}catch(e){
console.error(e);
notification.error({
message: t('提示'),
description: t('列表配置json格式有误'),
});
return false;
}
try{
generatorConfig.formJson= JSON.parse(formConfigObject.value);
}catch(e){
console.error(e);
notification.error({
message: t('提示'),
description: t('表单配置json格式有误'),
});
return false;
}
const initStep = () => {
listConfigObject.value = JSON.stringify(
{
queryConfigs: generatorConfig.listConfig.queryConfigs || [],
columnConfigs: generatorConfig.listConfig.columnConfigs || [],
buttonConfigs: generatorConfig.listConfig.buttonConfigs || []
},
null,
2
);
customFormConfig.renderConfig=renderConfigObject.value;
formConfigObject.value = JSON.stringify(generatorConfig.formJson, null, 2);
renderConfigObject.value = customFormConfig.renderConfig || '';
};
return true;
}
const validateStep = async (): Promise<boolean> => {
try {
let jsonObject = JSON.parse(listConfigObject.value);
generatorConfig.listConfig.queryConfigs = jsonObject.queryConfigs;
generatorConfig.listConfig.columnConfigs = jsonObject.columnConfigs;
generatorConfig.listConfig.buttonConfigs = jsonObject.buttonConfigs;
} catch (e) {
console.error(e);
notification.error({
message: t('提示'),
description: t('列表配置json格式有误')
});
return false;
}
try {
generatorConfig.formJson = JSON.parse(formConfigObject.value);
} catch (e) {
console.error(e);
notification.error({
message: t('提示'),
description: t('表单配置json格式有误')
});
return false;
}
defineExpose({initStep,validateStep});
</script>
customFormConfig.renderConfig = renderConfigObject.value;
return true;
};
defineExpose({ initStep, validateStep });
</script>
<style lang="less" scoped>
.entireConfigStep{
height:100%;
.entireConfigStep {
height: 100%;
}
:deep(.ant-tabs-nav-wrap) {
@ -141,10 +143,7 @@
margin-bottom: 0;
}
.tab-list {
height: 100%;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -1,263 +1,225 @@
<template>
<div style="height: 100%">
<div class="event-box">
<div>
<EventArea
:columnList="generatorConfig!.formEventConfig[0]"
:index="0"
@delete-event="deleteEvent"
@click-node="clickNode"
/>
<AddEvent :lineHeight="`${lineHeight[0]}px`" @click="addEvent(0)" />
</div>
<div class="box-second">
<EventArea
:columnList="generatorConfig!.formEventConfig[1]"
:index="1"
@delete-event="deleteEvent"
@click-node="clickNode"
/>
<AddEvent :lineHeight="`${lineHeight[1]}px`" @click="addEvent(1)" />
</div>
<div class="box-third">
<EventArea
:columnList="generatorConfig!.formEventConfig[2]"
:index="2"
@delete-event="deleteEvent"
@click-node="clickNode"
/>
<AddEvent :lineHeight="`${lineHeight[2]}px`" @click="addEvent(2)" />
</div>
<div class="box-fourth">
<EventArea
:columnList="generatorConfig!.formEventConfig[3]"
:index="3"
@delete-event="deleteEvent"
@click-node="clickNode"
/>
<AddEvent :isLast="true" @click="addEvent(3)" />
<EventArea
:columnList="generatorConfig!.formEventConfig[4]"
:index="4"
@click-node="clickNode"
/>
</div>
<div style="height: 100%">
<div class="event-box">
<div>
<EventArea :columnList="generatorConfig!.formEventConfig[0]" :index="0" @delete-event="deleteEvent" @click-node="clickNode" />
<AddEvent :lineHeight="`${lineHeight[0]}px`" @click="addEvent(0)" />
</div>
<div class="box-second">
<EventArea :columnList="generatorConfig!.formEventConfig[1]" :index="1" @delete-event="deleteEvent" @click-node="clickNode" />
<AddEvent :lineHeight="`${lineHeight[1]}px`" @click="addEvent(1)" />
</div>
<div class="box-third">
<EventArea :columnList="generatorConfig!.formEventConfig[2]" :index="2" @delete-event="deleteEvent" @click-node="clickNode" />
<AddEvent :lineHeight="`${lineHeight[2]}px`" @click="addEvent(2)" />
</div>
<div class="box-fourth">
<EventArea :columnList="generatorConfig!.formEventConfig[3]" :index="3" @delete-event="deleteEvent" @click-node="clickNode" />
<AddEvent :isLast="true" @click="addEvent(3)" />
<EventArea :columnList="generatorConfig!.formEventConfig[4]" :index="4" @click-node="clickNode" />
</div>
</div>
<NodeEvent v-model:columnList="generatorConfig!.formEventConfig" :selectedNode="selectedNode" />
</div>
<NodeEvent v-model:columnList="generatorConfig!.formEventConfig" :selectedNode="selectedNode" />
</div>
</template>
<script lang="ts" setup>
import { ref, Ref, reactive, inject, watch } from 'vue';
import EventArea from './components/EventArea.vue';
import NodeEvent from './components/NodeEvent.vue';
import AddEvent from './components/AddEvent.vue';
import { GeneratorConfig } from '/@/model/generator/generatorConfig';
import {
FormEventColumnConfig,
FormEventStyleConfig,
selectedNodeConfig,
} from '/@/model/generator/formEventConfig';
import { useMessage } from '/@/hooks/web/useMessage';
import { useI18n } from '/@/hooks/web/useI18n';
import { changeCompsApiConfig, changeEventApiConfig, getMainTable } from '/@/utils/event/design';
import { cloneDeep } from 'lodash-es';
import { ref, Ref, reactive, inject, watch } from 'vue';
import EventArea from './components/EventArea.vue';
import NodeEvent from './components/NodeEvent.vue';
import AddEvent from './components/AddEvent.vue';
import { GeneratorConfig } from '/@/model/generator/generatorConfig';
import { FormEventColumnConfig, FormEventStyleConfig, selectedNodeConfig } from '/@/model/generator/formEventConfig';
import { useMessage } from '/@/hooks/web/useMessage';
import { useI18n } from '/@/hooks/web/useI18n';
import { changeCompsApiConfig, changeEventApiConfig, getMainTable } from '/@/utils/event/design';
import { cloneDeep } from 'lodash-es';
const { t } = useI18n();
const { notification } = useMessage();
const current = inject<Ref<number>>('current');
const isCustomForm = inject<boolean>('isCustomForm', false);
const designType = inject<string>('designType');
const widgetForm = inject<any>('widgetForm');
const fromMobile = inject<Boolean>('fromMobile', false);
const generatorConfig = inject<GeneratorConfig>('generatorConfig');
let lineHeight = reactive<number[]>([]);
let column = reactive<FormEventColumnConfig>({
0: [
{
type: 'circle',
color: '#2774ff',
text: t('开始节点'),
icon: '#icon-kaishi',
bgcColor: '#D8E5FF',
isUserDefined: false,
},
{
color: '#F6AB01',
icon: '#icon-chushihua',
text: t('初始化表单'),
bgcColor: '#f9f5ea',
isUserDefined: false,
nodeInfo: {
processEvent: [],
},
},
],
1: [
{
color: '#B36EDB',
icon: '#icon-shujufenxi',
text: t('获取表单数据'),
detail: t('(新增无此操作)'),
bgcColor: '#F8F2FC',
isUserDefined: false,
nodeInfo: {
processEvent: [],
},
},
],
2: [
{
color: '#F8625C',
icon: '#icon-jiazai',
text: t('加载表单'),
bgcColor: '#FFF1F1',
isUserDefined: false,
nodeInfo: {
processEvent: [],
},
},
],
3: [
{
color: '#6C6AE0',
icon: '#icon-jsontijiao',
text: t('提交表单'),
bgcColor: '#F5F4FF',
isUserDefined: false,
nodeInfo: {
processEvent: [],
},
},
],
4: [
{
type: 'circle',
color: '#F8625C',
text: t('结束节点'),
icon: '#icon-jieshuzhiliao',
bgcColor: '#FFD6D6',
isLast: true,
isUserDefined: false,
},
],
});
watch(
() => current?.value,
(val) => {
//自定义表单当前步骤为2 或 代码生成器 数据优先当前步骤为2 或 代码生成器 界面优先、简易模板 当前步骤为1
if (
(isCustomForm && val === 2) ||
(!isCustomForm &&
((designType === 'data' && val === 2) || (designType !== 'data' && val === 1)))
) {
if (
((isCustomForm && designType == 'code') || (!isCustomForm && designType !== 'data')) &&
generatorConfig!.tableStructureConfigs
) {
let tableFieldConfigs = getMainTable(generatorConfig!.tableStructureConfigs);
changeCompsApiConfig(generatorConfig!.formJson.list, designType, tableFieldConfigs);
changeEventApiConfig(generatorConfig!.formEventConfig, designType, tableFieldConfigs);
widgetForm.value.list = cloneDeep(generatorConfig!.formJson.list);
}
if (
generatorConfig?.formEventConfig &&
Object.keys(generatorConfig!.formEventConfig)?.length
) {
column = generatorConfig!.formEventConfig!;
lineHeight[0] = 135 + (column[0].length - 2) * 158;
lineHeight[1] = 50 + (column[1].length - 1) * 158;
lineHeight[2] = 50 + (column[2].length - 1) * 158;
} else {
generatorConfig!.formEventConfig = column;
lineHeight[0] = 135;
lineHeight[1] = 50;
lineHeight[2] = 50;
}
}
},
);
const selectedNode = ref<selectedNodeConfig>();
const addEvent = (index) => {
if (fromMobile) return;
const columnInfo: FormEventStyleConfig = {
color: '#2774FF',
icon: '#icon-yonghu-xianxing',
text: t('用户自定义节点'),
bgcColor: '#F5F8FA',
isUserDefined: true,
nodeInfo: {
processEvent: [],
},
};
column[index].push(columnInfo);
if (index === 3) return;
lineHeight[index] += 158;
};
const deleteEvent = ({ index, columnIndex }) => {
if (fromMobile) return;
column[columnIndex].splice(index, 1);
lineHeight[columnIndex] -= 158;
};
const clickNode = (selected) => {
for (let key in column) {
column[key].map((item) => {
item.isClick = false;
});
}
column[selected.columnIndex][selected.index]['isClick'] = true;
selectedNode.value = selected;
};
//验证当前步骤的数据
const validateStep = async (): Promise<boolean> => {
const hasNodeName = Object.values(generatorConfig!.formEventConfig).every((config) => {
return config.every((item) => {
return !!item.text;
});
const { t } = useI18n();
const { notification } = useMessage();
const current = inject<Ref<number>>('current');
const isCustomForm = inject<boolean>('isCustomForm', false);
const designType = inject<string>('designType');
const widgetForm = inject<any>('widgetForm');
const fromMobile = inject<Boolean>('fromMobile', false);
const generatorConfig = inject<GeneratorConfig>('generatorConfig');
let lineHeight = reactive<number[]>([]);
let column = reactive<FormEventColumnConfig>({
0: [
{
type: 'circle',
color: '#2774ff',
text: t('开始节点'),
icon: '#icon-kaishi',
bgcColor: '#D8E5FF',
isUserDefined: false
},
{
color: '#F6AB01',
icon: '#icon-chushihua',
text: t('初始化表单'),
bgcColor: '#f9f5ea',
isUserDefined: false,
nodeInfo: {
processEvent: []
}
}
],
1: [
{
color: '#B36EDB',
icon: '#icon-shujufenxi',
text: t('获取表单数据'),
detail: t('(新增无此操作)'),
bgcColor: '#F8F2FC',
isUserDefined: false,
nodeInfo: {
processEvent: []
}
}
],
2: [
{
color: '#F8625C',
icon: '#icon-jiazai',
text: t('加载表单'),
bgcColor: '#FFF1F1',
isUserDefined: false,
nodeInfo: {
processEvent: []
}
}
],
3: [
{
color: '#6C6AE0',
icon: '#icon-jsontijiao',
text: t('提交表单'),
bgcColor: '#F5F4FF',
isUserDefined: false,
nodeInfo: {
processEvent: []
}
}
],
4: [
{
type: 'circle',
color: '#F8625C',
text: t('结束节点'),
icon: '#icon-jieshuzhiliao',
bgcColor: '#FFD6D6',
isLast: true,
isUserDefined: false
}
]
});
if (!hasNodeName) {
notification.error({
message: t('提示'),
description: t('节点名称不能为空!'),
});
return false;
}
return true;
};
defineExpose({ validateStep });
watch(
() => current?.value,
(val) => {
//自定义表单当前步骤为2 或 代码生成器 数据优先当前步骤为2 或 代码生成器 界面优先、简易模板 当前步骤为1
if ((isCustomForm && val === 2) || (!isCustomForm && ((designType === 'data' && val === 2) || (designType !== 'data' && val === 1)))) {
if (((isCustomForm && designType == 'code') || (!isCustomForm && designType !== 'data')) && generatorConfig!.tableStructureConfigs) {
let tableFieldConfigs = getMainTable(generatorConfig!.tableStructureConfigs);
changeCompsApiConfig(generatorConfig!.formJson.list, designType, tableFieldConfigs);
changeEventApiConfig(generatorConfig!.formEventConfig, designType, tableFieldConfigs);
widgetForm.value.list = cloneDeep(generatorConfig!.formJson.list);
}
if (generatorConfig?.formEventConfig && Object.keys(generatorConfig!.formEventConfig)?.length) {
column = generatorConfig!.formEventConfig!;
lineHeight[0] = 135 + (column[0].length - 2) * 158;
lineHeight[1] = 50 + (column[1].length - 1) * 158;
lineHeight[2] = 50 + (column[2].length - 1) * 158;
} else {
generatorConfig!.formEventConfig = column;
lineHeight[0] = 135;
lineHeight[1] = 50;
lineHeight[2] = 50;
}
}
}
);
const selectedNode = ref<selectedNodeConfig>();
const addEvent = (index) => {
if (fromMobile) return;
const columnInfo: FormEventStyleConfig = {
color: '#2774FF',
icon: '#icon-yonghu-xianxing',
text: t('用户自定义节点'),
bgcColor: '#F5F8FA',
isUserDefined: true,
nodeInfo: {
processEvent: []
}
};
column[index].push(columnInfo);
if (index === 3) return;
lineHeight[index] += 158;
};
const deleteEvent = ({ index, columnIndex }) => {
if (fromMobile) return;
column[columnIndex].splice(index, 1);
lineHeight[columnIndex] -= 158;
};
const clickNode = (selected) => {
for (let key in column) {
column[key].map((item) => {
item.isClick = false;
});
}
column[selected.columnIndex][selected.index]['isClick'] = true;
selectedNode.value = selected;
};
//验证当前步骤的数据
const validateStep = async (): Promise<boolean> => {
const hasNodeName = Object.values(generatorConfig!.formEventConfig).every((config) => {
return config.every((item) => {
return !!item.text;
});
});
if (!hasNodeName) {
notification.error({
message: t('提示'),
description: t('节点名称不能为空!')
});
return false;
}
return true;
};
defineExpose({ validateStep });
</script>
<style lang="less" scoped>
.event-box {
position: relative;
padding: 10px 50px;
font-size: 13px;
width: v-bind("!!selectedNode ? 'calc(100% - 410px)' : '100%'");
height: 100%;
overflow: auto;
.event-box {
position: relative;
padding: 10px 50px;
font-size: 13px;
width: v-bind("!!selectedNode ? 'calc(100% - 410px)' : '100%'");
height: 100%;
overflow: auto;
.box-second {
position: absolute;
top: 60px;
left: 310px;
}
.box-second {
position: absolute;
top: 60px;
left: 310px;
}
.box-third {
position: absolute;
top: 120px;
left: 570px;
}
.box-third {
position: absolute;
top: 120px;
left: 570px;
}
.box-fourth {
position: absolute;
top: 185px;
left: 830px;
.box-fourth {
position: absolute;
top: 185px;
left: 830px;
}
}
}
</style>

View File

@ -1,118 +1,118 @@
<template>
<div class="step1-form">
<BasicForm @register="register" />
</div>
<div class="step1-form">
<BasicForm @register="register" />
</div>
</template>
<script lang="ts" setup>
import { inject, onMounted } from 'vue';
import { FormSchema, useForm, BasicForm } from '/@/components/Form';
import { GeneratorConfig } from '/@/model/generator/generatorConfig';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();
const generatorConfig = inject<GeneratorConfig>('generatorConfig') as GeneratorConfig;
import { inject, onMounted } from 'vue';
import { FormSchema, useForm, BasicForm } from '/@/components/Form';
import { GeneratorConfig } from '/@/model/generator/generatorConfig';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();
const generatorConfig = inject<GeneratorConfig>('generatorConfig') as GeneratorConfig;
const formSchema: FormSchema[] = [
{
field: 'code',
label: t('菜单编号'),
required: true,
title: t('菜单信息'),
component: 'Input',
componentProps: {
placeholder: t('请输入菜单编号'),
},
colProps: { span: 12 },
},
{
field: 'name',
label: t('菜单名称'),
required: true,
component: 'Input',
componentProps: {
placeholder: t('请输入菜单名称'),
},
colProps: { span: 12 },
},
{
field: 'parentId',
label: t('上级菜单'),
component: 'MenuSelect',
required: process.env.NODE_ENV === 'production',
componentProps: {
placeholder: t('请选择上级菜单'),
},
colProps: { span: 12 },
},
{
field: 'sortCode',
label: t('排序'),
required: true,
component: 'InputNumber',
componentProps: {
placeholder: t('请输入排序号'),
min: 0,
},
colProps: { span: 12 },
},
{
field: 'icon',
label: t('图标'),
required: true,
component: 'IconPicker',
componentProps: {
placeholder: t('请选择图标'),
},
colProps: { span: 12 },
},
{
field: 'remark',
label: t('备注'),
component: 'InputTextArea',
componentProps: {
placeholder: t('请填写备注'),
},
colProps: { span: 24 },
},
];
const formSchema: FormSchema[] = [
{
field: 'code',
label: t('菜单编号'),
required: true,
title: t('菜单信息'),
component: 'Input',
componentProps: {
placeholder: t('请输入菜单编号')
},
colProps: { span: 12 }
},
{
field: 'name',
label: t('菜单名称'),
required: true,
component: 'Input',
componentProps: {
placeholder: t('请输入菜单名称')
},
colProps: { span: 12 }
},
{
field: 'parentId',
label: t('上级菜单'),
component: 'MenuSelect',
required: process.env.NODE_ENV === 'production',
componentProps: {
placeholder: t('请选择上级菜单')
},
colProps: { span: 12 }
},
{
field: 'sortCode',
label: t('排序'),
required: true,
component: 'InputNumber',
componentProps: {
placeholder: t('请输入排序号'),
min: 0
},
colProps: { span: 12 }
},
{
field: 'icon',
label: t('图标'),
required: true,
component: 'IconPicker',
componentProps: {
placeholder: t('请选择图标')
},
colProps: { span: 12 }
},
{
field: 'remark',
label: t('备注'),
component: 'InputTextArea',
componentProps: {
placeholder: t('请填写备注')
},
colProps: { span: 24 }
}
];
const [register, { validate, getFieldsValue, setFieldsValue }] = useForm({
labelWidth: 100,
schemas: formSchema,
showActionButtonGroup: false,
});
onMounted(() => {
setFieldsValue(generatorConfig.menuConfig);
});
//验证当前步骤的数据
const validateStep = async (): Promise<boolean> => {
try {
const formData = await validate();
setData(formData);
} catch (error) {
return false;
const [register, { validate, getFieldsValue, setFieldsValue }] = useForm({
labelWidth: 100,
schemas: formSchema,
showActionButtonGroup: false
});
onMounted(() => {
setFieldsValue(generatorConfig.menuConfig);
});
//验证当前步骤的数据
const validateStep = async (): Promise<boolean> => {
try {
const formData = await validate();
setData(formData);
} catch (error) {
return false;
}
return true;
};
function getFormData() {
const formData = getFieldsValue();
setData(formData);
}
function setData(formData) {
generatorConfig.menuConfig!.code = formData.code;
generatorConfig.menuConfig!.name = formData.name;
generatorConfig.menuConfig!.parentId = formData.parentId;
generatorConfig.menuConfig!.remark = formData.remark;
generatorConfig.menuConfig!.sortCode = formData.sortCode;
generatorConfig.menuConfig!.icon = formData.icon;
}
return true;
};
function getFormData() {
const formData = getFieldsValue();
setData(formData);
}
function setData(formData) {
generatorConfig.menuConfig!.code = formData.code;
generatorConfig.menuConfig!.name = formData.name;
generatorConfig.menuConfig!.parentId = formData.parentId;
generatorConfig.menuConfig!.remark = formData.remark;
generatorConfig.menuConfig!.sortCode = formData.sortCode;
generatorConfig.menuConfig!.icon = formData.icon;
}
function initStep(){
setFieldsValue(generatorConfig.menuConfig);
}
defineExpose({ validateStep, getFormData,initStep });
function initStep() {
setFieldsValue(generatorConfig.menuConfig);
}
defineExpose({ validateStep, getFormData, initStep });
</script>
<style lang="less" scoped>
:deep(.ant-input-number) {
width: 100%;
}
:deep(.ant-input-number) {
width: 100%;
}
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,121 +1,121 @@
<template>
<div class="add-box">
<svg class="icon add-icon" aria-hidden="true">
<use xlink:href="#icon-add" />
</svg>
<div class="dashed-arrow add-arrow" v-if="isLast"></div>
<div class="bottom-arrow" v-else>
<div class="top-arrow" :style="{ left: `-${lineHeight}`, width: lineHeight }"> </div>
<div class="add-box">
<svg class="icon add-icon" aria-hidden="true">
<use xlink:href="#icon-add" />
</svg>
<div class="dashed-arrow add-arrow" v-if="isLast"></div>
<div class="bottom-arrow" v-else>
<div class="top-arrow" :style="{ left: `-${lineHeight}`, width: lineHeight }"> </div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
const props = defineProps({
lineHeight: String,
isLast: {
type: Boolean,
default: false,
},
});
const props = defineProps({
lineHeight: String,
isLast: {
type: Boolean,
default: false
}
});
</script>
<style lang="less" scoped>
.add-box {
position: relative;
left: 40px;
width: 80px;
height: 80px;
margin-top: 65px;
background: #e7faf3;
display: flex;
justify-content: center;
align-items: center;
transform: rotate(45deg);
cursor: pointer;
&::after {
content: '';
background: #fff;
height: 10px;
width: 10px;
position: absolute;
top: v-bind("props.isLast ? 'calc(100% - 10px)' : '0'");
left: calc(100% - 10px);
border: 2px solid #00d37e;
border-radius: 50%;
}
.dashed-arrow {
height: 40px;
position: absolute;
bottom: -40px;
left: calc(50% - 1px);
border-left: 2px dashed #d9d9d9;
&::after {
content: '';
position: absolute;
left: -7px;
bottom: -14px;
height: 0;
width: 0;
border: 6px solid #000;
border-color: #d9d9d9 transparent transparent;
}
}
.add-icon {
font-size: 30px;
background-color: #fff;
padding: 5px;
border-radius: 50%;
transform: rotate(45deg);
fill: #00d37e;
}
.bottom-arrow {
height: 58px;
width: 45px;
position: absolute;
left: 64px;
top: -64px;
transform: rotate(45deg);
border-top: 2px dashed #d9d9d9;
border-right: 2px dashed #d9d9d9;
border-radius: 0 10%;
.top-arrow {
height: 48px;
position: absolute;
top: -48px;
border-bottom: 2px dashed #d9d9d9;
border-left: 2px dashed #d9d9d9;
border-radius: 0 10%;
.add-box {
position: relative;
left: 40px;
width: 80px;
height: 80px;
margin-top: 65px;
background: #e7faf3;
display: flex;
justify-content: center;
align-items: center;
transform: rotate(45deg);
cursor: pointer;
&::after {
content: '';
position: absolute;
left: -7px;
top: -14px;
height: 0;
width: 0;
border: 6px solid #000;
border-color: transparent transparent #d9d9d9;
content: '';
background: #fff;
height: 10px;
width: 10px;
position: absolute;
top: v-bind("props.isLast ? 'calc(100% - 10px)' : '0'");
left: calc(100% - 10px);
border: 2px solid #00d37e;
border-radius: 50%;
}
.dashed-arrow {
height: 40px;
position: absolute;
bottom: -40px;
left: calc(50% - 1px);
border-left: 2px dashed #d9d9d9;
&::after {
content: '';
position: absolute;
left: -7px;
bottom: -14px;
height: 0;
width: 0;
border: 6px solid #000;
border-color: #d9d9d9 transparent transparent;
}
}
.add-icon {
font-size: 30px;
background-color: #fff;
padding: 5px;
border-radius: 50%;
transform: rotate(45deg);
fill: #00d37e;
}
.bottom-arrow {
height: 58px;
width: 45px;
position: absolute;
left: 64px;
top: -64px;
transform: rotate(45deg);
border-top: 2px dashed #d9d9d9;
border-right: 2px dashed #d9d9d9;
border-radius: 0 10%;
.top-arrow {
height: 48px;
position: absolute;
top: -48px;
border-bottom: 2px dashed #d9d9d9;
border-left: 2px dashed #d9d9d9;
border-radius: 0 10%;
&::after {
content: '';
position: absolute;
left: -7px;
top: -14px;
height: 0;
width: 0;
border: 6px solid #000;
border-color: transparent transparent #d9d9d9;
}
}
}
.add-arrow {
left: 116%;
transform: rotate(-45deg);
top: 92%;
}
}
}
.add-arrow {
left: 116%;
transform: rotate(-45deg);
top: 92%;
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentcolor;
overflow: hidden;
}
}
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentcolor;
overflow: hidden;
}
</style>

View File

@ -1,183 +1,174 @@
<template>
<div v-for="(item, idx) in columnList" :key="idx" @click="eventClick(idx)">
<div
:style="{
'--bgcColor': item.bgcColor,
'--color': item.color,
marginTop: item.isLast ? '68px' : 0,
}"
:class="['circle-box', { dot: !item.isLast }]"
v-if="item.type === 'circle'"
>
<svg class="icon circle-icon" aria-hidden="true">
<use :xlink:href="item.icon" />
</svg>
<div class="dashed-arrow" v-if="!item.isLast"> </div>
<div v-for="(item, idx) in columnList" :key="idx" @click="eventClick(idx)">
<div
:style="{
'--bgcColor': item.bgcColor,
'--color': item.color,
marginTop: item.isLast ? '68px' : 0
}"
:class="['circle-box', { dot: !item.isLast }]"
v-if="item.type === 'circle'"
>
<svg class="icon circle-icon" aria-hidden="true">
<use :xlink:href="item.icon" />
</svg>
<div class="dashed-arrow" v-if="!item.isLast"> </div>
</div>
<div :style="{ background: item.bgcColor, '--color': item.color }" :class="[{ 'area-outline': item.isClick }, 'area-box']" v-else>
<svg class="icon svg-icon" aria-hidden="true">
<use :xlink:href="item.icon" />
</svg>
<p>{{ item.text }}</p>
<p v-if="item.detail" style="font-size: 12px">{{ item.detail }}</p>
<svg class="icon del-icon" aria-hidden="true" v-if="item.isUserDefined" @click.stop="delEvent(idx)">
<use xlink:href="#icon-shanchu" />
</svg>
<div class="dashed-arrow"></div>
</div>
</div>
<div
:style="{ background: item.bgcColor, '--color': item.color }"
:class="[{ 'area-outline': item.isClick }, 'area-box']"
v-else
>
<svg class="icon svg-icon" aria-hidden="true">
<use :xlink:href="item.icon" />
</svg>
<p>{{ item.text }}</p>
<p v-if="item.detail" style="font-size: 12px">{{ item.detail }}</p>
<svg
class="icon del-icon"
aria-hidden="true"
v-if="item.isUserDefined"
@click.stop="delEvent(idx)"
>
<use xlink:href="#icon-shanchu" />
</svg>
<div class="dashed-arrow"></div>
</div>
</div>
</template>
<script lang="ts" setup>
import { FormEventStyleConfig } from '../../../../model/generator/formEventConfig';
import { FormEventStyleConfig } from '../../../../model/generator/formEventConfig';
const props = defineProps({
index: Number,
isLast: {
type: Boolean,
default: false,
},
columnList: {
type: Array as PropType<FormEventStyleConfig[]>,
},
});
const props = defineProps({
index: Number,
isLast: {
type: Boolean,
default: false
},
columnList: {
type: Array as PropType<FormEventStyleConfig[]>
}
});
const emits = defineEmits(['deleteEvent', 'clickNode']);
const eventClick = (index) => {
const clickNode = {
index,
columnIndex: props.index,
const emits = defineEmits(['deleteEvent', 'clickNode']);
const eventClick = (index) => {
const clickNode = {
index,
columnIndex: props.index
};
emits('clickNode', clickNode);
};
emits('clickNode', clickNode);
};
const delEvent = (index) => {
const clickNode = {
index,
columnIndex: props.index,
const delEvent = (index) => {
const clickNode = {
index,
columnIndex: props.index
};
emits('deleteEvent', clickNode);
};
emits('deleteEvent', clickNode);
};
</script>
<style lang="less" scoped>
.circle-box {
position: relative;
left: 50px;
width: 60px;
height: 60px;
display: flex;
justify-content: center;
align-items: center;
background: var(--bgcColor);
margin-bottom: 54px;
border-radius: 50%;
cursor: pointer;
.circle-box {
position: relative;
left: 50px;
width: 60px;
height: 60px;
display: flex;
justify-content: center;
align-items: center;
background: var(--bgcColor);
margin-bottom: 54px;
border-radius: 50%;
cursor: pointer;
&.dot::after {
content: '';
background: #fff;
height: 10px;
width: 10px;
position: absolute;
bottom: -5px;
left: calc(50% - 5px);
border: 2px solid var(--color);
border-radius: 50%;
&.dot::after {
content: '';
background: #fff;
height: 10px;
width: 10px;
position: absolute;
bottom: -5px;
left: calc(50% - 5px);
border: 2px solid var(--color);
border-radius: 50%;
}
.circle-icon {
font-size: 32px;
fill: var(--color);
}
}
.circle-icon {
font-size: 32px;
fill: var(--color);
}
}
.area-box {
position: relative;
width: 135px;
height: 90px;
padding: 10px 0 0 15px;
// margin-bottom: 65px;
margin-top: 48px;
border-radius: 6px 6px 6px 6px;
border: 5px solid #fff;
box-sizing: content-box;
cursor: pointer;
// background: v-bind(bgcColor);
.area-box {
position: relative;
width: 135px;
height: 90px;
padding: 10px 0 0 15px;
// margin-bottom: 65px;
margin-top: 48px;
border-radius: 6px 6px 6px 6px;
border: 5px solid #fff;
box-sizing: content-box;
cursor: pointer;
// background: v-bind(bgcColor);
&::after {
content: '';
background: #fff;
height: 10px;
width: 10px;
position: absolute;
bottom: -5px;
left: calc(50% - 5px);
border: 2px solid var(--color);
border-radius: 50%;
}
&::after {
content: '';
background: #fff;
height: 10px;
width: 10px;
position: absolute;
bottom: -5px;
left: calc(50% - 5px);
border: 2px solid var(--color);
border-radius: 50%;
.svg-icon {
font-size: 22px;
background: #fff;
padding: 8px;
margin-bottom: 8px;
box-sizing: content-box;
border-radius: 50%;
fill: var(--color);
}
p {
margin-bottom: 0;
}
.del-icon {
position: absolute;
right: 10px;
font-size: 14px;
fill: #2774ff;
}
}
.svg-icon {
font-size: 22px;
background: #fff;
padding: 8px;
margin-bottom: 8px;
box-sizing: content-box;
border-radius: 50%;
fill: var(--color);
.area-outline {
outline: 2px dashed #2774ff !important;
}
p {
margin-bottom: 0;
.dashed-arrow {
height: 40px;
position: absolute;
bottom: -40px;
left: calc(50% - 1px);
border-left: 2px dashed #d9d9d9;
&::after {
content: '';
position: absolute;
left: -7px;
bottom: -14px;
height: 0px;
width: 0px;
border: 6px solid #000;
border-top-color: #d9d9d9;
border-bottom-color: transparent;
border-left-color: transparent;
border-right-color: transparent;
}
}
.del-icon {
position: absolute;
right: 10px;
font-size: 14px;
fill: #2774ff;
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
}
.area-outline {
outline: 2px dashed #2774ff !important;
}
.dashed-arrow {
height: 40px;
position: absolute;
bottom: -40px;
left: calc(50% - 1px);
border-left: 2px dashed #d9d9d9;
&::after {
content: '';
position: absolute;
left: -7px;
bottom: -14px;
height: 0px;
width: 0px;
border: 6px solid #000;
border-top-color: #d9d9d9;
border-bottom-color: transparent;
border-left-color: transparent;
border-right-color: transparent;
}
}
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>

View File

@ -1,103 +1,88 @@
<template>
<div>
<BasicDrawer
v-bind="$attrs"
@register="registerDrawer"
:isDetail="true"
@close="handleCloser"
:title="t('表单预览1')"
>
<div>
<BasicForm
@register="registerForm"
autoFocusFirstItem
:labelWidth="100"
:schemas="schemas"
:actionColOptions="{ span: 24 }"
:submitButtonOptions="{ text: t('提交') }"
@submit="handleSubmit"
@reset="handleReset"
/>
</div>
<template #titleToolbar> {{ t('重置') }} </template>
</BasicDrawer>
</div>
<div>
<BasicDrawer v-bind="$attrs" @register="registerDrawer" :isDetail="true" @close="handleCloser" :title="t('表单预览1')">
<div>
<BasicForm @register="registerForm" autoFocusFirstItem :labelWidth="100" :schemas="schemas" :actionColOptions="{ span: 24 }" :submitButtonOptions="{ text: t('提交') }" @submit="handleSubmit" @reset="handleReset" />
</div>
<template #titleToolbar> {{ t('重置') }} </template>
</BasicDrawer>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
import { BasicForm, FormProps, FormSchema, useForm } from '/@/components/Form/index';
import { useI18n } from '/@/hooks/web/useI18n';
import { buildOption } from '/@/utils/helper/designHelper';
// import { buildCode } from '/@/utils/helper/generatorHelper';
import { ref } from 'vue';
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
import { BasicForm, FormProps, FormSchema, useForm } from '/@/components/Form/index';
import { useI18n } from '/@/hooks/web/useI18n';
import { buildOption } from '/@/utils/helper/designHelper';
// import { buildCode } from '/@/utils/helper/generatorHelper';
const formProps = ref<FormProps>();
const formProps = ref<FormProps>();
const schemas: FormSchema[] = [];
// [
// {
// field: 'radio_1527c74b77dd43ceb8daceb35e22d657',
// label: '单选框组',
// component: 'ApiRadioGroup',
// colProps: {
// span: 24,
// },
// rules: [
// {
// trigger: 'blur',
// enum: '',
// message: '',
// pattern: '',
// required: false,
// type: 'any',
// },
// ],
// required: false,
// defaultValue: '',
// componentProps: {
// api: getMenuList,
// params: {
// count: 2,
// },
// resultField: 'data',
// // use name as label
// labelField: 'name',
// // use id as value
// valueField: 'id',
// isBtn: false,
// },
// },
// ];
const schemas: FormSchema[] = [];
// [
// {
// field: 'radio_1527c74b77dd43ceb8daceb35e22d657',
// label: '单选框组',
// component: 'ApiRadioGroup',
// colProps: {
// span: 24,
// },
// rules: [
// {
// trigger: 'blur',
// enum: '',
// message: '',
// pattern: '',
// required: false,
// type: 'any',
// },
// ],
// required: false,
// defaultValue: '',
// componentProps: {
// api: getMenuList,
// params: {
// count: 2,
// },
// resultField: 'data',
// // use name as label
// labelField: 'name',
// // use id as value
// valueField: 'id',
// isBtn: false,
// },
// },
// ];
//使用表单钩子 注册表单 获取到 操作表单的方法
const [registerForm, { setProps, resetFields, validate }] = useForm();
//使用表单钩子 注册表单 获取到 操作表单的方法
const [registerForm, { setProps, resetFields, validate }] = useForm();
//使用抽屉内部钩子 获取到 操作抽屉的方法
const [registerDrawer] = useDrawerInner((option) => {
formProps.value = buildOption(option);
// const codes = buildCode(generatorConfig, tableInfo, formProps.value.schemas as FormSchema[]);
// console.log(JSON.stringify(formProps.value), '@@@@@@@@@@', codes);
setProps(formProps.value);
});
//使用抽屉内部钩子 获取到 操作抽屉的方法
const [registerDrawer] = useDrawerInner((option) => {
formProps.value = buildOption(option);
// const codes = buildCode(generatorConfig, tableInfo, formProps.value.schemas as FormSchema[]);
// console.log(JSON.stringify(formProps.value), '@@@@@@@@@@', codes);
setProps(formProps.value);
});
//提交方法
const handleSubmit = async (formData: Recordable) => {
//提交之后将按钮设置为loading 不可操作状态
try {
const values = await validate();
console.log(values);
} finally {
console.log(formData);
}
};
//提交方法
const handleSubmit = async (formData: Recordable) => {
//提交之后将按钮设置为loading 不可操作状态
try {
const values = await validate();
console.log(values);
} finally {
console.log(formData);
}
};
const handleReset = () => {};
const handleReset = () => {};
//关闭方法
const handleCloser = () => {
resetFields(); //重置表单
// clearValidate(); //清空验证
};
//关闭方法
const handleCloser = () => {
resetFields(); //重置表单
// clearValidate(); //清空验证
};
const { t } = useI18n();
const { t } = useI18n();
</script>

View File

@ -1,299 +1,271 @@
<template>
<div class="node-box" v-if="node?.nodeInfo">
<div class="node-title">{{ node.text }}</div>
<a-tabs v-model:activeKey="nodeKey">
<a-tab-pane key="1" :tab="t('基本信息')">
<a-form :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
<a-form-item :label="t('节点名称')" required>
<a-input v-model:value="node.text" :disabled="!node.isUserDefined" />
</a-form-item>
</a-form>
</a-tab-pane>
<a-tab-pane key="2" :tab="t('过程处理')" v-if="node.isUserDefined">
<div class="process-top">
<div class="process-title">{{ t('过程处理事件列表') }}</div>
<a-button type="primary" @click="addProcess" :disabled="fromMobile">
{{ t('添加') }}
</a-button>
</div>
<a-table :columns="columns" :data-source="node.nodeInfo.processEvent" :pagination="false">
<template #headerCell="{ column }">
<template v-if="column.key === 'sort'">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-fangxiang1" />
</svg>
</template>
</template>
<template #bodyCell="{ column, record, index }">
<template v-if="column.key === 'sort'">
<svg class="icon draggable-icon" aria-hidden="true" style="cursor: move">
<use xlink:href="#icon-paixu" />
</svg>
</template>
<template v-if="column.key === 'operateType'">
<a-select v-model:value="record[column.dataIndex]" :disabled="fromMobile">
<a-select-option value="api">{{ t('执行API') }}</a-select-option>
<a-select-option value="liteflow">{{ t('规则引擎') }}</a-select-option>
<a-select-option value="js">JS脚本</a-select-option>
</a-select>
</template>
<template v-if="column.key === 'operateConfig'">
<a-input
v-if="record.operateType === 'api'"
v-model:value="record[column.dataIndex].path"
:disabled="fromMobile"
@click="showConfig(index)"
>
<template #suffix>
<Icon icon="ant-design:ellipsis-outlined" />
</template>
</a-input>
<a-input
v-model:value="record.showValue"
v-else-if="record.operateType === 'js'"
@click="showJSConfig(index)"
>
<template #suffix>
<Icon icon="ant-design:ellipsis-outlined" />
</template>
</a-input>
<a-select
v-else-if="record.operateType === 'liteflow'"
v-model:value="record[column.dataIndex]"
:options="liteFlowOptions"
:disabled="fromMobile"
:field-names="{ label: 'chainName', value: 'id' }"
/>
</template>
<template v-if="column.key === 'action'">
<DeleteTwoTone
two-tone-color="#ff8080"
@click="deleteEvent(index)"
:style="{ cursor: fromMobile ? 'not-allowed' : 'pointer' }"
/>
</template>
</template>
</a-table>
</a-tab-pane>
</a-tabs>
<ApiConfig
v-if="apiConfigDialog"
:title="t('API配置')"
v-model:apiConfigDialog="apiConfigDialog"
v-model:apiConfig="node.nodeInfo.processEvent[configIndex].operateConfig"
/>
<ScriptConfig
@register="registerModal"
@success="submitConfig"
:disabled="fromMobile ? true : false"
/>
</div>
<div class="node-box" v-if="node?.nodeInfo">
<div class="node-title">{{ node.text }}</div>
<a-tabs v-model:activeKey="nodeKey">
<a-tab-pane key="1" :tab="t('基本信息')">
<a-form :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
<a-form-item :label="t('节点名称')" required>
<a-input v-model:value="node.text" :disabled="!node.isUserDefined" />
</a-form-item>
</a-form>
</a-tab-pane>
<a-tab-pane key="2" :tab="t('过程处理')" v-if="node.isUserDefined">
<div class="process-top">
<div class="process-title">{{ t('过程处理事件列表') }}</div>
<a-button type="primary" @click="addProcess" :disabled="fromMobile">
{{ t('添加') }}
</a-button>
</div>
<a-table :columns="columns" :data-source="node.nodeInfo.processEvent" :pagination="false">
<template #headerCell="{ column }">
<template v-if="column.key === 'sort'">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-fangxiang1" />
</svg>
</template>
</template>
<template #bodyCell="{ column, record, index }">
<template v-if="column.key === 'sort'">
<svg class="icon draggable-icon" aria-hidden="true" style="cursor: move">
<use xlink:href="#icon-paixu" />
</svg>
</template>
<template v-if="column.key === 'operateType'">
<a-select v-model:value="record[column.dataIndex]" :disabled="fromMobile">
<a-select-option value="api">{{ t('执行API') }}</a-select-option>
<a-select-option value="liteflow">{{ t('规则引擎') }}</a-select-option>
<a-select-option value="js">JS脚本</a-select-option>
</a-select>
</template>
<template v-if="column.key === 'operateConfig'">
<a-input v-if="record.operateType === 'api'" v-model:value="record[column.dataIndex].path" :disabled="fromMobile" @click="showConfig(index)">
<template #suffix>
<Icon icon="ant-design:ellipsis-outlined" />
</template>
</a-input>
<a-input v-model:value="record.showValue" v-else-if="record.operateType === 'js'" @click="showJSConfig(index)">
<template #suffix>
<Icon icon="ant-design:ellipsis-outlined" />
</template>
</a-input>
<a-select v-else-if="record.operateType === 'liteflow'" v-model:value="record[column.dataIndex]" :options="liteFlowOptions" :disabled="fromMobile" :field-names="{ label: 'chainName', value: 'id' }" />
</template>
<template v-if="column.key === 'action'">
<DeleteTwoTone two-tone-color="#ff8080" @click="deleteEvent(index)" :style="{ cursor: fromMobile ? 'not-allowed' : 'pointer' }" />
</template>
</template>
</a-table>
</a-tab-pane>
</a-tabs>
<ApiConfig v-if="apiConfigDialog" :title="t('API配置')" v-model:apiConfigDialog="apiConfigDialog" v-model:apiConfig="node.nodeInfo.processEvent[configIndex].operateConfig" />
<ScriptConfig @register="registerModal" @success="submitConfig" :disabled="fromMobile ? true : false" />
</div>
</template>
<script lang="ts" setup>
import { ref, watch, nextTick, inject, Ref } from 'vue';
import { DeleteTwoTone } from '@ant-design/icons-vue';
import { Icon } from '/@/components/Icon';
import { ApiConfig } from '/@/components/ApiConfig';
import { getLiteflowList } from '/@/api/liteflow';
import { FormEventColumnConfig, selectedNodeConfig } from '/@/model/generator/formEventConfig';
import Sortable from 'sortablejs';
import { useI18n } from '/@/hooks/web/useI18n';
import { useModal } from '/@/components/Modal';
import ScriptConfig from '/@/components/Designer/src/components/componentProperty/settings/ScriptConfig.vue';
import { noHaveTableAndField } from '/@/components/Designer/src/types';
import { ref, watch, nextTick, inject, Ref } from 'vue';
import { DeleteTwoTone } from '@ant-design/icons-vue';
import { Icon } from '/@/components/Icon';
import { ApiConfig } from '/@/components/ApiConfig';
import { getLiteflowList } from '/@/api/liteflow';
import { FormEventColumnConfig, selectedNodeConfig } from '/@/model/generator/formEventConfig';
import Sortable from 'sortablejs';
import { useI18n } from '/@/hooks/web/useI18n';
import { useModal } from '/@/components/Modal';
import ScriptConfig from '/@/components/Designer/src/components/componentProperty/settings/ScriptConfig.vue';
import { noHaveTableAndField } from '/@/components/Designer/src/types';
const { t } = useI18n();
const nodeKey = ref<string>('1');
const props = defineProps({
columnList: {
type: Object as PropType<FormEventColumnConfig>,
default: () => {},
},
selectedNode: {
type: Object as PropType<selectedNodeConfig>,
},
});
const node = ref<any>();
const configIndex = ref(0);
const apiConfigDialog = ref(false);
const liteFlowOptions = ref();
const widgetForm = inject<Ref>('widgetForm');
const fromMobile = inject<Boolean>('fromMobile', false);
const [registerModal, { openModal }] = useModal();
const columns = ref([
{
dataIndex: 'sort',
key: 'sort',
},
{
title: t('操作类别'),
dataIndex: 'operateType',
key: 'operateType',
width: '35%',
align: 'center',
},
{
title: t('操作配置'),
dataIndex: 'operateConfig',
key: 'operateConfig',
width: '50%',
align: 'center',
},
{
title: t('操作'),
dataIndex: 'action',
key: 'action',
width: '25%',
align: 'center',
},
]);
watch(
() => props.selectedNode,
(val) => {
if (val) {
node.value = props.columnList[val.columnIndex][val.index];
if (!node.value.isUserDefined) nodeKey.value = '1';
}
},
{
deep: true,
},
);
watch(
() => node.value,
(val) => {
if (val.nodeInfo?.processEvent && val.nodeInfo?.processEvent.length) {
nextTick(() => {
const tbody: any = document.querySelector('.node-box .ant-table-tbody');
Sortable.create(tbody, {
handle: '.draggable-icon',
});
});
delete val.nodeInfo.processEvent[configIndex.value]?.operateConfig?.script;
}
if (val.isUserDefined && !Array.isArray(liteFlowOptions.value)) getList();
},
{ deep: true },
);
const showConfig = (index) => {
configIndex.value = index;
apiConfigDialog.value = true;
};
const getMainTableComponents = (list, mainTableComponent) => {
const rangeComponents = ['time-range', 'date-range'];
list.forEach((item) => {
if (['tab', 'grid', 'card'].includes(item.type)) {
for (const child of item.layout!) {
getMainTableComponents(child.list, mainTableComponent);
const { t } = useI18n();
const nodeKey = ref<string>('1');
const props = defineProps({
columnList: {
type: Object as PropType<FormEventColumnConfig>,
default: () => {}
},
selectedNode: {
type: Object as PropType<selectedNodeConfig>
}
} else if (rangeComponents.includes(item.type)) {
//时间范围、日期范围需改为两个字段
mainTableComponent.push({
label: t(`{name}开始时间`, { name: item.label }),
bindField: item.bindStartTime,
});
const node = ref<any>();
const configIndex = ref(0);
const apiConfigDialog = ref(false);
const liteFlowOptions = ref();
const widgetForm = inject<Ref>('widgetForm');
const fromMobile = inject<Boolean>('fromMobile', false);
const [registerModal, { openModal }] = useModal();
const columns = ref([
{
dataIndex: 'sort',
key: 'sort'
},
{
title: t('操作类别'),
dataIndex: 'operateType',
key: 'operateType',
width: '35%',
align: 'center'
},
{
title: t('操作配置'),
dataIndex: 'operateConfig',
key: 'operateConfig',
width: '50%',
align: 'center'
},
{
title: t('操作'),
dataIndex: 'action',
key: 'action',
width: '25%',
align: 'center'
}
]);
watch(
() => props.selectedNode,
(val) => {
if (val) {
node.value = props.columnList[val.columnIndex][val.index];
if (!node.value.isUserDefined) nodeKey.value = '1';
}
},
{
deep: true
}
);
watch(
() => node.value,
(val) => {
if (val.nodeInfo?.processEvent && val.nodeInfo?.processEvent.length) {
nextTick(() => {
const tbody: any = document.querySelector('.node-box .ant-table-tbody');
Sortable.create(tbody, {
handle: '.draggable-icon'
});
});
delete val.nodeInfo.processEvent[configIndex.value]?.operateConfig?.script;
}
if (val.isUserDefined && !Array.isArray(liteFlowOptions.value)) getList();
},
{ deep: true }
);
const showConfig = (index) => {
configIndex.value = index;
apiConfigDialog.value = true;
};
const getMainTableComponents = (list, mainTableComponent) => {
const rangeComponents = ['time-range', 'date-range'];
list.forEach((item) => {
if (['tab', 'grid', 'card'].includes(item.type)) {
for (const child of item.layout!) {
getMainTableComponents(child.list, mainTableComponent);
}
} else if (rangeComponents.includes(item.type)) {
//时间范围、日期范围需改为两个字段
mainTableComponent.push({
label: t(`{name}开始时间`, { name: item.label }),
bindField: item.bindStartTime
});
mainTableComponent.push({
label: t(`{name}结束时间`, { name: item.label }),
bindField: item.bindEndTime
});
} else if (item.type !== 'form' && !noHaveTableAndField.includes(item.type)) {
//除去不绑定表和字段的组件 以及表格组件
mainTableComponent.push(item);
}
});
mainTableComponent.push({
label: t(`{name}结束时间`, { name: item.label }),
bindField: item.bindEndTime,
};
const showJSConfig = (index) => {
console.log('widgetForm', widgetForm?.value, node.value);
const mainTableComponent = ref<any[]>([]);
getMainTableComponents(widgetForm?.value.list, mainTableComponent.value);
const operateConfig = node.value?.nodeInfo.processEvent[index].operateConfig;
const content = typeof operateConfig !== 'string' ? '' : operateConfig;
openModal(true, {
content,
list: mainTableComponent.value,
index
});
} else if (item.type !== 'form' && !noHaveTableAndField.includes(item.type)) {
//除去不绑定表和字段的组件 以及表格组件
mainTableComponent.push(item);
}
});
};
};
const showJSConfig = (index) => {
console.log('widgetForm', widgetForm?.value, node.value);
const mainTableComponent = ref<any[]>([]);
getMainTableComponents(widgetForm?.value.list, mainTableComponent.value);
const submitConfig = (_, script, index) => {
node.value.nodeInfo.processEvent[index].operateConfig = script;
node.value.nodeInfo.processEvent[index].showValue = script ? '已配置' : '';
};
const operateConfig = node.value?.nodeInfo.processEvent[index].operateConfig;
const content = typeof operateConfig !== 'string' ? '' : operateConfig;
openModal(true, {
content,
list: mainTableComponent.value,
index,
});
};
const addProcess = () => {
node.value.nodeInfo.processEvent.push({
operateType: 'api',
operateConfig: {}
});
};
const submitConfig = (_, script, index) => {
node.value.nodeInfo.processEvent[index].operateConfig = script;
node.value.nodeInfo.processEvent[index].showValue = script ? '已配置' : '';
};
const deleteEvent = (index) => {
if (fromMobile) return;
node.value.nodeInfo.processEvent.splice(index, 1);
};
const addProcess = () => {
node.value.nodeInfo.processEvent.push({
operateType: 'api',
operateConfig: {},
});
};
const deleteEvent = (index) => {
if (fromMobile) return;
node.value.nodeInfo.processEvent.splice(index, 1);
};
const getList = async () => {
liteFlowOptions.value = (await getLiteflowList()) || [];
};
const getList = async () => {
liteFlowOptions.value = (await getLiteflowList()) || [];
};
</script>
<style lang="less" scoped>
.node-box {
position: absolute;
top: 0;
right: 0;
box-shadow: -7px -1px 7px #dadcde;
padding: 20px 30px 20px 20px;
height: 100%;
width: 410px;
.node-box {
position: absolute;
top: 0;
right: 0;
box-shadow: -7px -1px 7px #dadcde;
padding: 20px 30px 20px 20px;
height: 100%;
width: 410px;
.node-title {
line-height: 20px;
margin-bottom: 10px;
padding-left: 6px;
border-left: 6px solid #5e95ff;
.node-title {
line-height: 20px;
margin-bottom: 10px;
padding-left: 6px;
border-left: 6px solid #5e95ff;
}
:deep(.ant-form-item) {
margin-bottom: 10px;
}
.process-top {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
.process-title {
line-height: 18px;
padding-left: 6px;
border-left: 6px solid #5e95ff;
}
}
:deep(.ant-select) {
width: 100%;
}
}
:deep(.ant-form-item) {
margin-bottom: 10px;
:deep(.ant-table-cell) {
padding: 10px !important;
}
.process-top {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
.process-title {
line-height: 18px;
padding-left: 6px;
border-left: 6px solid #5e95ff;
}
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentcolor;
overflow: hidden;
}
:deep(.ant-select) {
width: 100%;
}
}
:deep(.ant-table-cell) {
padding: 10px !important;
}
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentcolor;
overflow: hidden;
}
</style>

View File

@ -1,150 +1,142 @@
<template>
<BasicModal
wrap-class-name="fixedHeight"
@register="registerModal"
:title="t('选择数据库表')"
v-bind="$attrs"
width="800px"
:fixedHeight="true"
@ok="handlerClick"
>
<BasicTable @register="registerTable" />
</BasicModal>
<BasicModal wrap-class-name="fixedHeight" @register="registerModal" :title="t('选择数据库表')" v-bind="$attrs" width="800px" :fixedHeight="true" @ok="handlerClick">
<BasicTable @register="registerTable" />
</BasicModal>
</template>
<script lang="ts" setup>
import { BasicModal, useModalInner } from '/@/components/Modal';
import { useTable, FormSchema, BasicColumn, BasicTable } from '/@/components/Table';
import { getDatabaselinkTable } from '/@/api/system/databaselink';
import { ref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { TableConfig } from '/@/model/generator/tableConfig';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();
const searchFormSchema: FormSchema[] = [
{
field: 'tableName',
label: t('表名'),
component: 'Input',
},
];
import { BasicModal, useModalInner } from '/@/components/Modal';
import { useTable, FormSchema, BasicColumn, BasicTable } from '/@/components/Table';
import { getDatabaselinkTable } from '/@/api/system/databaselink';
import { ref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { TableConfig } from '/@/model/generator/tableConfig';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();
const searchFormSchema: FormSchema[] = [
{
field: 'tableName',
label: t('表名'),
component: 'Input'
}
];
const columns: BasicColumn[] = [
{
title: t('表名'),
dataIndex: 'tableName',
width: 200,
},
{
title: t('备注'),
dataIndex: 'tableComment',
width: 200,
},
];
const columns: BasicColumn[] = [
{
title: t('表名'),
dataIndex: 'tableName',
width: 200
},
{
title: t('备注'),
dataIndex: 'tableComment',
width: 200
}
];
const databaseId = ref('');
const selectedKeys = ref<string[] | number[]>([]);
const databaseId = ref('');
const selectedKeys = ref<string[] | number[]>([]);
const emit = defineEmits(['success', 'register']);
const props=defineProps({
forbidUncheck:{
type:Boolean,
default:true
}
});
const { createMessage } = useMessage();
const selectTableName = ref<string[]>([]);
const formConfig = {
rowProps: {
gutter: 16,
},
schemas: searchFormSchema,
showResetButton: false,
};
const [registerTable, { getSelectRows, setSelectedRowKeys, reload }] = useTable({
title: t('数据表列表'),
api: getDatabaselinkTable,
striped: false,
rowKey: 'tableName',
columns,
formConfig,
beforeFetch: (params) => {
//发送请求默认新增 左边树结构所选机构id
return { ...params, id: databaseId.value };
},
afterFetch: () => {
//搜索完成后 将选中项重新赋值给SelectedRowKeys
setSelectedRowKeys(selectedKeys.value);
},
rowSelection: {
type: 'checkbox',
getCheckboxProps: (record) => ({
disabled: props.forbidUncheck&&selectTableName.value.includes(record.tableName),
}),
onChange: (selectedRowKeys) => {
//搜索后会把原有选中项清空 所以需要进行存储
selectedKeys.value = selectedRowKeys;
},
},
isPaginateByDataSource: true,
useSearchForm: true,
showTableSetting: true,
tableSetting: {
size: false,
setting: false,
},
});
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
selectTableName.value = data.selectTableName;
setModalProps({ confirmLoading: false, canFullscreen: false });
setSelectedRowKeys(data.selectTableName);
databaseId.value = data.databaseId;
reload({ searchInfo: { id: databaseId.value } });
});
const handlerClick = () => {
const selectRows = getSelectRows() as TableConfig[];
if (selectRows.length === 0) {
createMessage.error(t('至少需要选择一个数据表!'));
return;
}
selectRows.map((item, index) => {
item.order = index + 1;
if (index === 0) {
item.isMain = true;
} else {
item.isMain = false;
}
const emit = defineEmits(['success', 'register']);
const props = defineProps({
forbidUncheck: {
type: Boolean,
default: true
}
});
emit('success', selectRows);
closeModal();
};
const { createMessage } = useMessage();
const selectTableName = ref<string[]>([]);
const formConfig = {
rowProps: {
gutter: 16
},
schemas: searchFormSchema,
showResetButton: false
};
const [registerTable, { getSelectRows, setSelectedRowKeys, reload }] = useTable({
title: t('数据表列表'),
api: getDatabaselinkTable,
striped: false,
rowKey: 'tableName',
columns,
formConfig,
beforeFetch: (params) => {
//发送请求默认新增 左边树结构所选机构id
return { ...params, id: databaseId.value };
},
afterFetch: () => {
//搜索完成后 将选中项重新赋值给SelectedRowKeys
setSelectedRowKeys(selectedKeys.value);
},
rowSelection: {
type: 'checkbox',
getCheckboxProps: (record) => ({
disabled: props.forbidUncheck && selectTableName.value.includes(record.tableName)
}),
onChange: (selectedRowKeys) => {
//搜索后会把原有选中项清空 所以需要进行存储
selectedKeys.value = selectedRowKeys;
}
},
isPaginateByDataSource: true,
useSearchForm: true,
showTableSetting: true,
tableSetting: {
size: false,
setting: false
}
});
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
selectTableName.value = data.selectTableName;
setModalProps({ confirmLoading: false, canFullscreen: false });
setSelectedRowKeys(data.selectTableName);
databaseId.value = data.databaseId;
reload({ searchInfo: { id: databaseId.value } });
});
const handlerClick = () => {
const selectRows = getSelectRows() as TableConfig[];
if (selectRows.length === 0) {
createMessage.error(t('至少需要选择一个数据表!'));
return;
}
selectRows.map((item, index) => {
item.order = index + 1;
if (index === 0) {
item.isMain = true;
} else {
item.isMain = false;
}
});
emit('success', selectRows);
closeModal();
};
</script>
<style scoped>
:deep(.ant-pagination) {
margin-top: 15px;
}
:deep(.ant-pagination) {
margin-top: 15px;
}
:deep(.ant-table-wrapper .ant-table-title) {
padding-bottom: 0 !important;
}
:deep(.ant-table-wrapper .ant-table-title) {
padding-bottom: 0 !important;
}
:deep(.ant-table) {
height: calc(100% - 44px);
}
:deep(.ant-table) {
height: calc(100% - 44px);
}
:deep(.ant-table-container) {
height: calc(100% - 102px);
}
:deep(.ant-table-container) {
height: calc(100% - 102px);
}
:deep(.ant-modal) {
top: 20px;
}
:deep(.ant-modal) {
top: 20px;
}
:deep(.ant-table-wrapper) {
padding-top: 0;
padding-bottom: 0;
}
:deep(.ant-table-wrapper) {
padding-top: 0;
padding-bottom: 0;
}
</style>

View File

@ -1,215 +1,198 @@
<template>
<BasicModal
@register="registerModal"
title="数据表处理"
:width="1400"
:destroyOnClose="true"
v-bind="$attrs"
@ok="handleSuccess"
>
<BasicTable @register="registerTable">
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'status'">
<span v-if="record.status === 1" class="text-blue-500">表结构相同</span>
<span v-else-if="record.status === 2" class="text-orange-500">表结构不同</span>
<span v-else-if="record.status === 3">数据库不存在该表按新增处理</span>
</template>
<template v-if="column.dataIndex === 'operator'">
<span v-if="record.status === 3">无需操作</span>
<a-radio-group
v-model:value="record.operator"
name="radioGroup"
@change="handleOperator(record)"
v-else
>
<a-radio :style="radioStyle" :value="1" v-if="record.status !== 2">沿用旧表</a-radio>
<a-radio :style="radioStyle" :value="2">创建新表重新生成表名</a-radio>
<a-radio :style="radioStyle" :value="3">
覆盖旧表
<span class="text-red-500" v-if="record.status === 1">此操作会清空旧表数据</span>
<span class="text-red-500" v-else>
此操作会删除旧表然后以相同表名按新结构进行生成
</span>
</a-radio>
<a-radio :style="radioStyle" :value="5">更新表
<span class="text-red-500">此操作会保留原表含数据只更新字段</span>
</a-radio>
</a-radio-group>
</template>
<template v-if="column.dataIndex === 'newTableName'">
<a-input
v-if="record.operator === 2"
v-model:value="record.newTableName"
placeholder="请输入表名"
/>
</template>
</template>
</BasicTable>
</BasicModal>
<BasicModal @register="registerModal" title="数据表处理" :width="1400" :destroyOnClose="true" v-bind="$attrs" @ok="handleSuccess">
<BasicTable @register="registerTable">
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'status'">
<span v-if="record.status === 1" class="text-blue-500">表结构相同</span>
<span v-else-if="record.status === 2" class="text-orange-500">表结构不同</span>
<span v-else-if="record.status === 3">数据库不存在该表按新增处理</span>
</template>
<template v-if="column.dataIndex === 'operator'">
<span v-if="record.status === 3">无需操作</span>
<a-radio-group v-model:value="record.operator" name="radioGroup" @change="handleOperator(record)" v-else>
<a-radio :style="radioStyle" :value="1" v-if="record.status !== 2">沿用旧表</a-radio>
<a-radio :style="radioStyle" :value="2">创建新表重新生成表名</a-radio>
<a-radio :style="radioStyle" :value="3">
覆盖旧表
<span class="text-red-500" v-if="record.status === 1">此操作会清空旧表数据</span>
<span class="text-red-500" v-else> 此操作会删除旧表然后以相同表名按新结构进行生成 </span>
</a-radio>
<a-radio :style="radioStyle" :value="5"
>更新表
<span class="text-red-500">此操作会保留原表含数据只更新字段</span>
</a-radio>
</a-radio-group>
</template>
<template v-if="column.dataIndex === 'newTableName'">
<a-input v-if="record.operator === 2" v-model:value="record.newTableName" placeholder="请输入表名" />
</template>
</template>
</BasicTable>
</BasicModal>
</template>
<script lang="ts" setup>
import { inject,reactive } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicTable, useTable, BasicColumn } from '/@/components/Table';
import { GeneratorConfig } from '/@/model/generator/generatorConfig';
import { validateTable, validateTableName } from '/@/api/system/generator';
import { useMessage } from '/@/hooks/web/useMessage';
import { useI18n } from '/@/hooks/web/useI18n';
import { inject, reactive } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicTable, useTable, BasicColumn } from '/@/components/Table';
import { GeneratorConfig } from '/@/model/generator/generatorConfig';
import { validateTable, validateTableName } from '/@/api/system/generator';
import { useMessage } from '/@/hooks/web/useMessage';
import { useI18n } from '/@/hooks/web/useI18n';
const radioStyle = reactive({
const radioStyle = reactive({
display: 'flex',
height: '30px',
lineHeight: '30px',
});
const { notification } = useMessage();
const { t } = useI18n();
const emits = defineEmits(['success', 'register']);
const generatorConfig = inject<GeneratorConfig>('generatorConfig');
const columns: BasicColumn[] = [
{
title: '数据库名称',
dataIndex: 'databaseName',
width: 100,
align: 'center',
},
{
title: '数据表名',
dataIndex: 'tableName',
width: 120,
align: 'center',
},
{
title: '表结构配置比对结果',
dataIndex: 'status',
width: 120,
align: 'center',
},
{
title: '操作',
dataIndex: 'operator',
width: 400,
align: 'center',
},
{
title: '新表表名',
dataIndex: 'newTableName',
width: 80,
align: 'center',
},
];
const [registerModal] = useModalInner();
const [registerTable, { getDataSource }] = useTable({
api: validateTable,
beforeFetch: () => {
return {
databaseId: generatorConfig?.databaseId,
tableStructureConfigs: generatorConfig?.tableStructureConfigs,
};
},
afterFetch: (data) => {
if (Array.isArray(data) && data.length) {
data.map((item) => {
//1表结构相同
//2表字段数量不一致
//3不存在该表
const operator = item.status === 3 ? 4 : item.status === 2 ? 5 : 1;
item.operator = operator;
item.newTableName = '';
});
}
},
columns,
striped: false,
pagination: false,
showIndexColumn: false,
});
const handleOperator = (record) => {
if (record.operator !== 2) record.newTableName = '';
};
const handleSuccess = async () => {
const newTableNameArr: string[] = [];
const hasNoTableName = getDataSource().some((info) => {
return info.operator === 2 && !info.newTableName;
lineHeight: '30px'
});
if (hasNoTableName) {
notification.error({
message: t('提示'),
description: '新表表名不能为空,否则无法创建数据表',
});
return;
}
getDataSource().map((item) => {
if (item.operator === 2) {
newTableNameArr.push(item.newTableName);
}
});
const reg = /^[a-zA-Z0-9_]*$/;
//判断表名是否符合要求
const isTableNotSuccess = newTableNameArr?.some((tableName) => !reg.test(tableName));
if (isTableNotSuccess) {
notification.error({
message: t('提示'),
description: '表名只能包括字母、数字、下划线',
});
return;
}
await validateTableName({
id: generatorConfig!.databaseId!,
tableNames: newTableNameArr.toString(),
});
generatorConfig?.tableStructureConfigs?.forEach((item) => {
getDataSource().forEach((data) => {
if (item.tableName === data.tableName) {
item.operator = data.operator;
if (data.operator === 2) {
item.tableName = data.newTableName;
item.tableFieldConfigs.forEach((field) => {
changeTableName(generatorConfig?.formJson.list, field.key, item.tableName, item.key);
});
}
const { notification } = useMessage();
const { t } = useI18n();
const emits = defineEmits(['success', 'register']);
const generatorConfig = inject<GeneratorConfig>('generatorConfig');
const columns: BasicColumn[] = [
{
title: '数据库名称',
dataIndex: 'databaseName',
width: 100,
align: 'center'
},
{
title: '数据表名',
dataIndex: 'tableName',
width: 120,
align: 'center'
},
{
title: '表结构配置比对结果',
dataIndex: 'status',
width: 120,
align: 'center'
},
{
title: '操作',
dataIndex: 'operator',
width: 400,
align: 'center'
},
{
title: '新表表名',
dataIndex: 'newTableName',
width: 80,
align: 'center'
}
});
});
emits('success');
};
];
const [registerModal] = useModalInner();
const changeTableName = (list, fieldKey, tableName, tableKey) => {
if (generatorConfig?.formJson.hiddenComponent?.length) {
generatorConfig?.formJson.hiddenComponent?.map((component: any) => {
if (component.key === fieldKey) {
component.bindTable = tableName;
}
});
}
list?.map((component: any) => {
if (component.type === 'form' || component.type === 'one-for-one') {
if (component.key === tableKey) {
component.bindTable = tableName;
}
if (component.children.length) {
component.children.map((subComponent: any) => {
if (subComponent.key === fieldKey) {
subComponent.bindTable = tableName;
const [registerTable, { getDataSource }] = useTable({
api: validateTable,
beforeFetch: () => {
return {
databaseId: generatorConfig?.databaseId,
tableStructureConfigs: generatorConfig?.tableStructureConfigs
};
},
afterFetch: (data) => {
if (Array.isArray(data) && data.length) {
data.map((item) => {
//1表结构相同
//2表字段数量不一致
//3不存在该表
const operator = item.status === 3 ? 4 : item.status === 2 ? 5 : 1;
item.operator = operator;
item.newTableName = '';
});
}
});
}
} else if (component.key === fieldKey) {
component.bindTable = tableName;
} else if (['tab', 'grid', 'card'].includes(component.type)) {
for (const child of component.layout!) {
changeTableName(child.list, fieldKey, tableName, tableKey);
}
}
},
columns,
striped: false,
pagination: false,
showIndexColumn: false
});
};
const handleOperator = (record) => {
if (record.operator !== 2) record.newTableName = '';
};
const handleSuccess = async () => {
const newTableNameArr: string[] = [];
const hasNoTableName = getDataSource().some((info) => {
return info.operator === 2 && !info.newTableName;
});
if (hasNoTableName) {
notification.error({
message: t('提示'),
description: '新表表名不能为空,否则无法创建数据表'
});
return;
}
getDataSource().map((item) => {
if (item.operator === 2) {
newTableNameArr.push(item.newTableName);
}
});
const reg = /^[a-zA-Z0-9_]*$/;
//判断表名是否符合要求
const isTableNotSuccess = newTableNameArr?.some((tableName) => !reg.test(tableName));
if (isTableNotSuccess) {
notification.error({
message: t('提示'),
description: '表名只能包括字母、数字、下划线'
});
return;
}
await validateTableName({
id: generatorConfig!.databaseId!,
tableNames: newTableNameArr.toString()
});
generatorConfig?.tableStructureConfigs?.forEach((item) => {
getDataSource().forEach((data) => {
if (item.tableName === data.tableName) {
item.operator = data.operator;
if (data.operator === 2) {
item.tableName = data.newTableName;
item.tableFieldConfigs.forEach((field) => {
changeTableName(generatorConfig?.formJson.list, field.key, item.tableName, item.key);
});
}
}
});
});
emits('success');
};
const changeTableName = (list, fieldKey, tableName, tableKey) => {
if (generatorConfig?.formJson.hiddenComponent?.length) {
generatorConfig?.formJson.hiddenComponent?.map((component: any) => {
if (component.key === fieldKey) {
component.bindTable = tableName;
}
});
}
list?.map((component: any) => {
if (component.type === 'form' || component.type === 'one-for-one') {
if (component.key === tableKey) {
component.bindTable = tableName;
}
if (component.children.length) {
component.children.map((subComponent: any) => {
if (subComponent.key === fieldKey) {
subComponent.bindTable = tableName;
}
});
}
} else if (component.key === fieldKey) {
component.bindTable = tableName;
} else if (['tab', 'grid', 'card'].includes(component.type)) {
for (const child of component.layout!) {
changeTableName(child.list, fieldKey, tableName, tableKey);
}
}
});
};
</script>
<style lang="less" scoped>
* {
font-size: 12px;
}
* {
font-size: 12px;
}
</style>