Preview.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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 { handleTree2 } from '@/utils/tree'
  35. import { previewCodegenApi } from '@/api/infra/codegen'
  36. import { CodegenTableVO, CodegenPreviewVO } from '@/api/infra/codegen/types'
  37. const { t } = useI18n() // 国际化
  38. const message = useMessage() // 消息弹窗
  39. // ======== 显示页面 ========
  40. const preview = reactive({
  41. open: false,
  42. titel: '代码预览',
  43. fileTree: [],
  44. activeName: ''
  45. })
  46. const previewCodegen = ref<CodegenPreviewVO[]>()
  47. const show = async (row: CodegenTableVO) => {
  48. const res = await previewCodegenApi(row.id)
  49. let file = handleFiles(res)
  50. previewCodegen.value = res
  51. preview.fileTree = handleTree2(file, 'id', 'parentId', 'children', '/')
  52. preview.activeName = res[0].filePath
  53. preview.open = true
  54. }
  55. const handleNodeClick = async (data, node) => {
  56. if (node && !node.isLeaf) {
  57. return false
  58. }
  59. preview.activeName = data.id
  60. }
  61. /** 生成 files 目录 **/
  62. interface filesType {
  63. id: string
  64. label: string
  65. parentId: string
  66. }
  67. const handleFiles = (datas: CodegenPreviewVO[]) => {
  68. let exists = {} // key:file 的 id;value:true
  69. let files: filesType[] = []
  70. // 遍历每个元素
  71. for (const data of datas) {
  72. let paths = data.filePath.split('/')
  73. let fullPath = '' // 从头开始的路径,用于生成 id
  74. // 特殊处理 java 文件
  75. if (paths[paths.length - 1].indexOf('.java') >= 0) {
  76. let newPaths: string[] = []
  77. for (let i = 0; i < paths.length; i++) {
  78. let path = paths[i]
  79. if (path !== 'java') {
  80. newPaths.push(path)
  81. continue
  82. }
  83. newPaths.push(path)
  84. // 特殊处理中间的 package,进行合并
  85. let tmp = ''
  86. while (i < paths.length) {
  87. path = paths[i + 1]
  88. if (
  89. path === 'controller' ||
  90. path === 'convert' ||
  91. path === 'dal' ||
  92. path === 'enums' ||
  93. path === 'service' ||
  94. path === 'vo' || // 下面三个,主要是兜底。可能考虑到有人改了包结构
  95. path === 'mysql' ||
  96. path === 'dataobject'
  97. ) {
  98. break
  99. }
  100. tmp = tmp ? tmp + '.' + path : path
  101. i++
  102. }
  103. if (tmp) {
  104. newPaths.push(tmp)
  105. }
  106. }
  107. paths = newPaths
  108. }
  109. // 遍历每个 path, 拼接成树
  110. for (let i = 0; i < paths.length; i++) {
  111. // 已经添加到 files 中,则跳过
  112. let oldFullPath = fullPath
  113. // 下面的 replaceAll 的原因,是因为上面包处理了,导致和 tabs 不匹配,所以 replaceAll 下
  114. fullPath = fullPath.length === 0 ? paths[i] : fullPath.replaceAll('.', '/') + '/' + paths[i]
  115. if (exists[fullPath]) {
  116. continue
  117. }
  118. // 添加到 files 中
  119. exists[fullPath] = true
  120. files.push({
  121. id: fullPath,
  122. label: paths[i],
  123. parentId: oldFullPath || '/' // "/" 为根节点
  124. })
  125. }
  126. }
  127. return files
  128. }
  129. /** 复制 **/
  130. const copy = async (text: string) => {
  131. const { copy, copied, isSupported } = useClipboard({ source: text })
  132. if (!isSupported) {
  133. message.error(t('common.copyError'))
  134. } else {
  135. await copy()
  136. if (unref(copied)) {
  137. message.success(t('common.copySuccess'))
  138. }
  139. }
  140. }
  141. defineExpose({
  142. show
  143. })
  144. </script>