review:代码生成,相关功能

pull/71/MERGE
YunaiV 2025-04-11 18:43:25 +08:00
parent 17734ab040
commit b67f1b1ecd
12 changed files with 138 additions and 119 deletions

View File

@ -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 },
});
}

View File

@ -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')],

View File

@ -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);
}

View File

@ -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 @puhui9991 可以是枚举么
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 @puhui9991 可以是枚举么
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: [

View File

@ -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" />
返回

View File

@ -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>

View File

@ -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,

View File

@ -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>

View File

@ -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>

View File

@ -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,

View File

@ -61,6 +61,7 @@ const copyCode = async () => {
/** 文件节点点击事件 */
const handleNodeClick = (_: any[], e: any) => {
// TODO @puhui999if 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>

View File

@ -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';