nsgm-cli 2.1.14 → 2.1.15
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/README.md +49 -26
- package/client/components/ClientProviders.tsx +29 -0
- package/client/components/LanguageSwitcher.tsx +59 -0
- package/client/components/SSRSafeAntdProvider.tsx +24 -0
- package/client/components/SuppressHydrationWarnings.tsx +55 -0
- package/client/layout/index.tsx +82 -126
- package/client/styled/common.ts +0 -1
- package/client/styled/layout/index.ts +218 -104
- package/client/styled/template/manage.ts +88 -1
- package/client/utils/i18n.ts +68 -0
- package/client/utils/menu.tsx +42 -36
- package/client/utils/navigation.ts +58 -0
- package/client/utils/suppressWarnings.ts +32 -0
- package/eslint.config.js +17 -20
- package/generation/client/redux/reducers.ts +1 -1
- package/generation/client/utils/menu.tsx +36 -30
- package/generation/env +3 -0
- package/generation/next.config.js +7 -3
- package/generation/package.json +5 -2
- package/generation/tsconfig.json +6 -19
- package/lib/cli/commands/create.js +1 -1
- package/lib/cli/commands/delete.js +1 -1
- package/lib/cli/commands/init.js +6 -6
- package/lib/cli/utils/prompt.d.ts +1 -1
- package/lib/cli/utils/prompt.js +76 -117
- package/lib/constants.d.ts +8 -1
- package/lib/constants.js +17 -2
- package/lib/generate.js +1 -0
- package/lib/generate_create.js +14 -11
- package/lib/generate_delete.js +86 -9
- package/lib/generate_init.d.ts +6 -0
- package/lib/generate_init.js +125 -5
- package/lib/generators/file-generator.d.ts +48 -0
- package/lib/generators/file-generator.js +455 -0
- package/lib/generators/i18n-generator.d.ts +51 -0
- package/lib/generators/i18n-generator.js +320 -0
- package/lib/generators/page-generator.d.ts +6 -2
- package/lib/generators/page-generator.js +182 -156
- package/lib/generators/resolver-generator.d.ts +6 -4
- package/lib/generators/resolver-generator.js +114 -75
- package/lib/generators/service-generator.d.ts +4 -0
- package/lib/generators/service-generator.js +120 -6
- package/lib/tsconfig.build.tsbuildinfo +1 -1
- package/next-i18next.config.js +18 -0
- package/next.config.js +55 -16
- package/package.json +7 -2
- package/pages/_app.tsx +84 -35
- package/pages/_document.tsx +39 -2
- package/pages/_error.tsx +66 -0
- package/pages/index.tsx +46 -29
- package/pages/login.tsx +58 -33
- package/pages/template/manage.tsx +95 -109
- package/public/locales/en-US/common.json +48 -0
- package/public/locales/en-US/home.json +57 -0
- package/public/locales/en-US/layout.json +22 -0
- package/public/locales/en-US/login.json +13 -0
- package/public/locales/en-US/template.json +42 -0
- package/public/locales/ja-JP/common.json +48 -0
- package/public/locales/ja-JP/home.json +57 -0
- package/public/locales/ja-JP/layout.json +22 -0
- package/public/locales/ja-JP/login.json +13 -0
- package/public/locales/ja-JP/template.json +42 -0
- package/public/locales/zh-CN/common.json +48 -0
- package/public/locales/zh-CN/home.json +57 -0
- package/public/locales/zh-CN/layout.json +22 -0
- package/public/locales/zh-CN/login.json +13 -0
- package/public/locales/zh-CN/template.json +42 -0
- package/server/utils/validation.js +163 -0
- package/types/i18next.d.ts +10 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// 这个文件需要在所有 React 组件加载之前执行
|
|
2
|
+
// 用于抑制 useLayoutEffect 在服务端渲染时的警告
|
|
3
|
+
|
|
4
|
+
if (typeof window === 'undefined') {
|
|
5
|
+
// 服务端环境
|
|
6
|
+
const originalError = console.error
|
|
7
|
+
const originalWarn = console.warn
|
|
8
|
+
|
|
9
|
+
console.error = function (...args) {
|
|
10
|
+
const message = args[0]
|
|
11
|
+
if (
|
|
12
|
+
typeof message === 'string' &&
|
|
13
|
+
(message.includes('useLayoutEffect does nothing on the server') ||
|
|
14
|
+
message.includes('Warning: useLayoutEffect does nothing on the server'))
|
|
15
|
+
) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
originalError.apply(console, args)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
console.warn = function (...args) {
|
|
22
|
+
const message = args[0]
|
|
23
|
+
if (
|
|
24
|
+
typeof message === 'string' &&
|
|
25
|
+
(message.includes('useLayoutEffect does nothing on the server') ||
|
|
26
|
+
message.includes('Warning: useLayoutEffect does nothing on the server'))
|
|
27
|
+
) {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
originalWarn.apply(console, args)
|
|
31
|
+
}
|
|
32
|
+
}
|
package/eslint.config.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const js = require('@eslint/js')
|
|
2
|
-
const typescript = require('@typescript-eslint/eslint-plugin')
|
|
3
|
-
const typescriptParser = require('@typescript-eslint/parser')
|
|
4
|
-
const prettier = require('eslint-plugin-prettier')
|
|
1
|
+
const js = require('@eslint/js')
|
|
2
|
+
const typescript = require('@typescript-eslint/eslint-plugin')
|
|
3
|
+
const typescriptParser = require('@typescript-eslint/parser')
|
|
4
|
+
const prettier = require('eslint-plugin-prettier')
|
|
5
5
|
|
|
6
6
|
module.exports = [
|
|
7
7
|
js.configs.recommended,
|
|
@@ -29,7 +29,7 @@ module.exports = [
|
|
|
29
29
|
},
|
|
30
30
|
plugins: {
|
|
31
31
|
'@typescript-eslint': typescript,
|
|
32
|
-
|
|
32
|
+
prettier: prettier
|
|
33
33
|
},
|
|
34
34
|
rules: {
|
|
35
35
|
'no-console': 'off', // 允许 console 语句用于调试
|
|
@@ -46,14 +46,17 @@ module.exports = [
|
|
|
46
46
|
'prefer-arrow-callback': 'warn',
|
|
47
47
|
'@typescript-eslint/no-var-requires': 'off', // 允许 require
|
|
48
48
|
'@typescript-eslint/no-explicit-any': 'warn', // 警告但不报错
|
|
49
|
-
'@typescript-eslint/no-unused-vars': [
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
'@typescript-eslint/no-unused-vars': [
|
|
50
|
+
'warn',
|
|
51
|
+
{
|
|
52
|
+
argsIgnorePattern: '^_',
|
|
53
|
+
varsIgnorePattern: '^_'
|
|
54
|
+
}
|
|
55
|
+
],
|
|
53
56
|
'@typescript-eslint/no-inferrable-types': 'warn',
|
|
54
57
|
'@typescript-eslint/prefer-optional-chain': 'warn',
|
|
55
58
|
'@typescript-eslint/no-explicit-any': 'off',
|
|
56
|
-
'prettier/prettier': '
|
|
59
|
+
'prettier/prettier': 'off'
|
|
57
60
|
}
|
|
58
61
|
},
|
|
59
62
|
{
|
|
@@ -82,14 +85,14 @@ module.exports = [
|
|
|
82
85
|
},
|
|
83
86
|
plugins: {
|
|
84
87
|
'@typescript-eslint': typescript,
|
|
85
|
-
|
|
88
|
+
prettier: prettier
|
|
86
89
|
},
|
|
87
90
|
rules: {
|
|
88
91
|
'no-console': 'off',
|
|
89
92
|
'no-undef': 'off',
|
|
90
93
|
'no-unused-vars': 'off',
|
|
91
94
|
'@typescript-eslint/no-explicit-any': 'off',
|
|
92
|
-
'prettier/prettier': '
|
|
95
|
+
'prettier/prettier': 'off'
|
|
93
96
|
}
|
|
94
97
|
},
|
|
95
98
|
{
|
|
@@ -113,12 +116,6 @@ module.exports = [
|
|
|
113
116
|
}
|
|
114
117
|
},
|
|
115
118
|
{
|
|
116
|
-
ignores: [
|
|
117
|
-
'node_modules/**',
|
|
118
|
-
'lib/**',
|
|
119
|
-
'.next/**',
|
|
120
|
-
'coverage/**',
|
|
121
|
-
'*.config.js'
|
|
122
|
-
]
|
|
119
|
+
ignores: ['node_modules/**', 'lib/**', '.next/**', 'coverage/**', '*.config.js']
|
|
123
120
|
}
|
|
124
|
-
]
|
|
121
|
+
]
|
|
@@ -1,34 +1,40 @@
|
|
|
1
1
|
import { BookOutlined, SolutionOutlined } from '@ant-design/icons'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
// 统一的菜单配置函数,支持可选的多语言翻译
|
|
5
|
+
export const getMenuConfig = (t?: (key: string) => string) => {
|
|
6
|
+
let key = 1
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
]
|
|
8
|
+
return [
|
|
9
|
+
{
|
|
10
|
+
key: (++key).toString(),
|
|
11
|
+
text: '', // 空目录不显示,为了使用 SolutionOutlined 而不报错
|
|
12
|
+
url: '/',
|
|
13
|
+
icon: <SolutionOutlined rev={undefined} />,
|
|
14
|
+
subMenus: null,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
key: (++key).toString(),
|
|
18
|
+
text: t ? t('layout:layout.menu.introduction') : '介绍',
|
|
19
|
+
url: '/',
|
|
20
|
+
icon: <BookOutlined rev={undefined} />,
|
|
21
|
+
subMenus: null,
|
|
22
|
+
},
|
|
23
|
+
/*{
|
|
24
|
+
key: (++key).toString(),
|
|
25
|
+
text: t ? t('layout:layout.menu.template') : '',
|
|
26
|
+
url: '/template/manage',
|
|
27
|
+
icon: <SolutionOutlined rev={undefined} />,
|
|
28
|
+
subMenus: [
|
|
29
|
+
{
|
|
30
|
+
key: `${key}_1`,
|
|
31
|
+
text: t ? t('layout:layout.menu.template1') : '',
|
|
32
|
+
url: '/template/manage',
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
}*/
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// 默认导出不传翻译函数,使用中文
|
|
40
|
+
export default getMenuConfig()
|
package/generation/env
ADDED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
const { nextConfig } = require('nsgm-cli')
|
|
2
|
+
const { i18n } = require('./next-i18next.config')
|
|
2
3
|
|
|
3
4
|
module.exports = (phase, defaultConfig) => {
|
|
4
|
-
|
|
5
|
+
let configObj = nextConfig(phase, defaultConfig)
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
// 确保国际化配置被正确应用
|
|
8
|
+
configObj.i18n = i18n
|
|
9
|
+
|
|
10
|
+
return configObj
|
|
11
|
+
}
|
package/generation/package.json
CHANGED
package/generation/tsconfig.json
CHANGED
|
@@ -5,25 +5,20 @@
|
|
|
5
5
|
"module": "commonjs",
|
|
6
6
|
"declaration": true,
|
|
7
7
|
"strict": true,
|
|
8
|
-
"lib": [
|
|
9
|
-
"dom",
|
|
10
|
-
"ES2022"
|
|
11
|
-
],
|
|
8
|
+
"lib": ["dom", "ES2022"],
|
|
12
9
|
"esModuleInterop": true,
|
|
13
10
|
"allowJs": true,
|
|
14
11
|
"skipLibCheck": true,
|
|
15
12
|
"forceConsistentCasingInFileNames": true,
|
|
16
13
|
"noEmit": false,
|
|
17
|
-
"moduleResolution": "
|
|
14
|
+
"moduleResolution": "bundler",
|
|
18
15
|
"resolveJsonModule": true,
|
|
19
16
|
"isolatedModules": true,
|
|
20
17
|
"noImplicitAny": false,
|
|
21
18
|
"incremental": true,
|
|
22
19
|
"baseUrl": ".",
|
|
23
20
|
"paths": {
|
|
24
|
-
"@/*": [
|
|
25
|
-
"client/*"
|
|
26
|
-
]
|
|
21
|
+
"@/*": ["client/*"]
|
|
27
22
|
},
|
|
28
23
|
"noUnusedLocals": true,
|
|
29
24
|
"noUnusedParameters": true,
|
|
@@ -31,14 +26,6 @@
|
|
|
31
26
|
"noImplicitReturns": true,
|
|
32
27
|
"noFallthroughCasesInSwitch": true
|
|
33
28
|
},
|
|
34
|
-
"include": [
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
],
|
|
38
|
-
"exclude": [
|
|
39
|
-
"node_modules",
|
|
40
|
-
"**/__tests__/*",
|
|
41
|
-
".next",
|
|
42
|
-
"lib"
|
|
43
|
-
]
|
|
44
|
-
}
|
|
29
|
+
"include": ["client/**/*", "pages/**/*"],
|
|
30
|
+
"exclude": ["node_modules", "**/__tests__/*", ".next", "lib"]
|
|
31
|
+
}
|
|
@@ -47,10 +47,10 @@ exports.createCommand = {
|
|
|
47
47
|
const wizardResult = await utils_1.Prompt.createControllerWizard();
|
|
48
48
|
utils_1.Console.separator();
|
|
49
49
|
utils_1.Console.title('📋 控制器配置确认');
|
|
50
|
+
utils_1.Console.info(`项目目录: ${wizardResult.dictionary}`);
|
|
50
51
|
utils_1.Console.info(`控制器名称: ${wizardResult.controller}`);
|
|
51
52
|
utils_1.Console.info(`功能模块: 完整CRUD + 导入导出 + 批量删除`);
|
|
52
53
|
utils_1.Console.info(`描述: ${wizardResult.description}`);
|
|
53
|
-
utils_1.Console.info(`项目目录: ${wizardResult.dictionary}`);
|
|
54
54
|
utils_1.Console.info(`数据库表: ${wizardResult.includeDatabase ? '是' : '否'}`);
|
|
55
55
|
if (wizardResult.includeDatabase && wizardResult.fields.length > 0) {
|
|
56
56
|
const fieldNames = wizardResult.fields.map((field) => field.name).join(', ');
|
|
@@ -48,9 +48,9 @@ exports.deleteCommand = {
|
|
|
48
48
|
const wizardResult = await utils_1.Prompt.deleteControllerWizard();
|
|
49
49
|
utils_1.Console.separator();
|
|
50
50
|
utils_1.Console.title('📋 删除确认');
|
|
51
|
+
utils_1.Console.info(`项目目录: ${wizardResult.dictionary}`);
|
|
51
52
|
utils_1.Console.info(`控制器名称: ${wizardResult.controller}`);
|
|
52
53
|
utils_1.Console.info(`删除范围: ${wizardResult.action === 'all' ? '所有相关文件' : '指定操作'}`);
|
|
53
|
-
utils_1.Console.info(`项目目录: ${wizardResult.dictionary}`);
|
|
54
54
|
utils_1.Console.info(`删除数据库: ${wizardResult.deleteDatabase ? '是' : '否'}`);
|
|
55
55
|
utils_1.Console.separator();
|
|
56
56
|
const confirmed = await utils_1.Prompt.confirm('确认删除?此操作不可恢复!', false);
|
package/lib/cli/commands/init.js
CHANGED
|
@@ -13,7 +13,7 @@ exports.initCommand = {
|
|
|
13
13
|
options: [
|
|
14
14
|
{
|
|
15
15
|
name: 'dictionary',
|
|
16
|
-
description: '
|
|
16
|
+
description: '项目目录',
|
|
17
17
|
default: '.',
|
|
18
18
|
type: 'string',
|
|
19
19
|
},
|
|
@@ -36,7 +36,7 @@ exports.initCommand = {
|
|
|
36
36
|
const wizardResult = await utils_1.Prompt.initWizard();
|
|
37
37
|
utils_1.Console.separator();
|
|
38
38
|
utils_1.Console.title('📋 项目配置确认');
|
|
39
|
-
utils_1.Console.info(
|
|
39
|
+
utils_1.Console.info(`项目目录: ${wizardResult.projectName}`);
|
|
40
40
|
utils_1.Console.info(`项目描述: ${wizardResult.description}`);
|
|
41
41
|
utils_1.Console.info(`作者: ${wizardResult.author}`);
|
|
42
42
|
utils_1.Console.info(`数据库: ${wizardResult.database ? '是' : '否'}`);
|
|
@@ -92,10 +92,10 @@ exports.initCommand = {
|
|
|
92
92
|
utils_1.Console.box(`项目已成功创建到 ${finalOptions.dictionary} 目录\n\n` +
|
|
93
93
|
`下一步:\n` +
|
|
94
94
|
`1. cd ${finalOptions.dictionary}\n` +
|
|
95
|
-
`2.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
`2. npm run dev\n\n` +
|
|
96
|
+
`默认登录账号: admin/admin123\n` +
|
|
97
|
+
`如需修改密码: npm run generate-password yourNewPassword\n` +
|
|
98
|
+
`然后修改 .env 中的 LOGIN_PASSWORD_HASH`, 'success');
|
|
99
99
|
}
|
|
100
100
|
catch (error) {
|
|
101
101
|
spinner.fail('项目初始化失败');
|
package/lib/cli/utils/prompt.js
CHANGED
|
@@ -90,14 +90,14 @@ class Prompt {
|
|
|
90
90
|
{
|
|
91
91
|
type: 'input',
|
|
92
92
|
name: 'projectName',
|
|
93
|
-
message: '
|
|
93
|
+
message: '项目目录:',
|
|
94
94
|
default: 'my-nsgm-project',
|
|
95
95
|
validate: (input) => {
|
|
96
96
|
if (!input.trim())
|
|
97
|
-
return '
|
|
97
|
+
return '项目目录不能为空';
|
|
98
98
|
// 允许路径格式,包括相对路径和绝对路径
|
|
99
99
|
if (!/^[a-zA-Z0-9\-_./\\]+$/.test(input))
|
|
100
|
-
return '
|
|
100
|
+
return '项目目录只能包含字母、数字、横线、下划线和路径分隔符';
|
|
101
101
|
return true;
|
|
102
102
|
},
|
|
103
103
|
},
|
|
@@ -129,6 +129,17 @@ class Prompt {
|
|
|
129
129
|
console_1.Console.title('📝 创建控制器向导 (包含完整CRUD + 导入导出 + 批量删除功能)');
|
|
130
130
|
console_1.Console.newLine();
|
|
131
131
|
const answers = await inquirer_1.default.prompt([
|
|
132
|
+
{
|
|
133
|
+
type: 'input',
|
|
134
|
+
name: 'dictionary',
|
|
135
|
+
message: '项目目录:',
|
|
136
|
+
default: '.',
|
|
137
|
+
validate: (input) => {
|
|
138
|
+
if (!input.trim())
|
|
139
|
+
return '项目目录不能为空';
|
|
140
|
+
return true;
|
|
141
|
+
},
|
|
142
|
+
},
|
|
132
143
|
{
|
|
133
144
|
type: 'input',
|
|
134
145
|
name: 'controller',
|
|
@@ -147,17 +158,6 @@ class Prompt {
|
|
|
147
158
|
message: '控制器描述:',
|
|
148
159
|
default: (answers) => `${answers.controller} 控制器`,
|
|
149
160
|
},
|
|
150
|
-
{
|
|
151
|
-
type: 'input',
|
|
152
|
-
name: 'dictionary',
|
|
153
|
-
message: '项目目录:',
|
|
154
|
-
default: '.',
|
|
155
|
-
validate: (input) => {
|
|
156
|
-
if (!input.trim())
|
|
157
|
-
return '项目目录不能为空';
|
|
158
|
-
return true;
|
|
159
|
-
},
|
|
160
|
-
},
|
|
161
161
|
{
|
|
162
162
|
type: 'confirm',
|
|
163
163
|
name: 'useCustomFields',
|
|
@@ -193,11 +193,10 @@ class Prompt {
|
|
|
193
193
|
return answers;
|
|
194
194
|
}
|
|
195
195
|
/**
|
|
196
|
-
* 收集字段定义
|
|
196
|
+
* 收集字段定义 (简化版本)
|
|
197
197
|
*/
|
|
198
198
|
static async collectFieldDefinitions() {
|
|
199
199
|
const fields = [];
|
|
200
|
-
let addMore = true;
|
|
201
200
|
// 默认添加ID字段
|
|
202
201
|
fields.push({
|
|
203
202
|
name: 'id',
|
|
@@ -207,97 +206,57 @@ class Prompt {
|
|
|
207
206
|
isPrimaryKey: true,
|
|
208
207
|
isAutoIncrement: true,
|
|
209
208
|
});
|
|
210
|
-
console_1.Console.info('💡
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
{ name: 'varchar - 字符串', value: 'varchar' },
|
|
235
|
-
{ name: 'text - 长文本', value: 'text' },
|
|
236
|
-
{ name: 'integer - 整数', value: 'integer' },
|
|
237
|
-
{ name: 'decimal - 小数', value: 'decimal' },
|
|
238
|
-
{ name: 'boolean - 布尔值', value: 'boolean' },
|
|
239
|
-
{ name: 'date - 日期', value: 'date' },
|
|
240
|
-
{ name: 'datetime - 日期时间', value: 'datetime' },
|
|
241
|
-
{ name: 'timestamp - 时间戳', value: 'timestamp' },
|
|
242
|
-
],
|
|
243
|
-
},
|
|
244
|
-
{
|
|
245
|
-
type: 'input',
|
|
246
|
-
name: 'length',
|
|
247
|
-
message: '字段长度 (可选,数字类型可指定精度):',
|
|
248
|
-
when: (answers) => ['varchar', 'decimal'].includes(answers.type),
|
|
249
|
-
default: (answers) => (answers.type === 'varchar' ? '255' : '10,2'),
|
|
250
|
-
},
|
|
251
|
-
{
|
|
252
|
-
type: 'confirm',
|
|
253
|
-
name: 'required',
|
|
254
|
-
message: '是否必填:',
|
|
255
|
-
default: false,
|
|
256
|
-
},
|
|
257
|
-
{
|
|
258
|
-
type: 'input',
|
|
259
|
-
name: 'comment',
|
|
260
|
-
message: '字段注释:',
|
|
261
|
-
default: (answers) => answers.name,
|
|
262
|
-
},
|
|
263
|
-
{
|
|
264
|
-
type: 'confirm',
|
|
265
|
-
name: 'showInList',
|
|
266
|
-
message: '是否在列表页显示:',
|
|
267
|
-
default: true,
|
|
268
|
-
},
|
|
269
|
-
{
|
|
270
|
-
type: 'confirm',
|
|
271
|
-
name: 'showInForm',
|
|
272
|
-
message: '是否在表单中显示:',
|
|
273
|
-
default: true,
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
type: 'confirm',
|
|
277
|
-
name: 'searchable',
|
|
278
|
-
message: '是否可搜索:',
|
|
279
|
-
default: (answers) => answers.type === 'varchar',
|
|
280
|
-
},
|
|
209
|
+
console_1.Console.info('💡 输入字段信息,输入空白字段名结束添加');
|
|
210
|
+
let fieldIndex = 1;
|
|
211
|
+
while (true) {
|
|
212
|
+
const fieldName = await this.input(`字段${fieldIndex} 名称 (留空结束):`);
|
|
213
|
+
if (!fieldName.trim())
|
|
214
|
+
break;
|
|
215
|
+
// 验证字段名
|
|
216
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(fieldName)) {
|
|
217
|
+
console_1.Console.error('字段名称格式无效,请重新输入');
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
if (fields.some((f) => f.name === fieldName) || ['create_date', 'update_date'].includes(fieldName)) {
|
|
221
|
+
console_1.Console.error('字段名称已存在或为系统保留字段,请重新输入');
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
// 简化的字段类型选择
|
|
225
|
+
const fieldType = await this.select('字段类型:', [
|
|
226
|
+
'varchar',
|
|
227
|
+
'text',
|
|
228
|
+
'integer',
|
|
229
|
+
'decimal',
|
|
230
|
+
'boolean',
|
|
231
|
+
'date',
|
|
232
|
+
'datetime',
|
|
281
233
|
]);
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
length
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
234
|
+
// 只对需要长度的类型询问长度
|
|
235
|
+
let length;
|
|
236
|
+
if (fieldType === 'varchar') {
|
|
237
|
+
length = await this.input('字符串长度:', '255');
|
|
238
|
+
}
|
|
239
|
+
else if (fieldType === 'decimal') {
|
|
240
|
+
length = await this.input('小数精度 (如: 10,2):', '10,2');
|
|
241
|
+
}
|
|
242
|
+
// 简化配置:只询问是否必填和注释
|
|
243
|
+
const required = await this.confirm('是否必填:', true);
|
|
244
|
+
const comment = await this.input('字段注释:', fieldName);
|
|
245
|
+
const field = {
|
|
246
|
+
name: fieldName,
|
|
247
|
+
type: fieldType,
|
|
248
|
+
required,
|
|
249
|
+
comment,
|
|
250
|
+
showInList: true, // 默认在列表显示
|
|
251
|
+
showInForm: true, // 默认在表单显示
|
|
252
|
+
searchable: fieldType === 'varchar', // varchar类型默认可搜索
|
|
253
|
+
};
|
|
254
|
+
// 只有当length有值时才添加
|
|
255
|
+
if (length) {
|
|
256
|
+
field.length = length;
|
|
257
|
+
}
|
|
258
|
+
fields.push(field);
|
|
259
|
+
fieldIndex++;
|
|
301
260
|
}
|
|
302
261
|
// 自动添加系统字段
|
|
303
262
|
fields.push({
|
|
@@ -322,6 +281,17 @@ class Prompt {
|
|
|
322
281
|
console_1.Console.title('🗑️ 删除控制器向导');
|
|
323
282
|
console_1.Console.newLine();
|
|
324
283
|
const answers = await inquirer_1.default.prompt([
|
|
284
|
+
{
|
|
285
|
+
type: 'input',
|
|
286
|
+
name: 'dictionary',
|
|
287
|
+
message: '项目目录:',
|
|
288
|
+
default: '.',
|
|
289
|
+
validate: (input) => {
|
|
290
|
+
if (!input.trim())
|
|
291
|
+
return '项目目录不能为空';
|
|
292
|
+
return true;
|
|
293
|
+
},
|
|
294
|
+
},
|
|
325
295
|
{
|
|
326
296
|
type: 'input',
|
|
327
297
|
name: 'controller',
|
|
@@ -344,17 +314,6 @@ class Prompt {
|
|
|
344
314
|
],
|
|
345
315
|
default: 'all',
|
|
346
316
|
},
|
|
347
|
-
{
|
|
348
|
-
type: 'input',
|
|
349
|
-
name: 'dictionary',
|
|
350
|
-
message: '项目目录:',
|
|
351
|
-
default: '.',
|
|
352
|
-
validate: (input) => {
|
|
353
|
-
if (!input.trim())
|
|
354
|
-
return '项目目录不能为空';
|
|
355
|
-
return true;
|
|
356
|
-
},
|
|
357
|
-
},
|
|
358
317
|
{
|
|
359
318
|
type: 'confirm',
|
|
360
319
|
name: 'deleteDatabase',
|
package/lib/constants.d.ts
CHANGED
|
@@ -13,12 +13,15 @@ declare const publicPathSource = "../public";
|
|
|
13
13
|
declare const publicPath = "./public";
|
|
14
14
|
declare const scriptsPathSource = "../scripts";
|
|
15
15
|
declare const scriptsPath = "./scripts";
|
|
16
|
+
declare const typesPathSource = "../types";
|
|
17
|
+
declare const typesPath = "./types";
|
|
16
18
|
declare const reduxPath = "/redux";
|
|
17
19
|
declare const servicePath = "/service";
|
|
18
20
|
declare const styledPath = "/styled";
|
|
19
21
|
declare const styledLayoutPath = "/layout";
|
|
20
22
|
declare const utilsPath = "/utils";
|
|
21
23
|
declare const layoutPath = "/layout";
|
|
24
|
+
declare const componentsPath = "/components";
|
|
22
25
|
declare const modulesPath = "/modules";
|
|
23
26
|
declare const apisPath = "/apis";
|
|
24
27
|
declare const sqlPath = "/sql";
|
|
@@ -35,6 +38,9 @@ declare const sourceServerPathGeneration: string;
|
|
|
35
38
|
declare const sourcePagesPath: string;
|
|
36
39
|
declare const sourcePublicPath: string;
|
|
37
40
|
declare const sourceScriptsPath: string;
|
|
41
|
+
declare const sourceTypesPath: string;
|
|
42
|
+
declare const projectClientPath: string;
|
|
43
|
+
declare const projectPublicPath: string;
|
|
38
44
|
declare const destClientPath: string;
|
|
39
45
|
declare const destClientReduxPath: string;
|
|
40
46
|
declare const destClientServicePath: string;
|
|
@@ -50,9 +56,10 @@ declare const destServerUtilsPath: string;
|
|
|
50
56
|
declare const destPagesPath: string;
|
|
51
57
|
declare const destPublicPath: string;
|
|
52
58
|
declare const destScriptsPath: string;
|
|
59
|
+
declare const destTypesPath: string;
|
|
53
60
|
declare const destClientUtilsMenuPath: string;
|
|
54
61
|
declare const destClientReduxReducersAllPath: string;
|
|
55
62
|
declare const destPublicHealthCheckPath: string;
|
|
56
63
|
declare const destPackagePath: string;
|
|
57
64
|
declare const destServerRestPath: string;
|
|
58
|
-
export { sourceFolder, destFolder, isLocal, generationPath, clientPathSource, clientPath, serverPathSource, serverPath, pagesPathSource, pagesPath, publicPathSource, publicPath, scriptsPathSource, scriptsPath, reduxPath, servicePath, styledPath, styledLayoutPath, utilsPath, layoutPath, modulesPath, apisPath, sqlPath, utilsMenuPath, reduxReducersPath, slbHealthCheckPath, packagePath, restPath, sourceGenerationPath, sourceClientPath, sourceClientPathGeneration, sourceServerPath, sourceServerPathGeneration, sourcePagesPath, sourcePublicPath, sourceScriptsPath, destClientPath, destClientReduxPath, destClientServicePath, destClientStyledPath, destClientStyledLayoutPath, destClientUtilsPath, destClientLayoutPath, destServerPath, destServerModulesPath, destServerApisPath, destServerSqlPath, destServerUtilsPath, destPagesPath, destPublicPath, destScriptsPath, destClientUtilsMenuPath, destClientReduxReducersAllPath, destPublicHealthCheckPath, destPackagePath, destServerRestPath, mysqlUser, mysqlPassword, mysqlHost, mysqlPort, mysqlDatabase, };
|
|
65
|
+
export { sourceFolder, destFolder, isLocal, generationPath, clientPathSource, clientPath, serverPathSource, serverPath, pagesPathSource, pagesPath, publicPathSource, publicPath, scriptsPathSource, scriptsPath, typesPathSource, typesPath, reduxPath, servicePath, styledPath, styledLayoutPath, utilsPath, layoutPath, componentsPath, modulesPath, apisPath, sqlPath, utilsMenuPath, reduxReducersPath, slbHealthCheckPath, packagePath, restPath, sourceGenerationPath, sourceClientPath, sourceClientPathGeneration, sourceServerPath, sourceServerPathGeneration, sourcePagesPath, sourcePublicPath, sourceScriptsPath, sourceTypesPath, projectClientPath, projectPublicPath, destClientPath, destClientReduxPath, destClientServicePath, destClientStyledPath, destClientStyledLayoutPath, destClientUtilsPath, destClientLayoutPath, destServerPath, destServerModulesPath, destServerApisPath, destServerSqlPath, destServerUtilsPath, destPagesPath, destPublicPath, destScriptsPath, destTypesPath, destClientUtilsMenuPath, destClientReduxReducersAllPath, destPublicHealthCheckPath, destPackagePath, destServerRestPath, mysqlUser, mysqlPassword, mysqlHost, mysqlPort, mysqlDatabase, };
|