diff --git a/apps/web-antd/package.json b/apps/web-antd/package.json index 26f6e8d54..c7d737379 100644 --- a/apps/web-antd/package.json +++ b/apps/web-antd/package.json @@ -43,6 +43,7 @@ "@vueuse/core": "catalog:", "ant-design-vue": "catalog:", "dayjs": "catalog:", + "highlight.js": "^11.11.1", "pinia": "catalog:", "vue": "catalog:", "vue-codemirror": "^6.1.1", diff --git a/apps/web-antd/src/views/infra/codegen/data.ts b/apps/web-antd/src/views/infra/codegen/data.ts index ed02c4720..7161281f1 100644 --- a/apps/web-antd/src/views/infra/codegen/data.ts +++ b/apps/web-antd/src/views/infra/codegen/data.ts @@ -46,19 +46,6 @@ export function useImportTableFormSchema(): VbenFormSchema[] { ]; } -/** 预览代码模态框 */ -export function usePreviewFormSchema(): VbenFormSchema[] { - return [ - { - fieldName: 'content', - component: 'Textarea', - componentProps: { - readonly: true, - }, - }, - ]; -} - /** 列表的搜索表单 */ export function useGridFormSchema(): VbenFormSchema[] { return [ diff --git a/apps/web-antd/src/views/infra/codegen/index.vue b/apps/web-antd/src/views/infra/codegen/index.vue index 917618f50..44d8d74aa 100644 --- a/apps/web-antd/src/views/infra/codegen/index.vue +++ b/apps/web-antd/src/views/infra/codegen/index.vue @@ -5,8 +5,8 @@ import type { InfraDataSourceConfigApi } from '#/api/infra/data-source-config'; import { DocAlert } from '#/components/doc-alert'; // import ImportTable from './modules/import-table.vue'; -// import PreviewCode from './modules/preview-code.vue'; -import { Page } from '@vben/common-ui'; +import PreviewCode from './modules/preview-code.vue'; +import { Page, useVbenModal } from '@vben/common-ui'; import { Plus } from '@vben/icons'; import { Button, message } from 'ant-design-vue'; @@ -28,10 +28,11 @@ const dataSourceConfigList = ref - + diff --git a/apps/web-antd/src/views/infra/codegen/modules/preview-code.vue b/apps/web-antd/src/views/infra/codegen/modules/preview-code.vue index ff3b1df4d..ea5d58836 100644 --- a/apps/web-antd/src/views/infra/codegen/modules/preview-code.vue +++ b/apps/web-antd/src/views/infra/codegen/modules/preview-code.vue @@ -2,12 +2,11 @@ import type { InfraCodegenApi } from '#/api/infra/codegen'; import { useVbenModal } from '@vben/common-ui'; -import { CopyOutlined } from '@vben/icons'; -import { message, Tree } from 'ant-design-vue'; +import { Copy } from '@vben/icons'; +import { Button, message, Tree } from 'ant-design-vue'; -import { useVbenForm } from '#/adapter/form'; import { previewCodegen } from '#/api/infra/codegen'; -import { ref } from 'vue'; +import { computed, h, ref } from 'vue'; import { useClipboard } from '@vueuse/core'; import hljs from 'highlight.js/lib/core'; @@ -17,10 +16,7 @@ import sql from 'highlight.js/lib/languages/sql'; import typescript from 'highlight.js/lib/languages/typescript'; import xml from 'highlight.js/lib/languages/xml'; -import { usePreviewFormSchema } from '../data'; - -import 'highlight.js/styles/github.css'; - +/** 注册代码高亮语言 */ hljs.registerLanguage('java', java); hljs.registerLanguage('xml', xml); hljs.registerLanguage('html', xml); @@ -29,7 +25,7 @@ hljs.registerLanguage('javascript', javascript); hljs.registerLanguage('sql', sql); hljs.registerLanguage('typescript', typescript); -// 文件树类型 +/** 文件树类型 */ interface FileNode { key: string; title: string; @@ -38,27 +34,30 @@ interface FileNode { children?: FileNode[]; } +/** 组件状态 */ const loading = ref(false); const fileTree = ref([]); const previewFiles = ref([]); const activeKey = ref(''); const highlightedCode = ref(''); -// 表单实例 -const [Form, formApi] = useVbenForm({ - schema: usePreviewFormSchema(), - showActionButtonGroup: false, +/** 当前活动文件的语言 */ +const activeLanguage = computed(() => { + return activeKey.value.split('.').pop() || ''; }); -// 复制代码 +/** 复制代码 */ const copyCode = async () => { const { copy } = useClipboard(); - await copy(highlightedCode.value); - message.success('复制成功'); + const file = previewFiles.value.find((item) => item.filePath === activeKey.value); + if (file) { + await copy(file.code); + message.success('复制成功'); + } }; -// 文件节点点击事件 -const handleNodeClick = (selectedKeys: string[], e: any) => { +/** 文件节点点击事件 */ +const handleNodeClick = (_: any[], e: any) => { if (e.node.isLeaf) { activeKey.value = e.node.key; const file = previewFiles.value.find((item) => item.filePath === activeKey.value); @@ -69,12 +68,11 @@ const handleNodeClick = (selectedKeys: string[], e: any) => { } catch { highlightedCode.value = file.code; } - formApi.setFieldValue('content', file.code); } } }; -// 处理文件树 +/** 处理文件树 */ const handleFiles = (data: InfraCodegenApi.CodegenPreview[]): FileNode[] => { const exists: Record = {}; const files: FileNode[] = []; @@ -97,7 +95,7 @@ const handleFiles = (data: InfraCodegenApi.CodegenPreview[]): FileNode[] => { let packagePath = ''; i++; while (i < paths.length) { - const nextPath = paths[i]; + const nextPath = paths[i] || ''; if (['controller', 'convert', 'dal', 'dataobject', 'enums', 'mysql', 'service', 'vo'].includes(nextPath)) { break; } @@ -118,7 +116,7 @@ const handleFiles = (data: InfraCodegenApi.CodegenPreview[]): FileNode[] => { // 构建文件树 for (let i = 0; i < newPaths.length; i++) { const oldFullPath = fullPath; - fullPath = fullPath.length === 0 ? newPaths[i] : `${fullPath.replaceAll('.', '/')}/${newPaths[i]}`; + fullPath = fullPath.length === 0 ? newPaths[i] || '' : `${fullPath.replaceAll('.', '/')}/${newPaths[i]}`; if (exists[fullPath]) { continue; @@ -127,14 +125,14 @@ const handleFiles = (data: InfraCodegenApi.CodegenPreview[]): FileNode[] => { exists[fullPath] = true; files.push({ key: fullPath, - title: newPaths[i], + title: newPaths[i] || '', parentKey: oldFullPath || '/', isLeaf: i === newPaths.length - 1, }); } } - // 构建树形结构 + /** 构建树形结构 */ const buildTree = (parentKey: string): FileNode[] => { return files .filter((file) => file.parentKey === parentKey) @@ -147,9 +145,10 @@ const handleFiles = (data: InfraCodegenApi.CodegenPreview[]): FileNode[] => { return buildTree('/'); }; -// 模态框实例 +/** 模态框实例 */ const [Modal, modalApi] = useVbenModal({ footer: false, + class: 'w-3/5', async onOpenChange(isOpen: boolean) { if (!isOpen) { previewFiles.value = []; @@ -159,27 +158,26 @@ const [Modal, modalApi] = useVbenModal({ return; } - // 获取表ID - const id = modalApi.getData(); - if (!id) return; + const row = modalApi.getData(); + if (!row) return; // 加载预览数据 loading.value = true; try { - const data = await previewCodegen(id); + const data = await previewCodegen(row.id); previewFiles.value = data; fileTree.value = handleFiles(data); // 默认选中第一个文件 if (data.length > 0) { - activeKey.value = data[0].filePath; - const lang = data[0].filePath.split('.').pop() || ''; + activeKey.value = data[0]?.filePath || ''; + const lang = activeKey.value.split('.').pop() || ''; + const code = data[0]?.code || ''; try { - highlightedCode.value = hljs.highlight(data[0].code, { language: lang }).value; + highlightedCode.value = hljs.highlight(code, { language: lang }).value; } catch { - highlightedCode.value = data[0].code; + highlightedCode.value = code; } - formApi.setFieldValue('content', data[0].code); } } finally { loading.value = false; @@ -190,22 +188,23 @@ const [Modal, modalApi] = useVbenModal({ - + - + - {{ activeKey.split('/').pop() }} - - - 复制代码 - + + {{ activeKey.split('/').pop() }} + ({{ activeLanguage }}) + + 复制代码 - + + @@ -213,10 +212,94 @@ const [Modal, modalApi] = useVbenModal({
+