nsgm-cli 2.1.20 → 2.1.22
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 +40 -0
- package/client/components/Button.tsx +2 -4
- package/client/components/ClientProviders.tsx +12 -12
- package/client/components/LanguageSwitcher.tsx +26 -26
- package/client/components/SSRSafeAntdProvider.tsx +7 -7
- package/client/components/SuppressHydrationWarnings.tsx +30 -30
- package/client/components/__tests__/Button.test.tsx +12 -12
- package/client/layout/index.tsx +122 -124
- package/client/redux/reducers.ts +2 -2
- package/client/redux/store.ts +24 -24
- package/client/redux/template/manage/actions.ts +40 -40
- package/client/redux/template/manage/reducers.ts +32 -32
- package/client/redux/template/manage/types.ts +19 -19
- package/client/service/template/manage.ts +29 -29
- package/client/styled/common.ts +6 -6
- package/client/styled/layout/index.ts +17 -17
- package/client/styled/template/manage.ts +19 -19
- package/client/utils/common.ts +52 -54
- package/client/utils/cookie.ts +30 -30
- package/client/utils/fetch.ts +111 -111
- package/client/utils/i18n.ts +41 -41
- package/client/utils/menu.tsx +11 -12
- package/client/utils/navigation.ts +22 -22
- package/client/utils/sso.ts +124 -124
- package/client/utils/suppressWarnings.ts +17 -17
- package/generation/client/utils/menu.tsx +0 -1
- package/jest.config.js +4 -4
- package/lib/args.js +19 -19
- package/lib/cli/app.d.ts +1 -1
- package/lib/cli/app.js +2 -2
- package/lib/cli/commands/build.d.ts +1 -1
- package/lib/cli/commands/build.js +9 -9
- package/lib/cli/commands/create.d.ts +1 -1
- package/lib/cli/commands/create.js +36 -36
- package/lib/cli/commands/delete.d.ts +1 -1
- package/lib/cli/commands/delete.js +55 -55
- package/lib/cli/commands/export.d.ts +1 -1
- package/lib/cli/commands/export.js +12 -12
- package/lib/cli/commands/help.d.ts +1 -1
- package/lib/cli/commands/help.js +29 -29
- package/lib/cli/commands/init.d.ts +1 -1
- package/lib/cli/commands/init.js +31 -31
- package/lib/cli/commands/server.d.ts +1 -1
- package/lib/cli/commands/server.js +12 -12
- package/lib/cli/commands/upgrade.d.ts +1 -1
- package/lib/cli/commands/upgrade.js +13 -13
- package/lib/cli/commands/version.d.ts +1 -1
- package/lib/cli/commands/version.js +7 -7
- package/lib/cli/index.d.ts +13 -13
- package/lib/cli/parser.d.ts +1 -1
- package/lib/cli/parser.js +12 -12
- package/lib/cli/registry.d.ts +1 -1
- package/lib/cli/types.d.ts +2 -2
- package/lib/cli/utils/console.d.ts +2 -2
- package/lib/cli/utils/console.js +22 -22
- package/lib/cli/utils/index.d.ts +2 -2
- package/lib/cli/utils/prompt.d.ts +1 -1
- package/lib/cli/utils/prompt.js +98 -98
- package/lib/constants.js +28 -28
- package/lib/generate.d.ts +2 -2
- package/lib/generate.js +19 -19
- package/lib/generate_create.d.ts +1 -1
- package/lib/generate_create.js +38 -38
- package/lib/generate_delete.js +63 -63
- package/lib/generate_init.js +93 -93
- package/lib/generators/base-generator.d.ts +1 -1
- package/lib/generators/base-generator.js +23 -23
- package/lib/generators/file-generator.js +15 -15
- package/lib/generators/generator-factory.d.ts +5 -5
- package/lib/generators/i18n-generator.d.ts +1 -1
- package/lib/generators/i18n-generator.js +127 -127
- package/lib/generators/page-generator.d.ts +1 -1
- package/lib/generators/page-generator.js +25 -25
- package/lib/generators/resolver-generator.d.ts +1 -1
- package/lib/generators/resolver-generator.js +27 -27
- package/lib/generators/schema-generator.d.ts +1 -1
- package/lib/generators/schema-generator.js +4 -4
- package/lib/generators/service-generator.d.ts +1 -1
- package/lib/generators/service-generator.js +29 -29
- package/lib/generators/sql-generator.d.ts +1 -1
- package/lib/generators/sql-generator.js +10 -10
- package/lib/index.js +33 -30
- package/lib/server/csrf.d.ts +3 -3
- package/lib/server/csrf.js +20 -20
- package/lib/server/db.d.ts +1 -1
- package/lib/server/db.js +21 -21
- package/lib/server/graphql.js +26 -26
- package/lib/server/plugins/date.d.ts +1 -1
- package/lib/server/plugins/date.js +6 -6
- package/lib/server/utils/graphql-cache.js +5 -5
- package/lib/tsconfig.build.tsbuildinfo +1 -1
- package/lib/utils/project-config.d.ts +1 -1
- package/lib/utils/project-config.js +20 -20
- package/lib/utils.js +3 -3
- package/next-env.d.ts +1 -0
- package/next.config.js +15 -109
- package/package.json +5 -3
- package/pages/_app.tsx +62 -65
- package/pages/_document.tsx +14 -15
- package/pages/_error.tsx +25 -26
- package/pages/index.tsx +47 -48
- package/pages/login.tsx +64 -64
- package/pages/template/manage.tsx +175 -175
|
@@ -52,17 +52,17 @@ function applyProjectConfig(projectPath, config) {
|
|
|
52
52
|
*/
|
|
53
53
|
function ensureDefaultFeatures(config) {
|
|
54
54
|
console.log(`✅ 项目已配置默认功能栈: Next.js + Styled Components + GraphQL + MySQL + TypeScript + ESLint`);
|
|
55
|
-
console.log(`✅ 数据库配置: ${config.database ?
|
|
56
|
-
console.log(`✅ 包含功能: ${config.features.join(
|
|
55
|
+
console.log(`✅ 数据库配置: ${config.database ? "已启用" : "未启用"}`);
|
|
56
|
+
console.log(`✅ 包含功能: ${config.features.join(", ")}`);
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
59
|
* 更新 package.json 文件
|
|
60
60
|
*/
|
|
61
61
|
function updatePackageJson(projectPath, config) {
|
|
62
|
-
const packageJsonPath = path.join(projectPath,
|
|
62
|
+
const packageJsonPath = path.join(projectPath, "package.json");
|
|
63
63
|
if (fs.existsSync(packageJsonPath)) {
|
|
64
64
|
try {
|
|
65
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath,
|
|
65
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
66
66
|
// 更新基本信息
|
|
67
67
|
packageJson.name = config.projectName;
|
|
68
68
|
packageJson.description = config.description;
|
|
@@ -90,49 +90,49 @@ function updatePackageJson(projectPath, config) {
|
|
|
90
90
|
* 更新 README.md 文件
|
|
91
91
|
*/
|
|
92
92
|
function updateReadme(projectPath, config) {
|
|
93
|
-
const readmePath = path.join(projectPath,
|
|
93
|
+
const readmePath = path.join(projectPath, "README.md");
|
|
94
94
|
if (fs.existsSync(readmePath)) {
|
|
95
95
|
try {
|
|
96
|
-
let readmeContent = fs.readFileSync(readmePath,
|
|
96
|
+
let readmeContent = fs.readFileSync(readmePath, "utf8");
|
|
97
97
|
// 替换项目名称
|
|
98
98
|
readmeContent = readmeContent.replace(/nsgm-cli-project/g, config.projectName);
|
|
99
99
|
// 如果有描述,添加到 README 开头
|
|
100
|
-
if (config.description && config.description !==
|
|
100
|
+
if (config.description && config.description !== "A NSGM fullstack project") {
|
|
101
101
|
const descriptionSection = `# ${config.projectName}\n\n${config.description}\n\n`;
|
|
102
102
|
// 检查是否已经有项目名称标题
|
|
103
|
-
if (readmeContent.startsWith(
|
|
103
|
+
if (readmeContent.startsWith("# ")) {
|
|
104
104
|
// 替换第一行
|
|
105
|
-
const lines = readmeContent.split(
|
|
105
|
+
const lines = readmeContent.split("\n");
|
|
106
106
|
lines[0] = `# ${config.projectName}`;
|
|
107
|
-
if (lines[1] ===
|
|
107
|
+
if (lines[1] === "" && lines[2] && !lines[2].startsWith("#")) {
|
|
108
108
|
lines[2] = config.description;
|
|
109
109
|
}
|
|
110
110
|
else {
|
|
111
|
-
lines.splice(2, 0,
|
|
111
|
+
lines.splice(2, 0, "", config.description);
|
|
112
112
|
}
|
|
113
|
-
readmeContent = lines.join(
|
|
113
|
+
readmeContent = lines.join("\n");
|
|
114
114
|
}
|
|
115
115
|
else {
|
|
116
116
|
readmeContent = descriptionSection + readmeContent;
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
// 添加作者信息
|
|
120
|
-
if (config.author && config.author !==
|
|
120
|
+
if (config.author && config.author !== "Your Name") {
|
|
121
121
|
const authorSection = `\n## 作者\n\n${config.author}\n`;
|
|
122
122
|
readmeContent += authorSection;
|
|
123
123
|
}
|
|
124
124
|
// 添加功能说明
|
|
125
125
|
if (config.features.length > 0) {
|
|
126
126
|
const featureMap = {
|
|
127
|
-
nextjs:
|
|
128
|
-
styled:
|
|
129
|
-
graphql:
|
|
130
|
-
mysql:
|
|
131
|
-
typescript:
|
|
132
|
-
eslint:
|
|
127
|
+
nextjs: "Next.js 全栈框架",
|
|
128
|
+
styled: "Styled Components CSS-in-JS",
|
|
129
|
+
graphql: "GraphQL API",
|
|
130
|
+
mysql: "MySQL 数据库",
|
|
131
|
+
typescript: "TypeScript 强类型支持",
|
|
132
|
+
eslint: "ESLint 代码质量检查",
|
|
133
133
|
};
|
|
134
134
|
const featureNames = config.features.map((feature) => featureMap[feature] || feature);
|
|
135
|
-
const featuresSection = `\n## 技术栈\n\n${featureNames.map((feature) => `- ${feature}`).join(
|
|
135
|
+
const featuresSection = `\n## 技术栈\n\n${featureNames.map((feature) => `- ${feature}`).join("\n")}\n`;
|
|
136
136
|
readmeContent += featuresSection;
|
|
137
137
|
}
|
|
138
138
|
fs.writeFileSync(readmePath, readmeContent);
|
package/lib/utils.js
CHANGED
|
@@ -84,18 +84,18 @@ const handleReplace = ({ regex, replacement, paths }) => {
|
|
|
84
84
|
exports.handleReplace = handleReplace;
|
|
85
85
|
const replaceInFileAll = async (array, index = 0, callback) => {
|
|
86
86
|
if (replaceInFileFlag) {
|
|
87
|
-
console.log(
|
|
87
|
+
console.log("replaceInFileAll", index);
|
|
88
88
|
const arrayLen = array.length;
|
|
89
89
|
if (index < arrayLen) {
|
|
90
90
|
const item = array[index];
|
|
91
91
|
(0, replace_in_file_1.replaceInFile)(item)
|
|
92
92
|
.then((changedFiles) => {
|
|
93
|
-
console.log(
|
|
93
|
+
console.log("Modified files:", changedFiles);
|
|
94
94
|
(0, exports.replaceInFileAll)(array, ++index, callback);
|
|
95
95
|
})
|
|
96
96
|
.catch((error) => {
|
|
97
97
|
if (error) {
|
|
98
|
-
console.error(
|
|
98
|
+
console.error("Error occurred:", error);
|
|
99
99
|
}
|
|
100
100
|
});
|
|
101
101
|
}
|
package/next-env.d.ts
CHANGED
package/next.config.js
CHANGED
|
@@ -40,21 +40,19 @@ module.exports = (phase, defaultConfig, options) => {
|
|
|
40
40
|
prefix = ''
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
// 设置环境变量用于客户端访问
|
|
44
|
+
process.env.NEXT_PUBLIC_VERSION = version
|
|
45
|
+
process.env.NEXT_PUBLIC_PREFIX = prefix
|
|
46
|
+
process.env.NEXT_PUBLIC_PROTOCOL = protocol
|
|
47
|
+
process.env.NEXT_PUBLIC_HOST = host
|
|
48
|
+
process.env.NEXT_PUBLIC_PORT = port
|
|
49
|
+
process.env.NEXT_PUBLIC_ENV = env
|
|
50
|
+
process.env.NEXT_PUBLIC_IS_EXPORT = phase === PHASE_EXPORT ? 'true' : 'false'
|
|
51
|
+
|
|
43
52
|
let configObj = {
|
|
44
53
|
// target: 'serverless',
|
|
45
54
|
// crossOrign: 'anonymous',
|
|
46
55
|
i18n,
|
|
47
|
-
serverRuntimeConfig: {},
|
|
48
|
-
publicRuntimeConfig: {
|
|
49
|
-
version,
|
|
50
|
-
prefix,
|
|
51
|
-
protocol,
|
|
52
|
-
host,
|
|
53
|
-
port,
|
|
54
|
-
env,
|
|
55
|
-
phase,
|
|
56
|
-
isExport: phase === PHASE_EXPORT,
|
|
57
|
-
},
|
|
58
56
|
transpilePackages: [
|
|
59
57
|
'antd',
|
|
60
58
|
'@ant-design',
|
|
@@ -90,114 +88,22 @@ module.exports = (phase, defaultConfig, options) => {
|
|
|
90
88
|
'127.0.0.1',
|
|
91
89
|
'localhost',
|
|
92
90
|
],
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (dev && isServer) {
|
|
96
|
-
const originalWarn = console.warn
|
|
97
|
-
const originalError = console.error
|
|
98
|
-
|
|
99
|
-
console.warn = (...args) => {
|
|
100
|
-
const warnMessage = args[0]
|
|
101
|
-
if (
|
|
102
|
-
typeof warnMessage === 'string' &&
|
|
103
|
-
(warnMessage.includes('useLayoutEffect does nothing on the server') ||
|
|
104
|
-
warnMessage.includes('Warning: useLayoutEffect does nothing on the server'))
|
|
105
|
-
) {
|
|
106
|
-
return
|
|
107
|
-
}
|
|
108
|
-
originalWarn.apply(console, args)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
console.error = (...args) => {
|
|
112
|
-
const errorMessage = args[0]
|
|
113
|
-
if (
|
|
114
|
-
typeof errorMessage === 'string' &&
|
|
115
|
-
(errorMessage.includes('useLayoutEffect does nothing on the server') ||
|
|
116
|
-
errorMessage.includes('Warning: useLayoutEffect does nothing on the server'))
|
|
117
|
-
) {
|
|
118
|
-
return
|
|
119
|
-
}
|
|
120
|
-
originalError.apply(console, args)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// 启用压缩
|
|
125
|
-
if (!dev && !isServer) {
|
|
126
|
-
config.optimization = {
|
|
127
|
-
...config.optimization,
|
|
128
|
-
splitChunks: {
|
|
129
|
-
chunks: 'all',
|
|
130
|
-
cacheGroups: {
|
|
131
|
-
vendor: {
|
|
132
|
-
test: /[\\/]node_modules[\\/]/,
|
|
133
|
-
name: 'vendors',
|
|
134
|
-
chunks: 'all',
|
|
135
|
-
enforce: true,
|
|
136
|
-
},
|
|
137
|
-
antd: {
|
|
138
|
-
test: /[\\/]node_modules[\\/](antd|@ant-design)[\\/]/,
|
|
139
|
-
name: 'antd',
|
|
140
|
-
chunks: 'all',
|
|
141
|
-
priority: 10,
|
|
142
|
-
},
|
|
143
|
-
react: {
|
|
144
|
-
test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
|
|
145
|
-
name: 'react',
|
|
146
|
-
chunks: 'all',
|
|
147
|
-
priority: 10,
|
|
148
|
-
},
|
|
149
|
-
common: {
|
|
150
|
-
name: 'common',
|
|
151
|
-
minChunks: 2,
|
|
152
|
-
chunks: 'all',
|
|
153
|
-
priority: 5,
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
},
|
|
157
|
-
minimize: true,
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// 添加分析工具
|
|
161
|
-
if (process.env.ANALYZE === 'true') {
|
|
162
|
-
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
|
|
163
|
-
config.plugins.push(
|
|
164
|
-
new BundleAnalyzerPlugin({
|
|
165
|
-
analyzerMode: 'static',
|
|
166
|
-
openAnalyzer: false,
|
|
167
|
-
})
|
|
168
|
-
)
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// 优化模块解析
|
|
173
|
-
config.resolve.alias = {
|
|
174
|
-
...config.resolve.alias,
|
|
175
|
-
'@': path.resolve(__dirname, 'client'),
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// 支持 TypeScript 路径映射
|
|
179
|
-
config.resolve.modules = [path.resolve(__dirname, 'client'), 'node_modules']
|
|
180
|
-
|
|
181
|
-
return config
|
|
182
|
-
},
|
|
91
|
+
// 使用 Turbopack(Next.js 16 默认)
|
|
92
|
+
turbopack: {},
|
|
183
93
|
generateBuildId: async () => {
|
|
184
94
|
return 'nsgm-cli-' + version
|
|
185
95
|
},
|
|
186
|
-
exportPathMap: async function (defaultPathMap, { dev, dir, outDir }) {
|
|
187
|
-
if (dev) {
|
|
188
|
-
return defaultPathMap
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return defaultPathMap
|
|
192
|
-
},
|
|
193
96
|
generateEtags: false,
|
|
194
97
|
useFileSystemPublicRoutes: true,
|
|
195
98
|
}
|
|
196
99
|
|
|
197
100
|
if (phase !== PHASE_DEVELOPMENT_SERVER) {
|
|
101
|
+
// 在 Vercel 环境中使用默认的 .next 目录,否则使用 build 目录
|
|
102
|
+
const distDir = process.env.VERCEL ? '.next' : 'build'
|
|
103
|
+
|
|
198
104
|
configObj = {
|
|
199
105
|
...configObj,
|
|
200
|
-
distDir
|
|
106
|
+
distDir,
|
|
201
107
|
assetPrefix: prefix,
|
|
202
108
|
async rewrites() {
|
|
203
109
|
return [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nsgm-cli",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.22",
|
|
4
4
|
"description": "A CLI tool to run Next/Style-components and Graphql/Mysql fullstack project",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -33,7 +33,9 @@
|
|
|
33
33
|
"test:coverage": "jest --coverage",
|
|
34
34
|
"test:watch": "jest --watch",
|
|
35
35
|
"performance": "./scripts/performance-check.sh",
|
|
36
|
-
"generate-password": "node scripts/generate-password-hash.js"
|
|
36
|
+
"generate-password": "node scripts/generate-password-hash.js",
|
|
37
|
+
"vercel-build": "npm run tsbuild && npm run build",
|
|
38
|
+
"vercel-dev": "npm run tsbuild && npm run dev"
|
|
37
39
|
},
|
|
38
40
|
"repository": {
|
|
39
41
|
"type": "git",
|
|
@@ -105,7 +107,7 @@
|
|
|
105
107
|
"lusca": "1.7.0",
|
|
106
108
|
"markdown-it": "14.1.0",
|
|
107
109
|
"mysql2": "3.14.2",
|
|
108
|
-
"next": "
|
|
110
|
+
"next": "16.1.0",
|
|
109
111
|
"next-i18next": "15.3.0",
|
|
110
112
|
"ora": "8.2.0",
|
|
111
113
|
"rc-util": "5.44.4",
|
package/pages/_app.tsx
CHANGED
|
@@ -1,104 +1,104 @@
|
|
|
1
1
|
// 必须在所有其他导入之前执行
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
import
|
|
5
|
-
import { Provider } from
|
|
6
|
-
import { Spin } from
|
|
7
|
-
import { appWithTranslation } from
|
|
8
|
-
import { useRouter } from
|
|
9
|
-
import { useStore } from
|
|
10
|
-
import { Loading } from
|
|
11
|
-
import LayoutComponent from
|
|
12
|
-
import ClientProviders from
|
|
13
|
-
import SuppressHydrationWarnings from
|
|
14
|
-
import SSRSafeAntdProvider from
|
|
15
|
-
import { login } from
|
|
16
|
-
import { getAntdLocale } from
|
|
17
|
-
import { navigateToLogin } from
|
|
18
|
-
import nextI18NextConfig from
|
|
19
|
-
import
|
|
2
|
+
import "@/utils/suppressWarnings";
|
|
3
|
+
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
import { Provider } from "react-redux";
|
|
6
|
+
import { Spin } from "antd";
|
|
7
|
+
import { appWithTranslation } from "next-i18next";
|
|
8
|
+
import { useRouter } from "next/router";
|
|
9
|
+
import { useStore } from "@/redux/store";
|
|
10
|
+
import { Loading } from "@/styled/common";
|
|
11
|
+
import LayoutComponent from "@/layout";
|
|
12
|
+
import ClientProviders from "@/components/ClientProviders";
|
|
13
|
+
import SuppressHydrationWarnings from "@/components/SuppressHydrationWarnings";
|
|
14
|
+
import SSRSafeAntdProvider from "@/components/SSRSafeAntdProvider";
|
|
15
|
+
import { login } from "@/utils/sso";
|
|
16
|
+
import { getAntdLocale } from "@/utils/i18n";
|
|
17
|
+
import { navigateToLogin } from "@/utils/navigation";
|
|
18
|
+
import nextI18NextConfig from "../next-i18next.config.js";
|
|
19
|
+
import "antd/dist/reset.css";
|
|
20
20
|
|
|
21
21
|
const theme = {
|
|
22
22
|
colors: {
|
|
23
|
-
primary:
|
|
23
|
+
primary: "#0070f3",
|
|
24
24
|
},
|
|
25
|
-
}
|
|
25
|
+
};
|
|
26
26
|
|
|
27
27
|
const App = ({ Component, pageProps }) => {
|
|
28
|
-
const store = useStore(pageProps.initialReduxState)
|
|
29
|
-
const router = useRouter()
|
|
30
|
-
const [ssoUser, setSsoUser] = useState(null)
|
|
31
|
-
const [pageLoad, setPageLoad] = useState(false)
|
|
32
|
-
const [loginChecked, setLoginChecked] = useState(false)
|
|
33
|
-
const [mounted, setMounted] = useState(false)
|
|
34
|
-
const [currentLocale, setCurrentLocale] = useState(
|
|
28
|
+
const store = useStore(pageProps.initialReduxState);
|
|
29
|
+
const router = useRouter();
|
|
30
|
+
const [ssoUser, setSsoUser] = useState(null);
|
|
31
|
+
const [pageLoad, setPageLoad] = useState(false);
|
|
32
|
+
const [loginChecked, setLoginChecked] = useState(false);
|
|
33
|
+
const [mounted, setMounted] = useState(false);
|
|
34
|
+
const [currentLocale, setCurrentLocale] = useState("zh-CN");
|
|
35
35
|
|
|
36
36
|
// 检查是否为特殊页面(登录页、错误页)
|
|
37
37
|
// 避免在服务器端访问 router.pathname
|
|
38
38
|
const isSpecialPage =
|
|
39
|
-
Component.displayName ===
|
|
40
|
-
Component.name ===
|
|
41
|
-
Component.displayName ===
|
|
42
|
-
Component.name ===
|
|
39
|
+
Component.displayName === "ErrorPage" ||
|
|
40
|
+
Component.name === "ErrorPage" ||
|
|
41
|
+
Component.displayName === "LoginPage" ||
|
|
42
|
+
Component.name === "LoginPage";
|
|
43
43
|
|
|
44
44
|
// Get Antd locale based on current locale
|
|
45
|
-
const antdLocale = getAntdLocale(currentLocale)
|
|
45
|
+
const antdLocale = getAntdLocale(currentLocale);
|
|
46
46
|
|
|
47
47
|
useEffect(() => {
|
|
48
|
-
setMounted(true)
|
|
48
|
+
setMounted(true);
|
|
49
49
|
// 只在客户端设置当前语言
|
|
50
|
-
if (typeof window !==
|
|
51
|
-
const locale = router.locale ||
|
|
52
|
-
setCurrentLocale(locale)
|
|
50
|
+
if (typeof window !== "undefined") {
|
|
51
|
+
const locale = router.locale || "zh-CN";
|
|
52
|
+
setCurrentLocale(locale);
|
|
53
53
|
}
|
|
54
|
-
}, [router.locale])
|
|
54
|
+
}, [router.locale]);
|
|
55
55
|
|
|
56
56
|
useEffect(() => {
|
|
57
|
-
if (!mounted) return
|
|
57
|
+
if (!mounted) return;
|
|
58
58
|
|
|
59
59
|
// 对于特殊页面,跳过登录检查
|
|
60
60
|
if (isSpecialPage) {
|
|
61
|
-
setLoginChecked(true)
|
|
62
|
-
setPageLoad(true)
|
|
63
|
-
return
|
|
61
|
+
setLoginChecked(true);
|
|
62
|
+
setPageLoad(true);
|
|
63
|
+
return;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
// 检查当前路径是否为登录页或错误页
|
|
67
|
-
const isLoginPage = typeof window !==
|
|
67
|
+
const isLoginPage = typeof window !== "undefined" && window.location.pathname === "/login";
|
|
68
68
|
const isErrorPage =
|
|
69
|
-
typeof window !==
|
|
70
|
-
(window.location.pathname ===
|
|
71
|
-
window.location.pathname ===
|
|
72
|
-
window.location.pathname ===
|
|
69
|
+
typeof window !== "undefined" &&
|
|
70
|
+
(window.location.pathname === "/404" ||
|
|
71
|
+
window.location.pathname === "/500" ||
|
|
72
|
+
window.location.pathname === "/_error");
|
|
73
73
|
|
|
74
74
|
// 如果是登录页或错误页,直接设置加载完成,不进行登录检查
|
|
75
75
|
if (isLoginPage || isErrorPage) {
|
|
76
|
-
setLoginChecked(true)
|
|
77
|
-
setPageLoad(true)
|
|
78
|
-
return
|
|
76
|
+
setLoginChecked(true);
|
|
77
|
+
setPageLoad(true);
|
|
78
|
+
return;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
// 检查是否有登录凭证
|
|
82
|
-
const hasLoginCookie = typeof window !==
|
|
82
|
+
const hasLoginCookie = typeof window !== "undefined" && document.cookie.includes("_cas_nsgm");
|
|
83
83
|
|
|
84
84
|
// 如果没有登录凭证,直接跳转到登录页面(保持当前语言)
|
|
85
|
-
if (!hasLoginCookie && typeof window !==
|
|
86
|
-
navigateToLogin(router)
|
|
87
|
-
return
|
|
85
|
+
if (!hasLoginCookie && typeof window !== "undefined") {
|
|
86
|
+
navigateToLogin(router);
|
|
87
|
+
return;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
// 否则执行登录检查
|
|
91
91
|
login((user: any) => {
|
|
92
92
|
if (user) {
|
|
93
|
-
setSsoUser(user)
|
|
93
|
+
setSsoUser(user);
|
|
94
94
|
}
|
|
95
|
-
setLoginChecked(true)
|
|
96
|
-
})
|
|
95
|
+
setLoginChecked(true);
|
|
96
|
+
});
|
|
97
97
|
|
|
98
98
|
setTimeout(() => {
|
|
99
|
-
setPageLoad(true)
|
|
100
|
-
}, 100)
|
|
101
|
-
}, [mounted, isSpecialPage])
|
|
99
|
+
setPageLoad(true);
|
|
100
|
+
}, 100);
|
|
101
|
+
}, [mounted, isSpecialPage]);
|
|
102
102
|
|
|
103
103
|
return (
|
|
104
104
|
<>
|
|
@@ -130,10 +130,7 @@ const App = ({ Component, pageProps }) => {
|
|
|
130
130
|
</ClientProviders>
|
|
131
131
|
</SSRSafeAntdProvider>
|
|
132
132
|
</>
|
|
133
|
-
)
|
|
134
|
-
}
|
|
133
|
+
);
|
|
134
|
+
};
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
// 如果需要页面级别的数据获取,请在各个页面中使用 getStaticProps 或 getServerSideProps
|
|
138
|
-
|
|
139
|
-
export default appWithTranslation(App, nextI18NextConfig)
|
|
136
|
+
export default appWithTranslation(App, nextI18NextConfig);
|
package/pages/_document.tsx
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import Document, { Html, Head, Main, NextScript, DocumentContext } from
|
|
2
|
-
import
|
|
3
|
-
import { ServerStyleSheet } from 'styled-components'
|
|
1
|
+
import Document, { Html, Head, Main, NextScript, DocumentContext } from "next/document";
|
|
2
|
+
import { ServerStyleSheet } from "styled-components";
|
|
4
3
|
|
|
5
4
|
const MyDocument = (props) => {
|
|
6
5
|
// 从 props 中获取语言信息,如果没有则默认为 zh-CN
|
|
7
|
-
const locale = props.locale ||
|
|
6
|
+
const locale = props.locale || "zh-CN";
|
|
8
7
|
|
|
9
8
|
return (
|
|
10
9
|
<Html lang={locale}>
|
|
@@ -86,31 +85,31 @@ const MyDocument = (props) => {
|
|
|
86
85
|
<NextScript />
|
|
87
86
|
</body>
|
|
88
87
|
</Html>
|
|
89
|
-
)
|
|
90
|
-
}
|
|
88
|
+
);
|
|
89
|
+
};
|
|
91
90
|
|
|
92
91
|
// MyDocument.renderDocument = Document.renderDocument
|
|
93
92
|
|
|
94
93
|
MyDocument.getInitialProps = async (ctx: DocumentContext) => {
|
|
95
|
-
const sheet = new ServerStyleSheet()
|
|
96
|
-
const originalRenderPage = ctx.renderPage
|
|
94
|
+
const sheet = new ServerStyleSheet();
|
|
95
|
+
const originalRenderPage = ctx.renderPage;
|
|
97
96
|
|
|
98
97
|
try {
|
|
99
98
|
ctx.renderPage = () =>
|
|
100
99
|
originalRenderPage({
|
|
101
100
|
enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />),
|
|
102
|
-
})
|
|
101
|
+
});
|
|
103
102
|
|
|
104
|
-
const initialProps = await Document?.getInitialProps(ctx)
|
|
103
|
+
const initialProps = await Document?.getInitialProps(ctx);
|
|
105
104
|
|
|
106
105
|
return {
|
|
107
106
|
...initialProps,
|
|
108
|
-
locale: ctx.locale ||
|
|
107
|
+
locale: ctx.locale || "zh-CN",
|
|
109
108
|
styles: [initialProps.styles, sheet.getStyleElement()],
|
|
110
|
-
}
|
|
109
|
+
};
|
|
111
110
|
} finally {
|
|
112
|
-
sheet.seal()
|
|
111
|
+
sheet.seal();
|
|
113
112
|
}
|
|
114
|
-
}
|
|
113
|
+
};
|
|
115
114
|
|
|
116
|
-
export default MyDocument
|
|
115
|
+
export default MyDocument;
|
package/pages/_error.tsx
CHANGED
|
@@ -1,50 +1,49 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { NextPageContext } from 'next'
|
|
1
|
+
import { Result, Button } from "antd";
|
|
2
|
+
import { NextPageContext } from "next";
|
|
4
3
|
|
|
5
4
|
interface ErrorProps {
|
|
6
|
-
statusCode?: number
|
|
5
|
+
statusCode?: number;
|
|
7
6
|
}
|
|
8
7
|
|
|
9
8
|
function ErrorPage({ statusCode }: ErrorProps) {
|
|
10
9
|
const getErrorMessage = () => {
|
|
11
10
|
if (statusCode === 404) {
|
|
12
|
-
return
|
|
11
|
+
return "页面未找到";
|
|
13
12
|
} else if (statusCode === 500) {
|
|
14
|
-
return
|
|
13
|
+
return "服务器错误";
|
|
15
14
|
}
|
|
16
|
-
return
|
|
17
|
-
}
|
|
15
|
+
return "发生了未知错误";
|
|
16
|
+
};
|
|
18
17
|
|
|
19
18
|
const getErrorTitle = () => {
|
|
20
19
|
if (statusCode === 404) {
|
|
21
|
-
return
|
|
20
|
+
return "404";
|
|
22
21
|
} else if (statusCode === 500) {
|
|
23
|
-
return
|
|
22
|
+
return "500";
|
|
24
23
|
}
|
|
25
|
-
return
|
|
26
|
-
}
|
|
24
|
+
return "错误";
|
|
25
|
+
};
|
|
27
26
|
|
|
28
27
|
return (
|
|
29
28
|
<div
|
|
30
29
|
style={{
|
|
31
|
-
minHeight:
|
|
32
|
-
display:
|
|
33
|
-
alignItems:
|
|
34
|
-
justifyContent:
|
|
35
|
-
padding:
|
|
30
|
+
minHeight: "100vh",
|
|
31
|
+
display: "flex",
|
|
32
|
+
alignItems: "center",
|
|
33
|
+
justifyContent: "center",
|
|
34
|
+
padding: "20px",
|
|
36
35
|
}}
|
|
37
36
|
>
|
|
38
37
|
<Result
|
|
39
|
-
status={statusCode === 404 ?
|
|
38
|
+
status={statusCode === 404 ? "404" : "500"}
|
|
40
39
|
title={getErrorTitle()}
|
|
41
40
|
subTitle={getErrorMessage()}
|
|
42
41
|
extra={
|
|
43
42
|
<Button
|
|
44
43
|
type="primary"
|
|
45
44
|
onClick={() => {
|
|
46
|
-
if (typeof window !==
|
|
47
|
-
window.location.href =
|
|
45
|
+
if (typeof window !== "undefined") {
|
|
46
|
+
window.location.href = "/";
|
|
48
47
|
}
|
|
49
48
|
}}
|
|
50
49
|
>
|
|
@@ -53,14 +52,14 @@ function ErrorPage({ statusCode }: ErrorProps) {
|
|
|
53
52
|
}
|
|
54
53
|
/>
|
|
55
54
|
</div>
|
|
56
|
-
)
|
|
55
|
+
);
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
ErrorPage.getInitialProps = ({ res, err }: NextPageContext) => {
|
|
60
|
-
const statusCode = res ? res.statusCode : err ? err.statusCode : 404
|
|
61
|
-
return { statusCode }
|
|
62
|
-
}
|
|
59
|
+
const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
|
|
60
|
+
return { statusCode };
|
|
61
|
+
};
|
|
63
62
|
|
|
64
|
-
ErrorPage.displayName =
|
|
63
|
+
ErrorPage.displayName = "ErrorPage";
|
|
65
64
|
|
|
66
|
-
export default ErrorPage
|
|
65
|
+
export default ErrorPage;
|