nsgm-cli 2.1.13 → 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.
Files changed (147) hide show
  1. package/README.md +394 -156
  2. package/client/components/Button.tsx +3 -5
  3. package/client/components/ClientProviders.tsx +29 -0
  4. package/client/components/LanguageSwitcher.tsx +59 -0
  5. package/client/components/SSRSafeAntdProvider.tsx +24 -0
  6. package/client/components/SuppressHydrationWarnings.tsx +55 -0
  7. package/client/components/__tests__/Button.test.tsx +10 -10
  8. package/client/layout/index.tsx +153 -185
  9. package/client/redux/reducers.ts +1 -1
  10. package/client/redux/store.ts +2 -1
  11. package/client/redux/template/manage/actions.ts +77 -88
  12. package/client/redux/template/manage/reducers.ts +25 -37
  13. package/client/redux/template/manage/types.ts +1 -1
  14. package/client/service/template/manage.ts +20 -21
  15. package/client/styled/common.ts +12 -14
  16. package/client/styled/layout/index.ts +234 -120
  17. package/client/styled/template/manage.ts +102 -14
  18. package/client/utils/common.ts +23 -21
  19. package/client/utils/cookie.ts +18 -19
  20. package/client/utils/fetch.ts +64 -100
  21. package/client/utils/i18n.ts +68 -0
  22. package/client/utils/menu.tsx +42 -23
  23. package/client/utils/navigation.ts +58 -0
  24. package/client/utils/sso.ts +74 -84
  25. package/client/utils/suppressWarnings.ts +32 -0
  26. package/eslint.config.js +53 -19
  27. package/generation/README.md +25 -6
  28. package/generation/__tests__/example.test.js +41 -0
  29. package/generation/client/redux/reducers.ts +1 -1
  30. package/generation/client/utils/menu.tsx +36 -23
  31. package/generation/env +3 -0
  32. package/generation/env.example +3 -0
  33. package/generation/eslint.config.js +112 -0
  34. package/generation/gitignore +6 -1
  35. package/generation/jest.config.js +40 -0
  36. package/generation/next.config.js +7 -3
  37. package/generation/package.json +28 -4
  38. package/generation/tsconfig.json +6 -19
  39. package/jest.config.js +23 -6
  40. package/lib/args.js +9 -1
  41. package/lib/cli/app.d.ts +28 -0
  42. package/lib/cli/app.js +99 -0
  43. package/lib/cli/commands/build.d.ts +2 -0
  44. package/lib/cli/commands/build.js +29 -0
  45. package/lib/cli/commands/create.d.ts +2 -0
  46. package/lib/cli/commands/create.js +113 -0
  47. package/lib/cli/commands/delete.d.ts +3 -0
  48. package/lib/cli/commands/delete.js +151 -0
  49. package/lib/cli/commands/export.d.ts +2 -0
  50. package/lib/cli/commands/export.js +42 -0
  51. package/lib/cli/commands/help.d.ts +2 -0
  52. package/lib/cli/commands/help.js +42 -0
  53. package/lib/cli/commands/init.d.ts +2 -0
  54. package/lib/cli/commands/init.js +115 -0
  55. package/lib/cli/commands/server.d.ts +3 -0
  56. package/lib/cli/commands/server.js +26 -0
  57. package/lib/cli/commands/upgrade.d.ts +2 -0
  58. package/lib/cli/commands/upgrade.js +38 -0
  59. package/lib/cli/commands/version.d.ts +2 -0
  60. package/lib/cli/commands/version.js +24 -0
  61. package/lib/cli/index.d.ts +16 -0
  62. package/lib/cli/index.js +33 -0
  63. package/lib/cli/parser.d.ts +22 -0
  64. package/lib/cli/parser.js +115 -0
  65. package/lib/cli/registry.d.ts +33 -0
  66. package/lib/cli/registry.js +81 -0
  67. package/lib/cli/types/project.d.ts +10 -0
  68. package/lib/cli/types/project.js +2 -0
  69. package/lib/cli/types.d.ts +31 -0
  70. package/lib/cli/types.js +20 -0
  71. package/lib/cli/utils/console.d.ts +62 -0
  72. package/lib/cli/utils/console.js +148 -0
  73. package/lib/cli/utils/index.d.ts +2 -0
  74. package/lib/cli/utils/index.js +7 -0
  75. package/lib/cli/utils/prompt.d.ts +83 -0
  76. package/lib/cli/utils/prompt.js +327 -0
  77. package/lib/constants.d.ts +65 -0
  78. package/lib/constants.js +177 -0
  79. package/lib/generate.d.ts +25 -3
  80. package/lib/generate.js +98 -621
  81. package/lib/generate_create.d.ts +9 -0
  82. package/lib/generate_create.js +329 -0
  83. package/lib/generate_delete.d.ts +8 -0
  84. package/lib/generate_delete.js +233 -0
  85. package/lib/generate_init.d.ts +56 -0
  86. package/lib/generate_init.js +612 -0
  87. package/lib/generators/base-generator.d.ts +47 -0
  88. package/lib/generators/base-generator.js +92 -0
  89. package/lib/generators/file-generator.d.ts +48 -0
  90. package/lib/generators/file-generator.js +455 -0
  91. package/lib/generators/generator-factory.d.ts +20 -0
  92. package/lib/generators/generator-factory.js +25 -0
  93. package/lib/generators/i18n-generator.d.ts +51 -0
  94. package/lib/generators/i18n-generator.js +320 -0
  95. package/lib/generators/page-generator.d.ts +45 -0
  96. package/lib/generators/page-generator.js +578 -0
  97. package/lib/generators/resolver-generator.d.ts +14 -0
  98. package/lib/generators/resolver-generator.js +342 -0
  99. package/lib/generators/schema-generator.d.ts +7 -0
  100. package/lib/generators/schema-generator.js +57 -0
  101. package/lib/generators/service-generator.d.ts +11 -0
  102. package/lib/generators/service-generator.js +233 -0
  103. package/lib/generators/sql-generator.d.ts +8 -0
  104. package/lib/generators/sql-generator.js +52 -0
  105. package/lib/index.d.ts +1 -1
  106. package/lib/index.js +14 -173
  107. package/lib/server/csrf.js +9 -16
  108. package/lib/server/db.js +6 -7
  109. package/lib/server/graphql.js +5 -6
  110. package/lib/server/plugins/date.js +1 -1
  111. package/lib/server/utils/graphql-cache.js +3 -3
  112. package/lib/tsconfig.build.tsbuildinfo +1 -1
  113. package/lib/utils/project-config.d.ts +5 -0
  114. package/lib/utils/project-config.js +145 -0
  115. package/lib/utils.js +1 -1
  116. package/next-i18next.config.js +18 -0
  117. package/next.config.js +61 -18
  118. package/package.json +16 -8
  119. package/pages/_app.tsx +77 -33
  120. package/pages/_document.tsx +78 -21
  121. package/pages/_error.tsx +66 -0
  122. package/pages/index.tsx +109 -47
  123. package/pages/login.tsx +66 -41
  124. package/pages/template/manage.tsx +162 -151
  125. package/public/fonts/font-awesome.min.css +4 -0
  126. package/public/fonts/fontawesome-webfont.woff +0 -0
  127. package/public/fonts/fontawesome-webfont.woff2 +0 -0
  128. package/public/locales/en-US/common.json +48 -0
  129. package/public/locales/en-US/home.json +57 -0
  130. package/public/locales/en-US/layout.json +22 -0
  131. package/public/locales/en-US/login.json +13 -0
  132. package/public/locales/en-US/template.json +42 -0
  133. package/public/locales/ja-JP/common.json +48 -0
  134. package/public/locales/ja-JP/home.json +57 -0
  135. package/public/locales/ja-JP/layout.json +22 -0
  136. package/public/locales/ja-JP/login.json +13 -0
  137. package/public/locales/ja-JP/template.json +42 -0
  138. package/public/locales/zh-CN/common.json +48 -0
  139. package/public/locales/zh-CN/home.json +57 -0
  140. package/public/locales/zh-CN/layout.json +22 -0
  141. package/public/locales/zh-CN/login.json +13 -0
  142. package/public/locales/zh-CN/template.json +42 -0
  143. package/public/slbhealthcheck.html +1 -1
  144. package/server/apis/template.js +0 -2
  145. package/server/utils/validation.js +163 -0
  146. package/types/i18next.d.ts +10 -0
  147. package/generation/eslintrc.js +0 -16
@@ -0,0 +1,59 @@
1
+ import React, { useEffect, useState } from 'react'
2
+ import { Select } from 'antd'
3
+ import { useRouter } from 'next/router'
4
+ import { GlobalOutlined } from '@ant-design/icons'
5
+
6
+ const { Option } = Select
7
+
8
+ interface LanguageSwitcherProps {
9
+ style?: React.CSSProperties
10
+ size?: 'small' | 'middle' | 'large'
11
+ }
12
+
13
+ const LanguageSwitcher: React.FC<LanguageSwitcherProps> = ({ style, size = 'middle' }) => {
14
+ const router = useRouter()
15
+ const [mounted, setMounted] = useState(false)
16
+ const [currentLocale, setCurrentLocale] = useState('zh-CN')
17
+
18
+ useEffect(() => {
19
+ setMounted(true)
20
+ // 只在客户端获取当前语言
21
+ if (typeof window !== 'undefined' && router.locale) {
22
+ setCurrentLocale(router.locale)
23
+ }
24
+ }, [router.locale])
25
+
26
+ const languages = [
27
+ { code: 'zh-CN', name: '中文', flag: '🇨🇳' },
28
+ { code: 'en-US', name: 'English', flag: '🇺🇸' },
29
+ { code: 'ja-JP', name: '日本語', flag: '🇯🇵' },
30
+ ]
31
+
32
+ const handleLanguageChange = (locale: string) => {
33
+ if (mounted && typeof window !== 'undefined') {
34
+ const { pathname, asPath, query } = router
35
+ router.push({ pathname, query }, asPath, { locale })
36
+ }
37
+ }
38
+
39
+ return (
40
+ <Select
41
+ value={currentLocale}
42
+ onChange={handleLanguageChange}
43
+ style={{ minWidth: 120, ...style }}
44
+ size={size}
45
+ suffixIcon={<GlobalOutlined />}
46
+ placeholder="Language"
47
+ disabled={!mounted}
48
+ >
49
+ {languages.map((language) => (
50
+ <Option key={language.code} value={language.code}>
51
+ <span style={{ marginRight: 8 }}>{language.flag}</span>
52
+ {language.name}
53
+ </Option>
54
+ ))}
55
+ </Select>
56
+ )
57
+ }
58
+
59
+ export default LanguageSwitcher
@@ -0,0 +1,24 @@
1
+ import React from 'react'
2
+ import { ConfigProvider } from 'antd'
3
+
4
+ interface SSRSafeAntdProviderProps {
5
+ children: React.ReactNode
6
+ locale?: any
7
+ }
8
+
9
+ const SSRSafeAntdProvider: React.FC<SSRSafeAntdProviderProps> = ({ children, locale }) => {
10
+ // 在服务端渲染时,我们仍然使用 ConfigProvider,但使用简化的配置
11
+ return (
12
+ <ConfigProvider
13
+ locale={locale}
14
+ theme={{
15
+ // 确保服务端渲染的一致性
16
+ cssVar: false,
17
+ }}
18
+ >
19
+ {children}
20
+ </ConfigProvider>
21
+ )
22
+ }
23
+
24
+ export default SSRSafeAntdProvider
@@ -0,0 +1,55 @@
1
+ import { useEffect } from 'react'
2
+
3
+ // 全局抑制 useLayoutEffect 警告的函数
4
+ const suppressUseLayoutEffectWarnings = () => {
5
+ if (typeof window === 'undefined' && process.env.NODE_ENV === 'development') {
6
+ const originalError = console.error
7
+ const originalWarn = console.warn
8
+
9
+ console.error = (...args) => {
10
+ const errorMessage = args[0]
11
+ if (
12
+ typeof errorMessage === 'string' &&
13
+ (errorMessage.includes('useLayoutEffect does nothing on the server') ||
14
+ errorMessage.includes('Warning: useLayoutEffect does nothing on the server'))
15
+ ) {
16
+ return
17
+ }
18
+ originalError.apply(console, args)
19
+ }
20
+
21
+ console.warn = (...args) => {
22
+ const warnMessage = args[0]
23
+ if (
24
+ typeof warnMessage === 'string' &&
25
+ (warnMessage.includes('useLayoutEffect does nothing on the server') ||
26
+ warnMessage.includes('Warning: useLayoutEffect does nothing on the server'))
27
+ ) {
28
+ return
29
+ }
30
+ originalWarn.apply(console, args)
31
+ }
32
+
33
+ // 返回清理函数
34
+ return () => {
35
+ console.error = originalError
36
+ console.warn = originalWarn
37
+ }
38
+ }
39
+ return undefined
40
+ }
41
+
42
+ // 在模块加载时立即执行
43
+ suppressUseLayoutEffectWarnings()
44
+
45
+ const SuppressHydrationWarnings = () => {
46
+ useEffect(() => {
47
+ // 在客户端也抑制这些警告(以防万一)
48
+ const cleanup = suppressUseLayoutEffectWarnings()
49
+ return cleanup
50
+ }, [])
51
+
52
+ return null
53
+ }
54
+
55
+ export default SuppressHydrationWarnings
@@ -1,15 +1,15 @@
1
1
  // src/components/Button.test.js
2
- import { render, screen, fireEvent } from '@testing-library/react';
3
- import Button from '../Button';
2
+ import { render, screen, fireEvent } from '@testing-library/react'
3
+ import Button from '../Button'
4
4
 
5
5
  test('renders button with text', () => {
6
- render(<Button>Click me</Button>);
7
- expect(screen.getByText('Click me')).toBeInTheDocument();
8
- });
6
+ render(<Button>Click me</Button>)
7
+ expect(screen.getByText('Click me')).toBeInTheDocument()
8
+ })
9
9
 
10
10
  test('calls onClick when clicked', () => {
11
- const handleClick = jest.fn();
12
- render(<Button onClick={handleClick}>Click me</Button>);
13
- fireEvent.click(screen.getByText('Click me'));
14
- expect(handleClick).toHaveBeenCalledTimes(1);
15
- });
11
+ const handleClick = jest.fn()
12
+ render(<Button onClick={handleClick}>Click me</Button>)
13
+ fireEvent.click(screen.getByText('Click me'))
14
+ expect(handleClick).toHaveBeenCalledTimes(1)
15
+ })
@@ -1,110 +1,46 @@
1
1
  import React, { useEffect, useState } from 'react'
2
- import { Layout, Menu, Breadcrumb, Image, Select, Dropdown, Space, Tooltip } from 'antd'
3
- import { Container } from '@/styled/layout'
4
- import styled from 'styled-components'
2
+ import { Layout, Menu, Dropdown, Space } from 'antd'
3
+ import {
4
+ Container,
5
+ FlexLayout,
6
+ StyledSider,
7
+ SideMenu,
8
+ ContentLayout,
9
+ StyledHeader,
10
+ StyledBreadcrumb,
11
+ StyledContent,
12
+ } from '@/styled/layout'
5
13
  import { useRouter } from 'next/router'
6
14
  import _ from 'lodash'
7
- import menuConfig from '@/utils/menu'
8
- import { logout } from '@/utils/sso'
15
+ import menuConfig, { getMenuConfig } from '@/utils/menu'
9
16
  import getConfig from 'next/config'
10
- import { LogoutOutlined, SettingOutlined, BellOutlined, UserOutlined } from '@ant-design/icons'
17
+ import { LogoutOutlined } from '@ant-design/icons'
18
+ import LanguageSwitcher from '@/components/LanguageSwitcher'
19
+ import { useTranslation } from 'next-i18next'
20
+ import { navigateToLogin } from '@/utils/navigation'
21
+
22
+ interface SubMenuItem {
23
+ key: string
24
+ text: string
25
+ url: string
26
+ }
11
27
 
12
- const { Option } = Select
13
- const { SubMenu } = Menu
14
- const { Header, Content, Sider } = Layout
28
+ interface MenuItem {
29
+ key: string
30
+ text: string
31
+ url: string
32
+ icon?: React.ReactNode
33
+ subMenus?: SubMenuItem[]
34
+ }
15
35
 
16
36
  const nextConfig = getConfig()
17
37
  const { publicRuntimeConfig } = nextConfig
18
38
  const { prefix } = publicRuntimeConfig
19
39
 
20
- // styled-components
21
- const FlexLayout = styled(Layout)`
22
- display: flex;
23
- flex: 1;
24
- `
25
- const StyledSider = styled(Sider)`
26
- display: flex;
27
- flex-direction: column;
28
- box-shadow: 2px 0 8px -4px rgba(0, 0, 0, 0.1);
29
- z-index: 5;
30
- position: relative;
31
- `
32
-
33
- const SideMenu = styled(Menu)`
34
- height: 100%;
35
- border-right: 0;
36
- padding: 8px 0;
37
- `
38
-
39
- const ContentLayout = styled(Layout)`
40
- display: flex;
41
- flex-direction: column;
42
- flex: 1;
43
- background: #f5f7fa;
44
- position: relative;
45
- z-index: 1;
46
- `
47
- const StyledHeader = styled(Header)`
48
- display: flex;
49
- align-items: center;
50
- padding: 0 24px;
51
- box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
52
- z-index: 11;
53
-
54
- .logo {
55
- margin-right: 24px;
56
- }
57
-
58
- .main-menu {
59
- flex: 1;
60
- }
61
-
62
- .user-actions {
63
- display: flex;
64
- align-items: center;
65
-
66
- .action-icon {
67
- font-size: 18px;
68
- color: rgba(255, 255, 255, 0.85);
69
- cursor: pointer;
70
- padding: 0 8px;
71
- transition: color 0.3s;
72
-
73
- &:hover {
74
- color: #fff;
75
- }
76
- }
77
-
78
- .user-dropdown {
79
- cursor: pointer;
80
- padding: 0 8px;
81
-
82
- .username {
83
- color: rgba(255, 255, 255, 0.85);
84
- margin-left: 8px;
85
- }
86
- }
87
- }
88
- `
89
- const StyledBreadcrumb = styled(Breadcrumb)`
90
- margin: 16px 24px;
91
- font-size: 14px;
92
- `
93
- const StyledContent = styled(Content)`
94
- margin: 0 24px 24px;
95
- padding: 24px;
96
- background: #fff;
97
- border-radius: 4px;
98
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
99
- min-height: calc(100vh - 180px);
100
- position: relative;
101
- z-index: 1;
102
- `
103
-
104
40
  const getLocationKey = () => {
105
- let result = {
41
+ const result = {
106
42
  topMenu: '1',
107
- slideMenu: '0'
43
+ slideMenu: '0',
108
44
  }
109
45
 
110
46
  if (typeof window !== 'undefined') {
@@ -123,13 +59,11 @@ const getLocationKey = () => {
123
59
  locationStr = locationStr.split(prefix)[1]
124
60
  }
125
61
 
126
- // console.log('locationStr', locationStr)
127
-
128
- _.each(menuConfig, (item, index) => {
62
+ _.each(menuConfig, (item) => {
129
63
  const { key, url, subMenus } = item
130
64
 
131
65
  if (subMenus) {
132
- _.each(subMenus, (subItem, subIndex) => {
66
+ _.each(subMenus, (subItem: MenuItem) => {
133
67
  const { key: subKey, url: subUrl } = subItem
134
68
 
135
69
  if (locationStr === subUrl.split('?')[0]) {
@@ -142,6 +76,7 @@ const getLocationKey = () => {
142
76
 
143
77
  return false
144
78
  }
79
+ return true
145
80
  })
146
81
  } else {
147
82
  if (url && locationStr === url.split('?')[0]) {
@@ -149,17 +84,16 @@ const getLocationKey = () => {
149
84
  return false
150
85
  }
151
86
  }
87
+ return true
152
88
  })
153
89
  }
154
90
  }
155
91
  }
156
- // console.log('result', result)
157
92
  return result
158
93
  }
159
94
 
160
95
  const routerPush = (router: any, url: string) => {
161
- // console.log('routerPush', url)
162
- if (router && url) {
96
+ if (router && url && typeof window !== 'undefined') {
163
97
  if (prefix && url.indexOf(prefix) === -1) {
164
98
  url = prefix + url
165
99
  }
@@ -168,12 +102,35 @@ const routerPush = (router: any, url: string) => {
168
102
  }
169
103
 
170
104
  const LayoutComponent = ({ user, children }) => {
105
+ const { t } = useTranslation(['layout', 'common'])
171
106
  const router = useRouter()
172
107
  const [topMenuKey, setTopMenuKey] = useState('1')
173
108
  const [sliderMenuKey, setSliderMenuKey] = useState('1')
174
109
  const [collapsed, setCollapsed] = useState(false)
110
+ const [mounted, setMounted] = useState(false)
111
+
112
+ useEffect(() => {
113
+ setMounted(true)
114
+ }, [])
175
115
 
176
- // console.log('topMenuKey: ' + topMenuKey, ', sliderMenuKey: ' + sliderMenuKey, user)
116
+ // 使用翻译后的菜单配置
117
+ const translatedMenuConfig = getMenuConfig(t)
118
+
119
+ // 自定义退出登录函数,保持语言设置
120
+ const handleLogout = () => {
121
+ if (!mounted || typeof window === 'undefined') return
122
+
123
+ // 删除登录相关的 cookie
124
+ const deleteCookie = (name: string) => {
125
+ document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`
126
+ }
127
+
128
+ deleteCookie('_cas_nsgm')
129
+ deleteCookie('_cas_nsgm_user')
130
+
131
+ // 跳转到登录页面,保持当前语言
132
+ navigateToLogin(router)
133
+ }
177
134
 
178
135
  useEffect(() => {
179
136
  const { topMenu, slideMenu } = getLocationKey()
@@ -184,23 +141,25 @@ const LayoutComponent = ({ user, children }) => {
184
141
  const menuItems: any = []
185
142
  const menuItemsVertical: any = []
186
143
 
187
- _.each(menuConfig, (item, index) => {
144
+ _.each(translatedMenuConfig, (item) => {
188
145
  const { key, text, url, icon, subMenus } = item
189
146
 
190
- if (key) {
147
+ if (key && text && url) {
191
148
  const menuObj = {
192
149
  label: text,
193
150
  key,
194
151
  onClick: () => {
195
- routerPush(router, url)
196
- setTopMenuKey(key)
152
+ if (mounted) {
153
+ routerPush(router, url)
154
+ setTopMenuKey(key)
197
155
 
198
- if (subMenus) {
199
- setSliderMenuKey('1')
200
- } else {
201
- setSliderMenuKey('0')
156
+ if (subMenus) {
157
+ setSliderMenuKey('1')
158
+ } else {
159
+ setSliderMenuKey('0')
160
+ }
202
161
  }
203
- }
162
+ },
204
163
  }
205
164
 
206
165
  menuItems.push(menuObj)
@@ -209,51 +168,57 @@ const LayoutComponent = ({ user, children }) => {
209
168
  if (subMenus) {
210
169
  const subMenusChildren: any = []
211
170
 
212
- _.each(subMenus, (subItem, subIndex) => {
171
+ _.each(subMenus, (subItem: MenuItem) => {
213
172
  const { key: subKey, text: subText, url: subUrl } = subItem
214
173
 
215
- const subMenusChildrenObj = {
216
- key: 'slider_' + subKey,
217
- label: subText,
218
- onClick: () => {
219
- routerPush(router, subUrl)
220
-
221
- const subKeyArr = subKey.split('_')
222
- const subKeyArrLen = subKeyArr.length
174
+ if (subKey && subText && subUrl) {
175
+ const subMenusChildrenObj = {
176
+ key: `slider_${subKey}`,
177
+ label: subText,
178
+ onClick: () => {
179
+ if (mounted) {
180
+ routerPush(router, subUrl)
223
181
 
224
- // console.log(subKeyArr, subKeyArrLen)
182
+ const subKeyArr = subKey.split('_')
183
+ const subKeyArrLen = subKeyArr.length
225
184
 
226
- if (subKeyArrLen >= 1) setTopMenuKey(subKeyArr[0])
227
- if (subKeyArrLen >= 2) setSliderMenuKey(subKeyArr[1])
185
+ if (subKeyArrLen >= 1) setTopMenuKey(subKeyArr[0])
186
+ if (subKeyArrLen >= 2) setSliderMenuKey(subKeyArr[1])
187
+ }
188
+ },
228
189
  }
229
- }
230
190
 
231
- subMenusChildren.push(subMenusChildrenObj)
191
+ subMenusChildren.push(subMenusChildrenObj)
192
+ }
232
193
  })
233
194
 
234
- const subMenuObjVertical = {
235
- key: 'slider_' + key,
236
- icon,
237
- label: text,
238
- onTitleClick: () => {
239
- setTopMenuKey(key)
240
- setSliderMenuKey('1')
241
- },
242
- children: subMenusChildren
243
- }
195
+ if (key && text && icon) {
196
+ const subMenuObjVertical = {
197
+ key: `slider_${key}`,
198
+ icon,
199
+ label: text,
200
+ onTitleClick: () => {
201
+ setTopMenuKey(key)
202
+ setSliderMenuKey('1')
203
+ },
204
+ children: subMenusChildren,
205
+ }
244
206
 
245
- menuItemsVertical.push(subMenuObjVertical)
207
+ menuItemsVertical.push(subMenuObjVertical)
208
+ }
246
209
  } else {
247
- if (key) {
210
+ if (key && text && url) {
248
211
  const menuObjVertical = {
249
212
  label: text,
250
213
  icon,
251
- key: 'slider_' + key + '_0',
214
+ key: `slider_${key}_0`,
252
215
  onClick: () => {
253
- routerPush(router, url)
254
- setTopMenuKey(key)
255
- setSliderMenuKey('0')
256
- }
216
+ if (mounted) {
217
+ routerPush(router, url)
218
+ setTopMenuKey(key)
219
+ setSliderMenuKey('0')
220
+ }
221
+ },
257
222
  }
258
223
 
259
224
  menuItemsVertical.push(menuObjVertical)
@@ -266,7 +231,7 @@ const LayoutComponent = ({ user, children }) => {
266
231
  <Container>
267
232
  <StyledHeader>
268
233
  <div className="logo">
269
- <Image width={120} src={prefix + "/images/zhizuotu_1.png"} preview={false} />
234
+ <span className="logo-text">NSGM</span>
270
235
  </div>
271
236
  <Menu
272
237
  theme="dark"
@@ -278,39 +243,40 @@ const LayoutComponent = ({ user, children }) => {
278
243
  />
279
244
  <div className="user-actions">
280
245
  <Space size={20} align="center">
281
- <Tooltip title="通知">
246
+ <LanguageSwitcher size="small" />
247
+ {/* <Tooltip title="通知">
282
248
  <BellOutlined className="action-icon" />
283
249
  </Tooltip>
284
250
  <Tooltip title="设置">
285
251
  <SettingOutlined className="action-icon" />
286
- </Tooltip>
252
+ </Tooltip> */}
287
253
  <Dropdown
288
254
  menu={{
289
255
  items: [
290
- {
291
- key: '1',
292
- icon: <UserOutlined />,
293
- label: '个人中心',
294
- },
295
- {
296
- key: '2',
297
- icon: <SettingOutlined />,
298
- label: '账户设置',
299
- },
256
+ // {
257
+ // key: '1',
258
+ // icon: <UserOutlined />,
259
+ // label: t('layout:layout.userActions.profile'),
260
+ // },
261
+ // {
262
+ // key: '2',
263
+ // icon: <SettingOutlined />,
264
+ // label: t('layout:layout.userActions.settings'),
265
+ // },
300
266
  {
301
267
  type: 'divider',
302
268
  },
303
269
  {
304
270
  key: '3',
305
271
  icon: <LogoutOutlined />,
306
- label: '退出登录',
307
- onClick: () => logout(),
272
+ label: t('layout:layout.userActions.logout'),
273
+ onClick: () => handleLogout(),
308
274
  },
309
275
  ],
310
276
  }}
311
277
  >
312
278
  <Space className="user-dropdown">
313
- <span className="username">{user?.displayName || '用户'}</span>
279
+ <span className="username">{user?.displayName || t('layout:layout.userActions.user')}</span>
314
280
  </Space>
315
281
  </Dropdown>
316
282
  </Space>
@@ -329,39 +295,41 @@ const LayoutComponent = ({ user, children }) => {
329
295
  mode="inline"
330
296
  defaultSelectedKeys={['slider_1_0']}
331
297
  defaultOpenKeys={['slider_1']}
332
- selectedKeys={['slider_' + topMenuKey + '_' + sliderMenuKey]}
333
- openKeys={['slider_' + topMenuKey]}
298
+ selectedKeys={[`slider_${topMenuKey}_${sliderMenuKey}`]}
299
+ openKeys={[`slider_${topMenuKey}`]}
334
300
  items={menuItemsVertical}
335
301
  className="side-menu"
336
302
  />
337
303
  </div>
338
304
  </StyledSider>
339
- <ContentLayout className="content-layout">
340
- <StyledBreadcrumb>
341
- {_.map(menuConfig, (item, index) => {
342
- const { key, text, subMenus } = item
343
-
344
- if (subMenus) {
345
- let subContent: any = []
346
- _.each(subMenus, (subItem, subIndex) => {
347
- const { key: subKey, text: subText } = subItem
348
- if (subKey === topMenuKey + '_' + sliderMenuKey) {
349
- subContent.push(<Breadcrumb.Item key={'breadcrumb' + subIndex}>{text}</Breadcrumb.Item>)
350
- subContent.push(<Breadcrumb.Item key={'breadcrumb' + subIndex + '_sub'}>{subText}</Breadcrumb.Item>)
351
- return false
305
+ <ContentLayout collapsed={collapsed} className="content-layout">
306
+ <StyledBreadcrumb
307
+ items={_.compact(
308
+ _.flatMap(translatedMenuConfig, (item, index) => {
309
+ const { key, text, subMenus } = item
310
+
311
+ if (subMenus) {
312
+ const subItems: any = []
313
+ _.each(subMenus, (subItem: MenuItem, subIndex: number) => {
314
+ const { key: subKey, text: subText } = subItem
315
+ if (subKey === `${topMenuKey}_${sliderMenuKey}`) {
316
+ subItems.push({ title: text, key: `breadcrumb${subIndex}` })
317
+ subItems.push({ title: subText, key: `breadcrumb${subIndex}_sub` })
318
+ return false
319
+ }
320
+ return true
321
+ })
322
+ return subItems
323
+ } else {
324
+ if (key && key === topMenuKey) {
325
+ return { title: text, key: `breadcrumb${index}` }
352
326
  }
353
- })
354
- return subContent
355
- } else {
356
- if (key && key === topMenuKey) {
357
- return <Breadcrumb.Item key={'breadcrumb' + index}>{text}</Breadcrumb.Item>
358
327
  }
359
- }
360
- })}
361
- </StyledBreadcrumb>
362
- <StyledContent>
363
- {children}
364
- </StyledContent>
328
+ return null
329
+ })
330
+ )}
331
+ />
332
+ <StyledContent>{children}</StyledContent>
365
333
  </ContentLayout>
366
334
  </FlexLayout>
367
335
  </Container>
@@ -2,4 +2,4 @@ import { templateManageReducer } from './template/manage/reducers'
2
2
 
3
3
  export default {
4
4
  templateManage: templateManageReducer,
5
- }
5
+ }
@@ -16,6 +16,7 @@ if (reducersKeysLen > 0) {
16
16
  export type RootState = ReturnType<typeof combineReducer>
17
17
 
18
18
  // 创建一个临时 store 实例来获取正确的 dispatch 类型
19
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
19
20
  const tempStore = configureStore({
20
21
  reducer: combineReducer,
21
22
  middleware: (getDefaultMiddleware) =>
@@ -48,7 +49,7 @@ export const initializeStore = (preloadedState?: any): EnhancedStore => {
48
49
  if (preloadedState && store) {
49
50
  _store = initStore({
50
51
  ...store.getState(),
51
- ...preloadedState
52
+ ...preloadedState,
52
53
  })
53
54
  store = undefined
54
55
  }