mirror of
https://github.com/m-xlsea/ruoyi-plus-soybean.git
synced 2025-09-23 23:39:47 +08:00
feat: 新增代码生成预览抽屉
This commit is contained in:
@ -7,6 +7,7 @@ import { setupElegantRouter } from './router';
|
|||||||
import { setupUnocss } from './unocss';
|
import { setupUnocss } from './unocss';
|
||||||
import { setupUnplugin } from './unplugin';
|
import { setupUnplugin } from './unplugin';
|
||||||
import { setupHtmlPlugin } from './html';
|
import { setupHtmlPlugin } from './html';
|
||||||
|
import { setupMonacoEditorPlugin } from './monaco-editor';
|
||||||
|
|
||||||
export function setupVitePlugins(viteEnv: Env.ImportMeta, buildTime: string) {
|
export function setupVitePlugins(viteEnv: Env.ImportMeta, buildTime: string) {
|
||||||
const plugins: PluginOption = [
|
const plugins: PluginOption = [
|
||||||
@ -21,7 +22,8 @@ export function setupVitePlugins(viteEnv: Env.ImportMeta, buildTime: string) {
|
|||||||
setupUnocss(viteEnv),
|
setupUnocss(viteEnv),
|
||||||
...setupUnplugin(viteEnv),
|
...setupUnplugin(viteEnv),
|
||||||
progress(),
|
progress(),
|
||||||
setupHtmlPlugin(buildTime)
|
setupHtmlPlugin(buildTime),
|
||||||
|
setupMonacoEditorPlugin()
|
||||||
];
|
];
|
||||||
|
|
||||||
return plugins;
|
return plugins;
|
||||||
|
7
build/plugins/monaco-editor.ts
Normal file
7
build/plugins/monaco-editor.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import monacoEditorPlugin from 'vite-plugin-monaco-editor';
|
||||||
|
|
||||||
|
export function setupMonacoEditorPlugin() {
|
||||||
|
return (monacoEditorPlugin as any).default({
|
||||||
|
languageWorkers: ['editorWorkerService', 'css', 'html', 'json', 'typescript']
|
||||||
|
});
|
||||||
|
}
|
@ -46,6 +46,7 @@
|
|||||||
"dayjs": "1.11.12",
|
"dayjs": "1.11.12",
|
||||||
"echarts": "5.5.1",
|
"echarts": "5.5.1",
|
||||||
"jsencrypt": "^3.3.2",
|
"jsencrypt": "^3.3.2",
|
||||||
|
"monaco-editor": "^0.48.0",
|
||||||
"naive-ui": "2.39.0",
|
"naive-ui": "2.39.0",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
"pinia": "2.2.2",
|
"pinia": "2.2.2",
|
||||||
@ -82,6 +83,7 @@
|
|||||||
"unplugin-icons": "0.19.2",
|
"unplugin-icons": "0.19.2",
|
||||||
"unplugin-vue-components": "0.27.4",
|
"unplugin-vue-components": "0.27.4",
|
||||||
"vite": "5.4.1",
|
"vite": "5.4.1",
|
||||||
|
"vite-plugin-monaco-editor": "^1.1.0",
|
||||||
"vite-plugin-progress": "0.0.7",
|
"vite-plugin-progress": "0.0.7",
|
||||||
"vite-plugin-svg-icons": "2.0.1",
|
"vite-plugin-svg-icons": "2.0.1",
|
||||||
"vite-plugin-vue-devtools": "7.3.8",
|
"vite-plugin-vue-devtools": "7.3.8",
|
||||||
|
20
pnpm-lock.yaml
generated
20
pnpm-lock.yaml
generated
@ -44,6 +44,9 @@ importers:
|
|||||||
jsencrypt:
|
jsencrypt:
|
||||||
specifier: ^3.3.2
|
specifier: ^3.3.2
|
||||||
version: 3.3.2
|
version: 3.3.2
|
||||||
|
monaco-editor:
|
||||||
|
specifier: ^0.48.0
|
||||||
|
version: 0.48.0
|
||||||
naive-ui:
|
naive-ui:
|
||||||
specifier: 2.39.0
|
specifier: 2.39.0
|
||||||
version: 2.39.0(vue@3.4.38(typescript@5.5.4))
|
version: 2.39.0(vue@3.4.38(typescript@5.5.4))
|
||||||
@ -147,6 +150,9 @@ importers:
|
|||||||
vite:
|
vite:
|
||||||
specifier: 5.4.1
|
specifier: 5.4.1
|
||||||
version: 5.4.1(@types/node@22.4.1)(sass@1.77.8)
|
version: 5.4.1(@types/node@22.4.1)(sass@1.77.8)
|
||||||
|
vite-plugin-monaco-editor:
|
||||||
|
specifier: ^1.1.0
|
||||||
|
version: 1.1.0(monaco-editor@0.48.0)
|
||||||
vite-plugin-progress:
|
vite-plugin-progress:
|
||||||
specifier: 0.0.7
|
specifier: 0.0.7
|
||||||
version: 0.0.7(vite@5.4.1(@types/node@22.4.1)(sass@1.77.8))
|
version: 0.0.7(vite@5.4.1(@types/node@22.4.1)(sass@1.77.8))
|
||||||
@ -3042,6 +3048,9 @@ packages:
|
|||||||
mlly@1.7.1:
|
mlly@1.7.1:
|
||||||
resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==}
|
resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==}
|
||||||
|
|
||||||
|
monaco-editor@0.48.0:
|
||||||
|
resolution: {integrity: sha512-goSDElNqFfw7iDHMg8WDATkfcyeLTNpBHQpO8incK6p5qZt5G/1j41X0xdGzpIkGojGXM+QiRQyLjnfDVvrpwA==}
|
||||||
|
|
||||||
mrmime@2.0.0:
|
mrmime@2.0.0:
|
||||||
resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==}
|
resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@ -4025,6 +4034,11 @@ packages:
|
|||||||
'@nuxt/kit':
|
'@nuxt/kit':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
vite-plugin-monaco-editor@1.1.0:
|
||||||
|
resolution: {integrity: sha512-IvtUqZotrRoVqwT0PBBDIZPNraya3BxN/bfcNfnxZ5rkJiGcNtO5eAOWWSgT7zullIAEqQwxMU83yL9J5k7gww==}
|
||||||
|
peerDependencies:
|
||||||
|
monaco-editor: '>=0.33.0'
|
||||||
|
|
||||||
vite-plugin-progress@0.0.7:
|
vite-plugin-progress@0.0.7:
|
||||||
resolution: {integrity: sha512-zyvKdcc/X+6hnw3J1HVV1TKrlFKC4Rh8GnDnWG/2qhRXjqytTcM++xZ+SAPnoDsSyWl8O93ymK0wZRgHAoglEQ==}
|
resolution: {integrity: sha512-zyvKdcc/X+6hnw3J1HVV1TKrlFKC4Rh8GnDnWG/2qhRXjqytTcM++xZ+SAPnoDsSyWl8O93ymK0wZRgHAoglEQ==}
|
||||||
engines: {node: '>=14', pnpm: '>=7.0.0'}
|
engines: {node: '>=14', pnpm: '>=7.0.0'}
|
||||||
@ -7270,6 +7284,8 @@ snapshots:
|
|||||||
pkg-types: 1.1.3
|
pkg-types: 1.1.3
|
||||||
ufo: 1.5.4
|
ufo: 1.5.4
|
||||||
|
|
||||||
|
monaco-editor@0.48.0: {}
|
||||||
|
|
||||||
mrmime@2.0.0: {}
|
mrmime@2.0.0: {}
|
||||||
|
|
||||||
ms@2.0.0: {}
|
ms@2.0.0: {}
|
||||||
@ -8335,6 +8351,10 @@ snapshots:
|
|||||||
- rollup
|
- rollup
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
vite-plugin-monaco-editor@1.1.0(monaco-editor@0.48.0):
|
||||||
|
dependencies:
|
||||||
|
monaco-editor: 0.48.0
|
||||||
|
|
||||||
vite-plugin-progress@0.0.7(vite@5.4.1(@types/node@22.4.1)(sass@1.77.8)):
|
vite-plugin-progress@0.0.7(vite@5.4.1(@types/node@22.4.1)(sass@1.77.8)):
|
||||||
dependencies:
|
dependencies:
|
||||||
picocolors: 1.0.1
|
picocolors: 1.0.1
|
||||||
|
227
src/components/common/monaco-editor.vue
Normal file
227
src/components/common/monaco-editor.vue
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { nextTick, onMounted, ref, watch } from 'vue';
|
||||||
|
import * as monaco from 'monaco-editor';
|
||||||
|
import type { editor } from 'monaco-editor';
|
||||||
|
import { useThemeStore } from '@/store/modules/theme';
|
||||||
|
|
||||||
|
defineOptions({ name: 'MonacoEditor' });
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
language?: string;
|
||||||
|
readOnly?: boolean;
|
||||||
|
valueFormat?: string;
|
||||||
|
height?: string;
|
||||||
|
config?: editor.IStandaloneEditorConstructionOptions;
|
||||||
|
lineNumbers?: 'on' | 'off';
|
||||||
|
autoToggleTheme?: boolean;
|
||||||
|
theme?: 'vs-light' | 'vs-dark' | 'hc-black';
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
language: 'json',
|
||||||
|
readOnly: false,
|
||||||
|
valueFormat: 'string',
|
||||||
|
lineNumbers: 'on',
|
||||||
|
theme: 'vs-light',
|
||||||
|
height: '150px',
|
||||||
|
autoToggleTheme: true,
|
||||||
|
config: () => ({
|
||||||
|
selectOnLineNumbers: true,
|
||||||
|
minimap: {
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const value = defineModel<any>('value', { required: true, default: '' });
|
||||||
|
|
||||||
|
const isActive = ref(false);
|
||||||
|
const editContainer = ref<HTMLElement | null>(null);
|
||||||
|
|
||||||
|
let monacoEditor: monaco.editor.IStandaloneCodeEditor | null = null;
|
||||||
|
const { darkMode: isDark } = useThemeStore();
|
||||||
|
|
||||||
|
function handleToggleTheme() {
|
||||||
|
if (isDark) {
|
||||||
|
monaco.editor.setTheme('vs-dark');
|
||||||
|
} else {
|
||||||
|
monaco.editor.setTheme('vs-light');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置文本
|
||||||
|
*
|
||||||
|
* @param text
|
||||||
|
*/
|
||||||
|
function setValue(text: string) {
|
||||||
|
monacoEditor?.setValue(text || '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 光标处插入文本
|
||||||
|
*
|
||||||
|
* @param text
|
||||||
|
*/
|
||||||
|
function insertText(text: string) {
|
||||||
|
// 获取光标位置
|
||||||
|
const position = monacoEditor?.getPosition();
|
||||||
|
// 未获取到光标位置信息
|
||||||
|
if (!position) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 插入
|
||||||
|
monacoEditor?.executeEdits('', [
|
||||||
|
{
|
||||||
|
range: new monaco.Range(position.lineNumber, position.column, position.lineNumber, position.column),
|
||||||
|
text
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
// 设置新的光标位置
|
||||||
|
monacoEditor?.setPosition({ ...position, column: position.column + text.length });
|
||||||
|
// 重新聚焦
|
||||||
|
monacoEditor?.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
monacoEditor = monaco.editor.create(editContainer.value as HTMLElement, {
|
||||||
|
value: getValue(),
|
||||||
|
...props.config,
|
||||||
|
language: props.language,
|
||||||
|
readOnly: props.readOnly,
|
||||||
|
lineNumbers: props.lineNumbers,
|
||||||
|
theme: props.theme,
|
||||||
|
automaticLayout: false
|
||||||
|
});
|
||||||
|
|
||||||
|
// 自动切换主题
|
||||||
|
if (props.autoToggleTheme) {
|
||||||
|
watch(
|
||||||
|
() => isDark,
|
||||||
|
() => {
|
||||||
|
nextTick(() => handleToggleTheme());
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取值
|
||||||
|
function getValue() {
|
||||||
|
// valueFormat 为json 格式,需要转换处理
|
||||||
|
if (props.valueFormat === 'json') {
|
||||||
|
if (value.value) {
|
||||||
|
return JSON.stringify(value.value, null, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value.value ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听值变化
|
||||||
|
monacoEditor.onDidChangeModelContent(() => {
|
||||||
|
const currenValue = monacoEditor?.getValue();
|
||||||
|
|
||||||
|
// valueFormat 为json 格式,需要转换处理
|
||||||
|
if (props.valueFormat === 'json' && currenValue) {
|
||||||
|
value.value = JSON.parse(currenValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
value.value = currenValue ?? '';
|
||||||
|
});
|
||||||
|
|
||||||
|
const decorationsOverviewRuler = document.querySelector('.decorationsOverviewRuler');
|
||||||
|
decorationsOverviewRuler?.removeAttribute('width');
|
||||||
|
decorationsOverviewRuler?.removeAttribute('height');
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => value.value,
|
||||||
|
val => {
|
||||||
|
monacoEditor?.setValue(val || '');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.language,
|
||||||
|
val => {
|
||||||
|
monaco.editor.setModelLanguage(monacoEditor?.getModel() as monaco.editor.ITextModel, val);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
setValue,
|
||||||
|
insertText
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NCard
|
||||||
|
class="h-full"
|
||||||
|
:class="isActive ? 'code-editor-border' : ''"
|
||||||
|
@click="() => (isActive = true)"
|
||||||
|
@mouseout="() => (isActive = false)"
|
||||||
|
>
|
||||||
|
<div ref="editContainer" class="azd-code-editor" :style="{ height: height }" />
|
||||||
|
</NCard>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style></style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.n-card {
|
||||||
|
border: 1px solid rgb(224, 224, 230) !important;
|
||||||
|
|
||||||
|
:deep(.n-card__content) {
|
||||||
|
padding: 6px 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
.n-card {
|
||||||
|
--n-color-modal: rgb(30, 30, 30, 1) !important;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.n-card:hover {
|
||||||
|
border: 1px solid rgb(var(--primary-color)) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-editor-border {
|
||||||
|
border: 1px solid rgb(var(--primary-color)) !important;
|
||||||
|
box-shadow: 0 0 0 2px rgba(30, 94, 253, 0.2) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.azd-code-editor {
|
||||||
|
--n-border-radius: 3px;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 150px;
|
||||||
|
border-radius: var(--n-border-radius);
|
||||||
|
|
||||||
|
:deep(.monaco-editor) {
|
||||||
|
height: 100%;
|
||||||
|
border-radius: var(--n-border-radius) !important;
|
||||||
|
|
||||||
|
.overflow-guard {
|
||||||
|
border-radius: var(--n-border-radius) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.decorationsOverviewRuler,
|
||||||
|
.scrollbar,
|
||||||
|
.slider {
|
||||||
|
border: 0 !important;
|
||||||
|
width: 7px !important;
|
||||||
|
color: rgba(0, 0, 0, 0.5) !important;
|
||||||
|
border-radius: 7px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-decoration {
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -18,6 +18,7 @@ const local: App.I18n.Schema = {
|
|||||||
expandColumn: 'Expand Column',
|
expandColumn: 'Expand Column',
|
||||||
columnSetting: 'Column Setting',
|
columnSetting: 'Column Setting',
|
||||||
config: 'Config',
|
config: 'Config',
|
||||||
|
login: 'Login',
|
||||||
confirm: 'Confirm',
|
confirm: 'Confirm',
|
||||||
save: 'Save',
|
save: 'Save',
|
||||||
delete: 'Delete',
|
delete: 'Delete',
|
||||||
@ -179,7 +180,7 @@ const local: App.I18n.Schema = {
|
|||||||
},
|
},
|
||||||
pwdLogin: {
|
pwdLogin: {
|
||||||
title: 'Password Login',
|
title: 'Password Login',
|
||||||
rememberMe: 'Remember me',
|
rememberMe: 'Remember password',
|
||||||
forgetPassword: 'Forget password?',
|
forgetPassword: 'Forget password?',
|
||||||
register: 'Register',
|
register: 'Register',
|
||||||
otherAccountLogin: 'Other Account Login',
|
otherAccountLogin: 'Other Account Login',
|
||||||
|
@ -18,6 +18,7 @@ const local: App.I18n.Schema = {
|
|||||||
expandColumn: '展开列',
|
expandColumn: '展开列',
|
||||||
columnSetting: '列设置',
|
columnSetting: '列设置',
|
||||||
config: '配置',
|
config: '配置',
|
||||||
|
login: '登录',
|
||||||
confirm: '确认',
|
confirm: '确认',
|
||||||
save: '保存',
|
save: '保存',
|
||||||
delete: '删除',
|
delete: '删除',
|
||||||
@ -179,7 +180,7 @@ const local: App.I18n.Schema = {
|
|||||||
},
|
},
|
||||||
pwdLogin: {
|
pwdLogin: {
|
||||||
title: '密码登录',
|
title: '密码登录',
|
||||||
rememberMe: '记住我',
|
rememberMe: '记住密码',
|
||||||
forgetPassword: '忘记密码?',
|
forgetPassword: '忘记密码?',
|
||||||
register: '注册账号',
|
register: '注册账号',
|
||||||
otherAccountLogin: '其他账号登录',
|
otherAccountLogin: '其他账号登录',
|
||||||
|
@ -76,7 +76,7 @@ export function fetchSynchGenDbList(tableId: CommonType.IdType) {
|
|||||||
|
|
||||||
/** 预览代码 */
|
/** 预览代码 */
|
||||||
export function fetchGetGenPreview(tableId: CommonType.IdType) {
|
export function fetchGetGenPreview(tableId: CommonType.IdType) {
|
||||||
return request<Api.Tool.GenTableDbList>({
|
return request<Api.Tool.GenTablePreview>({
|
||||||
url: `/tool/gen/preview/${tableId}`,
|
url: `/tool/gen/preview/${tableId}`,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import type { AxiosResponse, InternalAxiosRequestConfig } from 'axios';
|
import type { AxiosResponse, InternalAxiosRequestConfig } from 'axios';
|
||||||
import { BACKEND_ERROR_CODE, createFlatRequest } from '@sa/axios';
|
import { BACKEND_ERROR_CODE, createFlatRequest } from '@sa/axios';
|
||||||
import { useAuthStore } from '@/store/modules/auth';
|
import { useAuthStore } from '@/store/modules/auth';
|
||||||
import { $t } from '@/locales';
|
|
||||||
import { localStg, sessionStg } from '@/utils/storage';
|
import { localStg, sessionStg } from '@/utils/storage';
|
||||||
import { getServiceBaseURL } from '@/utils/service';
|
import { getServiceBaseURL } from '@/utils/service';
|
||||||
import { decryptBase64, decryptWithAes, encryptBase64, encryptWithAes, generateAesKey } from '@/utils/crypto';
|
import { decryptBase64, decryptWithAes, encryptBase64, encryptWithAes, generateAesKey } from '@/utils/crypto';
|
||||||
@ -58,7 +57,7 @@ export const request = createFlatRequest<App.Service.Response, RequestInstanceSt
|
|||||||
const responseCode = String(response.data.code);
|
const responseCode = String(response.data.code);
|
||||||
|
|
||||||
function handleLogout() {
|
function handleLogout() {
|
||||||
authStore.logout();
|
authStore.resetStore();
|
||||||
}
|
}
|
||||||
|
|
||||||
function logoutAndCleanup() {
|
function logoutAndCleanup() {
|
||||||
@ -69,31 +68,29 @@ export const request = createFlatRequest<App.Service.Response, RequestInstanceSt
|
|||||||
}
|
}
|
||||||
|
|
||||||
// when the backend response code is in `logoutCodes`, it means the user will be logged out and redirected to login page
|
// when the backend response code is in `logoutCodes`, it means the user will be logged out and redirected to login page
|
||||||
const logoutCodes = import.meta.env.VITE_SERVICE_LOGOUT_CODES?.split(',') || [];
|
// const logoutCodes = import.meta.env.VITE_SERVICE_LOGOUT_CODES?.split(',') || [];
|
||||||
if (logoutCodes.includes(responseCode)) {
|
// if (logoutCodes.includes(responseCode)) {
|
||||||
handleLogout();
|
// handleLogout();
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// when the backend response code is in `modalLogoutCodes`, it means the user will be logged out by displaying a modal
|
// when the backend response code is in `modalLogoutCodes`, it means the user will be logged out by displaying a modal
|
||||||
const modalLogoutCodes = import.meta.env.VITE_SERVICE_MODAL_LOGOUT_CODES?.split(',') || [];
|
const modalLogoutCodes = import.meta.env.VITE_SERVICE_MODAL_LOGOUT_CODES?.split(',') || [];
|
||||||
if (modalLogoutCodes.includes(responseCode) && !request.state.errMsgStack?.includes(response.data.msg)) {
|
if (modalLogoutCodes.includes(responseCode)) {
|
||||||
request.state.errMsgStack = [...(request.state.errMsgStack || []), response.data.msg];
|
request.state.errMsgStack = [...(request.state.errMsgStack || []), response.data.msg];
|
||||||
|
|
||||||
// prevent the user from refreshing the page
|
// prevent the user from refreshing the page
|
||||||
window.addEventListener('beforeunload', handleLogout);
|
window.addEventListener('beforeunload', handleLogout);
|
||||||
|
|
||||||
window.$dialog?.error({
|
window.$dialog?.warning({
|
||||||
title: $t('common.error'),
|
title: '系统提示',
|
||||||
content: response.data.msg,
|
content: '登录状态已过期,您可以继续留在该页面,或者重新登录',
|
||||||
positiveText: $t('common.confirm'),
|
positiveText: '重新登录',
|
||||||
|
negativeText: '取消',
|
||||||
maskClosable: false,
|
maskClosable: false,
|
||||||
closeOnEsc: false,
|
closeOnEsc: false,
|
||||||
onPositiveClick() {
|
onPositiveClick() {
|
||||||
logoutAndCleanup();
|
logoutAndCleanup();
|
||||||
},
|
|
||||||
onClose() {
|
|
||||||
logoutAndCleanup();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -319,7 +319,7 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
|||||||
setIsInitAuthRoute(true);
|
setIsInitAuthRoute(true);
|
||||||
} else {
|
} else {
|
||||||
// if fetch user routes failed, reset store
|
// if fetch user routes failed, reset store
|
||||||
authStore.logout();
|
authStore.resetStore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
src/typings/api/tool.api.d.ts
vendored
3
src/typings/api/tool.api.d.ts
vendored
@ -175,6 +175,9 @@ declare namespace Api {
|
|||||||
Pick<GenTable, 'dataName' | 'tableName' | 'tableComment'> & Common.CommonSearchParams
|
Pick<GenTable, 'dataName' | 'tableName' | 'tableComment'> & Common.CommonSearchParams
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
/** gen table preview */
|
||||||
|
type GenTablePreview = Record<string, string>;
|
||||||
|
|
||||||
/** gen table db list */
|
/** gen table db list */
|
||||||
type GenTableDbList = Common.PaginatingQueryRecord<
|
type GenTableDbList = Common.PaginatingQueryRecord<
|
||||||
Common.CommonRecord<Pick<GenTable, 'tableName' | 'tableComment'>>
|
Common.CommonRecord<Pick<GenTable, 'tableName' | 'tableComment'>>
|
||||||
|
1
src/typings/app.d.ts
vendored
1
src/typings/app.d.ts
vendored
@ -299,6 +299,7 @@ declare namespace App {
|
|||||||
expandColumn: string;
|
expandColumn: string;
|
||||||
columnSetting: string;
|
columnSetting: string;
|
||||||
config: string;
|
config: string;
|
||||||
|
login: string;
|
||||||
confirm: string;
|
confirm: string;
|
||||||
save: string;
|
save: string;
|
||||||
delete: string;
|
delete: string;
|
||||||
|
1
src/typings/components.d.ts
vendored
1
src/typings/components.d.ts
vendored
@ -45,6 +45,7 @@ declare module 'vue' {
|
|||||||
LookForward: typeof import('./../components/custom/look-forward.vue')['default']
|
LookForward: typeof import('./../components/custom/look-forward.vue')['default']
|
||||||
MenuToggler: typeof import('./../components/common/menu-toggler.vue')['default']
|
MenuToggler: typeof import('./../components/common/menu-toggler.vue')['default']
|
||||||
MenuTreeSelect: typeof import('./../components/custom/menu-tree-select.vue')['default']
|
MenuTreeSelect: typeof import('./../components/custom/menu-tree-select.vue')['default']
|
||||||
|
MonacoEditor: typeof import('./../components/common/monaco-editor.vue')['default']
|
||||||
NAlert: typeof import('naive-ui')['NAlert']
|
NAlert: typeof import('naive-ui')['NAlert']
|
||||||
NBreadcrumb: typeof import('naive-ui')['NBreadcrumb']
|
NBreadcrumb: typeof import('naive-ui')['NBreadcrumb']
|
||||||
NBreadcrumbItem: typeof import('naive-ui')['NBreadcrumbItem']
|
NBreadcrumbItem: typeof import('naive-ui')['NBreadcrumbItem']
|
||||||
|
4
src/typings/elegant-router.d.ts
vendored
4
src/typings/elegant-router.d.ts
vendored
@ -161,7 +161,7 @@ declare module "@elegant-router/types" {
|
|||||||
component: `view.${K}`;
|
component: `view.${K}`;
|
||||||
}
|
}
|
||||||
: never;
|
: never;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the center level route
|
* the center level route
|
||||||
*/
|
*/
|
||||||
@ -184,7 +184,7 @@ declare module "@elegant-router/types" {
|
|||||||
children: (CenterLevelRoute<GetChildRouteKey<K>> | LastLevelRoute<GetChildRouteKey<K>>)[];
|
children: (CenterLevelRoute<GetChildRouteKey<K>> | LastLevelRoute<GetChildRouteKey<K>>)[];
|
||||||
}
|
}
|
||||||
: never;
|
: never;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the custom first level route
|
* the custom first level route
|
||||||
*/
|
*/
|
||||||
|
2
src/typings/storage.d.ts
vendored
2
src/typings/storage.d.ts
vendored
@ -40,5 +40,7 @@ declare namespace StorageType {
|
|||||||
layout: UnionKey.ThemeLayoutMode;
|
layout: UnionKey.ThemeLayoutMode;
|
||||||
siderCollapse: boolean;
|
siderCollapse: boolean;
|
||||||
};
|
};
|
||||||
|
/** The login form rember */
|
||||||
|
loginRember: Api.Auth.PwdLoginForm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import { useRouterPush } from '@/hooks/common/router';
|
|||||||
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
|
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
|
||||||
import { useAuthStore } from '@/store/modules/auth';
|
import { useAuthStore } from '@/store/modules/auth';
|
||||||
import { fetchCaptchaCode, fetchTenantList } from '@/service/api';
|
import { fetchCaptchaCode, fetchTenantList } from '@/service/api';
|
||||||
|
import { localStg } from '@/utils/storage';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'PwdLogin'
|
name: 'PwdLogin'
|
||||||
@ -26,8 +27,8 @@ const tenantOption = ref<SelectOption[]>([]);
|
|||||||
|
|
||||||
const model: Api.Auth.PwdLoginForm = reactive({
|
const model: Api.Auth.PwdLoginForm = reactive({
|
||||||
tenantId: '000000',
|
tenantId: '000000',
|
||||||
username: 'admin',
|
username: '',
|
||||||
password: 'admin123'
|
password: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
type RuleKey = Extract<keyof Api.Auth.PwdLoginForm, 'username' | 'password' | 'code' | 'tenantId'>;
|
type RuleKey = Extract<keyof Api.Auth.PwdLoginForm, 'username' | 'password' | 'code' | 'tenantId'>;
|
||||||
@ -48,6 +49,14 @@ const rules = computed<Record<RuleKey, App.Global.FormRule[]>>(() => {
|
|||||||
|
|
||||||
async function handleSubmit() {
|
async function handleSubmit() {
|
||||||
await validate();
|
await validate();
|
||||||
|
// 勾选了需要记住密码设置在 localStorage 中设置记住用户名和密码
|
||||||
|
if (remberMe.value) {
|
||||||
|
const { tenantId, username, password } = model;
|
||||||
|
localStg.set('loginRember', { tenantId, username, password });
|
||||||
|
} else {
|
||||||
|
// 否则移除
|
||||||
|
localStg.remove('loginRember');
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await authStore.login(model);
|
await authStore.login(model);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -57,15 +66,14 @@ async function handleSubmit() {
|
|||||||
|
|
||||||
async function handleFetchTenantList() {
|
async function handleFetchTenantList() {
|
||||||
const { data, error } = await fetchTenantList();
|
const { data, error } = await fetchTenantList();
|
||||||
if (!error) {
|
if (error) return;
|
||||||
tenantEnabled.value = data.tenantEnabled;
|
tenantEnabled.value = data.tenantEnabled;
|
||||||
tenantOption.value = data.voList.map(tenant => {
|
tenantOption.value = data.voList.map(tenant => {
|
||||||
return {
|
return {
|
||||||
label: tenant.companyName,
|
label: tenant.companyName,
|
||||||
value: tenant.tenantId
|
value: tenant.tenantId
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFetchTenantList();
|
handleFetchTenantList();
|
||||||
@ -84,6 +92,15 @@ async function handleFetchCaptchaCode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleFetchCaptchaCode();
|
handleFetchCaptchaCode();
|
||||||
|
|
||||||
|
function handleLoginRember() {
|
||||||
|
const loginRember = localStg.get('loginRember');
|
||||||
|
if (!loginRember) return;
|
||||||
|
remberMe.value = true;
|
||||||
|
Object.assign(model, loginRember);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLoginRember();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -120,8 +137,8 @@ handleFetchCaptchaCode();
|
|||||||
{{ $t('page.login.pwdLogin.forgetPassword') }}
|
{{ $t('page.login.pwdLogin.forgetPassword') }}
|
||||||
</NButton>
|
</NButton>
|
||||||
</div>
|
</div>
|
||||||
<NButton type="primary" size="large" round block :loading="authStore.loginLoading" @click="handleSubmit">
|
<NButton type="primary" size="large" block :loading="authStore.loginLoading" @click="handleSubmit">
|
||||||
{{ $t('common.confirm') }}
|
{{ $t('common.login') }}
|
||||||
</NButton>
|
</NButton>
|
||||||
<div class="flex-y-center justify-between gap-12px">
|
<div class="flex-y-center justify-between gap-12px">
|
||||||
<NButton class="flex-1" block @click="toggleLoginModule('code-login')">
|
<NButton class="flex-1" block @click="toggleLoginModule('code-login')">
|
||||||
|
@ -373,8 +373,13 @@ const { record: showHideRecord } = useDict('sys_show_hide');
|
|||||||
<NDescriptionsItem v-if="currentMenu.menuType === 'C'" label="组件路径">
|
<NDescriptionsItem v-if="currentMenu.menuType === 'C'" label="组件路径">
|
||||||
{{ currentMenu.component }}
|
{{ currentMenu.component }}
|
||||||
</NDescriptionsItem>
|
</NDescriptionsItem>
|
||||||
<NDescriptionsItem label="路由地址">{{ currentMenu.path }}</NDescriptionsItem>
|
<NDescriptionsItem :label="currentMenu.isFrame !== '0' ? '路由地址' : '外链地址'">
|
||||||
<NDescriptionsItem v-if="currentMenu.menuType === 'C'" label="路由参数">
|
{{ currentMenu.path }}
|
||||||
|
</NDescriptionsItem>
|
||||||
|
<NDescriptionsItem
|
||||||
|
v-if="currentMenu.menuType === 'C'"
|
||||||
|
:label="currentMenu.isFrame !== '2' ? '路由参数' : 'iframe 地址'"
|
||||||
|
>
|
||||||
{{ currentMenu.queryParam }}
|
{{ currentMenu.queryParam }}
|
||||||
</NDescriptionsItem>
|
</NDescriptionsItem>
|
||||||
<NDescriptionsItem v-if="currentMenu.menuType !== 'M'" label="权限标识">
|
<NDescriptionsItem v-if="currentMenu.menuType !== 'M'" label="权限标识">
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import { NButton, NPopconfirm, NTooltip } from 'naive-ui';
|
import { NButton, NPopconfirm, NTooltip } from 'naive-ui';
|
||||||
import { useBoolean } from '@sa/hooks';
|
import { useBoolean } from '@sa/hooks';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import { jsonClone } from '@sa/utils';
|
||||||
import {
|
import {
|
||||||
fetchBatchDeleteGenTable,
|
fetchBatchDeleteGenTable,
|
||||||
fetchGenCode,
|
fetchGenCode,
|
||||||
@ -16,12 +17,14 @@ import ButtonIcon from '@/components/custom/button-icon.vue';
|
|||||||
import SvgIcon from '@/components/custom/svg-icon.vue';
|
import SvgIcon from '@/components/custom/svg-icon.vue';
|
||||||
import { useDownload } from '@/hooks/business/download';
|
import { useDownload } from '@/hooks/business/download';
|
||||||
import GenTableSearch from './modules/gen-table-search.vue';
|
import GenTableSearch from './modules/gen-table-search.vue';
|
||||||
import TableImportDrawer from './modules/table-import-drawer.vue';
|
import GenTableImportDrawer from './modules/gen-table-import-drawer.vue';
|
||||||
import GenTableOperateDrawer from './modules/gen-table-operate-drawer.vue';
|
import GenTableOperateDrawer from './modules/gen-table-operate-drawer.vue';
|
||||||
|
import GenTablePreviewDrawer from './modules/gen-table-preview-drawer.vue';
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const { zip } = useDownload();
|
const { zip } = useDownload();
|
||||||
const { bool: importVisible, setTrue: openImportVisible } = useBoolean();
|
const { bool: importVisible, setTrue: openImportVisible } = useBoolean();
|
||||||
|
const { bool: previewVisible, setTrue: openPreviewVisible } = useBoolean();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
columns,
|
columns,
|
||||||
@ -101,7 +104,13 @@ const {
|
|||||||
width: 180,
|
width: 180,
|
||||||
render: row => (
|
render: row => (
|
||||||
<div class="flex-center gap-16px">
|
<div class="flex-center gap-16px">
|
||||||
<ButtonIcon type="primary" text icon="ep:view" tooltipContent="预览" onClick={() => edit(row.tableId!)} />
|
<ButtonIcon
|
||||||
|
type="primary"
|
||||||
|
text
|
||||||
|
icon="ep:view"
|
||||||
|
tooltipContent="预览"
|
||||||
|
onClick={() => handlePreview(row.tableId!)}
|
||||||
|
/>
|
||||||
<ButtonIcon
|
<ButtonIcon
|
||||||
type="primary"
|
type="primary"
|
||||||
text
|
text
|
||||||
@ -191,6 +200,12 @@ function handleImport() {
|
|||||||
openImportVisible();
|
openImportVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handlePreview(id: CommonType.IdType) {
|
||||||
|
const findItem = data.value.find(item => item.tableId === id) || null;
|
||||||
|
editingData.value = jsonClone(findItem);
|
||||||
|
openPreviewVisible();
|
||||||
|
}
|
||||||
|
|
||||||
async function handleGenCode(row?: Api.Tool.GenTable) {
|
async function handleGenCode(row?: Api.Tool.GenTable) {
|
||||||
const tableIds = row?.tableId || checkedRowKeys.value.join(',');
|
const tableIds = row?.tableId || checkedRowKeys.value.join(',');
|
||||||
if (!tableIds || tableIds === '') {
|
if (!tableIds || tableIds === '') {
|
||||||
@ -203,7 +218,7 @@ async function handleGenCode(row?: Api.Tool.GenTable) {
|
|||||||
if (error) return;
|
if (error) return;
|
||||||
window.$message?.success('生成成功');
|
window.$message?.success('生成成功');
|
||||||
} else {
|
} else {
|
||||||
await zip(`/tool/gen/batchGenCode?tableIdStr=${tableIds}`, `ruoyi-${new Date().getTime()}.zip`);
|
zip(`/tool/gen/batchGenCode?tableIdStr=${tableIds}`, `ruoyi-${new Date().getTime()}.zip`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +234,7 @@ getDataNames();
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
|
<div class="min-h-500px flex-col-stretch gap-12px overflow-hidden lt-sm:overflow-auto">
|
||||||
<GenTableSearch
|
<GenTableSearch
|
||||||
v-model:model="searchParams"
|
v-model:model="searchParams"
|
||||||
:options="dataNameOptions"
|
:options="dataNameOptions"
|
||||||
@ -265,15 +280,20 @@ getDataNames();
|
|||||||
:data="data"
|
:data="data"
|
||||||
size="small"
|
size="small"
|
||||||
:flex-height="!appStore.isMobile"
|
:flex-height="!appStore.isMobile"
|
||||||
:scroll-x="962"
|
:scroll-x="1200"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
remote
|
remote
|
||||||
:row-key="row => row.tableId"
|
:row-key="row => row.tableId"
|
||||||
:pagination="mobilePagination"
|
:pagination="mobilePagination"
|
||||||
class="sm:h-full"
|
class="sm:h-full"
|
||||||
/>
|
/>
|
||||||
<TableImportDrawer v-model:visible="importVisible" :options="dataNameOptions" @submitted="getDataByPage" />
|
<GenTableImportDrawer v-model:visible="importVisible" :options="dataNameOptions" @submitted="getDataByPage" />
|
||||||
<GenTableOperateDrawer v-model:visible="drawerVisible" :row-data="editingData" @submitted="getDataByPage" />
|
<GenTableOperateDrawer v-model:visible="drawerVisible" :row-data="editingData" @submitted="getDataByPage" />
|
||||||
|
<GenTablePreviewDrawer
|
||||||
|
v-model:visible="previewVisible"
|
||||||
|
:row-data="editingData"
|
||||||
|
@submitted="() => handleGenCode(editingData!)"
|
||||||
|
/>
|
||||||
</NCard>
|
</NCard>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -7,7 +7,7 @@ import { useTable, useTableOperate } from '@/hooks/common/table';
|
|||||||
import GenTableDbSearch from './gen-table-db-search.vue';
|
import GenTableDbSearch from './gen-table-db-search.vue';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'TableImportDrawer'
|
name: 'GenTableImportDrawer'
|
||||||
});
|
});
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
150
src/views/tool/gen/modules/gen-table-preview-drawer.vue
Normal file
150
src/views/tool/gen/modules/gen-table-preview-drawer.vue
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useLoading } from '@sa/hooks';
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
import { fetchGetGenPreview } from '@/service/api';
|
||||||
|
import MonacoEditor from '@/components/common/monaco-editor.vue';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'GenTablePreviewDrawer'
|
||||||
|
});
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/** the edit row data */
|
||||||
|
rowData?: Api.Tool.GenTable | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
interface Emits {
|
||||||
|
(e: 'submitted'): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
|
const visible = defineModel<boolean>('visible', {
|
||||||
|
default: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const tab = ref('vm/java/domain.java.vm');
|
||||||
|
const previewData = ref<Api.Tool.GenTablePreview>({});
|
||||||
|
const { loading, startLoading, endLoading } = useLoading();
|
||||||
|
|
||||||
|
async function getGenPreview() {
|
||||||
|
if (!props.rowData?.tableId) return;
|
||||||
|
startLoading();
|
||||||
|
const { data, error } = await fetchGetGenPreview(props.rowData?.tableId);
|
||||||
|
if (error) {
|
||||||
|
endLoading();
|
||||||
|
closeDrawer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
previewData.value = data;
|
||||||
|
endLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeDrawer() {
|
||||||
|
visible.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleSubmit() {
|
||||||
|
closeDrawer();
|
||||||
|
emit('submitted');
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(visible, () => {
|
||||||
|
if (visible.value) {
|
||||||
|
previewData.value = {};
|
||||||
|
getGenPreview();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const genMap: Api.Tool.GenTablePreview = {
|
||||||
|
'vm/java/domain.java.vm': 'domain.java',
|
||||||
|
'vm/java/vo.java.vm': 'vo.java',
|
||||||
|
'vm/java/bo.java.vm': 'bo.java',
|
||||||
|
'vm/java/mapper.java.vm': 'mapper.java',
|
||||||
|
'vm/java/service.java.vm': 'service.java',
|
||||||
|
'vm/java/serviceImpl.java.vm': 'serviceImpl.java',
|
||||||
|
'vm/java/controller.java.vm': 'controller.java',
|
||||||
|
'vm/xml/mapper.xml.vm': 'mapper.xml',
|
||||||
|
'vm/sql/sql.vm': 'sql',
|
||||||
|
'vm/soybean/soy.api.ts.vm': 'api.ts',
|
||||||
|
'vm/soybean/typings/soy.api.d.ts.vm': 'type.d.ts',
|
||||||
|
'vm/soybean/soy.index.vue.vm': 'index.vue'
|
||||||
|
};
|
||||||
|
|
||||||
|
function getGenLanguage(name: string) {
|
||||||
|
if (name.endsWith('.java')) {
|
||||||
|
return 'java';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.endsWith('.xml')) {
|
||||||
|
return 'xml';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.endsWith('sql')) {
|
||||||
|
return 'sql';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.endsWith('.ts')) {
|
||||||
|
return 'typescript';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.endsWith('.vue')) {
|
||||||
|
return 'html';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'plaintext';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NDrawer v-model:show="visible" display-directive="show" width="100%">
|
||||||
|
<NDrawerContent title="代码预览" :native-scrollbar="false" closable>
|
||||||
|
<NSpin :show="loading" class="h-full" content-class="h-full">
|
||||||
|
<div class="flex flex-row">
|
||||||
|
<NTabs v-model:value="tab" type="line" placement="left" class="h-full" pane-class="h-full">
|
||||||
|
<NTab v-for="(gen, index) in Object.keys(genMap)" :key="index" :name="gen" display-directive="show">
|
||||||
|
{{ genMap[gen] }}
|
||||||
|
</NTab>
|
||||||
|
</NTabs>
|
||||||
|
<MonacoEditor
|
||||||
|
v-model:value="previewData[tab]"
|
||||||
|
class="tab-pane"
|
||||||
|
read-only
|
||||||
|
:language="getGenLanguage(genMap[tab])"
|
||||||
|
height="calc(100vh - 162px)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</NSpin>
|
||||||
|
<template #footer>
|
||||||
|
<NSpace :size="16">
|
||||||
|
<NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>
|
||||||
|
<NButton :disabled="loading" type="primary" @click="handleSubmit">生成代码</NButton>
|
||||||
|
</NSpace>
|
||||||
|
</template>
|
||||||
|
</NDrawerContent>
|
||||||
|
</NDrawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
:deep(.n-drawer-body-content-wrapper) {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.n-tabs) {
|
||||||
|
width: unset !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.n-tabs.n-tabs--left .n-tabs-bar) {
|
||||||
|
width: 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-pane {
|
||||||
|
transition:
|
||||||
|
color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||||
|
background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||||
|
opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
padding-left: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -106,7 +106,7 @@ async function handleDelete(id: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function edit(id: number) {
|
async function edit(id: number) {
|
||||||
handleEdit('#foreach ($column in $columns) #if($column.javaField.indexOf("id") != -1 || $column.javaField.indexOf("Id") != -1) $column.javaField #end #end', id);
|
handleEdit('#foreach($column in $columns)#if($column.isPk == '1')$column.javaField#end#end', id);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -6,11 +6,11 @@
|
|||||||
*/
|
*/
|
||||||
namespace ${ModuleName} {
|
namespace ${ModuleName} {
|
||||||
/** ${businessName} */
|
/** ${businessName} */
|
||||||
type ${ClassName} = Common.CommonRecord<{
|
type ${BusinessName} = Common.CommonRecord<{
|
||||||
#foreach($column in $columns)
|
#foreach($column in $columns)#if($column.insert || $column.edit)
|
||||||
/** $column.columnComment */
|
/** $column.columnComment */
|
||||||
$column.javaField:#if($column.javaField.indexOf("id") != -1 || $column.javaField.indexOf("Id") != -1) CommonType.IdType; #elseif($column.javaType == 'Long' || $column.javaType == 'Integer' || $column.javaType == 'Double' || $column.javaType == 'Float' || $column.javaType == 'BigDecimal') number; #elseif($column.javaType == 'Boolean') boolean; #else string; #end
|
$column.javaField:#if($column.javaField.indexOf("id") != -1 || $column.javaField.indexOf("Id") != -1) CommonType.IdType; #elseif($column.javaType == 'Long' || $column.javaType == 'Integer' || $column.javaType == 'Double' || $column.javaType == 'Float' || $column.javaType == 'BigDecimal') number; #elseif($column.javaType == 'Boolean') boolean; #else string; #end
|
||||||
#end
|
#end#end
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
/** ${businessName} search params */
|
/** ${businessName} search params */
|
||||||
@ -27,11 +27,11 @@ namespace ${ModuleName} {
|
|||||||
#else
|
#else
|
||||||
#set($comment=$column.columnComment)
|
#set($comment=$column.columnComment)
|
||||||
#end
|
#end
|
||||||
#if($foreach.hasNext) | #end ' ${column.javaField}'
|
#if($foreach.hasNext) |#end '${column.javaField}'
|
||||||
#end
|
#end
|
||||||
#end
|
#end
|
||||||
> &
|
> &
|
||||||
CommonSearchParams
|
Common.CommonSearchParams
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/** ${businessName} list */
|
/** ${businessName} list */
|
||||||
|
Reference in New Issue
Block a user