houzhongjian
2024-07-11 759b1c71011abd6b58c37d2566f3f3c208c2f1b2
提交 | 用户 | 时间
759b1c 1 <template>
H 2   <div class="app-container">
3     <!-- 操作工作栏 -->
4     <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
5       <el-form-item label="表名称" prop="tableName">
6         <el-input v-model="queryParams.tableName" placeholder="请输入表名称" clearable
7                   @keyup.enter.native="handleQuery"/>
8       </el-form-item>
9       <el-form-item label="表描述" prop="tableComment">
10         <el-input v-model="queryParams.tableComment" placeholder="请输入表描述" clearable
11                   @keyup.enter.native="handleQuery"/>
12       </el-form-item>
13       <el-form-item label="创建时间" prop="createTime">
14         <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
15                         range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
16       </el-form-item>
17       <el-form-item>
18         <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
19         <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
20       </el-form-item>
21     </el-form>
22
23     <!-- 操作工作栏 -->
24     <el-row :gutter="10" class="mb8">
25       <el-col :span="1.5">
26         <el-button type="info" plain icon="el-icon-upload" size="mini" @click="openImportTable"
27                    v-hasPermi="['infra:codegen:create']">导入</el-button>
28       </el-col>
29       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
30     </el-row>
31
32     <!-- 列表 -->
33     <el-table v-loading="loading" :data="tableList">
34       <el-table-column label="数据源" align="center" :formatter="dataSourceConfigNameFormat"/>
35       <el-table-column label="表名称" align="center" prop="tableName" width="200"/>
36       <el-table-column label="表描述" align="center" prop="tableComment" :show-overflow-tooltip="true" width="120"/>
37       <el-table-column label="实体" align="center" prop="className" width="200"/>
38       <el-table-column label="创建时间" align="center" prop="createTime" width="180">
39         <template v-slot="scope">
40           <span>{{ parseTime(scope.row.createTime) }}</span>
41         </template>
42       </el-table-column>
43       <el-table-column label="更新时间" align="center" prop="createTime" width="180">
44         <template v-slot="scope">
45           <span>{{ parseTime(scope.row.updateTime) }}</span>
46         </template>
47       </el-table-column>
48       <el-table-column label="操作" align="center" width="300px" class-name="small-padding fixed-width">
49         <template v-slot="scope">
50           <el-button type="text" size="small" icon="el-icon-view" @click="handlePreview(scope.row)" v-hasPermi="['infra:codegen:preview']">预览</el-button>
51           <el-button type="text" size="small" icon="el-icon-edit" @click="handleEditTable(scope.row)" v-hasPermi="['infra:codegen:update']">编辑</el-button>
52           <el-button type="text" size="small" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['infra:codegen:delete']">删除</el-button>
53           <el-button type="text" size="small" icon="el-icon-refresh" @click="handleSynchDb(scope.row)" v-hasPermi="['infra:codegen:update']">同步</el-button>
54           <el-button type="text" size="small" icon="el-icon-download" @click="handleGenTable(scope.row)" v-hasPermi="['infra:codegen:download']">生成代码</el-button>
55         </template>
56       </el-table-column>
57     </el-table>
58     <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" @pagination="getList"/>
59
60     <!-- 预览界面 -->
61     <el-dialog :title="preview.title" :visible.sync="preview.open" width="90%" top="5vh" append-to-body class="scrollbar">
62       <el-row>
63         <el-col :span="7">
64           <el-tree :data="preview.fileTree" :expand-on-click-node="false" default-expand-all highlight-current
65                    @node-click="handleNodeClick"/>
66         </el-col>
67         <el-col :span="17">
68           <el-tabs v-model="preview.activeName">
69             <el-tab-pane v-for="item in preview.data" :label="item.filePath.substring(item.filePath.lastIndexOf('/') + 1)"
70                          :name="item.filePath" :key="item.filePath">
71               <el-link :underline="false" icon="el-icon-document-copy" v-clipboard:copy="item.code" v-clipboard:success="clipboardSuccess" style="float:right">复制</el-link>
72               <pre><code class="hljs" v-html="highlightedCode(item)"></code></pre>
73             </el-tab-pane>
74           </el-tabs>
75         </el-col>
76       </el-row>
77     </el-dialog>
78
79     <!-- 基于 DB 导入 -->
80     <import-table ref="import" @ok="handleQuery" />
81   </div>
82 </template>
83
84 <script>
85 import { getCodegenTablePage, previewCodegen, downloadCodegen, deleteCodegen,
86   syncCodegenFromDB } from "@/api/infra/codegen";
87
88 import importTable from "./importTable";
89 // 代码高亮插件
90 import hljs from "highlight.js/lib/highlight";
91 import "highlight.js/styles/github-gist.css";
92 import {getDataSourceConfigList} from "@/api/infra/dataSourceConfig";
93 hljs.registerLanguage("java", require("highlight.js/lib/languages/java"));
94 hljs.registerLanguage("xml", require("highlight.js/lib/languages/xml"));
95 hljs.registerLanguage("html", require("highlight.js/lib/languages/xml"));
96 hljs.registerLanguage("vue", require("highlight.js/lib/languages/xml"));
97 hljs.registerLanguage("javascript", require("highlight.js/lib/languages/javascript"));
98 hljs.registerLanguage("sql", require("highlight.js/lib/languages/sql"));
99 hljs.registerLanguage("typescript", require("highlight.js/lib/languages/typescript"));
100 export default {
101   name: "InfraCodegen",
102   components: { importTable },
103   data() {
104     return {
105       // 遮罩层
106       loading: true,
107       // 唯一标识符
108       uniqueId: "",
109       // 选中表数组
110       tableNames: [],
111       // 显示搜索条件
112       showSearch: true,
113       // 总条数
114       total: 0,
115       // 表数据
116       tableList: [],
117       // 日期范围
118       dateRange: "",
119       // 查询参数
120       queryParams: {
121         pageNo: 1,
122         pageSize: 10,
123         tableName: undefined,
124         tableComment: undefined,
125         createTime: []
126       },
127       // 预览参数
128       preview: {
129         open: false,
130         title: "代码预览",
131         fileTree: [],
132         data: {},
133         activeName: "",
134       },
135       // 数据源列表
136       dataSourceConfigs: [],
137     };
138   },
139   created() {
140     this.getList();
141     // 加载数据源
142     getDataSourceConfigList().then(response => {
143       this.dataSourceConfigs = response.data;
144     });
145   },
146   activated() {
147     const time = this.$route.query.t;
148     if (time != null && time !== this.uniqueId) {
149       this.uniqueId = time;
150       this.resetQuery();
151     }
152   },
153   methods: {
154     /** 查询表集合 */
155     getList() {
156       this.loading = true;
157       getCodegenTablePage(this.queryParams).then(response => {
158             this.tableList = response.data.list;
159             this.total = response.data.total;
160             this.loading = false;
161           }
162       );
163     },
164     /** 搜索按钮操作 */
165     handleQuery() {
166       this.queryParams.pageNo = 1;
167       this.getList();
168     },
169     /** 生成代码操作 */
170     handleGenTable(row) {
171       downloadCodegen(row.id).then(response => {
172         this.$download.zip(response, 'codegen-' + row.tableName + '.zip');
173       })
174     },
175     /** 同步数据库操作 */
176     handleSynchDb(row) {
177       // 基于 DB 同步
178       const tableName = row.tableName;
179       this.$modal.confirm('确认要强制同步"' + tableName + '"表结构吗?').then(function() {
180           return syncCodegenFromDB(row.id);
181       }).then(() => {
182           this.$modal.msgSuccess("同步成功");
183       }).catch(() => {});
184     },
185     /** 打开导入表弹窗 */
186     openImportTable() {
187       this.$refs.import.show();
188     },
189     /** 重置按钮操作 */
190     resetQuery() {
191       this.resetForm("queryForm");
192       this.handleQuery();
193     },
194     /** 预览按钮 */
195     handlePreview(row) {
196       previewCodegen(row.id).then(response => {
197         this.preview.data = response.data;
198         let files = this.handleFiles(response.data);
199         this.preview.fileTree = this.handleTree(files, "id", "parentId", "children",
200             "/"); // "/" 为根节点
201         // console.log(this.preview.fileTree)
202         this.preview.activeName = response.data[0].filePath;
203         this.preview.open = true;
204       });
205     },
206     /** 高亮显示 */
207     highlightedCode(item) {
208       // const vmName = key.substring(key.lastIndexOf("/") + 1, key.indexOf(".vm"));
209       // var language = vmName.substring(vmName.indexOf(".") + 1, vmName.length);
210       const language = item.filePath.substring(item.filePath.lastIndexOf('.') + 1)
211       const result = hljs.highlight(language, item.code || "", true);
212       return result.value || '&nbsp;';
213     },
214     /** 复制代码成功 */
215     clipboardSuccess() {
216       this.$modal.msgSuccess("复制成功");
217     },
218     /** 生成 files 目录 **/
219     handleFiles(datas) {
220       let exists = {}; // key:file 的 id;value:true
221       let files = [];
222       // 遍历每个元素
223       for (const data of datas) {
224         let paths = data.filePath.split('/');
225         let fullPath = ''; // 从头开始的路径,用于生成 id
226         // 特殊处理 java 文件
227         if (paths[paths.length - 1].indexOf('.java') >= 0) {
228           let newPaths = [];
229           for (let i = 0; i < paths.length; i++) {
230             let path = paths[i];
231             if (path !== 'java') {
232               newPaths.push(path);
233               continue;
234             }
235             newPaths.push(path);
236             // 特殊处理中间的 package,进行合并
237             let tmp = undefined;
238             while (i < paths.length) {
239               path = paths[i + 1];
240               if (path === 'controller'
241                 || path === 'convert'
242                 || path === 'dal'
243                 || path === 'enums'
244                 || path === 'service'
245                 || path === 'vo' // 下面三个,主要是兜底。可能考虑到有人改了包结构
246                 || path === 'mysql'
247                 || path === 'dataobject') {
248                 break;
249               }
250               tmp = tmp ? tmp + '.' + path : path;
251               i++;
252             }
253             if (tmp) {
254               newPaths.push(tmp);
255             }
256           }
257           paths = newPaths;
258         }
259         // 遍历每个 path, 拼接成树
260         for (let i = 0; i < paths.length; i++) {
261           // 已经添加到 files 中,则跳过
262           let oldFullPath = fullPath;
263           // 下面的 replaceAll 的原因,是因为上面包处理了,导致和 tabs 不匹配,所以 replaceAll 下
264           fullPath = fullPath.length === 0 ? paths[i] : fullPath.replaceAll('.', '/') + '/' + paths[i];
265           if (exists[fullPath]) {
266             continue;
267           }
268           // 添加到 files 中
269           exists[fullPath] = true;
270           files.push({
271             id: fullPath,
272             label: paths[i],
273             parentId: oldFullPath || '/'  // "/" 为根节点
274           });
275         }
276       }
277       return files;
278     },
279     /** 节点单击事件 **/
280     handleNodeClick(data, node) {
281       if (node && !node.isLeaf) {
282         return false;
283       }
284       // 判断,如果非子节点,不允许选中
285       this.preview.activeName = data.id;
286     },
287     /** 修改按钮操作 */
288     handleEditTable(row) {
289       const tableId = row.id;
290       const tableName = row.tableName || this.tableNames[0];
291       const params = { pageNum: this.queryParams.pageNum };
292       this.$tab.openPage("修改[" + tableName + "]生成配置", '/codegen/edit/' + tableId, params);
293     },
294     /** 删除按钮操作 */
295     handleDelete(row) {
296       const tableIds = row.id;
297       this.$modal.confirm('是否确认删除表名称为"' + row.tableName + '"的数据项?').then(function() {
298           return deleteCodegen(tableIds);
299       }).then(() => {
300           this.getList();
301           this.$modal.msgSuccess("删除成功");
302       }).catch(() => {});
303     },
304     // 数据源配置的名字
305     dataSourceConfigNameFormat(row, column) {
306       for (const config of this.dataSourceConfigs) {
307         if (row.dataSourceConfigId === config.id) {
308           return config.name;
309         }
310       }
311       return '未知【' + row.leaderUserId + '】';
312     },
313   }
314 };
315 </script>