refactor: 代码生成字段信息编辑组件

pull/69/head
puhui999 2025-04-09 16:04:09 +08:00
parent 01a4c9dfe1
commit 8a5f7ede42
4 changed files with 273 additions and 155 deletions

View File

@ -1,151 +0,0 @@
<script lang="ts" setup>
import type { InfraCodegenApi } from '#/api/infra/codegen';
import type { SystemDictTypeApi } from '#/api/system/dict/type';
import { Checkbox, Input, Select, SelectOption, Table } from 'ant-design-vue';
import { getSimpleDictTypeList } from '#/api/system/dict/type';
import { computed, onMounted, ref, watch } from 'vue';
defineOptions({ name: 'InfraCodegenColumInfoForm' });
const props = defineProps<Props>();
interface Props {
columns?: InfraCodegenApi.CodegenColumn[];
}
const formData = ref<InfraCodegenApi.CodegenColumn[]>([]);
const tableHeight = computed(() => document.documentElement.scrollHeight - 350);
const dictOptions = ref<SystemDictTypeApi.SystemDictType[]>([]);
//
const tableColumns = [
{ title: '字段列名', dataIndex: 'columnName', width: 100 },
{ title: '字段描述', dataIndex: 'columnComment', width: 100 },
{ title: '物理类型', dataIndex: 'dataType', width: 100 },
{ title: 'Java类型', dataIndex: 'javaType', width: 110 },
{ title: 'java属性', dataIndex: 'javaField', width: 100 },
{ title: '插入', dataIndex: 'createOperation', width: 40 },
{ title: '编辑', dataIndex: 'updateOperation', width: 40 },
{ title: '列表', dataIndex: 'listOperationResult', width: 40 },
{ title: '查询', dataIndex: 'listOperation', width: 40 },
{ title: '查询方式', dataIndex: 'listOperationCondition', width: 100 },
{ title: '允许空', dataIndex: 'nullable', width: 50 },
{ title: '显示类型', dataIndex: 'htmlType', width: 120 },
{ title: '字典类型', dataIndex: 'dictType', width: 120 },
{ title: '示例', dataIndex: 'example', width: 100 },
];
//
const filterOption = (input: string, option: any) => {
return option.children[0].toLowerCase().includes(input.toLowerCase());
};
/** 查询字典下拉列表 */
const getDictOptions = async () => {
dictOptions.value = await getSimpleDictTypeList();
};
watch(
() => props.columns,
(columns) => {
if (!columns) return;
formData.value = [...columns];
},
{
deep: true,
immediate: true,
},
);
onMounted(async () => {
await getDictOptions();
});
</script>
<template>
<Table
:data-source="formData"
:columns="tableColumns"
:scroll="{ y: tableHeight }"
:pagination="false"
row-key="columnId"
>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'columnComment'">
<Input v-model:value="record.columnComment" />
</template>
<template v-else-if="column.dataIndex === 'javaType'">
<Select v-model:value="record.javaType" style="width: 100%">
<SelectOption value="Long">Long</SelectOption>
<SelectOption value="String">String</SelectOption>
<SelectOption value="Integer">Integer</SelectOption>
<SelectOption value="Double">Double</SelectOption>
<SelectOption value="BigDecimal">BigDecimal</SelectOption>
<SelectOption value="LocalDateTime">LocalDateTime</SelectOption>
<SelectOption value="Boolean">Boolean</SelectOption>
</Select>
</template>
<template v-else-if="column.dataIndex === 'javaField'">
<Input v-model:value="record.javaField" />
</template>
<template v-else-if="column.dataIndex === 'createOperation'">
<Checkbox v-model:checked="record.createOperation" />
</template>
<template v-else-if="column.dataIndex === 'updateOperation'">
<Checkbox v-model:checked="record.updateOperation" />
</template>
<template v-else-if="column.dataIndex === 'listOperationResult'">
<Checkbox v-model:checked="record.listOperationResult" />
</template>
<template v-else-if="column.dataIndex === 'listOperation'">
<Checkbox v-model:checked="record.listOperation" />
</template>
<template v-else-if="column.dataIndex === 'listOperationCondition'">
<Select v-model:value="record.listOperationCondition" style="width: 100%">
<SelectOption value="=">=</SelectOption>
<SelectOption value="!=">!=</SelectOption>
<SelectOption value=">">&gt;</SelectOption>
<SelectOption value=">=">&gt;=</SelectOption>
<SelectOption value="<">&lt;</SelectOption>
<SelectOption value="<=">&lt;=</SelectOption>
<SelectOption value="LIKE">LIKE</SelectOption>
<SelectOption value="BETWEEN">BETWEEN</SelectOption>
</Select>
</template>
<template v-else-if="column.dataIndex === 'nullable'">
<Checkbox v-model:checked="record.nullable" />
</template>
<template v-else-if="column.dataIndex === 'htmlType'">
<Select v-model:value="record.htmlType" style="width: 100%">
<SelectOption value="input">文本框</SelectOption>
<SelectOption value="textarea">文本域</SelectOption>
<SelectOption value="select">下拉框</SelectOption>
<SelectOption value="radio">单选框</SelectOption>
<SelectOption value="checkbox">复选框</SelectOption>
<SelectOption value="datetime">日期控件</SelectOption>
<SelectOption value="imageUpload">图片上传</SelectOption>
<SelectOption value="fileUpload">文件上传</SelectOption>
<SelectOption value="editor">富文本控件</SelectOption>
</Select>
</template>
<template v-else-if="column.dataIndex === 'dictType'">
<Select
v-model:value="record.dictType"
allow-clear
show-search
placeholder="请选择"
style="width: 100%"
:filter-option="filterOption"
>
<SelectOption v-for="dict in dictOptions" :key="dict.id" :value="dict.type">
{{ dict.name }}
</SelectOption>
</Select>
</template>
<template v-else-if="column.dataIndex === 'example'">
<Input v-model:value="record.example" />
</template>
</template>
</Table>
</template>

View File

@ -427,3 +427,119 @@ export function useGridColumns<T = InfraCodegenApi.CodegenTable>(
},
];
}
/** 代码生成表格列定义 */
export function useCodegenColumnTableColumns(): VxeTableGridOptions['columns'] {
return [
{ field: 'columnName', title: '字段列名', minWidth: 130 },
{
field: 'columnComment',
title: '字段描述',
minWidth: 100,
slots: { default: 'columnComment' },
},
{ field: 'dataType', title: '物理类型', minWidth: 100 },
{
field: 'javaType',
title: 'Java类型',
minWidth: 100,
slots: { default: 'javaType' },
params: {
options: [
{ label: 'Long', value: 'Long' },
{ label: 'String', value: 'String' },
{ label: 'Integer', value: 'Integer' },
{ label: 'Double', value: 'Double' },
{ label: 'BigDecimal', value: 'BigDecimal' },
{ label: 'LocalDateTime', value: 'LocalDateTime' },
{ label: 'Boolean', value: 'Boolean' },
],
},
},
{
field: 'javaField',
title: 'java属性',
minWidth: 100,
slots: { default: 'javaField' },
},
{
field: 'createOperation',
title: '插入',
width: 40,
slots: { default: 'createOperation' },
},
{
field: 'updateOperation',
title: '编辑',
width: 40,
slots: { default: 'updateOperation' },
},
{
field: 'listOperationResult',
title: '列表',
width: 40,
slots: { default: 'listOperationResult' },
},
{
field: 'listOperation',
title: '查询',
width: 40,
slots: { default: 'listOperation' },
},
{
field: 'listOperationCondition',
title: '查询方式',
minWidth: 100,
slots: { default: 'listOperationCondition' },
params: {
options: [
{ label: '=', value: '=' },
{ label: '!=', value: '!=' },
{ label: '>', value: '>' },
{ label: '>=', value: '>=' },
{ label: '<', value: '<' },
{ label: '<=', value: '<=' },
{ label: 'LIKE', value: 'LIKE' },
{ label: 'BETWEEN', value: 'BETWEEN' },
],
},
},
{
field: 'nullable',
title: '允许空',
width: 50,
slots: { default: 'nullable' },
},
{
field: 'htmlType',
title: '显示类型',
width: 120,
slots: { default: 'htmlType' },
params: {
options: [
{ label: '文本框', value: 'input' },
{ label: '文本域', value: 'textarea' },
{ label: '下拉框', value: 'select' },
{ label: '单选框', value: 'radio' },
{ label: '复选框', value: 'checkbox' },
{ label: '日期控件', value: 'datetime' },
{ label: '图片上传', value: 'imageUpload' },
{ label: '文件上传', value: 'fileUpload' },
{ label: '富文本控件', value: 'editor' },
],
},
},
{
field: 'dictType',
title: '字典类型',
width: 120,
slots: { default: 'dictType' },
},
{
field: 'example',
title: '示例',
minWidth: 100,
slots: { default: 'example' },
},
];
}

View File

@ -1,9 +1,9 @@
<script lang="ts" setup>
import type { InfraCodegenApi } from '#/api/infra/codegen';
import BasicInfo from './components/BasicInfoForm.vue';
import ColumnInfo from './components/ColumInfoForm.vue';
import GenerateInfo from './components/GenerateInfoForm.vue';
import BasicInfo from './modules/basic-info.vue';
import ColumnInfo from './modules/column-info.vue';
import GenerationInfo from './modules/generation-info.vue';
import { Page } from '@vben/common-ui';
import { ChevronsLeft } from '@vben/icons';
import { Button, message, Tabs } from 'ant-design-vue';
@ -89,7 +89,7 @@ getDetail();
<ColumnInfo ref="columnInfoRef" :columns="formData.columns" />
</Tabs.TabPane>
<Tabs.TabPane key="generateInfo" tab="生成信息">
<GenerateInfo ref="generateInfoRef" :table="formData.table" :columns="formData.columns" />
<GenerationInfo ref="generateInfoRef" :table="formData.table" :columns="formData.columns" />
</Tabs.TabPane>
</Tabs>

View File

@ -0,0 +1,153 @@
<script lang="ts" setup>
import type { InfraCodegenApi } from '#/api/infra/codegen';
import type { SystemDictTypeApi } from '#/api/system/dict/type';
import { Checkbox, Input, Select } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { getSimpleDictTypeList } from '#/api/system/dict/type';
import { ref, watch } from 'vue';
import { useCodegenColumnTableColumns } from '../data';
defineOptions({ name: 'InfraCodegenColumInfoForm' });
const props = defineProps<{
columns?: InfraCodegenApi.CodegenColumn[];
}>();
//
const [Grid, extendedApi] = useVbenVxeGrid({
gridOptions: {
columns: useCodegenColumnTableColumns(),
border: true,
showOverflow: true,
height: 'auto',
keepSource: true,
rowConfig: {
keyField: 'id',
},
pagerConfig: {
enabled: false,
},
toolbarConfig: {
enabled: false,
},
},
});
//
watch(
() => props.columns,
(columns) => {
if (!columns) {
return;
}
setTimeout(() => {
extendedApi.grid?.loadData(columns);
}, 100);
},
{
immediate: true,
},
);
//
defineExpose({
getData: extendedApi.grid?.getData,
});
//
const dictTypeOptions = ref<{ label: string; value: string }[]>([]);
const loadDictTypeOptions = async () => {
const dictTypes = await getSimpleDictTypeList();
dictTypeOptions.value = dictTypes.map((dict: SystemDictTypeApi.SystemDictType) => ({
label: dict.name,
value: dict.type,
}));
};
loadDictTypeOptions();
</script>
<template>
<div class="h-[80vh] w-full">
<Grid>
<!-- 字段描述 -->
<template #columnComment="{ row }">
<Input v-model:value="row.columnComment" />
</template>
<!-- Java类型 -->
<template #javaType="{ row, column }">
<Select v-model:value="row.javaType" style="width: 100%">
<Select.Option v-for="option in column.params.options" :key="option.value" :value="option.value">
{{ option.label }}
</Select.Option>
</Select>
</template>
<!-- Java属性 -->
<template #javaField="{ row }">
<Input v-model:value="row.javaField" />
</template>
<!-- 插入 -->
<template #createOperation="{ row }">
<Checkbox v-model:checked="row.createOperation" />
</template>
<!-- 编辑 -->
<template #updateOperation="{ row }">
<Checkbox v-model:checked="row.updateOperation" />
</template>
<!-- 列表 -->
<template #listOperationResult="{ row }">
<Checkbox v-model:checked="row.listOperationResult" />
</template>
<!-- 查询 -->
<template #listOperation="{ row }">
<Checkbox v-model:checked="row.listOperation" />
</template>
<!-- 查询方式 -->
<template #listOperationCondition="{ row, column }">
<Select v-model:value="row.listOperationCondition" style="width: 100%">
<Select.Option v-for="option in column.params.options" :key="option.value" :value="option.value">
{{ option.label }}
</Select.Option>
</Select>
</template>
<!-- 允许空 -->
<template #nullable="{ row }">
<Checkbox v-model:checked="row.nullable" />
</template>
<!-- 显示类型 -->
<template #htmlType="{ row, column }">
<Select v-model:value="row.htmlType" style="width: 100%">
<Select.Option v-for="option in column.params.options" :key="option.value" :value="option.value">
{{ option.label }}
</Select.Option>
</Select>
</template>
<!-- 字典类型 -->
<template #dictType="{ row }">
<Select v-model:value="row.dictType" style="width: 100%" allow-clear show-search>
<Select.Option v-for="option in dictTypeOptions" :key="option.value" :value="option.value">
{{ option.label }}
</Select.Option>
</Select>
</template>
<!-- 示例 -->
<template #example="{ row }">
<Input v-model:value="row.example" />
</template>
</Grid>
</div>
</template>