mirror of
https://github.com/moshowgame/SpringBootCodeGenerator.git
synced 2026-10-23 16:23:09 +08:00
2026.09.09 | 端全面重构为 jQuery3 + Bootstrap 5.3 + CodeMirror 5
2026.09.09 | 🎨 前端全面重构为 jQuery3 + Bootstrap 5.3 + CodeMirror 5:全新 `newui3` 现代化界面,`data-bs-theme` 原生深/浅色模式(CodeMirror 双主题跟随),输出区按模板类型动态切换语法高亮(Java/XML/SQL/JSON/JS);新增 `app.js` 独立命名空间 `CodeGenApp`(与旧版 main.js 零冲突),补齐本地 mode 文件(sql/clike/xml/javascript);新增🏺古法印章开关(isHeritage,致敬古法编程非遗传承者);模板选择区改为组内联布局,`template.json` 支持 `tier` 字段分级(main 常驻 / legacy 折叠),折叠与选中状态 localStorage 记忆;修复 JDK23+ 下 Lombok 注解处理不生效的编译问题; |
This commit is contained in:
@@ -309,6 +309,7 @@ ResultVo.error(message);
|
||||
|
||||
| 更新日期 | 更新内容 |
|
||||
| :--------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 2026.09.09 | 🎨 前端全面重构为 jQuery3 + Bootstrap 5.3 + CodeMirror 5:全新 `newui3` 现代化界面,`data-bs-theme` 原生深/浅色模式(CodeMirror 双主题跟随),输出区按模板类型动态切换语法高亮(Java/XML/SQL/JSON/JS);新增 `app.js` 独立命名空间 `CodeGenApp`(与旧版 main.js 零冲突),补齐本地 mode 文件(sql/clike/xml/javascript);新增🏺古法印章开关(isHeritage,致敬古法编程非遗传承者);模板选择区改为组内联布局,`template.json` 支持 `tier` 字段分级(main 常驻 / legacy 折叠),折叠与选中状态 localStorage 记忆;修复 JDK23+ 下 Lombok 注解处理不生效的编译问题; |
|
||||
| 2026.06.02 | 📦 新增"一键 ZIP 打包下载"功能:在生成按钮旁新增独立下载按钮,按模板 group 自动分目录打包成 ZIP;<br>支持 `template.json` 中 `fileName` 字段(含 `${className}` 占位符),智能推断文件后缀; |
|
||||
| 2025.12.09 | 优化Mybatis和Mybatis-Plus模板 |
|
||||
| 2025.12.08 | 引入单元测试和JaCoCo测试覆盖率,优化代码覆盖率 [UNIT\_TEST\_DOCUMENT.md](UNIT_TEST_DOCUMENT.md) |
|
||||
|
||||
29
pom.xml
29
pom.xml
@@ -183,13 +183,28 @@
|
||||
|
||||
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
|
||||
<!-- Maven Compiler Plugin:JDK23+ 默认禁用隐式注解处理,需显式声明 Lombok 处理器 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.42</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Maven Surefire Plugin for JUnit 5 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
||||
@@ -19,12 +19,12 @@ public class PageController {
|
||||
|
||||
@GetMapping("/")
|
||||
public ModelAndView defaultPage() {
|
||||
return new ModelAndView("newui2").addObject("value", valueUtil);
|
||||
return new ModelAndView("newui3").addObject("value", valueUtil);
|
||||
}
|
||||
|
||||
@GetMapping("/index")
|
||||
public ModelAndView indexPage() {
|
||||
return new ModelAndView("newui2").addObject("value", valueUtil);
|
||||
return new ModelAndView("newui3").addObject("value", valueUtil);
|
||||
}
|
||||
|
||||
}
|
||||
534
src/main/resources/statics/js/app.js
Normal file
534
src/main/resources/statics/js/app.js
Normal file
@@ -0,0 +1,534 @@
|
||||
/**
|
||||
* CodeGenApp — 大狼狗代码生成器前端应用(jQuery3 + Bootstrap 5.3 + CodeMirror 5)
|
||||
*
|
||||
* 独立命名空间实现,与旧版 main.js 完全隔离,可共存互不影响。
|
||||
* 页面约定:
|
||||
* - [data-action] 按钮行为(generate / copy / download-zip / toggle-theme)
|
||||
* - [data-cg-opt] 生成选项控件(name 即 options key)
|
||||
* - [data-template] 模板按钮(name 即模板名)
|
||||
* - #cg-input/#cg-output CodeMirror 挂载点
|
||||
*/
|
||||
(function (window, document) {
|
||||
'use strict';
|
||||
|
||||
var $ = window.jQuery;
|
||||
var axios = window.axios;
|
||||
var CodeMirror = window.CodeMirror;
|
||||
|
||||
var API = {
|
||||
generate: (window.basePath || '') + '/code/generate',
|
||||
generateZip: (window.basePath || '') + '/code/generate-zip',
|
||||
templates: (window.basePath || '') + '/template/all'
|
||||
};
|
||||
|
||||
var COOKIE_KEYS = ['authorName', 'packageName', 'returnUtilSuccess', 'returnUtilFailure',
|
||||
'ignorePrefix', 'tinyintTransType', 'timeTransType'];
|
||||
var COOKIE_AGE = 365 * 24 * 3600;
|
||||
var HISTORY_LIMIT = 9;
|
||||
var HISTORY_PREFIX = 'cg:history:';
|
||||
var THEME_KEY = 'cg:theme';
|
||||
var FOLD_KEY = 'cg:templates-fold';
|
||||
var TEMPLATE_KEY = 'cg:template';
|
||||
|
||||
var SAMPLE_SQL = 'CREATE TABLE \'sys_user_info\' (\n' +
|
||||
' \'user_id\' int(11) NOT NULL AUTO_INCREMENT COMMENT \'用户编号\',\n' +
|
||||
' \'user_name\' varchar(255) NOT NULL COMMENT \'用户名\',\n' +
|
||||
' \'status\' tinyint(1) NOT NULL COMMENT \'状态\',\n' +
|
||||
' \'create_time\' datetime NOT NULL COMMENT \'创建时间\',\n' +
|
||||
' PRIMARY KEY (\'user_id\')\n' +
|
||||
') ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT=\'用户信息\'';
|
||||
|
||||
var state = {
|
||||
options: {
|
||||
dataType: 'sql',
|
||||
authorName: '',
|
||||
packageName: '',
|
||||
returnUtilSuccess: '',
|
||||
returnUtilFailure: '',
|
||||
ignorePrefix: 'sys_',
|
||||
tinyintTransType: 'int',
|
||||
nameCaseType: 'CamelCase',
|
||||
timeTransType: 'Date',
|
||||
isPackageType: true,
|
||||
isSwagger: false,
|
||||
isAutoImport: false,
|
||||
isWithPackage: false,
|
||||
isComment: true,
|
||||
isLombok: true,
|
||||
isHeritage: true
|
||||
},
|
||||
templates: [],
|
||||
fileNameMap: {},
|
||||
history: [],
|
||||
currentTemplate: 'plusentity',
|
||||
outputJson: {},
|
||||
oemOutputStr: '',
|
||||
foldOpen: false
|
||||
};
|
||||
|
||||
var els = {};
|
||||
var editors = { input: null, output: null };
|
||||
|
||||
/* ============================== utils ============================== */
|
||||
|
||||
function notify(type, msg) {
|
||||
if (window.toastr) {
|
||||
toastr[type === 'warning' ? 'warning' : (type === 'error' ? 'error' : 'success')](msg);
|
||||
} else {
|
||||
window.alert(msg);
|
||||
}
|
||||
}
|
||||
|
||||
function escapeHtml(str) {
|
||||
return String(str == null ? '' : str).replace(/[&<>"']/g, function (c) {
|
||||
return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c];
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================== cookies ============================== */
|
||||
|
||||
function writeCookie(key, val) {
|
||||
try {
|
||||
document.cookie = key + '=' + encodeURIComponent(val == null ? '' : val) +
|
||||
';path=' + (window.basePath || '/') + ';max-age=' + COOKIE_AGE;
|
||||
} catch (e) { /* ignore */ }
|
||||
}
|
||||
|
||||
function readCookie(key) {
|
||||
try {
|
||||
var pairs = document.cookie.split(';');
|
||||
for (var i = 0; i < pairs.length; i++) {
|
||||
var kv = pairs[i].split('=');
|
||||
if (kv[0].replace(/^\s+/, '') === key) {
|
||||
return decodeURIComponent(kv.slice(1).join('='));
|
||||
}
|
||||
}
|
||||
} catch (e) { /* ignore */ }
|
||||
return '';
|
||||
}
|
||||
|
||||
function saveCookies() {
|
||||
COOKIE_KEYS.forEach(function (key) {
|
||||
writeCookie(key, state.options[key]);
|
||||
});
|
||||
}
|
||||
|
||||
function loadCookies() {
|
||||
COOKIE_KEYS.forEach(function (key) {
|
||||
var val = readCookie(key);
|
||||
if (val !== '') {
|
||||
state.options[key] = val;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================== theme ============================== */
|
||||
|
||||
function resolveInitialTheme() {
|
||||
try {
|
||||
var saved = localStorage.getItem(THEME_KEY);
|
||||
if (saved === 'dark' || saved === 'light') {
|
||||
return saved;
|
||||
}
|
||||
} catch (e) { /* ignore */ }
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
return 'dark';
|
||||
}
|
||||
return 'light';
|
||||
}
|
||||
|
||||
function editorTheme() {
|
||||
return document.documentElement.getAttribute('data-bs-theme') === 'dark'
|
||||
? 'material-darker' : 'idea';
|
||||
}
|
||||
|
||||
function applyTheme(mode, persist) {
|
||||
document.documentElement.setAttribute('data-bs-theme', mode);
|
||||
if (editors.input) {
|
||||
editors.input.setOption('theme', editorTheme());
|
||||
}
|
||||
if (editors.output) {
|
||||
editors.output.setOption('theme', editorTheme());
|
||||
}
|
||||
if (els.themeBtn.length) {
|
||||
els.themeBtn.html(mode === 'dark' ? '<i class="bi bi-sun"></i>' : '<i class="bi bi-moon-stars"></i>');
|
||||
}
|
||||
if (persist) {
|
||||
try { localStorage.setItem(THEME_KEY, mode); } catch (e) { /* ignore */ }
|
||||
}
|
||||
}
|
||||
|
||||
function toggleTheme() {
|
||||
applyTheme(document.documentElement.getAttribute('data-bs-theme') === 'dark' ? 'light' : 'dark', true);
|
||||
}
|
||||
|
||||
/* ============================== editors ============================== */
|
||||
|
||||
function initEditors() {
|
||||
editors.input = CodeMirror.fromTextArea(document.getElementById('cg-input'), {
|
||||
mode: 'text/x-sql',
|
||||
theme: editorTheme(),
|
||||
lineNumbers: true,
|
||||
smartIndent: true,
|
||||
autoCloseBrackets: true,
|
||||
styleActiveLine: true
|
||||
});
|
||||
editors.output = CodeMirror.fromTextArea(document.getElementById('cg-output'), {
|
||||
mode: 'text/x-java',
|
||||
theme: editorTheme(),
|
||||
lineNumbers: true,
|
||||
smartIndent: true,
|
||||
readOnly: false,
|
||||
autoCloseBrackets: true
|
||||
});
|
||||
editors.input.setValue(SAMPLE_SQL);
|
||||
}
|
||||
|
||||
function modeForTemplate(name) {
|
||||
var fileName = (state.fileNameMap[name] || name).toLowerCase();
|
||||
if (/\.(xml|html|vue)$/.test(fileName)) { return 'application/xml'; }
|
||||
if (/\.sql$/.test(fileName)) { return 'text/x-sql'; }
|
||||
if (/\.json$/.test(fileName)) { return 'application/json'; }
|
||||
if (/\.(jjs|js)$/.test(fileName)) { return 'text/javascript'; }
|
||||
return 'text/x-java';
|
||||
}
|
||||
|
||||
function setOutput(text) {
|
||||
editors.output.setOption('mode', modeForTemplate(state.currentTemplate));
|
||||
editors.output.setValue(text == null ? '' : text);
|
||||
}
|
||||
|
||||
/* ============================== options ============================== */
|
||||
|
||||
function applyOptionsToDom() {
|
||||
$('[data-cg-opt]').each(function () {
|
||||
var key = this.getAttribute('data-cg-opt');
|
||||
var val = state.options[key];
|
||||
if (this.type === 'checkbox') {
|
||||
this.checked = val === true || val === 'true';
|
||||
} else {
|
||||
this.value = val == null ? '' : val;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function collectOptions() {
|
||||
$('[data-cg-opt]').each(function () {
|
||||
state.options[this.getAttribute('data-cg-opt')] =
|
||||
this.type === 'checkbox' ? this.checked : this.value;
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================== templates ============================== */
|
||||
|
||||
function loadTemplates() {
|
||||
axios.post(API.templates, {}).then(function (res) {
|
||||
state.templates = (res.data && res.data.data) || [];
|
||||
state.templates.forEach(function (group) {
|
||||
(group.templates || []).forEach(function (t) {
|
||||
state.fileNameMap[t.name] = t.fileName || '';
|
||||
});
|
||||
});
|
||||
renderTemplates();
|
||||
}).catch(function () {
|
||||
els.templates.html('<div class="text-danger small">模板加载失败,请刷新页面重试</div>');
|
||||
});
|
||||
}
|
||||
|
||||
function renderGroup(group) {
|
||||
var html = '<div class="cg-template-row">' +
|
||||
'<span class="cg-template-label">' + escapeHtml(group.group) + '</span>' +
|
||||
'<div class="d-flex flex-wrap gap-1">';
|
||||
(group.templates || []).forEach(function (t) {
|
||||
var active = t.name === state.currentTemplate;
|
||||
html += '<button type="button" class="btn btn-sm cg-template-btn ' +
|
||||
(active ? 'btn-primary' : 'btn-outline-secondary') + '" data-template="' +
|
||||
escapeHtml(t.name) + '"' + (active ? ' aria-pressed="true"' : '') + ' title="' +
|
||||
escapeHtml(t.description || t.name) + '">' + escapeHtml(t.name) + '</button>';
|
||||
});
|
||||
html += '</div></div>';
|
||||
return html;
|
||||
}
|
||||
|
||||
function renderTemplates() {
|
||||
if (!els.templates.length) { return; }
|
||||
var mainHtml = '';
|
||||
var legacyHtml = '';
|
||||
var legacyCount = 0;
|
||||
var currentInLegacy = false;
|
||||
state.templates.forEach(function (group) {
|
||||
var rowHtml = renderGroup(group);
|
||||
if (group.tier === 'legacy') {
|
||||
legacyHtml += rowHtml;
|
||||
legacyCount++;
|
||||
(group.templates || []).forEach(function (t) {
|
||||
if (t.name === state.currentTemplate) { currentInLegacy = true; }
|
||||
});
|
||||
} else {
|
||||
mainHtml += rowHtml;
|
||||
}
|
||||
});
|
||||
var html = mainHtml;
|
||||
if (legacyHtml) {
|
||||
var open = state.foldOpen || currentInLegacy;
|
||||
html += '<details class="cg-fold" id="cgFold"' + (open ? ' open' : '') + '>' +
|
||||
'<summary><i class="bi bi-archive me-1"></i>更多模板 · 低频/遗产组(' + legacyCount + ' 组)</summary>' +
|
||||
'<div class="cg-fold-body">' + legacyHtml + '</div></details>';
|
||||
}
|
||||
els.templates.html(html || '<div class="text-body-secondary small">未找到模板</div>');
|
||||
var fold = document.getElementById('cgFold');
|
||||
if (fold) {
|
||||
fold.addEventListener('toggle', function () {
|
||||
state.foldOpen = fold.open;
|
||||
try { localStorage.setItem(FOLD_KEY, fold.open ? 'open' : 'closed'); } catch (e) { /* ignore */ }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function selectTemplate(name) {
|
||||
state.currentTemplate = name;
|
||||
try { localStorage.setItem(TEMPLATE_KEY, name); } catch (e) { /* ignore */ }
|
||||
renderTemplates();
|
||||
var content = state.outputJson[name];
|
||||
setOutput(typeof content === 'string' ? content.trim() : '');
|
||||
if (els.currentTemplate.length) {
|
||||
if (state.outputJson && state.outputJson.tableName) {
|
||||
els.currentTemplate.text(name).show();
|
||||
} else {
|
||||
els.currentTemplate.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================== history ============================== */
|
||||
|
||||
function saveHistory(tableName) {
|
||||
if (!tableName) { return; }
|
||||
try {
|
||||
sessionStorage.setItem(HISTORY_PREFIX + tableName, JSON.stringify(state.outputJson));
|
||||
} catch (e) { /* ignore */ }
|
||||
var idx = state.history.indexOf(tableName);
|
||||
if (idx >= 0) { state.history.splice(idx, 1); }
|
||||
state.history.unshift(tableName);
|
||||
if (state.history.length > HISTORY_LIMIT) {
|
||||
var removed = state.history.splice(HISTORY_LIMIT);
|
||||
removed.forEach(function (t) {
|
||||
try { sessionStorage.removeItem(HISTORY_PREFIX + t); } catch (e) { /* ignore */ }
|
||||
});
|
||||
}
|
||||
renderHistory();
|
||||
}
|
||||
|
||||
function renderHistory() {
|
||||
if (!els.historyChips.length) { return; }
|
||||
if (!state.history.length) {
|
||||
els.historyBar.hide();
|
||||
return;
|
||||
}
|
||||
els.historyBar.show();
|
||||
els.historyChips.html(state.history.map(function (name) {
|
||||
return '<button type="button" class="btn btn-outline-secondary btn-sm cg-chip" data-history="' +
|
||||
escapeHtml(name) + '"><i class="bi bi-clock-history me-1"></i>' + escapeHtml(name) + '</button>';
|
||||
}).join(''));
|
||||
}
|
||||
|
||||
function selectHistory(tableName) {
|
||||
var raw = null;
|
||||
try { raw = sessionStorage.getItem(HISTORY_PREFIX + tableName); } catch (e) { /* ignore */ }
|
||||
if (!raw) {
|
||||
notify('error', '历史记录已失效');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
state.outputJson = JSON.parse(raw);
|
||||
} catch (e) {
|
||||
notify('error', '历史记录解析失败');
|
||||
return;
|
||||
}
|
||||
selectTemplate(state.currentTemplate);
|
||||
notify('success', '已切换到 ' + tableName);
|
||||
}
|
||||
|
||||
/* ============================== actions ============================== */
|
||||
|
||||
function setBusy(busy) {
|
||||
els.generateBtn.prop('disabled', busy);
|
||||
els.zipBtn.prop('disabled', busy);
|
||||
}
|
||||
|
||||
function generate() {
|
||||
var tableSql = editors.input.getValue();
|
||||
if (!tableSql || tableSql.trim().length < 5) {
|
||||
notify('warning', '请先输入 SQL / JSON 表结构');
|
||||
return;
|
||||
}
|
||||
collectOptions();
|
||||
setBusy(true);
|
||||
axios.post(API.generate, { tableSql: tableSql, options: state.options }).then(function (res) {
|
||||
if (res.status === 500 || (res.data && res.data.code === 500)) {
|
||||
notify('error', '生成失败,请检查 SQL 语句!' + (res.data && res.data.msg ? ' ' + res.data.msg : ''));
|
||||
return;
|
||||
}
|
||||
state.outputJson = (res.data && res.data.data) || {};
|
||||
saveCookies();
|
||||
saveHistory(state.outputJson.tableName);
|
||||
selectTemplate(state.currentTemplate);
|
||||
notify('success', '生成成功');
|
||||
}).catch(function (err) {
|
||||
notify('error', '生成失败:' + (err && err.message ? err.message : '网络异常'));
|
||||
}).finally(function () {
|
||||
setBusy(false);
|
||||
});
|
||||
}
|
||||
|
||||
function fallbackCopy(text) {
|
||||
var ta = document.createElement('textarea');
|
||||
ta.value = text;
|
||||
ta.style.position = 'fixed';
|
||||
ta.style.opacity = '0';
|
||||
document.body.appendChild(ta);
|
||||
ta.select();
|
||||
try {
|
||||
document.execCommand('copy');
|
||||
notify('success', '已复制');
|
||||
} catch (e) {
|
||||
notify('error', '复制失败,请手动选择复制');
|
||||
}
|
||||
document.body.removeChild(ta);
|
||||
}
|
||||
|
||||
function copyOutput() {
|
||||
var text = editors.output.getValue();
|
||||
if (!text || !text.trim()) {
|
||||
notify('warning', '输出内容为空');
|
||||
return;
|
||||
}
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
navigator.clipboard.writeText(text).then(function () {
|
||||
notify('success', '已复制');
|
||||
}).catch(function () {
|
||||
fallbackCopy(text);
|
||||
});
|
||||
} else {
|
||||
fallbackCopy(text);
|
||||
}
|
||||
}
|
||||
|
||||
function downloadZip() {
|
||||
var tableSql = editors.input.getValue();
|
||||
if (!tableSql || tableSql.trim().length < 5) {
|
||||
notify('warning', '请先输入 SQL / JSON 表结构');
|
||||
return;
|
||||
}
|
||||
collectOptions();
|
||||
setBusy(true);
|
||||
axios.post(API.generateZip, { tableSql: tableSql, options: state.options },
|
||||
{ responseType: 'blob', timeout: 60000 }).then(function (res) {
|
||||
if (res.status !== 200) {
|
||||
notify('error', '下载失败,HTTP 状态码:' + res.status);
|
||||
return;
|
||||
}
|
||||
var dispo = res.headers && (res.headers['content-disposition'] || res.headers['Content-Disposition']);
|
||||
var fileName = 'code-generator.zip';
|
||||
if (dispo) {
|
||||
var matchStar = /filename\*=UTF-8''([^;]+)/i.exec(dispo);
|
||||
var matchQuoted = /filename="?([^";]+)"?/i.exec(dispo);
|
||||
if (matchStar && matchStar[1]) {
|
||||
fileName = decodeURIComponent(matchStar[1]);
|
||||
} else if (matchQuoted && matchQuoted[1]) {
|
||||
fileName = matchQuoted[1];
|
||||
}
|
||||
}
|
||||
var blob = new Blob([res.data], { type: 'application/zip' });
|
||||
var url = window.URL.createObjectURL(blob);
|
||||
var a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = fileName;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
window.URL.revokeObjectURL(url);
|
||||
notify('success', '已下载:' + fileName);
|
||||
}).catch(function (err) {
|
||||
notify('error', '下载失败:' + (err && err.message ? err.message : '未知错误'));
|
||||
}).finally(function () {
|
||||
setBusy(false);
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================== bootstrap ============================== */
|
||||
|
||||
var actions = {
|
||||
'generate': generate,
|
||||
'copy': copyOutput,
|
||||
'download-zip': downloadZip,
|
||||
'toggle-theme': toggleTheme
|
||||
};
|
||||
|
||||
function cacheEls() {
|
||||
els.themeBtn = $('#cgThemeBtn');
|
||||
els.templates = $('#cgTemplates');
|
||||
els.historyBar = $('#cgHistoryBar');
|
||||
els.historyChips = $('#cgHistoryChips');
|
||||
els.currentTemplate = $('#cgCurrentTemplate');
|
||||
els.generateBtn = $('[data-action="generate"]');
|
||||
els.zipBtn = $('[data-action="download-zip"]');
|
||||
}
|
||||
|
||||
function bindEvents() {
|
||||
$(document).on('click', '[data-action]', function (e) {
|
||||
e.preventDefault();
|
||||
var fn = actions[$(this).data('action')];
|
||||
if (fn) { fn(); }
|
||||
});
|
||||
els.templates.on('click', 'button[data-template]', function () {
|
||||
selectTemplate($(this).data('template'));
|
||||
});
|
||||
els.historyChips.on('click', 'button[data-history]', function () {
|
||||
selectHistory($(this).data('history'));
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
cacheEls();
|
||||
if (window.toastr) {
|
||||
toastr.options = { positionClass: 'toast-top-center', timeOut: 2200, preventDuplicates: true };
|
||||
}
|
||||
initEditors();
|
||||
applyTheme(resolveInitialTheme(), false);
|
||||
loadCookies();
|
||||
try { state.foldOpen = localStorage.getItem(FOLD_KEY) === 'open'; } catch (e) { /* ignore */ }
|
||||
try {
|
||||
var savedTemplate = localStorage.getItem(TEMPLATE_KEY);
|
||||
if (savedTemplate) { state.currentTemplate = savedTemplate; }
|
||||
} catch (e) { /* ignore */ }
|
||||
applyOptionsToDom();
|
||||
bindEvents();
|
||||
loadTemplates();
|
||||
if (state.oemOutputStr) {
|
||||
setOutput(state.oemOutputStr);
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================== public api ============================== */
|
||||
|
||||
window.CodeGenApp = {
|
||||
boot: function (config) {
|
||||
config = config || {};
|
||||
['authorName', 'packageName', 'returnUtilSuccess', 'returnUtilFailure'].forEach(function (k) {
|
||||
if (config[k]) { state.options[k] = config[k]; }
|
||||
});
|
||||
state.oemOutputStr = config.outputStr || '';
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
},
|
||||
generate: generate,
|
||||
copy: copyOutput,
|
||||
downloadZip: downloadZip,
|
||||
toggleTheme: toggleTheme
|
||||
};
|
||||
|
||||
})(window, document);
|
||||
6
src/main/resources/statics/libs/bootstrap5/css/bootstrap.min.css
vendored
Normal file
6
src/main/resources/statics/libs/bootstrap5/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
7
src/main/resources/statics/libs/bootstrap5/js/bootstrap.bundle.min.js
vendored
Normal file
7
src/main/resources/statics/libs/bootstrap5/js/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/main/resources/statics/libs/codemirror/mode/javascript/javascript.min.js
vendored
Normal file
1
src/main/resources/statics/libs/codemirror/mode/javascript/javascript.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
src/main/resources/statics/libs/codemirror/mode/xml/xml.min.js
vendored
Normal file
1
src/main/resources/statics/libs/codemirror/mode/xml/xml.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/main/resources/statics/libs/codemirror/theme/material-darker.min.css
vendored
Normal file
1
src/main/resources/statics/libs/codemirror/theme/material-darker.min.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.cm-s-material-darker.CodeMirror{background-color:#212121;color:#eff}.cm-s-material-darker .CodeMirror-gutters{background:#212121;color:#545454;border:none}.cm-s-material-darker .CodeMirror-guttermarker,.cm-s-material-darker .CodeMirror-guttermarker-subtle,.cm-s-material-darker .CodeMirror-linenumber{color:#545454}.cm-s-material-darker .CodeMirror-cursor{border-left:1px solid #fc0}.cm-s-material-darker div.CodeMirror-selected{background:rgba(97,97,97,.2)}.cm-s-material-darker.CodeMirror-focused div.CodeMirror-selected{background:rgba(97,97,97,.2)}.cm-s-material-darker .CodeMirror-line::selection,.cm-s-material-darker .CodeMirror-line>span::selection,.cm-s-material-darker .CodeMirror-line>span>span::selection{background:rgba(128,203,196,.2)}.cm-s-material-darker .CodeMirror-line::-moz-selection,.cm-s-material-darker .CodeMirror-line>span::-moz-selection,.cm-s-material-darker .CodeMirror-line>span>span::-moz-selection{background:rgba(128,203,196,.2)}.cm-s-material-darker .CodeMirror-activeline-background{background:rgba(0,0,0,.5)}.cm-s-material-darker .cm-keyword{color:#c792ea}.cm-s-material-darker .cm-operator{color:#89ddff}.cm-s-material-darker .cm-variable-2{color:#eff}.cm-s-material-darker .cm-type,.cm-s-material-darker .cm-variable-3{color:#f07178}.cm-s-material-darker .cm-builtin{color:#ffcb6b}.cm-s-material-darker .cm-atom{color:#f78c6c}.cm-s-material-darker .cm-number{color:#ff5370}.cm-s-material-darker .cm-def{color:#82aaff}.cm-s-material-darker .cm-string{color:#c3e88d}.cm-s-material-darker .cm-string-2{color:#f07178}.cm-s-material-darker .cm-comment{color:#545454}.cm-s-material-darker .cm-variable{color:#f07178}.cm-s-material-darker .cm-tag{color:#ff5370}.cm-s-material-darker .cm-meta{color:#ffcb6b}.cm-s-material-darker .cm-attribute{color:#c792ea}.cm-s-material-darker .cm-property{color:#c792ea}.cm-s-material-darker .cm-qualifier{color:#decb6b}.cm-s-material-darker .cm-type,.cm-s-material-darker .cm-variable-3{color:#decb6b}.cm-s-material-darker .cm-error{color:#fff;background-color:#ff5370}.cm-s-material-darker .CodeMirror-matchingbracket{text-decoration:underline;color:#fff!important}
|
||||
@@ -1,5 +1,6 @@
|
||||
[{
|
||||
"group": "ui",
|
||||
"tier": "main",
|
||||
"templates": [{
|
||||
"id": "10",
|
||||
"name": "swagger-ui",
|
||||
@@ -34,6 +35,7 @@
|
||||
},
|
||||
{
|
||||
"group": "mybatis",
|
||||
"tier": "main",
|
||||
"templates": [{
|
||||
"id": "20",
|
||||
"name": "controller",
|
||||
@@ -80,6 +82,7 @@
|
||||
},
|
||||
{
|
||||
"group": "jpa",
|
||||
"tier": "main",
|
||||
"templates": [{
|
||||
"id": "30",
|
||||
"name": "entity",
|
||||
@@ -103,6 +106,7 @@
|
||||
|
||||
{
|
||||
"group": "jdbc-template",
|
||||
"tier": "main",
|
||||
"templates": [{
|
||||
"id": "40",
|
||||
"name": "jtdao",
|
||||
@@ -120,6 +124,7 @@
|
||||
|
||||
{
|
||||
"group": "beetlsql",
|
||||
"tier": "legacy",
|
||||
"templates": [{
|
||||
"id": "50",
|
||||
"name": "beetlmd",
|
||||
@@ -143,6 +148,7 @@
|
||||
|
||||
{
|
||||
"group": "mybatis-plus",
|
||||
"tier": "main",
|
||||
"templates": [{
|
||||
"id": "60",
|
||||
"name": "pluscontroller",
|
||||
@@ -172,6 +178,7 @@
|
||||
|
||||
{
|
||||
"group": "util",
|
||||
"tier": "main",
|
||||
"templates": [{
|
||||
"id": "70",
|
||||
"name": "beanutil",
|
||||
@@ -207,6 +214,7 @@
|
||||
|
||||
{
|
||||
"group": "common-mapper",
|
||||
"tier": "legacy",
|
||||
"templates": [{
|
||||
"id": "81",
|
||||
"name": "tkentity",
|
||||
@@ -224,6 +232,7 @@
|
||||
|
||||
{
|
||||
"group": "renren-fast",
|
||||
"tier": "legacy",
|
||||
"templates": [{
|
||||
"id": "91",
|
||||
"name": "menu-sql",
|
||||
@@ -276,6 +285,7 @@
|
||||
},
|
||||
{
|
||||
"group": "jpa-starp",
|
||||
"tier": "legacy",
|
||||
"templates": [{
|
||||
"id": "101",
|
||||
"name": "starp-entity",
|
||||
@@ -298,6 +308,7 @@
|
||||
},
|
||||
{
|
||||
"group": "bi",
|
||||
"tier": "legacy",
|
||||
"templates": [{
|
||||
"id": "201",
|
||||
"name": "qliksense",
|
||||
@@ -307,6 +318,7 @@
|
||||
},
|
||||
{
|
||||
"group": "cloud",
|
||||
"tier": "legacy",
|
||||
"templates": [
|
||||
{
|
||||
"id": "301",
|
||||
@@ -324,6 +336,7 @@
|
||||
},
|
||||
{
|
||||
"group": "tk-mybatis",
|
||||
"tier": "legacy",
|
||||
"templates": [
|
||||
{
|
||||
"id": "401",
|
||||
|
||||
23
src/main/resources/templates/newui3-header.html
Normal file
23
src/main/resources/templates/newui3-header.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="keywords" content="${(value.keywords)!!}">
|
||||
|
||||
<script>
|
||||
/*统计代码,便于统计流量,请勿移除,谢谢!*/
|
||||
var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?97fd5ca1a4298ac8349c7e0de9029a0f";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
//set base path for fixing the revertProxy forwarding path issue
|
||||
var basePath = "${request.contextPath}";
|
||||
</script>
|
||||
|
||||
<#if value.mode=='local'>
|
||||
<#include "/newui3-import-local.html">
|
||||
<#else>
|
||||
<#include "/newui3-import-CDN.html">
|
||||
</#if>
|
||||
22
src/main/resources/templates/newui3-import-CDN.html
Normal file
22
src/main/resources/templates/newui3-import-CDN.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<!--###################################################-->
|
||||
<!--### CDN version : jQuery3 + Bootstrap5.3 + CodeMirror5 -->
|
||||
<!--###################################################-->
|
||||
|
||||
<!--jquery | axios | bootstrap5 | icons | toastr-->
|
||||
<script src="//cdn.staticfile.net/jquery/3.6.0/jquery.min.js"></script>
|
||||
<script src="//cdn.staticfile.net/axios/0.26.0/axios.min.js"></script>
|
||||
<script src="//cdn.staticfile.net/bootstrap/5.3.3/js/bootstrap.bundle.min.js"></script>
|
||||
<link href="//cdn.staticfile.net/bootstrap/5.3.3/css/bootstrap.min.css" type="text/css" rel="stylesheet" />
|
||||
<link href="//cdn.staticfile.net/bootstrap-icons/1.8.1/font/bootstrap-icons.min.css" type="text/css" rel="stylesheet" />
|
||||
<script src="//cdn.staticfile.net/toastr.js/2.1.4/toastr.min.js"></script>
|
||||
<link href="//cdn.staticfile.net/toastr.js/2.1.4/toastr.min.css" type="text/css" rel="stylesheet" />
|
||||
|
||||
<!-- import codemirror : core + modes(sql/clike/xml/javascript) + themes(idea/material-darker) -->
|
||||
<script src="//cdn.staticfile.net/codemirror/5.65.2/codemirror.min.js"></script>
|
||||
<script src="//cdn.staticfile.net/codemirror/5.65.2/mode/sql/sql.min.js"></script>
|
||||
<script src="//cdn.staticfile.net/codemirror/5.65.2/mode/clike/clike.min.js"></script>
|
||||
<script src="//cdn.staticfile.net/codemirror/5.65.2/mode/xml/xml.min.js"></script>
|
||||
<script src="//cdn.staticfile.net/codemirror/5.65.2/mode/javascript/javascript.min.js"></script>
|
||||
<link href="//cdn.staticfile.net/codemirror/5.65.2/codemirror.min.css" type="text/css" rel="stylesheet" />
|
||||
<link href="//cdn.staticfile.net/codemirror/5.65.2/theme/idea.min.css" type="text/css" rel="stylesheet" />
|
||||
<link href="//cdn.staticfile.net/codemirror/5.65.2/theme/material-darker.min.css" type="text/css" rel="stylesheet" />
|
||||
22
src/main/resources/templates/newui3-import-local.html
Normal file
22
src/main/resources/templates/newui3-import-local.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<!--###################################################-->
|
||||
<!--### Local mode : jQuery3 + Bootstrap5.3 + CodeMirror5 -->
|
||||
<!--###################################################-->
|
||||
|
||||
<!--jquery | axios | bootstrap5 | icons | toastr-->
|
||||
<script src="${request.contextPath}/statics/libs/jquery/jquery.min.js"></script>
|
||||
<script src="${request.contextPath}/statics/libs/axios/axios.min.js"></script>
|
||||
<script src="${request.contextPath}/statics/libs/bootstrap5/js/bootstrap.bundle.min.js"></script>
|
||||
<link href="${request.contextPath}/statics/libs/bootstrap5/css/bootstrap.min.css" type="text/css" rel="stylesheet" />
|
||||
<link href="${request.contextPath}/statics/libs/bootstrap-icons/bootstrap-icons.min.css" type="text/css" rel="stylesheet" />
|
||||
<script src="${request.contextPath}/statics/libs/toastr.js/toastr.min.js"></script>
|
||||
<link href="${request.contextPath}/statics/libs/toastr.js/toastr.min.css" type="text/css" rel="stylesheet" />
|
||||
|
||||
<!-- import codemirror : core + modes(sql/clike/xml/javascript) + themes(idea/material-darker) -->
|
||||
<script src="${request.contextPath}/statics/libs/codemirror/codemirror.min.js"></script>
|
||||
<script src="${request.contextPath}/statics/libs/codemirror/mode/sql/sql.min.js"></script>
|
||||
<script src="${request.contextPath}/statics/libs/codemirror/mode/clike/clike.min.js"></script>
|
||||
<script src="${request.contextPath}/statics/libs/codemirror/mode/xml/xml.min.js"></script>
|
||||
<script src="${request.contextPath}/statics/libs/codemirror/mode/javascript/javascript.min.js"></script>
|
||||
<link href="${request.contextPath}/statics/libs/codemirror/codemirror.min.css" type="text/css" rel="stylesheet" />
|
||||
<link href="${request.contextPath}/statics/libs/codemirror/theme/idea.min.css" type="text/css" rel="stylesheet" />
|
||||
<link href="${request.contextPath}/statics/libs/codemirror/theme/material-darker.min.css" type="text/css" rel="stylesheet" />
|
||||
388
src/main/resources/templates/newui3.html
Normal file
388
src/main/resources/templates/newui3.html
Normal file
@@ -0,0 +1,388 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN" data-bs-theme="light">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<#include "/newui3-header.html">
|
||||
<title>${(value.title)!!}</title>
|
||||
<style>
|
||||
:root {
|
||||
--cg-radius: 12px;
|
||||
--cg-shadow: 0 1px 2px rgba(var(--bs-emphasis-color-rgb), .06), 0 2px 8px rgba(var(--bs-emphasis-color-rgb), .04);
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: var(--bs-tertiary-bg);
|
||||
}
|
||||
|
||||
main { flex: 1 0 auto; }
|
||||
|
||||
/* ===== navbar ===== */
|
||||
.cg-navbar {
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
background-color: color-mix(in srgb, var(--bs-body-bg) 85%, transparent);
|
||||
border-bottom: 1px solid var(--bs-border-color-translucent);
|
||||
}
|
||||
.cg-navbar .navbar-brand {
|
||||
font-weight: 700;
|
||||
letter-spacing: .3px;
|
||||
}
|
||||
.cg-navbar .cg-links a {
|
||||
color: var(--bs-secondary-color);
|
||||
text-decoration: none;
|
||||
margin-left: var(--bs-spacer-3, 1rem);
|
||||
transition: color .15s ease;
|
||||
}
|
||||
.cg-navbar .cg-links a:hover { color: var(--bs-link-color); }
|
||||
|
||||
/* ===== cards ===== */
|
||||
.card {
|
||||
border: none;
|
||||
border-radius: var(--cg-radius);
|
||||
box-shadow: var(--cg-shadow);
|
||||
}
|
||||
.card-header {
|
||||
background-color: transparent;
|
||||
border-bottom: 1px solid var(--bs-border-color-translucent);
|
||||
font-weight: 600;
|
||||
padding: .75rem 1rem;
|
||||
}
|
||||
|
||||
/* ===== callout for OEM description ===== */
|
||||
.cg-callout {
|
||||
border-left: 3px solid var(--bs-primary);
|
||||
border-radius: .5rem;
|
||||
background-color: var(--bs-secondary-bg);
|
||||
padding: .75rem 1rem;
|
||||
font-size: .875rem;
|
||||
color: var(--bs-secondary-color);
|
||||
}
|
||||
|
||||
/* ===== form ===== */
|
||||
.cg-opt-label {
|
||||
font-size: .75rem;
|
||||
font-weight: 600;
|
||||
color: var(--bs-secondary-color);
|
||||
margin-bottom: .25rem;
|
||||
display: block;
|
||||
}
|
||||
.form-select, .form-control { font-size: .875rem; }
|
||||
.form-switch .form-check-input { cursor: pointer; }
|
||||
|
||||
/* ===== template groups (inline label + foldable legacy) ===== */
|
||||
.cg-template-row {
|
||||
display: flex;
|
||||
gap: .75rem;
|
||||
padding: .2rem 0;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.cg-template-label {
|
||||
flex: 0 0 92px;
|
||||
font-size: .75rem;
|
||||
font-weight: 600;
|
||||
color: var(--bs-secondary-color);
|
||||
padding-top: .25rem;
|
||||
}
|
||||
.cg-template-btn {
|
||||
--bs-btn-font-size: .8125rem;
|
||||
--bs-btn-padding-x: .6rem;
|
||||
--bs-btn-padding-y: .18rem;
|
||||
}
|
||||
.cg-fold {
|
||||
margin-top: .6rem;
|
||||
border-top: 1px dashed var(--bs-border-color);
|
||||
padding-top: .5rem;
|
||||
}
|
||||
.cg-fold summary {
|
||||
cursor: pointer;
|
||||
font-size: .8125rem;
|
||||
font-weight: 600;
|
||||
color: var(--bs-secondary-color);
|
||||
user-select: none;
|
||||
list-style: none;
|
||||
}
|
||||
.cg-fold summary::-webkit-details-marker { display: none; }
|
||||
.cg-fold summary::before { content: '\25B8\00a0'; }
|
||||
.cg-fold[open] summary::before { content: '\25BE\00a0'; }
|
||||
.cg-fold summary:hover { color: var(--bs-primary); }
|
||||
.cg-fold-body { padding-top: .4rem; }
|
||||
|
||||
/* ===== history chips ===== */
|
||||
.cg-chip {
|
||||
--bs-btn-font-size: .75rem;
|
||||
--bs-btn-padding-x: .55rem;
|
||||
--bs-btn-padding-y: .1rem;
|
||||
border-radius: 50rem;
|
||||
}
|
||||
|
||||
/* ===== CodeMirror ===== */
|
||||
.CodeMirror {
|
||||
height: 360px;
|
||||
font-family: var(--bs-font-monospace);
|
||||
font-size: 13px;
|
||||
border-radius: .5rem;
|
||||
border: 1px solid var(--bs-border-color);
|
||||
}
|
||||
|
||||
/* 输入区编辑器:flex 填满整个卡片,min-height 保底(小屏单列时) */
|
||||
.cg-input-card .card-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
}
|
||||
.cg-input-card .card-body .CodeMirror {
|
||||
height: auto;
|
||||
flex: 1 1 auto;
|
||||
min-height: 320px;
|
||||
}
|
||||
.CodeMirror-gutters {
|
||||
border-right: 1px solid var(--bs-border-color-translucent);
|
||||
background-color: var(--bs-secondary-bg);
|
||||
}
|
||||
.CodeMirror-cursor { border-left: 2px solid var(--bs-primary); }
|
||||
|
||||
/* ===== footer ===== */
|
||||
.cg-footer {
|
||||
padding: 1rem 0;
|
||||
text-align: center;
|
||||
font-size: .8125rem;
|
||||
color: var(--bs-secondary-color);
|
||||
}
|
||||
|
||||
[v-cloak] { display: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- ===== Navbar ===== -->
|
||||
<nav class="navbar navbar-expand sticky-top cg-navbar">
|
||||
<div class="container-xxl">
|
||||
<a class="navbar-brand d-flex align-items-center gap-2" href="#">
|
||||
<i class="bi bi-braces-asterisk fs-4 text-primary"></i>
|
||||
<span>${(value.title)!!}</span>
|
||||
</a>
|
||||
<div class="d-none d-md-block ms-3 small text-body-secondary">${(value.slogan)!!}</div>
|
||||
<div class="ms-auto d-flex align-items-center">
|
||||
<div class="cg-links d-none d-sm-block">
|
||||
<a href="https://github.com/moshowgame/SpringBootCodeGenerator/" target="_blank"><i class="bi bi-github me-1"></i>GitHub</a>
|
||||
<a href="https://zhengkai.blog.csdn.net/" target="_blank"><i class="bi bi-journal-text me-1"></i>CSDN</a>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm ms-3" id="cgThemeBtn"
|
||||
data-action="toggle-theme" title="切换深色/浅色模式" aria-label="切换主题">
|
||||
<i class="bi bi-moon-stars"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="container-xxl py-4">
|
||||
|
||||
<!-- OEM description -->
|
||||
<div class="cg-callout mb-4">${(value.description)!!}</div>
|
||||
|
||||
<div class="row g-4">
|
||||
|
||||
<!-- ===== Input & actions ===== -->
|
||||
<div class="col-lg-8">
|
||||
<div class="card h-100 cg-input-card">
|
||||
<div class="card-header d-flex flex-wrap align-items-center gap-2">
|
||||
<span><i class="bi bi-terminal me-2 text-primary"></i>输入 SQL / JSON</span>
|
||||
<div class="ms-auto d-flex flex-wrap gap-2">
|
||||
<button type="button" class="btn btn-primary btn-sm px-3" data-action="generate">
|
||||
<i class="bi bi-play-fill me-1"></i>生成
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-primary btn-sm" data-action="copy">
|
||||
<i class="bi bi-clipboard me-1"></i>复制
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-success btn-sm" data-action="download-zip">
|
||||
<i class="bi bi-file-earmark-zip me-1"></i>下载 ZIP
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<textarea id="cg-input" class="d-none"
|
||||
placeholder="粘贴建表 DDL / INSERT SQL / SELECT SQL 或 JSON 表结构..."></textarea>
|
||||
</div>
|
||||
<div class="card-footer bg-transparent d-flex flex-wrap align-items-center gap-2"
|
||||
id="cgHistoryBar" style="display:none;">
|
||||
<span class="text-body-secondary small"><i class="bi bi-clock-history me-1"></i>历史记录</span>
|
||||
<div class="d-flex flex-wrap gap-1" id="cgHistoryChips"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== Options ===== -->
|
||||
<div class="col-lg-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-header"><i class="bi bi-sliders me-2 text-primary"></i>生成设置</div>
|
||||
<div class="card-body">
|
||||
<div class="row g-3">
|
||||
|
||||
<div class="col-12">
|
||||
<label class="cg-opt-label" for="opt-dataType">解析引擎</label>
|
||||
<select id="opt-dataType" class="form-select" data-cg-opt="dataType">
|
||||
<option value="sql" selected>DDL SQL · 自研解析引擎</option>
|
||||
<option value="select-sql">SELECT SQL · JSqlParser</option>
|
||||
<option value="create-sql">CREATE SQL · JSqlParser</option>
|
||||
<option value="json">JSON (Beta)</option>
|
||||
<option value="insert-sql">INSERT SQL</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<label class="cg-opt-label" for="opt-authorName">作者</label>
|
||||
<input id="opt-authorName" type="text" class="form-control" data-cg-opt="authorName" placeholder="author">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="cg-opt-label" for="opt-packageName">包名</label>
|
||||
<input id="opt-packageName" type="text" class="form-control" data-cg-opt="packageName" placeholder="com.example">
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<label class="cg-opt-label" for="opt-returnUtilSuccess">返回 (成功)</label>
|
||||
<input id="opt-returnUtilSuccess" type="text" class="form-control" data-cg-opt="returnUtilSuccess" placeholder="ResponseUtil.success">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="cg-opt-label" for="opt-returnUtilFailure">返回 (失败)</label>
|
||||
<input id="opt-returnUtilFailure" type="text" class="form-control" data-cg-opt="returnUtilFailure" placeholder="ResponseUtil.error">
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<label class="cg-opt-label" for="opt-ignorePrefix">忽略前缀</label>
|
||||
<input id="opt-ignorePrefix" type="text" class="form-control" data-cg-opt="ignorePrefix" placeholder="sys_">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="cg-opt-label" for="opt-tinyintTransType">TinyInt 转换</label>
|
||||
<select id="opt-tinyintTransType" class="form-select" data-cg-opt="tinyintTransType">
|
||||
<option value="int" selected>int</option>
|
||||
<option value="Integer">Integer</option>
|
||||
<option value="boolean">boolean</option>
|
||||
<option value="Boolean">Boolean</option>
|
||||
<option value="String">String</option>
|
||||
<option value="Short">Short</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<label class="cg-opt-label" for="opt-timeTransType">时间类型</label>
|
||||
<select id="opt-timeTransType" class="form-select" data-cg-opt="timeTransType">
|
||||
<option value="Date" selected>Date</option>
|
||||
<option value="DateTime">DateTime</option>
|
||||
<option value="Time">Time</option>
|
||||
<option value="Timestamp">Timestamp</option>
|
||||
<option value="Calendar">Calendar</option>
|
||||
<option value="LocalDate">LocalDate</option>
|
||||
<option value="LocalDateTime">LocalDateTime</option>
|
||||
<option value="LocalTime">LocalTime</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="cg-opt-label" for="opt-nameCaseType">命名类型</label>
|
||||
<select id="opt-nameCaseType" class="form-select" data-cg-opt="nameCaseType">
|
||||
<option value="CamelCase" selected>驼峰</option>
|
||||
<option value="UnderScoreCase">下划线</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<hr class="my-1">
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="opt-isPackageType" data-cg-opt="isPackageType" checked>
|
||||
<label class="form-check-label small" for="opt-isPackageType">包装类型</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="opt-isComment" data-cg-opt="isComment" checked>
|
||||
<label class="form-check-label small" for="opt-isComment">字段注释</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="opt-isLombok" data-cg-opt="isLombok" checked>
|
||||
<label class="form-check-label small" for="opt-isLombok">Lombok</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="opt-isSwagger" data-cg-opt="isSwagger">
|
||||
<label class="form-check-label small" for="opt-isSwagger">Swagger UI</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="opt-isAutoImport" data-cg-opt="isAutoImport">
|
||||
<label class="form-check-label small" for="opt-isAutoImport">自动引包</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="opt-isWithPackage" data-cg-opt="isWithPackage">
|
||||
<label class="form-check-label small" for="opt-isWithPackage">带包路径</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="opt-isHeritage" data-cg-opt="isHeritage" checked>
|
||||
<label class="form-check-label small" for="opt-isHeritage">🏺 古法印章 · 非遗传承</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== Templates ===== -->
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header"><i class="bi bi-collection me-2 text-primary"></i>模板选择</div>
|
||||
<div class="card-body" id="cgTemplates">
|
||||
<div class="text-body-secondary small">模板加载中...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== Output ===== -->
|
||||
<div class="col-12">
|
||||
<div class="card cg-output-card">
|
||||
<div class="card-header d-flex align-items-center gap-2">
|
||||
<span><i class="bi bi-filetype-java me-2 text-primary"></i>输出代码</span>
|
||||
<span class="badge text-bg-primary" id="cgCurrentTemplate" style="display:none;"></span>
|
||||
<button type="button" class="btn btn-outline-primary btn-sm ms-auto" data-action="copy">
|
||||
<i class="bi bi-clipboard me-1"></i>复制
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<textarea id="cg-output" class="d-none" placeholder="点击上方模板,查看生成的代码..."></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- ===== Footer ===== -->
|
||||
<footer class="cg-footer border-top border-opacity-10">
|
||||
<div class="container-xxl">${(value.copyright)!!}</div>
|
||||
</footer>
|
||||
|
||||
<script src="${request.contextPath}/statics/js/app.js?v=20260909"></script>
|
||||
<script>
|
||||
CodeGenApp.boot({
|
||||
author: "${(value.author)!!}",
|
||||
packageName: "${(value.packageName)!!}",
|
||||
returnUtilSuccess: "${(value.returnUtilSuccess)!!}",
|
||||
returnUtilFailure: "${(value.returnUtilFailure)!!}",
|
||||
outputStr: "${(value.outputStr)!!}"
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user