ol-base-components 2.7.9 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +42 -5
- package/scripts/build-vscode.js +30 -0
- package/src/bin/initTemplate.js +26 -19
- package/src/vscode/extension.js +20 -0
- package/src/vscode/webview/panel.js +734 -0
package/package.json
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ol-base-components",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"main": "src/package/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"init": "src/api/init.js",
|
|
8
8
|
"run": "src/api/run.js",
|
|
9
9
|
"api": "src/api/api.js",
|
|
10
|
-
"add": "src/bin/add.js"
|
|
10
|
+
"add": "src/bin/add.js",
|
|
11
|
+
"install-vscode": "scripts/install-vscode.js"
|
|
11
12
|
},
|
|
12
13
|
"scripts": {
|
|
13
14
|
"serve": "vue-cli-service serve --no-verify",
|
|
14
15
|
"build": "vue-cli-service build",
|
|
15
16
|
"lint": "vue-cli-service lint",
|
|
16
|
-
"add": "node src/bin/add.js"
|
|
17
|
+
"add": "node src/bin/add.js",
|
|
18
|
+
"vscode:build": "node scripts/build-vscode.js",
|
|
19
|
+
"vscode:install": "node scripts/install-vscode.js"
|
|
17
20
|
},
|
|
18
21
|
"dependencies": {
|
|
19
22
|
"commander": "^14.0.0",
|
|
@@ -36,7 +39,41 @@
|
|
|
36
39
|
"prettier": "^2.8.8",
|
|
37
40
|
"sass": "^1.89.2",
|
|
38
41
|
"sass-loader": "^16.0.5",
|
|
39
|
-
"vue-template-compiler": "^2.6.14"
|
|
42
|
+
"vue-template-compiler": "^2.6.14",
|
|
43
|
+
"@types/vscode": "^1.60.0"
|
|
44
|
+
},
|
|
45
|
+
"vscode": {
|
|
46
|
+
"extension": {
|
|
47
|
+
"name": "vue-page-generator",
|
|
48
|
+
"displayName": "Vue Page Generator",
|
|
49
|
+
"description": "Generate Vue CRUD pages from Swagger API",
|
|
50
|
+
"version": "0.0.1",
|
|
51
|
+
"engines": {
|
|
52
|
+
"vscode": "^1.60.0"
|
|
53
|
+
},
|
|
54
|
+
"activationEvents": [
|
|
55
|
+
"onCommand:vue-generator.createPage"
|
|
56
|
+
],
|
|
57
|
+
"main": "./src/vscode/extension.js",
|
|
58
|
+
"contributes": {
|
|
59
|
+
"commands": [
|
|
60
|
+
{
|
|
61
|
+
"command": "vue-generator.createPage",
|
|
62
|
+
"title": "Generate Vue Page",
|
|
63
|
+
"category": "Vue Generator"
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
"menus": {
|
|
67
|
+
"explorer/context": [
|
|
68
|
+
{
|
|
69
|
+
"command": "vue-generator.createPage",
|
|
70
|
+
"group": "navigation",
|
|
71
|
+
"when": "resourceExtname == .vue || resourceExtname == .js"
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
40
77
|
},
|
|
41
78
|
"eslintConfig": {
|
|
42
79
|
"root": true,
|
|
@@ -55,7 +92,7 @@
|
|
|
55
92
|
"keywords": [
|
|
56
93
|
"ol-base-components"
|
|
57
94
|
],
|
|
58
|
-
"description": "
|
|
95
|
+
"description": "交互式命令行方式自动生成联调好的CRUD页面",
|
|
59
96
|
"browserslist": [
|
|
60
97
|
"> 1%",
|
|
61
98
|
"last 2 versions",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
// 复制扩展文件到输出目录
|
|
5
|
+
function buildVSCodeExtension() {
|
|
6
|
+
const srcDir = path.join(__dirname, "../src/vscode");
|
|
7
|
+
const outDir = path.join(__dirname, "../dist/vscode-extension");
|
|
8
|
+
|
|
9
|
+
// 创建输出目录
|
|
10
|
+
if (!fs.existsSync(outDir)) {
|
|
11
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// 复制文件
|
|
15
|
+
fs.copyFileSync(path.join(srcDir, "extension.js"), path.join(outDir, "extension.js"));
|
|
16
|
+
|
|
17
|
+
// 复制 webview 目录
|
|
18
|
+
const webviewSrcDir = path.join(srcDir, "webview");
|
|
19
|
+
const webviewOutDir = path.join(outDir, "webview");
|
|
20
|
+
|
|
21
|
+
if (!fs.existsSync(webviewOutDir)) {
|
|
22
|
+
fs.mkdirSync(webviewOutDir, { recursive: true });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
fs.copyFileSync(path.join(webviewSrcDir, "panel.js"), path.join(webviewOutDir, "panel.js"));
|
|
26
|
+
|
|
27
|
+
console.log("VSCode extension built successfully!");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
buildVSCodeExtension();
|
package/src/bin/initTemplate.js
CHANGED
|
@@ -70,7 +70,7 @@ const vue2Template = (moduleName, config = {}) => {
|
|
|
70
70
|
if (config.hasAdd || config.hasEdit || config.hasDetail) {
|
|
71
71
|
methods.push(`
|
|
72
72
|
onCancel() {
|
|
73
|
-
this.dialogVisible = false;
|
|
73
|
+
this.formConfig.dialogVisible = false;
|
|
74
74
|
}`);
|
|
75
75
|
}
|
|
76
76
|
|
|
@@ -98,8 +98,10 @@ const vue2Template = (moduleName, config = {}) => {
|
|
|
98
98
|
if (config.hasAdd) {
|
|
99
99
|
methods.push(`
|
|
100
100
|
addBtnHandler() {
|
|
101
|
-
this.
|
|
102
|
-
this.
|
|
101
|
+
this.formConfig.title = "新增";
|
|
102
|
+
this.formConfig.type = 1;
|
|
103
|
+
this.formConfig.formData = {};
|
|
104
|
+
this.formConfig.dialogVisible = true;
|
|
103
105
|
}`);
|
|
104
106
|
}
|
|
105
107
|
|
|
@@ -112,11 +114,12 @@ const vue2Template = (moduleName, config = {}) => {
|
|
|
112
114
|
${
|
|
113
115
|
config.hasDetail
|
|
114
116
|
? `const { result = {} } = await ${detailUrlKey}(row.${config.rowId});
|
|
115
|
-
this.formData = result || {};`
|
|
116
|
-
: `this.formData = { ...row };`
|
|
117
|
+
this.formConfig.formData = result || {};`
|
|
118
|
+
: `this.formConfig.formData = { ...row };`
|
|
117
119
|
}
|
|
118
|
-
this.
|
|
119
|
-
this.
|
|
120
|
+
this.formConfig.title = "编辑";
|
|
121
|
+
this.formConfig.type = 2;
|
|
122
|
+
this.formConfig.dialogVisible = true;
|
|
120
123
|
}`);
|
|
121
124
|
}
|
|
122
125
|
|
|
@@ -128,9 +131,10 @@ const vue2Template = (moduleName, config = {}) => {
|
|
|
128
131
|
if(data.length !== 1) return this.$message.info("请选择一条数据");
|
|
129
132
|
const row = data[0];
|
|
130
133
|
const { result = {} } = await ${detailUrlKey}(row.${config.rowId});
|
|
131
|
-
this.formData = result || {};
|
|
132
|
-
this.
|
|
133
|
-
this.
|
|
134
|
+
this.formConfig.formData = result || {};
|
|
135
|
+
this.formConfig.title = "详情";
|
|
136
|
+
this.formConfig.type = 0;
|
|
137
|
+
this.formConfig.dialogVisible = true;
|
|
134
138
|
}`);
|
|
135
139
|
}
|
|
136
140
|
|
|
@@ -204,10 +208,11 @@ const vue2Template = (moduleName, config = {}) => {
|
|
|
204
208
|
/>
|
|
205
209
|
${
|
|
206
210
|
config.hasDialog
|
|
207
|
-
? `<el-dialog :title="
|
|
211
|
+
? `<el-dialog :title="formConfig.title" :visible.sync="formConfig.dialogVisible" width="80%">
|
|
208
212
|
<FormModule
|
|
209
|
-
v-if="dialogVisible"
|
|
210
|
-
:formData="formData"
|
|
213
|
+
v-if="formConfig.dialogVisible"
|
|
214
|
+
:formData="formConfig.formData"
|
|
215
|
+
:type="formConfig.type"
|
|
211
216
|
@onCancel="onCancel"
|
|
212
217
|
@onSubmit="onSubmit"
|
|
213
218
|
/>
|
|
@@ -265,9 +270,12 @@ export default {
|
|
|
265
270
|
},
|
|
266
271
|
${
|
|
267
272
|
config.hasDialog
|
|
268
|
-
? `
|
|
269
|
-
|
|
270
|
-
|
|
273
|
+
? `formConfig: {
|
|
274
|
+
type: 1,
|
|
275
|
+
formData: {},
|
|
276
|
+
title:"",
|
|
277
|
+
dialogVisible: false
|
|
278
|
+
}`
|
|
271
279
|
: ""
|
|
272
280
|
}
|
|
273
281
|
}
|
|
@@ -311,8 +319,7 @@ export default {
|
|
|
311
319
|
handleindexChange(val) {
|
|
312
320
|
this.paginations.page = val;
|
|
313
321
|
this.init();
|
|
314
|
-
}
|
|
315
|
-
${generateMethods()}
|
|
322
|
+
},${generateMethods()}
|
|
316
323
|
}
|
|
317
324
|
}
|
|
318
325
|
</script>
|
|
@@ -387,7 +394,7 @@ export default {
|
|
|
387
394
|
}
|
|
388
395
|
},
|
|
389
396
|
created(){
|
|
390
|
-
|
|
397
|
+
if(this.type !== 1) this.form.value = { ...this.formData };
|
|
391
398
|
},
|
|
392
399
|
methods: {
|
|
393
400
|
onCancel() {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const vscode = require("vscode");
|
|
2
|
+
const { GeneratorPanel } = require("./webview/panel");
|
|
3
|
+
|
|
4
|
+
function activate(context) {
|
|
5
|
+
console.log("Vue Page Generator is now active!");
|
|
6
|
+
|
|
7
|
+
// 注册右键菜单命令
|
|
8
|
+
const disposable = vscode.commands.registerCommand("vue-generator.createPage", uri => {
|
|
9
|
+
GeneratorPanel.createOrShow(context.extensionUri, uri);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
context.subscriptions.push(disposable);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function deactivate() {}
|
|
16
|
+
|
|
17
|
+
module.exports = {
|
|
18
|
+
activate,
|
|
19
|
+
deactivate,
|
|
20
|
+
};
|
|
@@ -0,0 +1,734 @@
|
|
|
1
|
+
const vscode = require("vscode");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
|
|
5
|
+
// 复用现有的模板生成逻辑
|
|
6
|
+
function generateKeyName(url, method) {
|
|
7
|
+
const cleanedUrl = url.replace(/\/api\/app/, "");
|
|
8
|
+
const arr = cleanedUrl.split("/");
|
|
9
|
+
|
|
10
|
+
const processedArr = arr.map(item =>
|
|
11
|
+
item
|
|
12
|
+
.replace(/{(.*?)}/, (_, param) => `By${param.charAt(0).toUpperCase() + param.slice(1)}`)
|
|
13
|
+
.replace(/[-_]/g, "")
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
if (processedArr[0] === "") {
|
|
17
|
+
processedArr.shift();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const resultArr = [];
|
|
21
|
+
for (let i = 0; i < processedArr.length; i++) {
|
|
22
|
+
if (i === 0 || processedArr[i] !== processedArr[i - 1]) {
|
|
23
|
+
const capitalizedItem = processedArr[i].charAt(0).toUpperCase() + processedArr[i].slice(1);
|
|
24
|
+
resultArr.push(capitalizedItem);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const key = resultArr.join("");
|
|
28
|
+
return `${method.toLowerCase()}${key}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// 复用现有的 vue2Template 函数
|
|
32
|
+
function vue2Template(moduleName, config) {
|
|
33
|
+
let pageUrlKey = "",
|
|
34
|
+
exportUrlKey = "",
|
|
35
|
+
addUrlKey = "",
|
|
36
|
+
editUrlKey = "",
|
|
37
|
+
deleteUrlKey = "",
|
|
38
|
+
detailUrlKey = "",
|
|
39
|
+
baseUrlKey = "";
|
|
40
|
+
|
|
41
|
+
if (config.pageUrl) pageUrlKey = generateKeyName(config.pageUrl, "get");
|
|
42
|
+
if (config.exportUrl) exportUrlKey = generateKeyName(config.exportUrl, "post");
|
|
43
|
+
if (config.detailUrl) {
|
|
44
|
+
detailUrlKey = generateKeyName(config.detailUrl, "get");
|
|
45
|
+
baseUrlKey = `${detailUrlKey}CompleteUrl`;
|
|
46
|
+
}
|
|
47
|
+
if (config.editUrl) {
|
|
48
|
+
editUrlKey = generateKeyName(config.editUrl, "put");
|
|
49
|
+
baseUrlKey = `${editUrlKey}CompleteUrl`;
|
|
50
|
+
}
|
|
51
|
+
if (config.addUrl) baseUrlKey = addUrlKey = generateKeyName(config.addUrl, "post");
|
|
52
|
+
if (config.deleteUrl) deleteUrlKey = generateKeyName(config.deleteUrl, "delete");
|
|
53
|
+
|
|
54
|
+
const generateImports = () => {
|
|
55
|
+
const imports = [];
|
|
56
|
+
if (config.pageUrl) imports.push(`${pageUrlKey}`);
|
|
57
|
+
if (config.addUrl) imports.push(`${addUrlKey}`);
|
|
58
|
+
if (config.editUrl) imports.push(`${editUrlKey}`);
|
|
59
|
+
if (config.detailUrl) imports.push(`${detailUrlKey}`);
|
|
60
|
+
if (config.deleteUrl) imports.push(`${deleteUrlKey}`);
|
|
61
|
+
return imports.join(", ");
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const generateMethods = () => {
|
|
65
|
+
const methods = [];
|
|
66
|
+
if (config.hasAdd) {
|
|
67
|
+
methods.push(`
|
|
68
|
+
addBtnHandler() {
|
|
69
|
+
this.type = 1;
|
|
70
|
+
this.dialogVisible = true;
|
|
71
|
+
}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (config.hasEdit) {
|
|
75
|
+
methods.push(`
|
|
76
|
+
${config.hasDetail ? `async ` : ``}editBtnHandler() {
|
|
77
|
+
const data = this.multipleSelection;
|
|
78
|
+
if(data.length !== 1) return this.$message.info("请选择一条数据");
|
|
79
|
+
const row = data[0];
|
|
80
|
+
${
|
|
81
|
+
config.hasDetail
|
|
82
|
+
? `const { result = {} } = await ${detailUrlKey}(row.${config.rowId});
|
|
83
|
+
this.formData = result || {};`
|
|
84
|
+
: `this.formData = { ...row };`
|
|
85
|
+
}
|
|
86
|
+
this.type = 2;
|
|
87
|
+
this.dialogVisible = true;
|
|
88
|
+
}`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (config.hasDetail) {
|
|
92
|
+
methods.push(`async detailBtnHandler() {
|
|
93
|
+
const data = this.multipleSelection;
|
|
94
|
+
if(data.length !== 1) return this.$message.info("请选择一条数据");
|
|
95
|
+
const row = data[0];
|
|
96
|
+
const { result = {} } = await ${detailUrlKey}(row.${config.rowId});
|
|
97
|
+
this.formData = result || {};
|
|
98
|
+
this.type = 0;
|
|
99
|
+
this.dialogVisible = true;
|
|
100
|
+
}`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (config.hasDelete) {
|
|
104
|
+
methods.push(`
|
|
105
|
+
deleteBtnHandler() {
|
|
106
|
+
const data = this.multipleSelection;
|
|
107
|
+
if(data.length !== 1) return this.$message.info("请选择一条数据");
|
|
108
|
+
const row = data[0];
|
|
109
|
+
this.$confirm('确认删除当前数据吗?', '提示', {
|
|
110
|
+
confirmButtonText: '确定',
|
|
111
|
+
cancelButtonText: '取消',
|
|
112
|
+
type: 'warning'
|
|
113
|
+
}).then(() => {
|
|
114
|
+
${deleteUrlKey}(row.${config.rowId}).then(() => {
|
|
115
|
+
this.$message.success('删除成功');
|
|
116
|
+
this.init();
|
|
117
|
+
}).catch(() => {
|
|
118
|
+
this.$message.error('删除失败');
|
|
119
|
+
});
|
|
120
|
+
}).catch(() => {});
|
|
121
|
+
}`);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (config.hasAdd || config.hasEdit || config.hasDetail) {
|
|
125
|
+
methods.push(`
|
|
126
|
+
onCancel() {
|
|
127
|
+
this.dialogVisible = false;
|
|
128
|
+
}`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (config.hasAdd || config.hasEdit) {
|
|
132
|
+
methods.push(`
|
|
133
|
+
async onSubmit({ form, data }) {
|
|
134
|
+
if(form.type === 1){
|
|
135
|
+
const res = await ${addUrlKey}(data);
|
|
136
|
+
if(res.code !== 200) return;
|
|
137
|
+
this.$message("新建成功");
|
|
138
|
+
}else if (form.type === 2) {
|
|
139
|
+
const res = await ${editUrlKey}(data['${config.rowId}'], data);
|
|
140
|
+
if(res.code !== 200) return;
|
|
141
|
+
this.$message("编辑成功");
|
|
142
|
+
this.init();
|
|
143
|
+
};
|
|
144
|
+
this.init();
|
|
145
|
+
this.onCancel()
|
|
146
|
+
}`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return methods.join(",");
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
return `<!--
|
|
153
|
+
Filename: ${moduleName}.vue
|
|
154
|
+
name: ${moduleName}
|
|
155
|
+
Created Date: ${new Date().toLocaleString()}
|
|
156
|
+
Author:
|
|
157
|
+
-->
|
|
158
|
+
<template>
|
|
159
|
+
<div>
|
|
160
|
+
<ol-search
|
|
161
|
+
:url="swaggerUrl.${pageUrlKey}"
|
|
162
|
+
:form-search-data="formSearchData"
|
|
163
|
+
@handleSearch="handleSearch"
|
|
164
|
+
@handleReset="handleReset"
|
|
165
|
+
/>
|
|
166
|
+
<ol-table
|
|
167
|
+
:url="swaggerUrl.${pageUrlKey}"
|
|
168
|
+
:paginations="paginations"
|
|
169
|
+
:btnlist="this.hasBtn(this)"
|
|
170
|
+
:empty-img="tableData.emptyImg"
|
|
171
|
+
:table-data="tableData"
|
|
172
|
+
:multiple-selection="multipleSelection"
|
|
173
|
+
@SelectionChange="SelectionChange"
|
|
174
|
+
@handleSizeChange="handleSizeChange"
|
|
175
|
+
@handleindexChange="handleindexChange"
|
|
176
|
+
/>
|
|
177
|
+
${
|
|
178
|
+
config.hasDialog
|
|
179
|
+
? `<el-dialog :title="this.form.title" :visible.sync="dialogVisible" width="80%">
|
|
180
|
+
<FormModule
|
|
181
|
+
v-if="dialogVisible"
|
|
182
|
+
:formData="formData"
|
|
183
|
+
@onCancel="onCancel"
|
|
184
|
+
@onSubmit="onSubmit"
|
|
185
|
+
/>
|
|
186
|
+
</el-dialog>`
|
|
187
|
+
: ""
|
|
188
|
+
}
|
|
189
|
+
</div>
|
|
190
|
+
</template>
|
|
191
|
+
<script>
|
|
192
|
+
import { ${generateImports()} } from "@/api/modules";
|
|
193
|
+
import { ${config.swaggerModule} } from '@/api/swagger';
|
|
194
|
+
${config.hasDialog ? `import FormModule from "./components/formModule.vue"` : ""}
|
|
195
|
+
export default {
|
|
196
|
+
name: "${moduleName}",
|
|
197
|
+
${
|
|
198
|
+
config.hasDialog
|
|
199
|
+
? `components: {
|
|
200
|
+
FormModule
|
|
201
|
+
},`
|
|
202
|
+
: ""
|
|
203
|
+
}
|
|
204
|
+
data() {
|
|
205
|
+
return {
|
|
206
|
+
swaggerUrl: ${config.swaggerModule},
|
|
207
|
+
multipleSelection: [],
|
|
208
|
+
formSearchData: {
|
|
209
|
+
reset: true,
|
|
210
|
+
expendShow: true,
|
|
211
|
+
value: {},
|
|
212
|
+
tableSearch: []
|
|
213
|
+
},
|
|
214
|
+
tableData: {
|
|
215
|
+
loading: false,
|
|
216
|
+
emptyImg: true,
|
|
217
|
+
options: {
|
|
218
|
+
selection: true,
|
|
219
|
+
index: null,
|
|
220
|
+
headTool: true,
|
|
221
|
+
refreshBtn: true,
|
|
222
|
+
downloadBtn: true
|
|
223
|
+
},
|
|
224
|
+
rows: [],
|
|
225
|
+
columns: [],
|
|
226
|
+
operatesAttrs: {},
|
|
227
|
+
operates: [],
|
|
228
|
+
tableHeightDiff: 330
|
|
229
|
+
},
|
|
230
|
+
paginations: {
|
|
231
|
+
page: 1,
|
|
232
|
+
total: 10,
|
|
233
|
+
limit: 30,
|
|
234
|
+
pagetionShow: true
|
|
235
|
+
},
|
|
236
|
+
${
|
|
237
|
+
config.hasDialog
|
|
238
|
+
? `type: 1,
|
|
239
|
+
formData: {},
|
|
240
|
+
dialogVisible: false`
|
|
241
|
+
: ""
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
created() {
|
|
246
|
+
this.init()
|
|
247
|
+
},
|
|
248
|
+
methods: {
|
|
249
|
+
async init() {
|
|
250
|
+
const params = {
|
|
251
|
+
...this.formSearchData.value,
|
|
252
|
+
Page: this.paginations.page,
|
|
253
|
+
MaxResultCount: this.paginations.limit
|
|
254
|
+
};
|
|
255
|
+
const { result: { items = [], totalCount = 0 } = {} } = await ${pageUrlKey}(params, {
|
|
256
|
+
isLoading: true
|
|
257
|
+
});
|
|
258
|
+
this.tableData.rows = items;
|
|
259
|
+
this.paginations.total = totalCount;
|
|
260
|
+
this.tableData.emptyImg = true;
|
|
261
|
+
},
|
|
262
|
+
handleSearch(from) {
|
|
263
|
+
this.formSearchData.value = { ...from };
|
|
264
|
+
this.paginations.page = 1;
|
|
265
|
+
this.init();
|
|
266
|
+
},
|
|
267
|
+
handleReset() {
|
|
268
|
+
for (let key in this.formSearchData.value) {
|
|
269
|
+
this.formSearchData.value[key] = null;
|
|
270
|
+
}
|
|
271
|
+
this.paginations.page = 1;
|
|
272
|
+
},
|
|
273
|
+
SelectionChange(row) {
|
|
274
|
+
this.multipleSelection = row;
|
|
275
|
+
},
|
|
276
|
+
handleSizeChange(val) {
|
|
277
|
+
this.paginations.page = 1;
|
|
278
|
+
this.paginations.limit = val;
|
|
279
|
+
this.init();
|
|
280
|
+
},
|
|
281
|
+
handleindexChange(val) {
|
|
282
|
+
this.paginations.page = val;
|
|
283
|
+
this.init();
|
|
284
|
+
},
|
|
285
|
+
${
|
|
286
|
+
config.hasExport
|
|
287
|
+
? `export() {
|
|
288
|
+
const timer = this.formSearchData.value.createdTime;
|
|
289
|
+
this.formSearchData.value.BeginTime = timer ? timer[0] : "";
|
|
290
|
+
this.formSearchData.value.EndTime = timer ? timer[1] : "";
|
|
291
|
+
this.post({
|
|
292
|
+
url: ${config.swaggerModule}.${exportUrlKey},
|
|
293
|
+
isLoading: true,
|
|
294
|
+
responseType: "blob",
|
|
295
|
+
data: Object.assign(this.formSearchData.value, {
|
|
296
|
+
Page: this.paginations.page,
|
|
297
|
+
MaxResultCount: this.paginations.limit
|
|
298
|
+
})
|
|
299
|
+
}).then(res => {
|
|
300
|
+
this.fnexsl(res);
|
|
301
|
+
});
|
|
302
|
+
},`
|
|
303
|
+
: ""
|
|
304
|
+
}${generateMethods()}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
</script>
|
|
308
|
+
`;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// 复用现有的 vue2Form 函数
|
|
312
|
+
function vue2Form(moduleName, config) {
|
|
313
|
+
let editUrlKey = "",
|
|
314
|
+
detailUrlKey = "",
|
|
315
|
+
baseUrlKey = "";
|
|
316
|
+
|
|
317
|
+
if (config.detailUrl) {
|
|
318
|
+
detailUrlKey = generateKeyName(config.detailUrl, "get");
|
|
319
|
+
baseUrlKey = `${detailUrlKey}CompleteUrl`;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (config.editUrl) {
|
|
323
|
+
editUrlKey = generateKeyName(config.editUrl, "put");
|
|
324
|
+
baseUrlKey = `${editUrlKey}CompleteUrl`;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (config.addUrl) baseUrlKey = generateKeyName(config.addUrl, "post");
|
|
328
|
+
|
|
329
|
+
return `<!--
|
|
330
|
+
Filename: ${moduleName}.vue
|
|
331
|
+
name: ${moduleName}
|
|
332
|
+
Created Date: ${new Date().toLocaleString()}
|
|
333
|
+
Author:
|
|
334
|
+
-->
|
|
335
|
+
<template>
|
|
336
|
+
<ol-form
|
|
337
|
+
v-if="dialogVisible"
|
|
338
|
+
:url="swaggerUrl.${baseUrlKey}"
|
|
339
|
+
:form="form"
|
|
340
|
+
@onCancel="onCancel"
|
|
341
|
+
@onSubmit="onSubmit"
|
|
342
|
+
/>
|
|
343
|
+
</template>
|
|
344
|
+
<script>
|
|
345
|
+
import { ${config.swaggerModule} } from '@/api/swagger';
|
|
346
|
+
export default {
|
|
347
|
+
name: "${moduleName}Form",
|
|
348
|
+
props: {
|
|
349
|
+
formData: {
|
|
350
|
+
type: Object,
|
|
351
|
+
default: () => ({})
|
|
352
|
+
},
|
|
353
|
+
type: {
|
|
354
|
+
type: Number,
|
|
355
|
+
default: 1
|
|
356
|
+
}
|
|
357
|
+
},
|
|
358
|
+
data() {
|
|
359
|
+
return {
|
|
360
|
+
swaggerUrl: ${config.swaggerModule},
|
|
361
|
+
form: {
|
|
362
|
+
type: this.type,
|
|
363
|
+
title: "",
|
|
364
|
+
defaultValue: {},
|
|
365
|
+
value: {},
|
|
366
|
+
model: [],
|
|
367
|
+
rules: {},
|
|
368
|
+
attrs: {},
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
watch: {
|
|
373
|
+
type: {
|
|
374
|
+
handler(val){
|
|
375
|
+
this.form.type = val;
|
|
376
|
+
},
|
|
377
|
+
immediate: true
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
created(){
|
|
381
|
+
this.form.value = { ...this.formData };
|
|
382
|
+
},
|
|
383
|
+
methods: {
|
|
384
|
+
onCancel() {
|
|
385
|
+
this.$emit("onCancel");
|
|
386
|
+
},
|
|
387
|
+
onSubmit({form, data}) {
|
|
388
|
+
this.$emit("onSubmit", { form, data });
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
</script>
|
|
393
|
+
`;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
class GeneratorPanel {
|
|
397
|
+
static currentPanel = undefined;
|
|
398
|
+
|
|
399
|
+
static createOrShow(extensionUri, targetUri) {
|
|
400
|
+
const column = vscode.window.activeTextEditor
|
|
401
|
+
? vscode.window.activeTextEditor.viewColumn
|
|
402
|
+
: undefined;
|
|
403
|
+
|
|
404
|
+
if (GeneratorPanel.currentPanel) {
|
|
405
|
+
GeneratorPanel.currentPanel._panel.reveal(column);
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const panel = vscode.window.createWebviewPanel(
|
|
410
|
+
"vueGenerator",
|
|
411
|
+
"Vue 页面生成器",
|
|
412
|
+
column || vscode.ViewColumn.One,
|
|
413
|
+
{
|
|
414
|
+
enableScripts: true,
|
|
415
|
+
localResourceRoots: [extensionUri],
|
|
416
|
+
}
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
GeneratorPanel.currentPanel = new GeneratorPanel(panel, extensionUri, targetUri);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
constructor(panel, extensionUri, targetUri) {
|
|
423
|
+
this._panel = panel;
|
|
424
|
+
this._extensionUri = extensionUri;
|
|
425
|
+
this._targetUri = targetUri;
|
|
426
|
+
this._disposables = [];
|
|
427
|
+
|
|
428
|
+
this._setWebviewMessageListener();
|
|
429
|
+
this._update();
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
_setWebviewMessageListener() {
|
|
433
|
+
this._panel.webview.onDidReceiveMessage(
|
|
434
|
+
message => {
|
|
435
|
+
switch (message.command) {
|
|
436
|
+
case "generate":
|
|
437
|
+
this._generateFiles(message.config);
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
undefined,
|
|
442
|
+
this._disposables
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
async _generateFiles(config) {
|
|
447
|
+
try {
|
|
448
|
+
const moduleName = config.moduleName;
|
|
449
|
+
const targetPath = path.dirname(this._targetUri.fsPath);
|
|
450
|
+
const outputDir = path.join(targetPath, moduleName);
|
|
451
|
+
|
|
452
|
+
// 检查目录是否存在
|
|
453
|
+
if (fs.existsSync(outputDir)) {
|
|
454
|
+
vscode.window.showErrorMessage(`❌ 创建失败,文件夹 ${outputDir} 已存在`);
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// 创建目录
|
|
459
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
460
|
+
|
|
461
|
+
// 生成主页面
|
|
462
|
+
const mainContent = vue2Template(moduleName, config);
|
|
463
|
+
const mainPath = path.join(outputDir, "index.vue");
|
|
464
|
+
fs.writeFileSync(mainPath, mainContent);
|
|
465
|
+
|
|
466
|
+
// 如果有弹窗功能,生成表单组件
|
|
467
|
+
if (config.hasDialog) {
|
|
468
|
+
const componentsDir = path.join(outputDir, "components");
|
|
469
|
+
fs.mkdirSync(componentsDir, { recursive: true });
|
|
470
|
+
|
|
471
|
+
const formContent = vue2Form(moduleName, config);
|
|
472
|
+
const formPath = path.join(componentsDir, "formModule.vue");
|
|
473
|
+
fs.writeFileSync(formPath, formContent);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
vscode.window.showInformationMessage(`✅ 模板已生成并保存到 ${outputDir}`);
|
|
477
|
+
|
|
478
|
+
// 打开生成的文件
|
|
479
|
+
const document = await vscode.workspace.openTextDocument(mainPath);
|
|
480
|
+
vscode.window.showTextDocument(document);
|
|
481
|
+
} catch (error) {
|
|
482
|
+
vscode.window.showErrorMessage(`❌ 发生错误:${error.message}`);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
_update() {
|
|
487
|
+
const webview = this._panel.webview;
|
|
488
|
+
this._panel.title = "Vue 页面生成器";
|
|
489
|
+
this._panel.webview.html = this._getHtmlForWebview(webview);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
_getHtmlForWebview(webview) {
|
|
493
|
+
return `<!DOCTYPE html>
|
|
494
|
+
<html lang="zh-CN">
|
|
495
|
+
<head>
|
|
496
|
+
<meta charset="UTF-8">
|
|
497
|
+
<title>Vue 页面生成器</title>
|
|
498
|
+
<style>
|
|
499
|
+
body {
|
|
500
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
501
|
+
padding: 20px;
|
|
502
|
+
background-color: var(--vscode-editor-background);
|
|
503
|
+
color: var(--vscode-editor-foreground);
|
|
504
|
+
}
|
|
505
|
+
.container {
|
|
506
|
+
max-width: 600px;
|
|
507
|
+
margin: 0 auto;
|
|
508
|
+
}
|
|
509
|
+
.form-group {
|
|
510
|
+
margin-bottom: 20px;
|
|
511
|
+
}
|
|
512
|
+
label {
|
|
513
|
+
display: block;
|
|
514
|
+
margin-bottom: 5px;
|
|
515
|
+
font-weight: 500;
|
|
516
|
+
}
|
|
517
|
+
input[type="text"], input[type="url"] {
|
|
518
|
+
width: 100%;
|
|
519
|
+
padding: 8px 12px;
|
|
520
|
+
border: 1px solid var(--vscode-input-border);
|
|
521
|
+
border-radius: 4px;
|
|
522
|
+
background-color: var(--vscode-input-background);
|
|
523
|
+
color: var(--vscode-input-foreground);
|
|
524
|
+
box-sizing: border-box;
|
|
525
|
+
}
|
|
526
|
+
.checkbox-group {
|
|
527
|
+
display: flex;
|
|
528
|
+
flex-wrap: wrap;
|
|
529
|
+
gap: 15px;
|
|
530
|
+
}
|
|
531
|
+
.checkbox-group label {
|
|
532
|
+
display: flex;
|
|
533
|
+
align-items: center;
|
|
534
|
+
margin-bottom: 0;
|
|
535
|
+
cursor: pointer;
|
|
536
|
+
}
|
|
537
|
+
.checkbox-group input[type="checkbox"] {
|
|
538
|
+
margin-right: 5px;
|
|
539
|
+
}
|
|
540
|
+
.btn {
|
|
541
|
+
background-color: var(--vscode-button-background);
|
|
542
|
+
color: var(--vscode-button-foreground);
|
|
543
|
+
border: none;
|
|
544
|
+
padding: 10px 20px;
|
|
545
|
+
border-radius: 4px;
|
|
546
|
+
cursor: pointer;
|
|
547
|
+
font-size: 14px;
|
|
548
|
+
}
|
|
549
|
+
.btn:hover {
|
|
550
|
+
background-color: var(--vscode-button-hoverBackground);
|
|
551
|
+
}
|
|
552
|
+
.section {
|
|
553
|
+
background-color: var(--vscode-editor-inactiveSelectionBackground);
|
|
554
|
+
padding: 15px;
|
|
555
|
+
border-radius: 6px;
|
|
556
|
+
margin-bottom: 20px;
|
|
557
|
+
}
|
|
558
|
+
.section h3 {
|
|
559
|
+
margin-top: 0;
|
|
560
|
+
margin-bottom: 15px;
|
|
561
|
+
color: var(--vscode-editor-foreground);
|
|
562
|
+
}
|
|
563
|
+
</style>
|
|
564
|
+
</head>
|
|
565
|
+
<body>
|
|
566
|
+
<div class="container">
|
|
567
|
+
<h2>🎉 Vue 页面生成器</h2>
|
|
568
|
+
|
|
569
|
+
<div class="section">
|
|
570
|
+
<h3>基础配置</h3>
|
|
571
|
+
<div class="form-group">
|
|
572
|
+
<label for="moduleName">页面名称:</label>
|
|
573
|
+
<input type="text" id="moduleName" placeholder="请输入页面名称" required>
|
|
574
|
+
</div>
|
|
575
|
+
</div>
|
|
576
|
+
|
|
577
|
+
<div class="section">
|
|
578
|
+
<h3>API 配置</h3>
|
|
579
|
+
<div class="form-group">
|
|
580
|
+
<label for="pageUrl">分页接口地址:</label>
|
|
581
|
+
<input type="url" id="pageUrl" placeholder="/api/app/xxx/paged-result" required>
|
|
582
|
+
</div>
|
|
583
|
+
|
|
584
|
+
<div class="form-group">
|
|
585
|
+
<label>
|
|
586
|
+
<input type="checkbox" id="hasExport"> 是否有导出接口
|
|
587
|
+
</label>
|
|
588
|
+
</div>
|
|
589
|
+
|
|
590
|
+
<div class="form-group" id="exportUrlGroup" style="display:none;">
|
|
591
|
+
<label for="exportUrl">导出接口地址:</label>
|
|
592
|
+
<input type="url" id="exportUrl" placeholder="/api/app/xxx/export">
|
|
593
|
+
</div>
|
|
594
|
+
</div>
|
|
595
|
+
|
|
596
|
+
<div class="section">
|
|
597
|
+
<h3>功能选择</h3>
|
|
598
|
+
<div class="form-group">
|
|
599
|
+
<div class="checkbox-group">
|
|
600
|
+
<label><input type="checkbox" id="hasAdd"> 新增功能</label>
|
|
601
|
+
<label><input type="checkbox" id="hasEdit"> 编辑功能</label>
|
|
602
|
+
<label><input type="checkbox" id="hasDelete"> 删除功能</label>
|
|
603
|
+
<label><input type="checkbox" id="hasDetail"> 详情功能</label>
|
|
604
|
+
</div>
|
|
605
|
+
</div>
|
|
606
|
+
</div>
|
|
607
|
+
|
|
608
|
+
<div class="section" id="operationConfig" style="display:none;">
|
|
609
|
+
<h3>操作接口配置</h3>
|
|
610
|
+
<div class="form-group">
|
|
611
|
+
<label for="baseUrl">操作接口基础路径:</label>
|
|
612
|
+
<input type="url" id="baseUrl" placeholder="/api/app/xxx">
|
|
613
|
+
</div>
|
|
614
|
+
|
|
615
|
+
<div class="form-group">
|
|
616
|
+
<label for="idField">URL后缀ID字段名:</label>
|
|
617
|
+
<input type="text" id="idField" placeholder="admissionInfoId">
|
|
618
|
+
</div>
|
|
619
|
+
|
|
620
|
+
<div class="form-group">
|
|
621
|
+
<label for="rowId">行数据中ID字段键名:</label>
|
|
622
|
+
<input type="text" id="rowId" placeholder="id">
|
|
623
|
+
</div>
|
|
624
|
+
</div>
|
|
625
|
+
|
|
626
|
+
<div class="section">
|
|
627
|
+
<h3>模块配置</h3>
|
|
628
|
+
<div class="form-group">
|
|
629
|
+
<label for="swaggerModule">接口模块名:</label>
|
|
630
|
+
<input type="text" id="swaggerModule" placeholder="AdmissionInfo">
|
|
631
|
+
</div>
|
|
632
|
+
</div>
|
|
633
|
+
|
|
634
|
+
<button class="btn" id="generateBtn">🚀 生成页面</button>
|
|
635
|
+
</div>
|
|
636
|
+
|
|
637
|
+
<script>
|
|
638
|
+
const vscode = acquireVsCodeApi();
|
|
639
|
+
|
|
640
|
+
// 获取DOM元素
|
|
641
|
+
const moduleNameInput = document.getElementById('moduleName');
|
|
642
|
+
const pageUrlInput = document.getElementById('pageUrl');
|
|
643
|
+
const hasExportCheckbox = document.getElementById('hasExport');
|
|
644
|
+
const exportUrlGroup = document.getElementById('exportUrlGroup');
|
|
645
|
+
const exportUrlInput = document.getElementById('exportUrl');
|
|
646
|
+
const hasAddCheckbox = document.getElementById('hasAdd');
|
|
647
|
+
const hasEditCheckbox = document.getElementById('hasEdit');
|
|
648
|
+
const hasDeleteCheckbox = document.getElementById('hasDelete');
|
|
649
|
+
const hasDetailCheckbox = document.getElementById('hasDetail');
|
|
650
|
+
const operationConfig = document.getElementById('operationConfig');
|
|
651
|
+
const baseUrlInput = document.getElementById('baseUrl');
|
|
652
|
+
const idFieldInput = document.getElementById('idField');
|
|
653
|
+
const rowIdInput = document.getElementById('rowId');
|
|
654
|
+
const swaggerModuleInput = document.getElementById('swaggerModule');
|
|
655
|
+
const generateBtn = document.getElementById('generateBtn');
|
|
656
|
+
|
|
657
|
+
// 监听导出功能选择
|
|
658
|
+
hasExportCheckbox.addEventListener('change', () => {
|
|
659
|
+
exportUrlGroup.style.display = hasExportCheckbox.checked ? 'block' : 'none';
|
|
660
|
+
});
|
|
661
|
+
|
|
662
|
+
// 监听功能选择
|
|
663
|
+
function updateOperationConfig() {
|
|
664
|
+
const hasOperations = hasAddCheckbox.checked || hasEditCheckbox.checked ||
|
|
665
|
+
hasDeleteCheckbox.checked || hasDetailCheckbox.checked;
|
|
666
|
+
operationConfig.style.display = hasOperations ? 'block' : 'none';
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
hasAddCheckbox.addEventListener('change', updateOperationConfig);
|
|
670
|
+
hasEditCheckbox.addEventListener('change', updateOperationConfig);
|
|
671
|
+
hasDeleteCheckbox.addEventListener('change', updateOperationConfig);
|
|
672
|
+
hasDetailCheckbox.addEventListener('change', updateOperationConfig);
|
|
673
|
+
|
|
674
|
+
// 生成按钮点击事件
|
|
675
|
+
generateBtn.addEventListener('click', () => {
|
|
676
|
+
// 验证必填字段
|
|
677
|
+
if (!moduleNameInput.value.trim()) {
|
|
678
|
+
alert('请输入页面名称');
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
if (!pageUrlInput.value.trim()) {
|
|
682
|
+
alert('请输入分页接口地址');
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
const config = {
|
|
687
|
+
moduleName: moduleNameInput.value.trim(),
|
|
688
|
+
pageUrl: pageUrlInput.value.trim(),
|
|
689
|
+
hasExport: hasExportCheckbox.checked,
|
|
690
|
+
exportUrl: exportUrlInput.value.trim(),
|
|
691
|
+
hasAdd: hasAddCheckbox.checked,
|
|
692
|
+
hasEdit: hasEditCheckbox.checked,
|
|
693
|
+
hasDelete: hasDeleteCheckbox.checked,
|
|
694
|
+
hasDetail: hasDetailCheckbox.checked,
|
|
695
|
+
baseUrl: baseUrlInput.value.trim(),
|
|
696
|
+
idField: idFieldInput.value.trim() || 'id',
|
|
697
|
+
rowId: rowIdInput.value.trim() || 'id',
|
|
698
|
+
swaggerModule: swaggerModuleInput.value.trim() || 'Module',
|
|
699
|
+
hasDialog: hasAddCheckbox.checked || hasEditCheckbox.checked || hasDetailCheckbox.checked
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
// 发送消息给扩展
|
|
703
|
+
vscode.postMessage({
|
|
704
|
+
command: 'generate',
|
|
705
|
+
config: config
|
|
706
|
+
});
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
// 设置默认值
|
|
710
|
+
pageUrlInput.value = '/api/app/admission-info/paged-result';
|
|
711
|
+
baseUrlInput.value = '/api/app/admission-info/admission-info';
|
|
712
|
+
idFieldInput.value = 'admissionInfoId';
|
|
713
|
+
rowIdInput.value = 'id';
|
|
714
|
+
swaggerModuleInput.value = 'AdmissionInfo';
|
|
715
|
+
</script>
|
|
716
|
+
</body>
|
|
717
|
+
</html>`;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
dispose() {
|
|
721
|
+
GeneratorPanel.currentPanel = undefined;
|
|
722
|
+
this._panel.dispose();
|
|
723
|
+
while (this._disposables.length) {
|
|
724
|
+
const x = this._disposables.pop();
|
|
725
|
+
if (x) {
|
|
726
|
+
x.dispose();
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
module.exports = {
|
|
733
|
+
GeneratorPanel,
|
|
734
|
+
};
|