review:代码生成,相关功能
parent
17734ab040
commit
b67f1b1ecd
|
@ -65,13 +65,13 @@ export namespace InfraCodegenApi {
|
|||
}
|
||||
|
||||
/** 更新代码生成请求 */
|
||||
export interface CodegenUpdateReq {
|
||||
export interface CodegenUpdateReqVO {
|
||||
table: any | CodegenTable;
|
||||
columns: CodegenColumn[];
|
||||
}
|
||||
|
||||
/** 创建代码生成请求 */
|
||||
export interface CodegenCreateListReq {
|
||||
export interface CodegenCreateListReqVO {
|
||||
dataSourceConfigId?: number;
|
||||
tableNames: string[];
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ export namespace InfraCodegenApi {
|
|||
|
||||
/** 查询列表代码生成表定义 */
|
||||
export function getCodegenTableList(dataSourceConfigId: number) {
|
||||
return requestClient.get<InfraCodegenApi.CodegenTable[]>('/infra/codegen/table/list', {
|
||||
return requestClient.get<InfraCodegenApi.CodegenTable[]>('/infra/codegen/table/list?', {
|
||||
params: { dataSourceConfigId },
|
||||
});
|
||||
}
|
||||
|
@ -90,40 +90,35 @@ export function getCodegenTablePage(params: PageParam) {
|
|||
}
|
||||
|
||||
/** 查询详情代码生成表定义 */
|
||||
export function getCodegenTable(id: number) {
|
||||
export function getCodegenTable(tableId: number) {
|
||||
return requestClient.get<InfraCodegenApi.CodegenDetail>('/infra/codegen/detail', {
|
||||
params: { tableId: id },
|
||||
params: { tableId },
|
||||
});
|
||||
}
|
||||
|
||||
/** 新增代码生成表定义 */
|
||||
export function createCodegenTable(data: InfraCodegenApi.CodegenCreateListReq) {
|
||||
return requestClient.post('/infra/codegen/create', data);
|
||||
}
|
||||
|
||||
/** 修改代码生成表定义 */
|
||||
export function updateCodegenTable(data: InfraCodegenApi.CodegenUpdateReq) {
|
||||
export function updateCodegenTable(data: InfraCodegenApi.CodegenUpdateReqVO) {
|
||||
return requestClient.put('/infra/codegen/update', data);
|
||||
}
|
||||
|
||||
/** 基于数据库的表结构,同步数据库的表和字段定义 */
|
||||
export function syncCodegenFromDB(id: number) {
|
||||
export function syncCodegenFromDB(tableId: number) {
|
||||
return requestClient.put('/infra/codegen/sync-from-db', {
|
||||
params: { tableId: id },
|
||||
params: { tableId },
|
||||
});
|
||||
}
|
||||
|
||||
/** 预览生成代码 */
|
||||
export function previewCodegen(id: number) {
|
||||
export function previewCodegen(tableId: number) {
|
||||
return requestClient.get<InfraCodegenApi.CodegenPreview[]>('/infra/codegen/preview', {
|
||||
params: { tableId: id },
|
||||
params: { tableId },
|
||||
});
|
||||
}
|
||||
|
||||
/** 下载生成代码 */
|
||||
export function downloadCodegen(id: number) {
|
||||
export function downloadCodegen(tableId: number) {
|
||||
return requestClient.download('/infra/codegen/download', {
|
||||
params: { tableId: id },
|
||||
params: { tableId },
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -133,13 +128,13 @@ export function getSchemaTableList(params: any) {
|
|||
}
|
||||
|
||||
/** 基于数据库的表结构,创建代码生成器的表定义 */
|
||||
export function createCodegenList(data: InfraCodegenApi.CodegenCreateListReq) {
|
||||
export function createCodegenList(data: InfraCodegenApi.CodegenCreateListReqVO) {
|
||||
return requestClient.post('/infra/codegen/create-list', data);
|
||||
}
|
||||
|
||||
/** 删除代码生成表定义 */
|
||||
export function deleteCodegenTable(id: number) {
|
||||
export function deleteCodegenTable(tableId: number) {
|
||||
return requestClient.delete('/infra/codegen/delete', {
|
||||
params: { tableId: id },
|
||||
params: { tableId },
|
||||
});
|
||||
}
|
||||
|
|
|
@ -7,10 +7,7 @@ export function getRangePickerDefaultProps() {
|
|||
return {
|
||||
showTime: {
|
||||
format: 'HH:mm:ss',
|
||||
defaultValue: [
|
||||
dayjs('00:00:00', 'HH:mm:ss'),
|
||||
dayjs('23:59:59', 'HH:mm:ss'),
|
||||
],
|
||||
defaultValue: [dayjs('00:00:00', 'HH:mm:ss'), dayjs('23:59:59', 'HH:mm:ss')],
|
||||
},
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
|
@ -18,8 +15,7 @@ export function getRangePickerDefaultProps() {
|
|||
// prettier-ignore
|
||||
ranges: {
|
||||
'今天': [dayjs().startOf('day'), dayjs().endOf('day')],
|
||||
'昨天': [dayjs().subtract(1, 'day').startOf('day'),
|
||||
dayjs().subtract(1, 'day').endOf('day')],
|
||||
'昨天': [dayjs().subtract(1, 'day').startOf('day'), dayjs().subtract(1, 'day').endOf('day')],
|
||||
'本周': [dayjs().startOf('week'), dayjs().endOf('day')],
|
||||
'本月': [dayjs().startOf('month'), dayjs().endOf('day')],
|
||||
'最近 7 天': [dayjs().subtract(7, 'day').startOf('day'), dayjs().endOf('day')],
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// 参数校验,对标 Hutool 的 Validator 工具类
|
||||
|
||||
/** 手机号正则表达式(中国) */
|
||||
const MOBILE_REGEX = /(?:0|86|\+86)?1[3-9]\d{9}/;
|
||||
|
||||
/**
|
||||
* 验证是否为手机号码(中国)
|
||||
*
|
||||
* @param value 值
|
||||
* @returns 是否为手机号码(中国)
|
||||
*/
|
||||
export function isMobile(value?: string | null): boolean {
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
return MOBILE_REGEX.test(value);
|
||||
}
|
||||
|
|
@ -27,6 +27,7 @@ export function useImportTableFormSchema(
|
|||
{
|
||||
fieldName: 'dataSourceConfigId',
|
||||
label: '数据源',
|
||||
// TODO @puhui999:不确定使用 ApiSelect 的话,使用 afterEach,可以设置默认 defaultValue 不
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
options: dataSourceConfigList.map((item) => ({
|
||||
|
@ -76,7 +77,7 @@ export function useBasicInfoFormSchema(): VbenFormSchema[] {
|
|||
label: '表描述',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入',
|
||||
placeholder: '请输入表描述',
|
||||
},
|
||||
rules: 'required',
|
||||
},
|
||||
|
@ -85,7 +86,7 @@ export function useBasicInfoFormSchema(): VbenFormSchema[] {
|
|||
label: '实体类名称',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入',
|
||||
placeholder: '请输入实体类名称',
|
||||
},
|
||||
rules: 'required',
|
||||
help: '默认去除表名的前缀。如果存在重复,则需要手动添加前缀,避免 MyBatis 报 Alias 重复的问题。',
|
||||
|
@ -95,7 +96,7 @@ export function useBasicInfoFormSchema(): VbenFormSchema[] {
|
|||
label: '作者',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入',
|
||||
placeholder: '请输入作者',
|
||||
},
|
||||
rules: 'required',
|
||||
},
|
||||
|
@ -105,8 +106,8 @@ export function useBasicInfoFormSchema(): VbenFormSchema[] {
|
|||
component: 'Textarea',
|
||||
componentProps: {
|
||||
rows: 3,
|
||||
placeholder: '请输入备注',
|
||||
},
|
||||
// 使用 Tailwind 的 col-span-2 让元素跨越两列
|
||||
formItemClass: 'md:col-span-2',
|
||||
},
|
||||
];
|
||||
|
@ -120,8 +121,8 @@ export function useGenerationInfoBaseFormSchema(): VbenFormSchema[] {
|
|||
fieldName: 'templateType',
|
||||
label: '生成模板',
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
options: getDictOptions(DICT_TYPE.INFRA_CODEGEN_TEMPLATE_TYPE, 'number'),
|
||||
class: 'w-full',
|
||||
},
|
||||
rules: z.number().min(1, { message: '生成模板不能为空' }),
|
||||
},
|
||||
|
@ -130,9 +131,10 @@ export function useGenerationInfoBaseFormSchema(): VbenFormSchema[] {
|
|||
fieldName: 'frontType',
|
||||
label: '前端类型',
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
options: getDictOptions(DICT_TYPE.INFRA_CODEGEN_FRONT_TYPE, 'number'),
|
||||
class: 'w-full',
|
||||
},
|
||||
// todo @puhui999:1 可以是枚举么
|
||||
rules: z.number().min(1, { message: '前端类型不能为空' }),
|
||||
},
|
||||
{
|
||||
|
@ -140,9 +142,10 @@ export function useGenerationInfoBaseFormSchema(): VbenFormSchema[] {
|
|||
fieldName: 'scene',
|
||||
label: '生成场景',
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
options: getDictOptions(DICT_TYPE.INFRA_CODEGEN_SCENE, 'number'),
|
||||
class: 'w-full',
|
||||
},
|
||||
// todo @puhui999:1 可以是枚举么
|
||||
rules: z.number().min(1, { message: '生成场景不能为空' }),
|
||||
},
|
||||
{
|
||||
|
@ -196,6 +199,7 @@ export function useGenerationInfoBaseFormSchema(): VbenFormSchema[] {
|
|||
fieldName: 'moduleName',
|
||||
label: '模块名',
|
||||
help: '模块名,即一级目录,例如 system、infra、tool 等等',
|
||||
// TODO @puhui999:这种 rules,可以使用 required
|
||||
rules: z.string().min(1, { message: '模块名不能为空' }),
|
||||
},
|
||||
{
|
||||
|
@ -222,6 +226,7 @@ export function useGenerationInfoBaseFormSchema(): VbenFormSchema[] {
|
|||
];
|
||||
}
|
||||
|
||||
// TODO @puhui999:是不是使用 useGenerationInfoTreeFormSchema,主要考虑对称
|
||||
/** 树表信息 schema */
|
||||
export function useTreeTableFormSchema(columns: InfraCodegenApi.CodegenColumn[] = []): VbenFormSchema[] {
|
||||
return [
|
||||
|
@ -240,7 +245,7 @@ export function useTreeTableFormSchema(columns: InfraCodegenApi.CodegenColumn[]
|
|||
component: 'Select',
|
||||
fieldName: 'treeParentColumnId',
|
||||
label: '父编号字段',
|
||||
help: '树显示的父编码字段名, 如:parent_Id',
|
||||
help: '树显示的父编码字段名,例如 parent_Id',
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
allowClear: true,
|
||||
|
@ -256,11 +261,11 @@ export function useTreeTableFormSchema(columns: InfraCodegenApi.CodegenColumn[]
|
|||
component: 'Select',
|
||||
fieldName: 'treeNameColumnId',
|
||||
label: '名称字段',
|
||||
help: '树节点显示的名称字段,一般是name',
|
||||
help: '树节点显示的名称字段,一般是 name',
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
allowClear: true,
|
||||
placeholder: '请选择',
|
||||
placeholder: '请选择名称字段',
|
||||
options: columns.map((column) => ({
|
||||
label: column.columnName,
|
||||
value: column.id,
|
||||
|
@ -271,6 +276,7 @@ export function useTreeTableFormSchema(columns: InfraCodegenApi.CodegenColumn[]
|
|||
];
|
||||
}
|
||||
|
||||
// TODO @puhui999:【类似】是不是使用 useGenerationInfoTreeFormSchema,主要考虑对称
|
||||
/** 主子表信息 schema */
|
||||
export function useSubTableFormSchema(
|
||||
columns: InfraCodegenApi.CodegenColumn[] = [],
|
||||
|
@ -476,8 +482,8 @@ export function useCodegenColumnTableColumns(): VxeTableGridOptions['columns'] {
|
|||
{ field: 'dataType', title: '物理类型', minWidth: 100 },
|
||||
{
|
||||
field: 'javaType',
|
||||
title: 'Java类型',
|
||||
minWidth: 100,
|
||||
title: 'Java 类型',
|
||||
minWidth: 130,
|
||||
slots: { default: 'javaType' },
|
||||
params: {
|
||||
options: [
|
||||
|
@ -493,7 +499,7 @@ export function useCodegenColumnTableColumns(): VxeTableGridOptions['columns'] {
|
|||
},
|
||||
{
|
||||
field: 'javaField',
|
||||
title: 'java属性',
|
||||
title: 'Java 属性',
|
||||
minWidth: 100,
|
||||
slots: { default: 'javaField' },
|
||||
},
|
||||
|
@ -542,13 +548,13 @@ export function useCodegenColumnTableColumns(): VxeTableGridOptions['columns'] {
|
|||
{
|
||||
field: 'nullable',
|
||||
title: '允许空',
|
||||
width: 50,
|
||||
width: 60,
|
||||
slots: { default: 'nullable' },
|
||||
},
|
||||
{
|
||||
field: 'htmlType',
|
||||
title: '显示类型',
|
||||
width: 120,
|
||||
width: 130,
|
||||
slots: { default: 'htmlType' },
|
||||
params: {
|
||||
options: [
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<script lang="ts" setup>
|
||||
// TODO @puhui999:要不新建一个 edit 目录,把它挪进去?
|
||||
import type { InfraCodegenApi } from '#/api/infra/codegen';
|
||||
|
||||
import BasicInfo from './modules/basic-info.vue';
|
||||
|
@ -31,8 +32,9 @@ const generateInfoRef = ref<InstanceType<typeof GenerationInfo>>();
|
|||
/** 获取详情数据 */
|
||||
const getDetail = async () => {
|
||||
const id = route.query.id as any;
|
||||
if (!id) return;
|
||||
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
try {
|
||||
formData.value = await getCodegenTable(id);
|
||||
|
@ -55,18 +57,19 @@ const submitForm = async () => {
|
|||
return;
|
||||
}
|
||||
|
||||
// 提交
|
||||
// 提交表单
|
||||
const hideLoading = message.loading({
|
||||
content: $t('ui.actionMessage.updating'),
|
||||
duration: 0,
|
||||
key: 'action_process_msg',
|
||||
});
|
||||
try {
|
||||
// 获取相关信息
|
||||
// 拼接相关信息
|
||||
const basicInfo = await basicInfoRef.value?.getValues();
|
||||
const columns = columnInfoRef.value?.getData() || unref(formData).columns;
|
||||
const generateInfo = await generateInfoRef.value?.getValues();
|
||||
await updateCodegenTable({ table: { ...unref(formData).table, ...basicInfo, ...generateInfo }, columns });
|
||||
// 关闭并提示
|
||||
message.success({
|
||||
content: $t('ui.actionMessage.operationSuccess'),
|
||||
key: 'action_process_msg',
|
||||
|
@ -79,6 +82,7 @@ const submitForm = async () => {
|
|||
}
|
||||
};
|
||||
|
||||
// TODO @puhui999:可能要关闭下当前的编辑页面
|
||||
/** 返回列表 */
|
||||
const close = () => {
|
||||
router.push('/infra/codegen');
|
||||
|
@ -138,6 +142,7 @@ getDetail();
|
|||
<Button v-show="currentStep === steps.length - 1" type="primary" :loading="loading" @click="submitForm">
|
||||
保存
|
||||
</Button>
|
||||
<!-- TODO @puhui999:返回要不去掉,感觉一般自己点击关闭就好啦! -->
|
||||
<Button @click="close">
|
||||
<ChevronsLeft class="mr-1" />
|
||||
返回
|
||||
|
|
|
@ -50,6 +50,7 @@ function onPreview(row: InfraCodegenApi.CodegenTable) {
|
|||
|
||||
/** 编辑表格 */
|
||||
function onEdit(row: InfraCodegenApi.CodegenTable) {
|
||||
// TODO @puhui999:使用 name。这样后续换路径,不会有问题哈;
|
||||
router.push(`/codegen/edit?id=${row.id}`);
|
||||
}
|
||||
|
||||
|
@ -119,14 +120,14 @@ async function onGenerate(row: InfraCodegenApi.CodegenTable) {
|
|||
/** 表格操作按钮的回调函数 */
|
||||
function onActionClick({ code, row }: OnActionClickParams<InfraCodegenApi.CodegenTable>) {
|
||||
switch (code) {
|
||||
case 'delete': {
|
||||
onDelete(row);
|
||||
break;
|
||||
}
|
||||
case 'edit': {
|
||||
onEdit(row);
|
||||
break;
|
||||
}
|
||||
case 'delete': {
|
||||
onDelete(row);
|
||||
break;
|
||||
}
|
||||
case 'generate': {
|
||||
onGenerate(row);
|
||||
break;
|
||||
|
@ -171,6 +172,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||
} as VxeTableGridOptions<InfraCodegenApi.CodegenTable>,
|
||||
});
|
||||
|
||||
// TODO @puhui999:这个,是不是可以使用 apiselect
|
||||
/** 获取数据源配置列表 */
|
||||
async function initDataSourceConfig() {
|
||||
try {
|
||||
|
@ -199,7 +201,7 @@ initDataSourceConfig();
|
|||
<template #toolbar-tools>
|
||||
<Button type="primary" @click="onImport" v-access:code="['infra:codegen:create']">
|
||||
<Plus class="size-5" />
|
||||
{{ $t('ui.actionTitle.create', ['导入']) }}
|
||||
导入
|
||||
</Button>
|
||||
</template>
|
||||
</Grid>
|
||||
|
|
|
@ -12,8 +12,7 @@ const props = defineProps<{
|
|||
|
||||
/** 表单实例 */
|
||||
const [Form, formApi] = useVbenForm({
|
||||
// 配置表单布局为两列
|
||||
wrapperClass: 'grid grid-cols-1 md:grid-cols-2 gap-4',
|
||||
wrapperClass: 'grid grid-cols-1 md:grid-cols-2 gap-4', // 配置表单布局为两列
|
||||
schema: useBasicInfoFormSchema(),
|
||||
layout: 'horizontal',
|
||||
showDefaultActions: false,
|
||||
|
|
|
@ -6,23 +6,20 @@ 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 { nextTick, onMounted, ref, watch } from 'vue';
|
||||
|
||||
import { useCodegenColumnTableColumns } from '../data';
|
||||
|
||||
defineOptions({ name: 'InfraCodegenColumInfoForm' });
|
||||
|
||||
const props = defineProps<{
|
||||
columns?: InfraCodegenApi.CodegenColumn[];
|
||||
}>();
|
||||
|
||||
/** 表格配置 */
|
||||
const [Grid, extendedApi] = useVbenVxeGrid({
|
||||
const [Grid, gridApi] = useVbenVxeGrid({
|
||||
gridOptions: {
|
||||
columns: useCodegenColumnTableColumns(),
|
||||
border: true,
|
||||
showOverflow: true,
|
||||
height: 'auto',
|
||||
autoResize: true,
|
||||
keepSource: true,
|
||||
rowConfig: {
|
||||
|
@ -40,13 +37,12 @@ const [Grid, extendedApi] = useVbenVxeGrid({
|
|||
/** 监听外部传入的列数据 */
|
||||
watch(
|
||||
() => props.columns,
|
||||
(columns) => {
|
||||
async (columns) => {
|
||||
if (!columns) {
|
||||
return;
|
||||
}
|
||||
setTimeout(() => {
|
||||
extendedApi.grid?.loadData(columns);
|
||||
}, 100);
|
||||
await nextTick();
|
||||
gridApi.grid?.loadData(columns);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
|
@ -55,20 +51,14 @@ watch(
|
|||
|
||||
/** 提供获取表格数据的方法供父组件调用 */
|
||||
defineExpose({
|
||||
getData: (): InfraCodegenApi.CodegenColumn[] => extendedApi.grid.getData(),
|
||||
getData: (): InfraCodegenApi.CodegenColumn[] => gridApi.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();
|
||||
/** 初始化 */
|
||||
const dictTypeOptions = ref<SystemDictTypeApi.SystemDictType[]>([]); // 字典类型选项
|
||||
onMounted(async () => {
|
||||
dictTypeOptions.value = await getSimpleDictTypeList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -78,7 +68,7 @@ loadDictTypeOptions();
|
|||
<Input v-model:value="row.columnComment" />
|
||||
</template>
|
||||
|
||||
<!-- Java类型 -->
|
||||
<!-- 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">
|
||||
|
@ -86,8 +76,7 @@ loadDictTypeOptions();
|
|||
</Select.Option>
|
||||
</Select>
|
||||
</template>
|
||||
|
||||
<!-- Java属性 -->
|
||||
<!-- Java 属性 -->
|
||||
<template #javaField="{ row }">
|
||||
<Input v-model:value="row.javaField" />
|
||||
</template>
|
||||
|
@ -96,17 +85,14 @@ loadDictTypeOptions();
|
|||
<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" />
|
||||
|
@ -114,7 +100,7 @@ loadDictTypeOptions();
|
|||
|
||||
<!-- 查询方式 -->
|
||||
<template #listOperationCondition="{ row, column }">
|
||||
<Select v-model:value="row.listOperationCondition" style="width: 100%">
|
||||
<Select v-model:value="row.listOperationCondition" class="w-full">
|
||||
<Select.Option v-for="option in column.params.options" :key="option.value" :value="option.value">
|
||||
{{ option.label }}
|
||||
</Select.Option>
|
||||
|
@ -128,7 +114,7 @@ loadDictTypeOptions();
|
|||
|
||||
<!-- 显示类型 -->
|
||||
<template #htmlType="{ row, column }">
|
||||
<Select v-model:value="row.htmlType" style="width: 100%">
|
||||
<Select v-model:value="row.htmlType" class="w-full">
|
||||
<Select.Option v-for="option in column.params.options" :key="option.value" :value="option.value">
|
||||
{{ option.label }}
|
||||
</Select.Option>
|
||||
|
@ -137,9 +123,9 @@ loadDictTypeOptions();
|
|||
|
||||
<!-- 字典类型 -->
|
||||
<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 v-model:value="row.dictType" class="w-full" allow-clear show-search>
|
||||
<Select.Option v-for="option in dictTypeOptions" :key="option.type" :value="option.type">
|
||||
{{ option.name }}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</template>
|
||||
|
|
|
@ -10,23 +10,21 @@ import { isEmpty } from '@vben/utils';
|
|||
|
||||
import { useGenerationInfoBaseFormSchema, useSubTableFormSchema, useTreeTableFormSchema } from '../data';
|
||||
|
||||
defineOptions({ name: 'InfraCodegenGenerateInfoForm' });
|
||||
|
||||
const props = defineProps<{
|
||||
columns?: InfraCodegenApi.CodegenColumn[];
|
||||
table?: InfraCodegenApi.CodegenTable;
|
||||
}>();
|
||||
|
||||
const tables = ref<InfraCodegenApi.CodegenTable[]>([]);
|
||||
const currentTemplateType = ref<number>();
|
||||
const wrapperClass = 'grid grid-cols-1 md:grid-cols-2 gap-4 mb-4'; // 一行两列布局
|
||||
|
||||
/** 计算当前模板类型 */
|
||||
const currentTemplateType = ref<number>();
|
||||
const isTreeTable = computed(() => currentTemplateType.value === InfraCodegenTemplateTypeEnum.TREE);
|
||||
const isSubTable = computed(() => currentTemplateType.value === InfraCodegenTemplateTypeEnum.SUB);
|
||||
|
||||
/** 基础表单实例 */
|
||||
const [BaseForm, baseFormApi] = useVbenForm({
|
||||
wrapperClass,
|
||||
wrapperClass: 'grid grid-cols-1 md:grid-cols-2 gap-4', // 配置表单布局为两列
|
||||
layout: 'horizontal',
|
||||
showDefaultActions: false,
|
||||
schema: useGenerationInfoBaseFormSchema(),
|
||||
|
@ -40,7 +38,7 @@ const [BaseForm, baseFormApi] = useVbenForm({
|
|||
|
||||
/** 树表信息表单实例 */
|
||||
const [TreeForm, treeFormApi] = useVbenForm({
|
||||
wrapperClass,
|
||||
wrapperClass: 'grid grid-cols-1 md:grid-cols-2 gap-4', // 配置表单布局为两列
|
||||
layout: 'horizontal',
|
||||
showDefaultActions: false,
|
||||
schema: [],
|
||||
|
@ -48,7 +46,7 @@ const [TreeForm, treeFormApi] = useVbenForm({
|
|||
|
||||
/** 主子表信息表单实例 */
|
||||
const [SubForm, subFormApi] = useVbenForm({
|
||||
wrapperClass,
|
||||
wrapperClass: 'grid grid-cols-1 md:grid-cols-2 gap-4', // 配置表单布局为两列
|
||||
layout: 'horizontal',
|
||||
showDefaultActions: false,
|
||||
schema: [],
|
||||
|
@ -56,29 +54,30 @@ const [SubForm, subFormApi] = useVbenForm({
|
|||
|
||||
/** 更新树表信息表单 schema */
|
||||
function updateTreeSchema(): void {
|
||||
const schema = useTreeTableFormSchema(props.columns);
|
||||
treeFormApi.setState({ schema });
|
||||
treeFormApi.setState({
|
||||
schema: useTreeTableFormSchema(props.columns)
|
||||
});
|
||||
}
|
||||
|
||||
/** 更新主子表信息表单 schema */
|
||||
function updateSubSchema(): void {
|
||||
const schema = useSubTableFormSchema(props.columns, tables.value);
|
||||
subFormApi.setState({ schema });
|
||||
subFormApi.setState({
|
||||
schema: useSubTableFormSchema(props.columns, tables.value)
|
||||
});
|
||||
}
|
||||
|
||||
/** 获取合并的表单值 */
|
||||
async function getAllFormValues(): Promise<Record<string, any>> {
|
||||
// 基础表单值
|
||||
const baseValues = await baseFormApi.getValues();
|
||||
|
||||
// 根据模板类型获取对应的额外表单值
|
||||
// TODO @puhui999:使用二元表达式
|
||||
let extraValues = {};
|
||||
if (isTreeTable.value) {
|
||||
extraValues = await treeFormApi.getValues();
|
||||
} else if (isSubTable.value) {
|
||||
extraValues = await subFormApi.getValues();
|
||||
}
|
||||
|
||||
// 合并表单值
|
||||
return { ...baseValues, ...extraValues };
|
||||
}
|
||||
|
@ -90,6 +89,7 @@ async function validateAllForms() {
|
|||
const { valid: baseFormValid } = await baseFormApi.validate();
|
||||
validateResult = baseFormValid;
|
||||
// 根据模板类型验证对应的额外表单
|
||||
// TODO @puhui999:可以类似上面,抽个类似 extraValid,然后最后 validateResult && extraValid 类似这种哇?
|
||||
if (isTreeTable.value) {
|
||||
const { valid: treeFormValid } = await treeFormApi.validate();
|
||||
validateResult = baseFormValid && treeFormValid;
|
||||
|
@ -102,14 +102,15 @@ async function validateAllForms() {
|
|||
|
||||
/** 设置表单值 */
|
||||
function setAllFormValues(values: Record<string, any>): void {
|
||||
if (!values) return;
|
||||
if (!values) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 记录模板类型
|
||||
currentTemplateType.value = values.templateType;
|
||||
|
||||
// 设置基础表单值
|
||||
baseFormApi.setValues(values);
|
||||
|
||||
// 根据模板类型设置对应的额外表单值
|
||||
if (isTreeTable.value) {
|
||||
treeFormApi.setValues(values);
|
||||
|
@ -125,7 +126,7 @@ watch(
|
|||
if (!val || isEmpty(val)) {
|
||||
return;
|
||||
}
|
||||
// 初始化树表的schema
|
||||
// 初始化树表的 schema
|
||||
updateTreeSchema();
|
||||
// 设置表单值
|
||||
setAllFormValues(val);
|
||||
|
@ -151,10 +152,8 @@ defineExpose({
|
|||
<div>
|
||||
<!-- 基础表单 -->
|
||||
<BaseForm />
|
||||
|
||||
<!-- 树表信息表单 -->
|
||||
<TreeForm v-if="isTreeTable" />
|
||||
|
||||
<!-- 主子表信息表单 -->
|
||||
<SubForm v-if="isSubTable" />
|
||||
</div>
|
||||
|
|
|
@ -21,26 +21,29 @@ const emit = defineEmits<{
|
|||
}>();
|
||||
|
||||
const dataSourceConfigList = ref<InfraDataSourceConfigApi.InfraDataSourceConfig[]>([]);
|
||||
const formData = reactive<InfraCodegenApi.CodegenCreateListReq>({
|
||||
const formData = reactive<InfraCodegenApi.CodegenCreateListReqVO>({
|
||||
dataSourceConfigId: undefined,
|
||||
tableNames: [], // 已选择的表列表
|
||||
});
|
||||
|
||||
/** 表格实例 */
|
||||
const [Grid, gridApi] = useVbenVxeGrid({
|
||||
formOptions: {
|
||||
schema: useImportTableFormSchema([]),
|
||||
},
|
||||
gridOptions: {
|
||||
// TODO @puhui999:这个要不也挪出去,保持统一?
|
||||
columns: [
|
||||
{ type: 'checkbox', width: 40 },
|
||||
{ field: 'name', title: '表名称', minWidth: 200 },
|
||||
{ field: 'comment', title: '表描述', minWidth: 200 },
|
||||
],
|
||||
height: '600px',
|
||||
height: 600,
|
||||
keepSource: true,
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
query: async ({ page }, formValues) => {
|
||||
// TODO @puhui999:貌似可以直接使用 formValues.dataSourceConfigId。肯定可以读到值。
|
||||
if (formValues.dataSourceConfigId === undefined) {
|
||||
if (unref(dataSourceConfigList).length > 0) {
|
||||
formValues.dataSourceConfigId = unref(dataSourceConfigList)[0]?.id;
|
||||
|
@ -81,20 +84,21 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||
/** 模态框实例 */
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
title: '导入表',
|
||||
class: 'w-2/3',
|
||||
class: 'w-1/2',
|
||||
async onConfirm() {
|
||||
modalApi.lock();
|
||||
// 1. 获取表单值
|
||||
// 1.1 获取表单值
|
||||
if (formData?.dataSourceConfigId === undefined) {
|
||||
message.error('请选择数据源');
|
||||
return;
|
||||
}
|
||||
// 2. 校验是否选择了表
|
||||
// 1.2 校验是否选择了表
|
||||
if (formData.tableNames.length === 0) {
|
||||
message.error('请选择需要导入的表');
|
||||
return;
|
||||
}
|
||||
// 3. 提交请求
|
||||
|
||||
// 2. 提交请求
|
||||
const hideLoading = message.loading({
|
||||
content: '导入中...',
|
||||
duration: 0,
|
||||
|
|
|
@ -61,6 +61,7 @@ const copyCode = async () => {
|
|||
|
||||
/** 文件节点点击事件 */
|
||||
const handleNodeClick = (_: any[], e: any) => {
|
||||
// TODO @puhui999:可以简化,if return;减少括号
|
||||
if (e.node.isLeaf) {
|
||||
activeKey.value = e.node.key;
|
||||
const file = previewFiles.value.find(
|
||||
|
@ -80,6 +81,7 @@ const handleNodeClick = (_: any[], e: any) => {
|
|||
};
|
||||
|
||||
/** 处理文件树 */
|
||||
// TODO @puhui999:看看能不能用 cursor 优化下这个方法;= = 比较冗余
|
||||
const handleFiles = (data: InfraCodegenApi.CodegenPreview[]): FileNode[] => {
|
||||
const exists: Record<string, boolean> = {};
|
||||
const files: FileNode[] = [];
|
||||
|
@ -161,6 +163,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||
class: 'w-3/5',
|
||||
async onOpenChange(isOpen: boolean) {
|
||||
if (!isOpen) {
|
||||
// TODO @puhui999:貌似下面不要,也没关系?
|
||||
previewFiles.value = [];
|
||||
fileTree.value = [];
|
||||
activeKey.value = '';
|
||||
|
@ -176,9 +179,9 @@ const [Modal, modalApi] = useVbenModal({
|
|||
try {
|
||||
const data = await previewCodegen(row.id);
|
||||
previewFiles.value = data;
|
||||
fileTree.value = handleFiles(data);
|
||||
|
||||
// 默认选中第一个文件
|
||||
// 构建代码树,并默认选中第一个文件
|
||||
fileTree.value = handleFiles(data);
|
||||
if (data.length > 0) {
|
||||
activeKey.value = data[0]?.filePath || '';
|
||||
const lang = activeKey.value.split('.').pop() || '';
|
||||
|
@ -200,9 +203,11 @@ const [Modal, modalApi] = useVbenModal({
|
|||
|
||||
<template>
|
||||
<Modal title="代码预览">
|
||||
<div class="h-1/1 flex" v-loading="loading">
|
||||
<div class="h-full flex" v-loading="loading">
|
||||
<!-- 文件树 -->
|
||||
<div class="w-1/3 border-r border-gray-200 pr-4 dark:border-gray-700">
|
||||
<!-- TODO @puhui999:树默认展示; -->
|
||||
<!-- TODO @puhui999:默认节点点击,可以展开 -->
|
||||
<Tree
|
||||
:selected-keys="[activeKey]"
|
||||
:tree-data="fileTree"
|
||||
|
@ -210,14 +215,18 @@ const [Modal, modalApi] = useVbenModal({
|
|||
/>
|
||||
</div>
|
||||
<!-- 代码预览 -->
|
||||
<!-- TODO @puhui999:可以顶部有个 tab 么? -->
|
||||
<!-- TODO @puhui999:貌似 java 的缩进,不太对,首行空了很长; -->
|
||||
<div class="w-2/3 pl-4">
|
||||
<div class="mb-2 flex justify-between">
|
||||
<div class="text-lg font-medium dark:text-gray-200">
|
||||
{{ activeKey.split('/').pop() }}
|
||||
<!-- TODO @puhui999:貌似不用 activeLanguage 哇? -->
|
||||
<span class="ml-2 text-xs text-gray-500 dark:text-gray-400">
|
||||
({{ activeLanguage }})
|
||||
</span>
|
||||
</div>
|
||||
<!-- TODO @芋艿:貌似别的模块,也可以通过 :icon="h(Copy)"??? -->
|
||||
<Button type="primary" ghost @click="copyCode" :icon="h(Copy)">
|
||||
复制代码
|
||||
</Button>
|
||||
|
|
|
@ -9,7 +9,7 @@ import Form from './modules/form.vue';
|
|||
|
||||
import { $t } from '#/locales';
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import { getConfigPage, deleteConfig, exportConfig, getConfigKey } from '#/api/infra/config';
|
||||
import { getConfigPage, deleteConfig, exportConfig } from '#/api/infra/config';
|
||||
import { useGridColumns, useGridFormSchema } from './data';
|
||||
import { downloadByData } from '#/utils/download';
|
||||
|
||||
|
|
Loading…
Reference in New Issue