@skills-cli/vue2-springboot-mybatis 1.0.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/.claude/settings.local.json +8 -0
- package/README.md +106 -0
- package/index.js +1035 -0
- package/package.json +39 -0
- package/skills.json +36 -0
package/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# @skills-cli/vue2-springboot-mybatis
|
|
2
|
+
|
|
3
|
+
Universal coding assistance skills for **Vue2 + SpringBoot + MyBatis** full-stack development. Provides code generation templates and helpers for rapid development.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
skills add @skills-cli/vue2-springboot-mybatis
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **Vue2 Code Generation**
|
|
14
|
+
- Single-file component template
|
|
15
|
+
- CRUD list page with pagination
|
|
16
|
+
- Form modal component
|
|
17
|
+
- API service module
|
|
18
|
+
|
|
19
|
+
- **SpringBoot Code Generation**
|
|
20
|
+
- Controller layer with RESTful APIs
|
|
21
|
+
- Service layer with business logic interface
|
|
22
|
+
- Entity class with Lombok
|
|
23
|
+
- Mapper interface
|
|
24
|
+
|
|
25
|
+
- **MyBatis Code Generation**
|
|
26
|
+
- XML Mapper with CRUD operations
|
|
27
|
+
- Result map configuration
|
|
28
|
+
- Dynamic SQL support
|
|
29
|
+
|
|
30
|
+
## Capabilities
|
|
31
|
+
|
|
32
|
+
- `generate-vue2-component` - Generate Vue2 single-file component
|
|
33
|
+
- `generate-vue2-crud-page` - Generate complete CRUD page (list + form + API)
|
|
34
|
+
- `generate-springboot-controller` - Generate SpringBoot REST Controller
|
|
35
|
+
- `generate-springboot-service` - Generate Service interface and implementation
|
|
36
|
+
- `generate-mybatis-entity` - Generate MyBatis entity class
|
|
37
|
+
- `generate-mybatis-mapper` - Generate Mapper interface
|
|
38
|
+
- `generate-mybatis-xml` - Generate MyBatis XML mapper
|
|
39
|
+
- `generate-crud-fullstack` - Generate full-stack CRUD from table definition
|
|
40
|
+
|
|
41
|
+
## Usage Example
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
const skill = require('@skills-cli/vue2-springboot-mybatis');
|
|
45
|
+
|
|
46
|
+
// Generate Vue2 CRUD page
|
|
47
|
+
const vueCrud = skill.generateVue2Crud('User', 'user', [
|
|
48
|
+
{ name: 'id', type: 'Long', label: 'ID', primaryKey: true },
|
|
49
|
+
{ name: 'username', type: 'String', label: 'Username', required: true },
|
|
50
|
+
{ name: 'email', type: 'String', label: 'Email' },
|
|
51
|
+
{ name: 'createTime', type: 'Date', label: 'Create Time' }
|
|
52
|
+
]);
|
|
53
|
+
|
|
54
|
+
// Generate SpringBoot Controller
|
|
55
|
+
const controller = skill.generateSpringBootController('User', 'user');
|
|
56
|
+
|
|
57
|
+
// Generate MyBatis Entity
|
|
58
|
+
const entity = skill.generateMyBatisEntity('User', columns);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Configuration
|
|
62
|
+
|
|
63
|
+
You can configure in your `skills.json`:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"config": {
|
|
68
|
+
"@skills-cli/vue2-springboot-mybatis": {
|
|
69
|
+
"vue2": {
|
|
70
|
+
"componentPath": "src/components",
|
|
71
|
+
"viewPath": "src/views",
|
|
72
|
+
"apiPath": "src/api"
|
|
73
|
+
},
|
|
74
|
+
"springboot": {
|
|
75
|
+
"basePackage": "com.yourcompany.project",
|
|
76
|
+
"author": "Your Name"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## API
|
|
84
|
+
|
|
85
|
+
### Vue2 Generation
|
|
86
|
+
|
|
87
|
+
- `generateVue2Component(name, options)` - Generate Vue2 single-file component
|
|
88
|
+
- `generateVue2CrudPage(entityName, tableName, columns)` - Generate CRUD list page
|
|
89
|
+
- `generateVue2FormModal(entityName, columns)` - Generate form modal component
|
|
90
|
+
- `generateVue2Api(entityName, tableName)` - Generate API service module
|
|
91
|
+
|
|
92
|
+
### SpringBoot Generation
|
|
93
|
+
|
|
94
|
+
- `generateMyBatisEntity(entityName, columns, packageName)` - Generate entity class
|
|
95
|
+
- `generateMyBatisMapper(entityName, packageName)` - Generate Mapper interface
|
|
96
|
+
- `generateSpringBootService(entityName, packageName)` - Generate Service
|
|
97
|
+
- `generateSpringBootController(entityName, packageName)` - Generate Controller
|
|
98
|
+
- `generateMyBatisXml(entityName, tableName, columns)` - Generate XML mapper
|
|
99
|
+
|
|
100
|
+
### Full Stack
|
|
101
|
+
|
|
102
|
+
- `generateFullStackCrud(entityName, tableName, columns, config)` - Generate all files
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
MIT
|
package/index.js
ADDED
|
@@ -0,0 +1,1035 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @skills-cli/vue2-springboot-mybatis
|
|
3
|
+
* Universal coding assistance skills for Vue2 + SpringBoot + MyBatis full-stack development
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const skills = require('./skills.json');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Get skill information
|
|
10
|
+
*/
|
|
11
|
+
function getInfo() {
|
|
12
|
+
return {
|
|
13
|
+
name: skills.name,
|
|
14
|
+
version: skills.version,
|
|
15
|
+
description: skills.description,
|
|
16
|
+
priority: skills.priority,
|
|
17
|
+
tags: skills.tags,
|
|
18
|
+
capabilities: skills.capabilities
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Capitalize first letter
|
|
24
|
+
*/
|
|
25
|
+
function capitalize(str) {
|
|
26
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* camelCase to snake_case
|
|
31
|
+
*/
|
|
32
|
+
function camelToSnake(str) {
|
|
33
|
+
return str.replace(/([A-Z])/g, '_$1').toLowerCase();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ========== Vue2 Generation ==========
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Generate Vue2 single-file component (.vue)
|
|
40
|
+
*/
|
|
41
|
+
function generateVue2Component(componentName, options = {}) {
|
|
42
|
+
const { template = 'basic' } = options;
|
|
43
|
+
const compName = capitalize(componentName);
|
|
44
|
+
|
|
45
|
+
return `<template>
|
|
46
|
+
<div class="${componentName}-wrapper">
|
|
47
|
+
<!-- Component content -->
|
|
48
|
+
</div>
|
|
49
|
+
</template>
|
|
50
|
+
|
|
51
|
+
<script>
|
|
52
|
+
export default {
|
|
53
|
+
name: '${compName}',
|
|
54
|
+
components: {},
|
|
55
|
+
props: {},
|
|
56
|
+
data() {
|
|
57
|
+
return {};
|
|
58
|
+
},
|
|
59
|
+
computed: {},
|
|
60
|
+
watch: {},
|
|
61
|
+
created() {},
|
|
62
|
+
mounted() {},
|
|
63
|
+
methods: {}
|
|
64
|
+
};
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
<style scoped lang="scss">
|
|
68
|
+
.${componentName}-wrapper {
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
</style>
|
|
72
|
+
`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Generate Vue2 CRUD list page
|
|
77
|
+
*/
|
|
78
|
+
function generateVue2CrudPage(entityName, tableName, columns) {
|
|
79
|
+
const entityLower = entityName.toLowerCase();
|
|
80
|
+
const entityCapital = capitalize(entityName);
|
|
81
|
+
|
|
82
|
+
const searchForm = columns
|
|
83
|
+
.filter(col => !col.primaryKey && col.name !== 'createTime' && col.name !== 'updateTime')
|
|
84
|
+
.map(col => ` <el-form-item label="${col.label}">
|
|
85
|
+
<el-input v-model="searchForm.${col.name}" placeholder="Please enter ${col.label}" clearable />
|
|
86
|
+
</el-form-item>`)
|
|
87
|
+
.join('\n');
|
|
88
|
+
|
|
89
|
+
const tableColumns = columns
|
|
90
|
+
.map(col => ` <el-table-column prop="${col.name}" label="${col.label}"${col.width ? ` width="${col.width}"` : ''} />`)
|
|
91
|
+
.join('\n');
|
|
92
|
+
|
|
93
|
+
return `<template>
|
|
94
|
+
<div class="${entityLower}-page">
|
|
95
|
+
<!-- Search Form -->
|
|
96
|
+
<el-card class="search-card">
|
|
97
|
+
<el-form :inline="true" :model="searchForm" class="search-form">
|
|
98
|
+
${searchForm}
|
|
99
|
+
<el-form-item>
|
|
100
|
+
<el-button type="primary" @click="handleSearch">Search</el-button>
|
|
101
|
+
<el-button @click="handleReset">Reset</el-button>
|
|
102
|
+
</el-form-item>
|
|
103
|
+
</el-form>
|
|
104
|
+
</el-card>
|
|
105
|
+
|
|
106
|
+
<!-- Toolbar -->
|
|
107
|
+
<el-card class="toolbar-card">
|
|
108
|
+
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">Add ${entityCapital}</el-button>
|
|
109
|
+
</el-card>
|
|
110
|
+
|
|
111
|
+
<!-- Data Table -->
|
|
112
|
+
<el-card>
|
|
113
|
+
<el-table :data="tableData" border loading="loading">
|
|
114
|
+
${tableColumns}
|
|
115
|
+
<el-table-column label="Operation" width="180" fixed="right">
|
|
116
|
+
<template slot-scope="scope">
|
|
117
|
+
<el-button size="mini" type="primary" @click="handleEdit(scope.row)">Edit</el-button>
|
|
118
|
+
<el-button size="mini" type="danger" @click="handleDelete(scope.row)">Delete</el-button>
|
|
119
|
+
</template>
|
|
120
|
+
</el-table-column>
|
|
121
|
+
</el-table>
|
|
122
|
+
<div class="pagination-wrapper">
|
|
123
|
+
<el-pagination
|
|
124
|
+
@size-change="handleSizeChange"
|
|
125
|
+
@current-change="handleCurrentChange"
|
|
126
|
+
:current-page="pagination.current"
|
|
127
|
+
:page-sizes="[10, 20, 50, 100]"
|
|
128
|
+
:page-size="pagination.size"
|
|
129
|
+
layout="total, sizes, prev, pager, next, jumper"
|
|
130
|
+
:total="pagination.total">
|
|
131
|
+
</el-pagination>
|
|
132
|
+
</div>
|
|
133
|
+
</el-card>
|
|
134
|
+
|
|
135
|
+
<!-- Add/Edit Dialog -->
|
|
136
|
+
<${entityLower}-form-dialog
|
|
137
|
+
:visible.sync="dialogVisible"
|
|
138
|
+
:form-data="currentRow"
|
|
139
|
+
:is-edit="isEdit"
|
|
140
|
+
@success="handleDialogSuccess"
|
|
141
|
+
/>
|
|
142
|
+
</div>
|
|
143
|
+
</template>
|
|
144
|
+
|
|
145
|
+
<script>
|
|
146
|
+
import { ${entityLower}List, ${entityLower}Delete } from '@/api/${entityLower}';
|
|
147
|
+
import ${entityLower}FormDialog from './components/${entityLower}FormDialog.vue';
|
|
148
|
+
|
|
149
|
+
export default {
|
|
150
|
+
name: '${entityCapital}Page',
|
|
151
|
+
components: { ${entityLower}FormDialog },
|
|
152
|
+
data() {
|
|
153
|
+
return {
|
|
154
|
+
searchForm: {
|
|
155
|
+
${columns
|
|
156
|
+
.filter(col => !col.primaryKey && col.name !== 'createTime' && col.name !== 'updateTime')
|
|
157
|
+
.map(col => ` ${col.name}: ''`)
|
|
158
|
+
.join(',\n')}
|
|
159
|
+
},
|
|
160
|
+
tableData: [],
|
|
161
|
+
dialogVisible: false,
|
|
162
|
+
isEdit: false,
|
|
163
|
+
currentRow: null,
|
|
164
|
+
loading: false,
|
|
165
|
+
pagination: {
|
|
166
|
+
current: 1,
|
|
167
|
+
size: 10,
|
|
168
|
+
total: 0
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
},
|
|
172
|
+
created() {
|
|
173
|
+
this.loadData();
|
|
174
|
+
},
|
|
175
|
+
methods: {
|
|
176
|
+
async loadData() {
|
|
177
|
+
this.loading = true;
|
|
178
|
+
try {
|
|
179
|
+
const { pageNum, pageSize } = { pageNum: this.pagination.current, pageSize: this.pagination.size };
|
|
180
|
+
const params = { ...this.searchForm, pageNum, pageSize };
|
|
181
|
+
const res = await ${entityLower}List(params);
|
|
182
|
+
this.tableData = res.list || [];
|
|
183
|
+
this.pagination.total = res.total || 0;
|
|
184
|
+
} catch (error) {
|
|
185
|
+
this.$message.error('Failed to load data');
|
|
186
|
+
console.error(error);
|
|
187
|
+
} finally {
|
|
188
|
+
this.loading = false;
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
handleSearch() {
|
|
192
|
+
this.pagination.current = 1;
|
|
193
|
+
this.loadData();
|
|
194
|
+
},
|
|
195
|
+
handleReset() {
|
|
196
|
+
${columns
|
|
197
|
+
.filter(col => !col.primaryKey && col.name !== 'createTime' && col.name !== 'updateTime')
|
|
198
|
+
.map(col => ` this.searchForm.${col.name} = '';`)
|
|
199
|
+
.join('\n')}
|
|
200
|
+
this.handleSearch();
|
|
201
|
+
},
|
|
202
|
+
handleSizeChange(val) {
|
|
203
|
+
this.pagination.size = val;
|
|
204
|
+
this.loadData();
|
|
205
|
+
},
|
|
206
|
+
handleCurrentChange(val) {
|
|
207
|
+
this.pagination.current = val;
|
|
208
|
+
this.loadData();
|
|
209
|
+
},
|
|
210
|
+
handleAdd() {
|
|
211
|
+
this.isEdit = false;
|
|
212
|
+
this.currentRow = null;
|
|
213
|
+
this.dialogVisible = true;
|
|
214
|
+
},
|
|
215
|
+
handleEdit(row) {
|
|
216
|
+
this.isEdit = true;
|
|
217
|
+
this.currentRow = { ...row };
|
|
218
|
+
this.dialogVisible = true;
|
|
219
|
+
},
|
|
220
|
+
async handleDelete(row) {
|
|
221
|
+
try {
|
|
222
|
+
await this.$confirm('Confirm to delete this record?', 'Prompt', {
|
|
223
|
+
type: 'warning'
|
|
224
|
+
});
|
|
225
|
+
await ${entityLower}Delete(row.id);
|
|
226
|
+
this.$message.success('Deleted successfully');
|
|
227
|
+
this.loadData();
|
|
228
|
+
} catch (error) {
|
|
229
|
+
if (error !== 'cancel') {
|
|
230
|
+
this.$message.error('Delete failed');
|
|
231
|
+
console.error(error);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
handleDialogSuccess() {
|
|
236
|
+
this.dialogVisible = false;
|
|
237
|
+
this.loadData();
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
</script>
|
|
242
|
+
|
|
243
|
+
<style scoped lang="scss">
|
|
244
|
+
.${entityLower}-page {
|
|
245
|
+
padding: 16px;
|
|
246
|
+
}
|
|
247
|
+
.search-card, .toolbar-card {
|
|
248
|
+
margin-bottom: 16px;
|
|
249
|
+
}
|
|
250
|
+
.pagination-wrapper {
|
|
251
|
+
margin-top: 16px;
|
|
252
|
+
text-align: right;
|
|
253
|
+
}
|
|
254
|
+
</style>
|
|
255
|
+
`;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Generate Vue2 Form Modal component
|
|
260
|
+
*/
|
|
261
|
+
function generateVue2FormModal(entityName, columns) {
|
|
262
|
+
const entityLower = entityName.toLowerCase();
|
|
263
|
+
const entityCapital = capitalize(entityName);
|
|
264
|
+
|
|
265
|
+
const formItems = columns
|
|
266
|
+
.filter(col => !col.primaryKey)
|
|
267
|
+
.map(col => {
|
|
268
|
+
let input = `<el-input v-model="formData.${col.name}" placeholder="Please enter ${col.label}" />`;
|
|
269
|
+
if (col.type === 'Date' || col.type === 'DateTime') {
|
|
270
|
+
input = `<el-date-picker
|
|
271
|
+
v-model="formData.${col.name}"
|
|
272
|
+
type="date"
|
|
273
|
+
placeholder="Select ${col.label}"
|
|
274
|
+
value-format="yyyy-MM-dd"
|
|
275
|
+
/>`;
|
|
276
|
+
} else if (col.type === 'Boolean' || col.type === 'boolean') {
|
|
277
|
+
input = `<el-switch v-model="formData.${col.name}" />`;
|
|
278
|
+
}
|
|
279
|
+
return ` <el-form-item label="${col.label}" prop="${col.name}"${col.required ? ' required' : ''}>
|
|
280
|
+
${input}
|
|
281
|
+
</el-form-item>`;
|
|
282
|
+
})
|
|
283
|
+
.join('\n');
|
|
284
|
+
|
|
285
|
+
const initialData = columns
|
|
286
|
+
.filter(col => !col.primaryKey)
|
|
287
|
+
.map(col => ` ${col.name}: ${col.default ? JSON.stringify(col.default) : getDefaultValue(col.type)}`)
|
|
288
|
+
.join(',\n');
|
|
289
|
+
|
|
290
|
+
const rules = columns
|
|
291
|
+
.filter(col => col.required && !col.primaryKey)
|
|
292
|
+
.map(col => ` ${col.name}: [{ required: true, message: 'Please enter ${col.label}', trigger: 'blur' }]`)
|
|
293
|
+
.join(',\n');
|
|
294
|
+
|
|
295
|
+
const addEditMethod = `
|
|
296
|
+
async handleSubmit() {
|
|
297
|
+
this.$refs.form.validate(async valid => {
|
|
298
|
+
if (!valid) return;
|
|
299
|
+
try {
|
|
300
|
+
if (this.isEdit) {
|
|
301
|
+
await ${entityLower}Update(this.formData);
|
|
302
|
+
this.$message.success('Updated successfully');
|
|
303
|
+
} else {
|
|
304
|
+
await ${entityLower}Add(this.formData);
|
|
305
|
+
this.$message.success('Added successfully');
|
|
306
|
+
}
|
|
307
|
+
this.$emit('success');
|
|
308
|
+
this.resetForm();
|
|
309
|
+
} catch (error) {
|
|
310
|
+
this.$message.error(this.isEdit ? 'Update failed' : 'Add failed');
|
|
311
|
+
console.error(error);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
}`;
|
|
315
|
+
|
|
316
|
+
return `<template>
|
|
317
|
+
<el-dialog
|
|
318
|
+
:title="dialogTitle"
|
|
319
|
+
:visible.sync="visible"
|
|
320
|
+
width="600px"
|
|
321
|
+
@close="resetForm">
|
|
322
|
+
<el-form ref="form" :model="formData" :rules="rules" label-width="100px">
|
|
323
|
+
${formItems}
|
|
324
|
+
</el-form>
|
|
325
|
+
<span slot="footer" class="dialog-footer">
|
|
326
|
+
<el-button @click="visible = false">Cancel</el-button>
|
|
327
|
+
<el-button type="primary" @click="handleSubmit">Confirm</el-button>
|
|
328
|
+
</span>
|
|
329
|
+
</el-dialog>
|
|
330
|
+
</template>
|
|
331
|
+
|
|
332
|
+
<script>
|
|
333
|
+
import { ${entityLower}Add, ${entityLower}Update } from '@/api/${entityLower}';
|
|
334
|
+
|
|
335
|
+
function getDefaultValue(type) {
|
|
336
|
+
switch (type) {
|
|
337
|
+
case 'String': return '';
|
|
338
|
+
case 'Number': case 'Integer': case 'Long': return 0;
|
|
339
|
+
case 'Boolean': return false;
|
|
340
|
+
case 'Date': return '';
|
|
341
|
+
default: return '';
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export default {
|
|
346
|
+
name: '${entityCapital}FormDialog',
|
|
347
|
+
props: {
|
|
348
|
+
visible: {
|
|
349
|
+
type: Boolean,
|
|
350
|
+
default: false
|
|
351
|
+
},
|
|
352
|
+
formData: {
|
|
353
|
+
type: Object,
|
|
354
|
+
default: null
|
|
355
|
+
},
|
|
356
|
+
isEdit: {
|
|
357
|
+
type: Boolean,
|
|
358
|
+
default: false
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
data() {
|
|
362
|
+
return {
|
|
363
|
+
formData: {
|
|
364
|
+
${initialData}
|
|
365
|
+
},
|
|
366
|
+
rules: {
|
|
367
|
+
${rules}
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
},
|
|
371
|
+
computed: {
|
|
372
|
+
dialogTitle() {
|
|
373
|
+
return this.isEdit ? 'Edit ${entityCapital}' : 'Add ${entityCapital}';
|
|
374
|
+
}
|
|
375
|
+
},
|
|
376
|
+
watch: {
|
|
377
|
+
formData(val) {
|
|
378
|
+
if (val && this.isEdit) {
|
|
379
|
+
this.formData = { ...val };
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
},
|
|
383
|
+
methods: {
|
|
384
|
+
resetForm() {
|
|
385
|
+
this.$refs.form && this.$refs.form.clearValidate();
|
|
386
|
+
${initialData
|
|
387
|
+
.split('\n')
|
|
388
|
+
.map(line => ' this.formData.' + line.trim().split(':')[0] + ' = ' + line.trim().split('=')[1].trim())
|
|
389
|
+
.join('\n')}
|
|
390
|
+
},
|
|
391
|
+
${addEditMethod.trim()}
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
</script>
|
|
395
|
+
`;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Generate Vue2 API module
|
|
400
|
+
*/
|
|
401
|
+
function generateVue2Api(entityName, tableName) {
|
|
402
|
+
const entityLower = entityName.toLowerCase();
|
|
403
|
+
const entityCapital = capitalize(entityName);
|
|
404
|
+
const baseUrl = `/${tableName || entityLower}`;
|
|
405
|
+
|
|
406
|
+
return `import request from '@/utils/request';
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* ${entityCapital} API
|
|
410
|
+
*/
|
|
411
|
+
|
|
412
|
+
// Get ${entityCapital} list with pagination
|
|
413
|
+
export function ${entityLower}List(params) {
|
|
414
|
+
return request({
|
|
415
|
+
url: '${baseUrl}/list',
|
|
416
|
+
method: 'get',
|
|
417
|
+
params
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Get ${entityCapital} by id
|
|
422
|
+
export function ${entityLower}GetById(id) {
|
|
423
|
+
return request({
|
|
424
|
+
url: '${baseUrl}/${id}',
|
|
425
|
+
method: 'get'
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// Add ${entityCapital}
|
|
430
|
+
export function ${entityLower}Add(data) {
|
|
431
|
+
return request({
|
|
432
|
+
url: '${baseUrl}',
|
|
433
|
+
method: 'post',
|
|
434
|
+
data
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Update ${entityCapital}
|
|
439
|
+
export function ${entityLower}Update(data) {
|
|
440
|
+
return request({
|
|
441
|
+
url: '${baseUrl}',
|
|
442
|
+
method: 'put',
|
|
443
|
+
data
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// Delete ${entityCapital}
|
|
448
|
+
export function ${entityLower}Delete(id) {
|
|
449
|
+
return request({
|
|
450
|
+
url: '${baseUrl}/${id}',
|
|
451
|
+
method: 'delete'
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
`;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// ========== SpringBoot + MyBatis Generation ==========
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Generate MyBatis Entity class
|
|
461
|
+
*/
|
|
462
|
+
function generateMyBatisEntity(entityName, columns, packageName = 'com.example.demo.entity') {
|
|
463
|
+
const fields = columns.map(col => {
|
|
464
|
+
return ` /**
|
|
465
|
+
* ${col.label || col.name}
|
|
466
|
+
*/
|
|
467
|
+
private ${col.type} ${col.name};`;
|
|
468
|
+
}).join('\n\n');
|
|
469
|
+
|
|
470
|
+
return `package ${packageName};
|
|
471
|
+
|
|
472
|
+
import lombok.Data;
|
|
473
|
+
import java.io.Serializable;
|
|
474
|
+
${columns.some(c => c.type === 'Date') ? 'import java.util.Date;' : ''}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* ${entityName} Entity
|
|
478
|
+
*/
|
|
479
|
+
@Data
|
|
480
|
+
public class ${entityName} implements Serializable {
|
|
481
|
+
|
|
482
|
+
private static final long serialVersionUID = 1L;
|
|
483
|
+
|
|
484
|
+
${fields}
|
|
485
|
+
}
|
|
486
|
+
`;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Generate MyBatis Mapper interface
|
|
491
|
+
*/
|
|
492
|
+
function generateMyBatisMapper(entityName, packageName = 'com.example.demo.mapper') {
|
|
493
|
+
const entityLower = entityName.toLowerCase();
|
|
494
|
+
|
|
495
|
+
return `package ${packageName};
|
|
496
|
+
|
|
497
|
+
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
498
|
+
import ${packageName.replace('.mapper', '.entity')}.${entityName};
|
|
499
|
+
import org.apache.ibatis.annotations.Mapper;
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* ${entityName} Mapper Interface
|
|
503
|
+
*/
|
|
504
|
+
@Mapper
|
|
505
|
+
public interface ${entityName}Mapper extends BaseMapper<${entityName}> {
|
|
506
|
+
|
|
507
|
+
}
|
|
508
|
+
`;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Generate plain MyBatis Mapper interface (without MP)
|
|
513
|
+
*/
|
|
514
|
+
function generatePlainMyBatisMapper(entityName, packageName = 'com.example.demo.mapper') {
|
|
515
|
+
const entityLower = entityName.toLowerCase();
|
|
516
|
+
|
|
517
|
+
return `package ${packageName};
|
|
518
|
+
|
|
519
|
+
import ${packageName.replace('.mapper', '.entity')}.${entityName};
|
|
520
|
+
import org.apache.ibatis.annotations.Mapper;
|
|
521
|
+
import org.apache.ibatis.annotations.Param;
|
|
522
|
+
import java.util.List;
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* ${entityName} Mapper Interface
|
|
526
|
+
*/
|
|
527
|
+
@Mapper
|
|
528
|
+
public interface ${entityName}Mapper {
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Query by primary key
|
|
532
|
+
*/
|
|
533
|
+
${entityName} selectById(Long id);
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Query list by condition
|
|
537
|
+
*/
|
|
538
|
+
List<${entityName}> selectList(@Param("query") ${entityName} query);
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Count total
|
|
542
|
+
*/
|
|
543
|
+
int count(@Param("query") ${entityName} query);
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Insert
|
|
547
|
+
*/
|
|
548
|
+
int insert(${entityName} record);
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Update by primary key
|
|
552
|
+
*/
|
|
553
|
+
int updateById(${entityName} record);
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Delete by primary key
|
|
557
|
+
*/
|
|
558
|
+
int deleteById(Long id);
|
|
559
|
+
}
|
|
560
|
+
`;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Generate SpringBoot Service interface
|
|
565
|
+
*/
|
|
566
|
+
function generateSpringBootService(entityName, packageName = 'com.example.demo.service') {
|
|
567
|
+
const entityLower = entityName.toLowerCase();
|
|
568
|
+
|
|
569
|
+
return `package ${packageName};
|
|
570
|
+
|
|
571
|
+
import ${packageName.replace('.service', '.entity')}.${entityName};
|
|
572
|
+
import com.baomidou.mybatisplus.extension.service.IService;
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* ${entityName} Service Interface
|
|
576
|
+
*/
|
|
577
|
+
public interface ${entityName}Service extends IService<${entityName}> {
|
|
578
|
+
|
|
579
|
+
}
|
|
580
|
+
`;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* Generate plain Service interface (without MP)
|
|
585
|
+
*/
|
|
586
|
+
function generatePlainSpringBootService(entityName, packageName = 'com.example.demo.service') {
|
|
587
|
+
const entityLower = entityName.toLowerCase();
|
|
588
|
+
|
|
589
|
+
return `package ${packageName};
|
|
590
|
+
|
|
591
|
+
import ${packageName.replace('.service', '.entity')}.${entityName};
|
|
592
|
+
import com.github.pagehelper.PageInfo;
|
|
593
|
+
import java.util.List;
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* ${entityName} Service Interface
|
|
597
|
+
*/
|
|
598
|
+
public interface ${entityName}Service {
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* Get by ID
|
|
602
|
+
*/
|
|
603
|
+
${entityName} getById(Long id);
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Query page
|
|
607
|
+
*/
|
|
608
|
+
PageInfo<${entityName}> pageList(${entityName} query, int pageNum, int pageSize);
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* Create
|
|
612
|
+
*/
|
|
613
|
+
int create(${entityName} record);
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Update
|
|
617
|
+
*/
|
|
618
|
+
int update(${entityName} record);
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* Delete
|
|
622
|
+
*/
|
|
623
|
+
int delete(Long id);
|
|
624
|
+
}
|
|
625
|
+
`;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Generate Service Implementation
|
|
630
|
+
*/
|
|
631
|
+
function generateSpringBootServiceImpl(entityName, packageName = 'com.example.demo.service.impl') {
|
|
632
|
+
const entityLower = entityName.toLowerCase();
|
|
633
|
+
const basePackage = packageName.replace('.service.impl', '');
|
|
634
|
+
|
|
635
|
+
return `package ${packageName};
|
|
636
|
+
|
|
637
|
+
import ${basePackage}.entity.${entityName};
|
|
638
|
+
import ${basePackage}.mapper.${entityName}Mapper;
|
|
639
|
+
import ${basePackage}.service.${entityName}Service;
|
|
640
|
+
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
641
|
+
import org.springframework.stereotype.Service;
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* ${entityName} Service Implementation
|
|
645
|
+
*/
|
|
646
|
+
@Service
|
|
647
|
+
public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements ${entityName}Service {
|
|
648
|
+
|
|
649
|
+
}
|
|
650
|
+
`;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Generate plain Service Implementation
|
|
655
|
+
*/
|
|
656
|
+
function generatePlainSpringBootServiceImpl(entityName, packageName = 'com.example.demo.service.impl') {
|
|
657
|
+
const entityLower = entityName.toLowerCase();
|
|
658
|
+
const basePackage = packageName.replace('.service.impl', '');
|
|
659
|
+
|
|
660
|
+
return `package ${packageName};
|
|
661
|
+
|
|
662
|
+
import ${basePackage}.entity.${entityName};
|
|
663
|
+
import ${basePackage}.mapper.${entityName}Mapper;
|
|
664
|
+
import ${basePackage}.service.${entityName}Service;
|
|
665
|
+
import com.github.pagehelper.PageHelper;
|
|
666
|
+
import com.github.pagehelper.PageInfo;
|
|
667
|
+
import org.springframework.beans.factory.annotation.Autowired;
|
|
668
|
+
import org.springframework.stereotype.Service;
|
|
669
|
+
|
|
670
|
+
import java.util.List;
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* ${entityName} Service Implementation
|
|
674
|
+
*/
|
|
675
|
+
@Service
|
|
676
|
+
public class ${entityName}ServiceImpl implements ${entityName}Service {
|
|
677
|
+
|
|
678
|
+
@Autowired
|
|
679
|
+
private ${entityName}Mapper ${entityLower}Mapper;
|
|
680
|
+
|
|
681
|
+
@Override
|
|
682
|
+
public ${entityName} getById(Long id) {
|
|
683
|
+
return ${entityLower}Mapper.selectById(id);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
@Override
|
|
687
|
+
public PageInfo<${entityName}> pageList(${entityName} query, int pageNum, int pageSize) {
|
|
688
|
+
PageHelper.startPage(pageNum, pageSize);
|
|
689
|
+
List<${entityName}> list = ${entityLower}Mapper.selectList(query);
|
|
690
|
+
return new PageInfo<>(list);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
@Override
|
|
694
|
+
public int create(${entityName} record) {
|
|
695
|
+
return ${entityLower}Mapper.insert(record);
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
@Override
|
|
699
|
+
public int update(${entityName} record) {
|
|
700
|
+
return ${entityLower}Mapper.updateById(record);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
@Override
|
|
704
|
+
public int delete(Long id) {
|
|
705
|
+
return ${entityLower}Mapper.deleteById(id);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
`;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* Generate SpringBoot Controller
|
|
713
|
+
*/
|
|
714
|
+
function generateSpringBootController(entityName, packageName = 'com.example.demo.controller') {
|
|
715
|
+
const entityLower = entityName.toLowerCase();
|
|
716
|
+
const basePackage = packageName.replace('.controller', '');
|
|
717
|
+
const basePath = `/${entityLower}`;
|
|
718
|
+
|
|
719
|
+
return `package ${packageName};
|
|
720
|
+
|
|
721
|
+
import ${basePackage}.entity.${entityName};
|
|
722
|
+
import ${basePackage}.service.${entityName}Service;
|
|
723
|
+
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
724
|
+
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
725
|
+
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
726
|
+
import org.springframework.beans.factory.annotation.Autowired;
|
|
727
|
+
import org.springframework.web.bind.annotation.*;
|
|
728
|
+
import io.swagger.annotations.Api;
|
|
729
|
+
import io.swagger.annotations.ApiOperation;
|
|
730
|
+
import com.common.result.Result;
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* ${entityName} Controller
|
|
734
|
+
*/
|
|
735
|
+
@Api(tags = "${entityName} Controller")
|
|
736
|
+
@RestController
|
|
737
|
+
@RequestMapping("${basePath}")
|
|
738
|
+
public class ${entityName}Controller {
|
|
739
|
+
|
|
740
|
+
@Autowired
|
|
741
|
+
private ${entityName}Service ${entityLower}Service;
|
|
742
|
+
|
|
743
|
+
@ApiOperation("Get ${entityName} page list")
|
|
744
|
+
@GetMapping("/list")
|
|
745
|
+
public Result<IPage<${entityName}>> list(
|
|
746
|
+
@RequestParam(defaultValue = "1") Integer pageNum,
|
|
747
|
+
@RequestParam(defaultValue = "10") Integer pageSize,
|
|
748
|
+
${entityName} query) {
|
|
749
|
+
Page<${entityName}> page = new Page<>(pageNum, pageSize);
|
|
750
|
+
LambdaQueryWrapper<${entityName}> wrapper = new LambdaQueryWrapper<>();
|
|
751
|
+
// TODO: Add query conditions
|
|
752
|
+
IPage<${entityName}> result = ${entityLower}Service.page(page, wrapper);
|
|
753
|
+
return Result.success(result);
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
@ApiOperation("Get ${entityName} detail by ID")
|
|
757
|
+
@GetMapping("/{id}")
|
|
758
|
+
public Result<${entityName}> getById(@PathVariable Long id) {
|
|
759
|
+
${entityName} ${entityLower} = ${entityLower}Service.getById(id);
|
|
760
|
+
return Result.success(${entityLower});
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
@ApiOperation("Create ${entityName}")
|
|
764
|
+
@PostMapping
|
|
765
|
+
public Result<Boolean> create(@RequestBody ${entityName} record) {
|
|
766
|
+
boolean result = ${entityLower}Service.save(record);
|
|
767
|
+
return Result.success(result);
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
@ApiOperation("Update ${entityName}")
|
|
771
|
+
@PutMapping
|
|
772
|
+
public Result<Boolean> update(@RequestBody ${entityName} record) {
|
|
773
|
+
boolean result = ${entityLower}Service.updateById(record);
|
|
774
|
+
return Result.success(result);
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
@ApiOperation("Delete ${entityName}")
|
|
778
|
+
@DeleteMapping("/{id}")
|
|
779
|
+
public Result<Boolean> delete(@PathVariable Long id) {
|
|
780
|
+
boolean result = ${entityLower}Service.removeById(id);
|
|
781
|
+
return Result.success(result);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
`;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
/**
|
|
788
|
+
* Generate plain Controller (without MP)
|
|
789
|
+
*/
|
|
790
|
+
function generatePlainSpringBootController(entityName, packageName = 'com.example.demo.controller') {
|
|
791
|
+
const entityLower = entityName.toLowerCase();
|
|
792
|
+
const basePackage = packageName.replace('.controller', '');
|
|
793
|
+
const basePath = `/${entityLower}`;
|
|
794
|
+
|
|
795
|
+
return `package ${packageName};
|
|
796
|
+
|
|
797
|
+
import ${basePackage}.entity.${entityName};
|
|
798
|
+
import ${basePackage}.service.${entityName}Service;
|
|
799
|
+
import com.github.pagehelper.PageInfo;
|
|
800
|
+
import org.springframework.beans.factory.annotation.Autowired;
|
|
801
|
+
import org.springframework.web.bind.annotation.*;
|
|
802
|
+
import io.swagger.annotations.Api;
|
|
803
|
+
import io.swagger.annotations.ApiOperation;
|
|
804
|
+
import com.common.result.Result;
|
|
805
|
+
|
|
806
|
+
/**
|
|
807
|
+
* ${entityName} Controller
|
|
808
|
+
*/
|
|
809
|
+
@Api(tags = "${entityName} Controller")
|
|
810
|
+
@RestController
|
|
811
|
+
@RequestMapping("${basePath}")
|
|
812
|
+
public class ${entityName}Controller {
|
|
813
|
+
|
|
814
|
+
@Autowired
|
|
815
|
+
private ${entityName}Service ${entityLower}Service;
|
|
816
|
+
|
|
817
|
+
@ApiOperation("Get ${entityName} page list")
|
|
818
|
+
@GetMapping("/list")
|
|
819
|
+
public Result<PageInfo<${entityName}>> list(
|
|
820
|
+
@RequestParam(defaultValue = "1") Integer pageNum,
|
|
821
|
+
@RequestParam(defaultValue = "10") Integer pageSize,
|
|
822
|
+
${entityName} query) {
|
|
823
|
+
PageInfo<${entityName}> result = ${entityLower}Service.pageList(query, pageNum, pageSize);
|
|
824
|
+
return Result.success(result);
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
@ApiOperation("Get ${entityName} detail by ID")
|
|
828
|
+
@GetMapping("/{id}")
|
|
829
|
+
public Result<${entityName}> getById(@PathVariable Long id) {
|
|
830
|
+
${entityName} ${entityLower} = ${entityLower}Service.getById(id);
|
|
831
|
+
return Result.success(${entityLower});
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
@ApiOperation("Create ${entityName}")
|
|
835
|
+
@PostMapping
|
|
836
|
+
public Result<Integer> create(@RequestBody ${entityName} record) {
|
|
837
|
+
int result = ${entityLower}Service.create(record);
|
|
838
|
+
return Result.success(result);
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
@ApiOperation("Update ${entityName}")
|
|
842
|
+
@PutMapping
|
|
843
|
+
public Result<Integer> update(@RequestBody ${entityName} record) {
|
|
844
|
+
int result = ${entityLower}Service.update(record);
|
|
845
|
+
return Result.success(result);
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
@ApiOperation("Delete ${entityName}")
|
|
849
|
+
@DeleteMapping("/{id}")
|
|
850
|
+
public Result<Integer> delete(@PathVariable Long id) {
|
|
851
|
+
int result = ${entityLower}Service.delete(id);
|
|
852
|
+
return Result.success(result);
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
`;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
/**
|
|
859
|
+
* Generate MyBatis XML Mapper
|
|
860
|
+
*/
|
|
861
|
+
function generateMyBatisXml(entityName, tableName, columns) {
|
|
862
|
+
const table = tableName || camelToSnake(entityName);
|
|
863
|
+
const primaryKey = columns.find(c => c.primaryKey) || columns[0];
|
|
864
|
+
|
|
865
|
+
const resultMap = ` <resultMap id="BaseResultMap" type="${entityName}">
|
|
866
|
+
${columns.map(col => ` <${col.primaryKey ? 'id' : 'result'} column="${camelToSnake(col.name)}" property="${col.name}" jdbcType="${getJdbcType(col.type)}" />`).join('\n')}
|
|
867
|
+
</resultMap>`;
|
|
868
|
+
|
|
869
|
+
const baseColumnList = columns.map(col => camelToSnake(col.name)).join(',\n ');
|
|
870
|
+
|
|
871
|
+
const insertColumns = columns.map(col => camelToSnake(col.name)).join(',\n ');
|
|
872
|
+
const insertValues = columns.map(col => `#{${col.name}}`).join(',\n ');
|
|
873
|
+
|
|
874
|
+
const dynamicSet = columns
|
|
875
|
+
.filter(col => !col.primaryKey)
|
|
876
|
+
.map(col => ` <if test="${col.name} != null">
|
|
877
|
+
${camelToSnake(col.name)} = #{${col.name}},
|
|
878
|
+
</if>`)
|
|
879
|
+
.join('\n');
|
|
880
|
+
|
|
881
|
+
const dynamicWhere = columns
|
|
882
|
+
.filter(col => !col.primaryKey)
|
|
883
|
+
.map(col => ` <if test="query.${col.name} != null and query.${col.name} != ''">
|
|
884
|
+
AND ${camelToSnake(col.name)} = #{query.${col.name}}
|
|
885
|
+
</if>`)
|
|
886
|
+
.join('\n');
|
|
887
|
+
|
|
888
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
889
|
+
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
|
890
|
+
<mapper namespace="com.example.demo.mapper.${entityName}Mapper">
|
|
891
|
+
|
|
892
|
+
${resultMap}
|
|
893
|
+
|
|
894
|
+
<sql id="Base_Column_List">
|
|
895
|
+
${baseColumnList}
|
|
896
|
+
</sql>
|
|
897
|
+
|
|
898
|
+
<select id="selectById" resultMap="BaseResultMap">
|
|
899
|
+
SELECT
|
|
900
|
+
<include refid="Base_Column_List" />
|
|
901
|
+
FROM ${table}
|
|
902
|
+
WHERE ${camelToSnake(primaryKey.name)} = #{id}
|
|
903
|
+
</select>
|
|
904
|
+
|
|
905
|
+
<select id="selectList" resultMap="BaseResultMap">
|
|
906
|
+
SELECT
|
|
907
|
+
<include refid="Base_Column_List" />
|
|
908
|
+
FROM ${table}
|
|
909
|
+
<where>
|
|
910
|
+
${dynamicWhere}
|
|
911
|
+
</where>
|
|
912
|
+
ORDER BY ${camelToSnake(primaryKey.name)} DESC
|
|
913
|
+
</select>
|
|
914
|
+
|
|
915
|
+
<select id="count" resultType="int">
|
|
916
|
+
SELECT COUNT(*)
|
|
917
|
+
FROM ${table}
|
|
918
|
+
<where>
|
|
919
|
+
${dynamicWhere}
|
|
920
|
+
</where>
|
|
921
|
+
</select>
|
|
922
|
+
|
|
923
|
+
<insert id="insert" parameterType="${entityName}">
|
|
924
|
+
INSERT INTO ${table} (
|
|
925
|
+
${insertColumns}
|
|
926
|
+
) VALUES (
|
|
927
|
+
${insertValues}
|
|
928
|
+
);
|
|
929
|
+
</insert>
|
|
930
|
+
|
|
931
|
+
<update id="updateById" parameterType="${entityName}">
|
|
932
|
+
UPDATE ${table}
|
|
933
|
+
<set>
|
|
934
|
+
${dynamicSet}
|
|
935
|
+
</set>
|
|
936
|
+
WHERE ${camelToSnake(primaryKey.name)} = #{${primaryKey.name}}
|
|
937
|
+
</update>
|
|
938
|
+
|
|
939
|
+
<delete id="deleteById">
|
|
940
|
+
DELETE FROM ${table}
|
|
941
|
+
WHERE ${camelToSnake(primaryKey.name)} = #{id}
|
|
942
|
+
</delete>
|
|
943
|
+
</mapper>
|
|
944
|
+
`;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
/**
|
|
948
|
+
* Get JDBC type from Java type
|
|
949
|
+
*/
|
|
950
|
+
function getJdbcType(javaType) {
|
|
951
|
+
const map = {
|
|
952
|
+
'String': 'VARCHAR',
|
|
953
|
+
'Long': 'BIGINT',
|
|
954
|
+
'Integer': 'INTEGER',
|
|
955
|
+
'int': 'INTEGER',
|
|
956
|
+
'Boolean': 'BOOLEAN',
|
|
957
|
+
'Date': 'TIMESTAMP',
|
|
958
|
+
'DateTime': 'TIMESTAMP',
|
|
959
|
+
'BigDecimal': 'DECIMAL',
|
|
960
|
+
'Double': 'DOUBLE',
|
|
961
|
+
'Float': 'FLOAT'
|
|
962
|
+
};
|
|
963
|
+
return map[javaType] || 'VARCHAR';
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
/**
|
|
967
|
+
* Get default value for Vue data
|
|
968
|
+
*/
|
|
969
|
+
function getDefaultValue(type) {
|
|
970
|
+
switch (type) {
|
|
971
|
+
case 'String': case 'Date': return "''";
|
|
972
|
+
case 'Number': case 'Integer': case 'Long': return '0';
|
|
973
|
+
case 'Boolean': return 'false';
|
|
974
|
+
default: return "''";
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
/**
|
|
979
|
+
* Generate full-stack CRUD
|
|
980
|
+
*/
|
|
981
|
+
function generateFullStackCrud(entityName, tableName, columns, options = {}) {
|
|
982
|
+
const { useMyBatisPlus = true, basePackage = 'com.example.demo' } = options;
|
|
983
|
+
|
|
984
|
+
return {
|
|
985
|
+
vue: {
|
|
986
|
+
crudPage: generateVue2CrudPage(entityName, tableName, columns),
|
|
987
|
+
formDialog: generateVue2FormModal(entityName, columns),
|
|
988
|
+
api: generateVue2Api(entityName, tableName)
|
|
989
|
+
},
|
|
990
|
+
springboot: {
|
|
991
|
+
entity: generateMyBatisEntity(entityName, columns, `${basePackage}.entity`),
|
|
992
|
+
mapper: useMyBatisPlus
|
|
993
|
+
? generateMyBatisMapper(entityName, `${basePackage}.mapper`)
|
|
994
|
+
: generatePlainMyBatisMapper(entityName, `${basePackage}.mapper`),
|
|
995
|
+
service: useMyBatisPlus
|
|
996
|
+
? generateSpringBootService(entityName, `${basePackage}.service`)
|
|
997
|
+
: generatePlainSpringBootService(entityName, `${basePackage}.service`),
|
|
998
|
+
serviceImpl: useMyBatisPlus
|
|
999
|
+
? generateSpringBootServiceImpl(entityName, `${basePackage}.service.impl`)
|
|
1000
|
+
: generatePlainSpringBootServiceImpl(entityName, `${basePackage}.service.impl`),
|
|
1001
|
+
controller: useMyBatisPlus
|
|
1002
|
+
? generateSpringBootController(entityName, `${basePackage}.controller`)
|
|
1003
|
+
: generatePlainSpringBootController(entityName, `${basePackage}.controller`)
|
|
1004
|
+
},
|
|
1005
|
+
mybatis: {
|
|
1006
|
+
xml: useMyBatisPlus ? null : generateMyBatisXml(entityName, tableName, columns)
|
|
1007
|
+
}
|
|
1008
|
+
};
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
// ========== Export ==========
|
|
1012
|
+
|
|
1013
|
+
module.exports = {
|
|
1014
|
+
getInfo,
|
|
1015
|
+
// Vue2
|
|
1016
|
+
generateVue2Component,
|
|
1017
|
+
generateVue2CrudPage,
|
|
1018
|
+
generateVue2FormModal,
|
|
1019
|
+
generateVue2Api,
|
|
1020
|
+
// MyBatis
|
|
1021
|
+
generateMyBatisEntity,
|
|
1022
|
+
generateMyBatisMapper,
|
|
1023
|
+
generatePlainMyBatisMapper,
|
|
1024
|
+
generateMyBatisXml,
|
|
1025
|
+
// SpringBoot
|
|
1026
|
+
generateSpringBootService,
|
|
1027
|
+
generatePlainSpringBootService,
|
|
1028
|
+
generateSpringBootServiceImpl,
|
|
1029
|
+
generatePlainSpringBootServiceImpl,
|
|
1030
|
+
generateSpringBootController,
|
|
1031
|
+
generatePlainSpringBootController,
|
|
1032
|
+
// Full Stack
|
|
1033
|
+
generateFullStackCrud
|
|
1034
|
+
};
|
|
1035
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@skills-cli/vue2-springboot-mybatis",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Universal coding assistance skills for Vue2 + SpringBoot + MyBatis full-stack development",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"skills-cli",
|
|
11
|
+
"vue2",
|
|
12
|
+
"springboot",
|
|
13
|
+
"mybatis",
|
|
14
|
+
"code-generation",
|
|
15
|
+
"crud",
|
|
16
|
+
"fullstack",
|
|
17
|
+
"coding-assistance"
|
|
18
|
+
],
|
|
19
|
+
"author": "skills-cli",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"tags": [
|
|
22
|
+
"vue2",
|
|
23
|
+
"springboot",
|
|
24
|
+
"mybatis",
|
|
25
|
+
"code-generation",
|
|
26
|
+
"crud",
|
|
27
|
+
"fullstack"
|
|
28
|
+
],
|
|
29
|
+
"capabilities": [
|
|
30
|
+
"vue2-component",
|
|
31
|
+
"vue2-crud",
|
|
32
|
+
"springboot-controller",
|
|
33
|
+
"springboot-service",
|
|
34
|
+
"mybatis-entity",
|
|
35
|
+
"mybatis-mapper",
|
|
36
|
+
"crud-generation",
|
|
37
|
+
"code-template"
|
|
38
|
+
]
|
|
39
|
+
}
|
package/skills.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vue2-springboot-mybatis",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Universal coding assistance skills for Vue2 + SpringBoot + MyBatis full-stack development",
|
|
5
|
+
"priority": 80,
|
|
6
|
+
"tags": ["vue2", "springboot", "mybatis", "code-generation", "crud", "fullstack", "coding-assistance"],
|
|
7
|
+
"capabilities": [
|
|
8
|
+
"generate-vue2-component",
|
|
9
|
+
"generate-vue2-crud-page",
|
|
10
|
+
"generate-springboot-controller",
|
|
11
|
+
"generate-springboot-service",
|
|
12
|
+
"generate-mybatis-entity",
|
|
13
|
+
"generate-mybatis-mapper",
|
|
14
|
+
"generate-mybatis-xml",
|
|
15
|
+
"generate-crud-fullstack",
|
|
16
|
+
"code-templates"
|
|
17
|
+
],
|
|
18
|
+
"dependencies": {},
|
|
19
|
+
"devDependencies": {},
|
|
20
|
+
"priorityOverrides": {},
|
|
21
|
+
"config": {
|
|
22
|
+
"vue2": {
|
|
23
|
+
"componentPath": "src/components",
|
|
24
|
+
"viewPath": "src/views",
|
|
25
|
+
"apiPath": "src/api"
|
|
26
|
+
},
|
|
27
|
+
"springboot": {
|
|
28
|
+
"basePackage": "com.example.demo",
|
|
29
|
+
"entityPath": "src/main/java/**/entity",
|
|
30
|
+
"mapperPath": "src/main/java/**/mapper",
|
|
31
|
+
"servicePath": "src/main/java/**/service",
|
|
32
|
+
"controllerPath": "src/main/java/**/controller",
|
|
33
|
+
"xmlPath": "src/main/resources/mapper"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|