Preview.vue 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. <template>
  2. <XModal title="预览" v-model="preview.open">
  3. <div class="flex">
  4. <el-card class="w-1/4" :gutter="12" shadow="hover">
  5. <el-scrollbar height="calc(100vh - 88px - 40px - 50px)">
  6. <el-tree
  7. ref="treeRef"
  8. node-key="id"
  9. :data="preview.fileTree"
  10. :expand-on-click-node="false"
  11. highlight-current
  12. @node-click="handleNodeClick"
  13. />
  14. </el-scrollbar>
  15. </el-card>
  16. <el-card class="w-3/4 ml-3" :gutter="12" shadow="hover">
  17. <el-tabs v-model="preview.activeName">
  18. <el-tab-pane
  19. v-for="item in previewCodegen"
  20. :label="item.filePath.substring(item.filePath.lastIndexOf('/') + 1)"
  21. :name="item.filePath"
  22. :key="item.filePath"
  23. >
  24. <XTextButton style="float: right" :title="t('common.copy')" @click="copy(item.code)" />
  25. <pre>{{ item.code }}</pre>
  26. </el-tab-pane>
  27. </el-tabs>
  28. </el-card>
  29. </div>
  30. </XModal>
  31. </template>
  32. <script setup lang="ts">
  33. import { useClipboard } from '@vueuse/core'
  34. import { useI18n } from '@/hooks/web/useI18n'
  35. import { useMessage } from '@/hooks/web/useMessage'
  36. import { handleTree2 } from '@/utils/tree'
  37. import { previewCodegenApi } from '@/api/infra/codegen'
  38. import { CodegenTableVO, CodegenPreviewVO } from '@/api/infra/codegen/types'
  39. const { t } = useI18n() // 国际化
  40. const message = useMessage() // 消息弹窗
  41. // ======== 显示页面 ========
  42. const preview = reactive({
  43. open: false,
  44. titel: '代码预览',
  45. fileTree: [],
  46. activeName: ''
  47. })
  48. const previewCodegen = ref<CodegenPreviewVO[]>()
  49. const show = async (row: CodegenTableVO) => {
  50. const res = await previewCodegenApi(row.id)
  51. let file = handleFiles(res)
  52. previewCodegen.value = res
  53. preview.fileTree = handleTree2(file, 'id', 'parentId', 'children', '/')
  54. preview.activeName = res[0].filePath
  55. preview.open = true
  56. }
  57. const handleNodeClick = async (data, node) => {
  58. if (node && !node.isLeaf) {
  59. return false
  60. }
  61. preview.activeName = data.id
  62. }
  63. /** 生成 files 目录 **/
  64. interface filesType {
  65. id: string
  66. label: string
  67. parentId: string
  68. }
  69. const handleFiles = (datas: CodegenPreviewVO[]) => {
  70. let exists = {} // key:file 的 id;value:true
  71. let files: filesType[] = []
  72. // 遍历每个元素
  73. for (const data of datas) {
  74. let paths = data.filePath.split('/')
  75. let fullPath = '' // 从头开始的路径,用于生成 id
  76. // 特殊处理 java 文件
  77. if (paths[paths.length - 1].indexOf('.java') >= 0) {
  78. let newPaths: string[] = []
  79. for (let i = 0; i < paths.length; i++) {
  80. let path = paths[i]
  81. if (path !== 'java') {
  82. newPaths.push(path)
  83. continue
  84. }
  85. newPaths.push(path)
  86. // 特殊处理中间的 package,进行合并
  87. let tmp = ''
  88. while (i < paths.length) {
  89. path = paths[i + 1]
  90. if (
  91. path === 'controller' ||
  92. path === 'convert' ||
  93. path === 'dal' ||
  94. path === 'enums' ||
  95. path === 'service' ||
  96. path === 'vo' || // 下面三个,主要是兜底。可能考虑到有人改了包结构
  97. path === 'mysql' ||
  98. path === 'dataobject'
  99. ) {
  100. break
  101. }
  102. tmp = tmp ? tmp + '.' + path : path
  103. i++
  104. }
  105. if (tmp) {
  106. newPaths.push(tmp)
  107. }
  108. }
  109. paths = newPaths
  110. }
  111. // 遍历每个 path, 拼接成树
  112. for (let i = 0; i < paths.length; i++) {
  113. // 已经添加到 files 中,则跳过
  114. let oldFullPath = fullPath
  115. // 下面的 replaceAll 的原因,是因为上面包处理了,导致和 tabs 不匹配,所以 replaceAll 下
  116. fullPath = fullPath.length === 0 ? paths[i] : fullPath.replaceAll('.', '/') + '/' + paths[i]
  117. if (exists[fullPath]) {
  118. continue
  119. }
  120. // 添加到 files 中
  121. exists[fullPath] = true
  122. files.push({
  123. id: fullPath,
  124. label: paths[i],
  125. parentId: oldFullPath || '/' // "/" 为根节点
  126. })
  127. }
  128. }
  129. return files
  130. }
  131. /** 复制 **/
  132. const copy = async (text: string) => {
  133. const { copy, copied, isSupported } = useClipboard({ source: text })
  134. if (!isSupported) {
  135. message.error(t('common.copyError'))
  136. } else {
  137. await copy()
  138. if (unref(copied)) {
  139. message.success(t('common.copySuccess'))
  140. }
  141. }
  142. }
  143. defineExpose({
  144. show
  145. })
  146. </script>