refactor: 代码生成预览调整为以文件树结构形式显示

This commit is contained in:
罗敬
2024-05-09 12:05:37 +00:00
committed by Charles7c
parent 5d9fedc354
commit c9198b315c
3 changed files with 129 additions and 58 deletions

View File

@@ -44,6 +44,7 @@ export interface GeneratorConfigResp {
fieldConfigs: FieldConfigResp[] fieldConfigs: FieldConfigResp[]
} }
export interface GeneratePreviewResp { export interface GeneratePreviewResp {
path: string
fileName: string fileName: string
content: string content: string
} }

View File

@@ -7,53 +7,122 @@
width="90%" width="90%"
:footer="false" :footer="false"
> >
<div> <template #title>
<a-scrollbar style="height: 700px; overflow: auto"> <a-button type="primary" status="success" size="medium" title="生成预览" @click="onGenerate()">
<a-link style="position: absolute; right: 20px; top: 50px; z-index: 999" @click="onCopy"> <template #icon><icon-download /></template>生成 {{ previewTableName }}
<template #icon> </a-button>
<icon-copy size="large" /> </template>
</template> <div class="preview-content">
复制 <a-layout>
</a-link> <a-layout-sider theme="dark" :resize-directions="['right']" style="height: 700px">
<a-tabs size="large" @tab-click="onTabClick"> <a-tree class="selectPreview" :data="treeData" :show-line="true" @select="onSelectPreview" />
<a-tab-pane v-for="item in genPreviewList" :key="item.fileName" :title="item.fileName"> </a-layout-sider>
<GiCodeView <a-layout-content>
:type="'vue' === item.fileName.split('.')[1] ? 'vue' : 'javascript'" <a-scrollbar style="height: 700px; overflow: auto">
:code-json="item.content" <a-link style="position: absolute; right: 20px; top: 50px; z-index: 999" @click="onCopy">
/> <template #icon>
</a-tab-pane> <icon-copy size="large" />
</a-tabs> </template>
</a-scrollbar> 复制
</a-link>
<a-card :title="currentPreview?.fileName">
<GiCodeView
:type="'vue' === currentPreview?.fileName.split('.')[1] ? 'vue' : 'javascript'"
:code-json="currentPreview?.content"
/>
</a-card>
</a-scrollbar>
</a-layout-content>
</a-layout>
</div> </div>
</a-modal> </a-modal>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { genPreview, type GeneratePreviewResp } from '@/apis' import { genPreview, type GeneratePreviewResp, generate } from '@/apis'
import { Message } from '@arco-design/web-vue' import { Message, type TreeNodeData } from '@arco-design/web-vue'
import { useClipboard } from '@vueuse/core' import { useClipboard } from '@vueuse/core'
const { copy, copied } = useClipboard() const { copy, copied } = useClipboard()
const copyCodeContent = ref() const currentPreview = ref<GeneratePreviewResp>()
const genPreviewList = ref<GeneratePreviewResp[]>([]) const genPreviewList = ref<GeneratePreviewResp[]>([])
const visible = ref(false) const visible = ref(false)
const treeData = ref<TreeNodeData[]>([])
const previewTableName = ref<string>('')
// 打开 // 打开
const onPreview = async (tableName: string) => { const onPreview = async (tableName: string) => {
treeData.value = []
previewTableName.value = tableName
const res = await genPreview(tableName) const res = await genPreview(tableName)
genPreviewList.value = res.data genPreviewList.value = res.data
copyCodeContent.value = genPreviewList.value[0].content for (const genPreview of genPreviewList.value) {
assembleTree(genPreview)
}
for (const valueElement of treeData.value) {
mergeDir(valueElement)
}
currentPreview.value = genPreviewList.value[0]
visible.value = true visible.value = true
} }
// 点击 Tab // 自增的一个key 因为key相同的节点会出现一些问题
const onTabClick = (key: any) => { let autoIncrementKey = 0
copyCodeContent.value = genPreviewList.value.filter((p) => p.fileName === key)[0].content // 将生成的目录组装成树结构
const assembleTree = (genPreview: GeneratePreviewResp) => {
const paths: string[] = genPreview.path.split('\\')
let tempChildren: TreeNodeData[] | undefined = treeData.value
for (const path of paths) {
// 向treeData中推送目录,如果该级目录有那么不推送进行下级的合并
tempChildren = pushDir(tempChildren, { title: path, key: autoIncrementKey++, children: new Array<TreeNodeData>() })
}
tempChildren?.push({ title: genPreview.fileName, key: genPreview.fileName, children: new Array<TreeNodeData>() })
}
const pushDir = (children: TreeNodeData[] | undefined, treeNode: TreeNodeData) => {
if (children) {
for (const child of children) {
if (child.title === treeNode.title) {
return child.children
}
}
}
children?.push(treeNode)
return treeNode.children
}
const mergeDir = (parent: TreeNodeData) => {
// 合并目录
if (parent.children?.length == 1 && typeof parent.children[0].key === 'number') {
const mergeTitle = mergeDir(parent.children[0])
if (mergeTitle != '') {
parent.title = parent.title + '/' + mergeTitle
}
parent.children = parent.children[0].children
return parent.title
}
// 合并子目录
if (parent?.children) {
for (const child of parent.children) {
mergeDir(child)
}
}
return ''
}
// 选择文件预览
const onSelectPreview = (selectedKeys) => {
if (typeof selectedKeys[0] === 'string') {
currentPreview.value = genPreviewList.value.filter((p) => p.fileName === selectedKeys[0])[0]
}
} }
// 复制 // 复制
const onCopy = () => { const onCopy = () => {
copy(copyCodeContent.value) if (currentPreview.value) {
copy(currentPreview.value?.content)
}
} }
watch(copied, () => { watch(copied, () => {
if (copied.value) { if (copied.value) {
@@ -61,5 +130,37 @@ watch(copied, () => {
} }
}) })
// 生成
const onGenerate = async () => {
const res = await generate([previewTableName.value])
const contentDisposition = res.headers['content-disposition']
const pattern = new RegExp('filename=([^;]+\\.[^\.;]+);*')
const result = pattern.exec(contentDisposition) || ''
// 对名字进行解码
const fileName = window.decodeURI(result[1])
// 创建下载的链接
const blob = new Blob([res.data])
const downloadElement = document.createElement('a')
const href = window.URL.createObjectURL(blob)
downloadElement.style.display = 'none'
downloadElement.href = href
// 下载后文件名
downloadElement.download = fileName
document.body.appendChild(downloadElement)
// 点击下载
downloadElement.click()
// 下载完成,移除元素
document.body.removeChild(downloadElement)
// 释放掉 blob 对象
window.URL.revokeObjectURL(href)
}
defineExpose({ onPreview }) defineExpose({ onPreview })
</script> </script>
<style scoped>
.preview-content :deep(.arco-layout-sider) {
min-width: 200px;
white-space: nowrap;
}
</style>

View File

@@ -21,16 +21,10 @@
<template #action="{ record }"> <template #action="{ record }">
<a-space> <a-space>
<a-link @click="onConfig(record.tableName, record.comment)">配置</a-link> <a-link @click="onConfig(record.tableName, record.comment)">配置</a-link>
<a-link
:title="record.isConfiged ? '生成预览' : '请先进行生成配置'"
:disabled="!record.isConfiged"
@click="onPreview(record.tableName)"
>预览</a-link
>
<a-link <a-link
:title="record.isConfiged ? '生成' : '请先进行生成配置'" :title="record.isConfiged ? '生成' : '请先进行生成配置'"
:disabled="!record.isConfiged" :disabled="!record.isConfiged"
@click="onGenerate([record.tableName])" @click="onPreview(record.tableName)"
>生成</a-link >生成</a-link
> >
</a-space> </a-space>
@@ -44,7 +38,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { listGenerator, generate } from '@/apis' import { listGenerator } from '@/apis'
import GenConfigDrawer from './GenConfigDrawer.vue' import GenConfigDrawer from './GenConfigDrawer.vue'
import GenPreviewModal from './GenPreviewModal.vue' import GenPreviewModal from './GenPreviewModal.vue'
import type { TableInstanceColumns } from '@/components/GiTable/type' import type { TableInstanceColumns } from '@/components/GiTable/type'
@@ -97,31 +91,6 @@ const GenPreviewModalRef = ref<InstanceType<typeof GenPreviewModal>>()
const onPreview = (tableName: string) => { const onPreview = (tableName: string) => {
GenPreviewModalRef.value?.onPreview(tableName) GenPreviewModalRef.value?.onPreview(tableName)
} }
// 生成
const onGenerate = async (tableNames: Array<string>) => {
const res = await generate(tableNames)
const contentDisposition = res.headers['content-disposition']
const pattern = new RegExp('filename=([^;]+\\.[^\\.;]+);*')
const result = pattern.exec(contentDisposition) || ''
// 对名字进行解码
const fileName = window.decodeURI(result[1])
// 创建下载的链接
const blob = new Blob([res.data])
const downloadElement = document.createElement('a')
const href = window.URL.createObjectURL(blob)
downloadElement.style.display = 'none'
downloadElement.href = href
// 下载后文件名
downloadElement.download = fileName
document.body.appendChild(downloadElement)
// 点击下载
downloadElement.click()
// 下载完成,移除元素
document.body.removeChild(downloadElement)
// 释放掉 blob 对象
window.URL.revokeObjectURL(href)
}
</script> </script>
<style></style> <style></style>