You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
4.4 KiB
144 lines
4.4 KiB
<script lang="ts" setup> |
|
import { ref, unref } from 'vue' |
|
import { Card, Tabs } from 'ant-design-vue' |
|
import { useClipboard } from '@vueuse/core' |
|
import { BasicTree } from '@/components/Tree' |
|
import { BasicModal, useModalInner } from '@/components/Modal' |
|
import { CodeEditor, MODE } from '@/components/CodeEditor' |
|
import { previewCodegen } from '@/api/infra/codegen' |
|
import type { CodegenPreviewVO } from '@/api/infra/codegen/types' |
|
import { handleTree2 } from '@/utils/tree' |
|
import { useMessage } from '@/hooks/web/useMessage' |
|
|
|
defineOptions({ name: 'InfraPreviewModal' }) |
|
|
|
const { createMessage } = useMessage() |
|
|
|
const fileTree = ref([]) |
|
const activeKey = ref('') |
|
const modeValue = ref(MODE.JS) |
|
const previewCodes = ref<CodegenPreviewVO[]>() |
|
|
|
const [registerModal, { setModalProps }] = useModalInner(async (data) => { |
|
setModalProps({ confirmLoading: false }) |
|
|
|
const res = await previewCodegen(data.record.id) |
|
const file = handleFiles(res) |
|
previewCodes.value = res |
|
activeKey.value = res[0].filePath |
|
fileTree.value = handleTree2(file, 'id', 'parentId', 'children', '/') |
|
}) |
|
|
|
function handleSelect(keys) { |
|
activeKey.value = keys[0] |
|
} |
|
|
|
/** 生成 files 目录 **/ |
|
interface filesType { |
|
id: string |
|
label: string |
|
parentId: string |
|
} |
|
|
|
function handleFiles(datas) { |
|
const exists = {} // key:file 的 id;value:true |
|
const files: filesType[] = [] |
|
// 遍历每个元素 |
|
for (const data of datas) { |
|
let paths = data.filePath.split('/') |
|
let fullPath = '' // 从头开始的路径,用于生成 id |
|
// 特殊处理 java 文件 |
|
if (paths[paths.length - 1].includes('.java')) { |
|
const newPaths: string[] = [] |
|
for (let i = 0; i < paths.length; i++) { |
|
let path = paths[i] |
|
if (path !== 'java') { |
|
newPaths.push(path) |
|
continue |
|
} |
|
newPaths.push(path) |
|
// 特殊处理中间的 package,进行合并 |
|
let tmp = '' |
|
while (i < paths.length) { |
|
path = paths[i + 1] |
|
if ( |
|
path === 'controller' |
|
|| path === 'convert' |
|
|| path === 'dal' |
|
|| path === 'enums' |
|
|| path === 'service' |
|
|| path === 'vo' // 下面三个,主要是兜底。可能考虑到有人改了包结构 |
|
|| path === 'mysql' |
|
|| path === 'dataobject' |
|
) |
|
break |
|
|
|
tmp = tmp ? `${tmp}.${path}` : path |
|
i++ |
|
} |
|
if (tmp) |
|
newPaths.push(tmp) |
|
} |
|
paths = newPaths |
|
} |
|
// 遍历每个 path, 拼接成树 |
|
for (let i = 0; i < paths.length; i++) { |
|
// 已经添加到 files 中,则跳过 |
|
const oldFullPath = fullPath |
|
// 下面的 replaceAll 的原因,是因为上面包处理了,导致和 tabs 不匹配,所以 replaceAll 下 |
|
fullPath = fullPath.length === 0 ? paths[i] : `${fullPath.replaceAll('.', '/')}/${paths[i]}` |
|
if (exists[fullPath]) |
|
continue |
|
|
|
// 添加到 files 中 |
|
exists[fullPath] = true |
|
files.push({ |
|
id: fullPath, |
|
label: paths[i], |
|
parentId: oldFullPath || '/', // "/" 为根节点 |
|
}) |
|
} |
|
} |
|
return files |
|
} |
|
|
|
/** 复制 **/ |
|
async function copy(text: string) { |
|
const { copy, copied, isSupported } = useClipboard({ source: text }) |
|
if (!isSupported) { |
|
createMessage.error('复制失败') |
|
} |
|
else { |
|
await copy() |
|
if (unref(copied)) |
|
createMessage.success('复制成功') |
|
} |
|
} |
|
</script> |
|
|
|
<template> |
|
<BasicModal v-bind="$attrs" :default-fullscreen="true" title="预览代码" @register="registerModal"> |
|
<div class="flex"> |
|
<Card class="min-w-130 w-1/4"> |
|
<BasicTree |
|
title="文件夹列表" toolbar :default-expand-all="true" tree-wrapper-class-name="h-[800px] overflow-auto" |
|
:click-row-to-expand="false" :tree-data="fileTree" :field-names="{ key: 'id', title: 'label' }" |
|
@select="handleSelect" |
|
/> |
|
</Card> |
|
<Card class="w-3/4"> |
|
<Tabs v-model:activeKey="activeKey"> |
|
<Tabs.TabPane |
|
v-for="item in previewCodes" :key="item.filePath" |
|
:tab="item.filePath.substring(item.filePath.lastIndexOf('/') + 1)" |
|
> |
|
<a-button type="link" style="float: right; padding: 4px 60px;" @click="copy(item.code)"> |
|
复制 |
|
</a-button> |
|
<CodeEditor class="max-h-200" :value="item.code" :mode="modeValue" :readonly="true" /> |
|
</Tabs.TabPane> |
|
</Tabs> |
|
</Card> |
|
</div> |
|
</BasicModal> |
|
</template>
|
|
|