mirror of
https://github.com/continew-org/continew-admin-ui.git
synced 2025-09-09 20:57:17 +08:00
refactor: 代码生成预览调整为以文件树结构形式显示
This commit is contained in:
@@ -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
|
||||||
}
|
}
|
||||||
|
@@ -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>
|
||||||
|
@@ -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>
|
||||||
|
Reference in New Issue
Block a user