nsgm-cli 2.1.5 → 2.1.6

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 CHANGED
@@ -4,8 +4,6 @@
4
4
  - 数据库采用 Mysql, 配置见 mysql.config.js
5
5
  - 项目配置见 project.config.js
6
6
  - Next 框架配置见 next.config.js
7
- - [ERISHEN](https://www.erishen.cn/)
8
- - [Demo](https://nsgm.erishen.cn:8443/)
9
7
 
10
8
  ## 命令
11
9
  - nsgm init 初始化项目
@@ -1,11 +1,13 @@
1
1
  import React, { useEffect, useState } from 'react'
2
- import { Layout, Menu, Breadcrumb, Image, Select } from 'antd'
2
+ import { Layout, Menu, Breadcrumb, Image, Select, Avatar, Dropdown, Space, Tooltip } from 'antd'
3
3
  import { Container } from '../styled/layout'
4
+ import styled from 'styled-components'
4
5
  import { useRouter } from 'next/router'
5
6
  import _ from 'lodash'
6
7
  import menuConfig from '../utils/menu'
7
8
  import { logout } from '../utils/sso'
8
9
  import getConfig from 'next/config'
10
+ import { UserOutlined, LogoutOutlined, SettingOutlined, BellOutlined } from '@ant-design/icons'
9
11
 
10
12
  const { Option } = Select
11
13
  const { SubMenu } = Menu
@@ -15,6 +17,34 @@ const nextConfig = getConfig()
15
17
  const { publicRuntimeConfig } = nextConfig
16
18
  const { prefix } = publicRuntimeConfig
17
19
 
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
+ justify-content: space-between;
29
+ `
30
+ const SiderFooter = styled.div<{ collapsed: boolean }>`
31
+ padding: ${props => props.collapsed ? '8px 0' : '8px 16px'};
32
+ text-align: center;
33
+ color: rgba(0,0,0,0.45);
34
+ font-size: 12px;
35
+ border-top: 1px solid #ebeef5;
36
+ background: #f5f7fa;
37
+ `
38
+ const SideMenu = styled(Menu)`
39
+ height: 100%;
40
+ border-right: 0;
41
+ `
42
+ const ContentLayout = styled(Layout)`
43
+ display: flex;
44
+ flex-direction: column;
45
+ flex: 1;
46
+ `
47
+
18
48
  const getLocationKey = () => {
19
49
  let result = {
20
50
  topMenu: '1',
@@ -85,6 +115,7 @@ const LayoutComponent = ({ user, children }) => {
85
115
  const router = useRouter()
86
116
  const [topMenuKey, setTopMenuKey] = useState('1')
87
117
  const [sliderMenuKey, setSliderMenuKey] = useState('1')
118
+ const [collapsed, setCollapsed] = useState(false)
88
119
 
89
120
  // console.log('topMenuKey: ' + topMenuKey, ', sliderMenuKey: ' + sliderMenuKey, user)
90
121
 
@@ -175,44 +206,92 @@ const LayoutComponent = ({ user, children }) => {
175
206
  })
176
207
 
177
208
  return (
178
- <Layout>
209
+ <Layout className="main-layout">
179
210
  <Container>
180
211
  <Header className="header">
181
212
  <div className="logo">
182
213
  <Image width={100} src={prefix + "/images/zhizuotu_1.png"} preview={false} />
183
214
  </div>
184
- <Menu theme="dark" mode="horizontal" defaultSelectedKeys={['1']} selectedKeys={[topMenuKey]} items={menuItems} />
185
- <div className="user">
186
- <Select value={user?.displayName} onChange={() => { logout() }}>
187
- <Option value=''>{'退出'}</Option>
188
- </Select>
215
+ <Menu
216
+ theme="dark"
217
+ mode="horizontal"
218
+ defaultSelectedKeys={['1']}
219
+ selectedKeys={[topMenuKey]}
220
+ items={menuItems}
221
+ className="main-menu"
222
+ />
223
+ <div className="user-actions">
224
+ <Space size={16} align="center">
225
+ <Tooltip title="通知">
226
+ <BellOutlined className="action-icon" />
227
+ </Tooltip>
228
+ <Tooltip title="设置">
229
+ <SettingOutlined className="action-icon" />
230
+ </Tooltip>
231
+ <Dropdown
232
+ menu={{
233
+ items: [
234
+ {
235
+ key: '1',
236
+ icon: <UserOutlined />,
237
+ label: '个人中心',
238
+ },
239
+ {
240
+ key: '2',
241
+ icon: <SettingOutlined />,
242
+ label: '账户设置',
243
+ },
244
+ {
245
+ type: 'divider',
246
+ },
247
+ {
248
+ key: '3',
249
+ icon: <LogoutOutlined />,
250
+ label: '退出登录',
251
+ onClick: () => logout(),
252
+ },
253
+ ],
254
+ }}
255
+ >
256
+ <Space className="user-dropdown">
257
+ <span className="username">{user?.displayName || '用户'}</span>
258
+ </Space>
259
+ </Dropdown>
260
+ </Space>
189
261
  </div>
190
262
  </Header>
191
- <Layout>
192
- <Sider width={200} className="site-layout-background">
193
- <Menu
194
- mode="inline"
195
- defaultSelectedKeys={['slider_1_0']}
196
- defaultOpenKeys={['slider_1']}
197
- selectedKeys={['slider_' + topMenuKey + '_' + sliderMenuKey]}
198
- openKeys={['slider_' + topMenuKey]}
199
- style={{ height: '100%', borderRight: 0 }}
200
- items={menuItemsVertical}
201
- />
202
- </Sider>
203
- <Layout style={{ padding: '0 24px 24px' }}>
204
- <Breadcrumb style={{ margin: '16px 0' }}>
263
+ <FlexLayout>
264
+ <StyledSider
265
+ width={200}
266
+ className="site-layout-background sidebar"
267
+ collapsible
268
+ collapsed={collapsed}
269
+ onCollapse={(value) => setCollapsed(value)}
270
+ >
271
+ <div>
272
+ <SideMenu
273
+ mode="inline"
274
+ defaultSelectedKeys={['slider_1_0']}
275
+ defaultOpenKeys={['slider_1']}
276
+ selectedKeys={['slider_' + topMenuKey + '_' + sliderMenuKey]}
277
+ openKeys={['slider_' + topMenuKey]}
278
+ items={menuItemsVertical}
279
+ className="side-menu"
280
+ />
281
+ </div>
282
+ <SiderFooter collapsed={collapsed}>
283
+ {collapsed ? '©' : '© 2025 NSGM'}
284
+ </SiderFooter>
285
+ </StyledSider>
286
+ <ContentLayout className="content-layout">
287
+ <Breadcrumb className="breadcrumb-container">
205
288
  {_.map(menuConfig, (item, index) => {
206
289
  const { key, text, subMenus } = item
207
290
 
208
291
  if (subMenus) {
209
- // console.log('subMenus', subMenus)
210
-
211
292
  let subContent: any = []
212
293
  _.each(subMenus, (subItem, subIndex) => {
213
294
  const { key: subKey, text: subText } = subItem
214
- // console.log('subKey', subKey, key, topMenuKey, sliderMenuKey)
215
-
216
295
  if (subKey === topMenuKey + '_' + sliderMenuKey) {
217
296
  subContent.push(<Breadcrumb.Item key={'breadcrumb' + subIndex}>{text}</Breadcrumb.Item>)
218
297
  subContent.push(<Breadcrumb.Item key={'breadcrumb' + subIndex}>{subText}</Breadcrumb.Item>)
@@ -228,17 +307,12 @@ const LayoutComponent = ({ user, children }) => {
228
307
  })}
229
308
  </Breadcrumb>
230
309
  <Content
231
- className="site-layout-background"
232
- style={{
233
- padding: 24,
234
- margin: 0,
235
- minHeight: 280
236
- }}
310
+ className="site-layout-background content-container"
237
311
  >
238
312
  {children}
239
313
  </Content>
240
- </Layout>
241
- </Layout>
314
+ </ContentLayout>
315
+ </FlexLayout>
242
316
  </Container>
243
317
  </Layout>
244
318
  )
@@ -19,33 +19,29 @@ export const Container = styled.div`
19
19
 
20
20
  export const LoginContainer = styled.div`
21
21
  margin: auto;
22
- margin-top: 200px;
23
- width: 250px;
22
+ margin-top: 100px;
23
+ width: 350px;
24
24
  display: flex;
25
25
  flex-direction: column;
26
26
  justify-content: center;
27
- align-items: flex-start;
28
- border: 1px solid gray;
29
- border-radius: 5px;
30
- padding: 20px;
31
-
32
- .row {
33
- width: 100%;
34
- display: flex;
35
- flex: 1;
36
- flex-direction: row;
37
- justify-content: flex-start;
38
- align-items: center;
39
-
40
- .user-input {
41
- width: 210px;
42
- margin-bottom: 5px;
43
- }
27
+ align-items: center;
28
+ border: 1px solid #e8e8e8;
29
+ border-radius: 8px;
30
+ padding: 30px;
31
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
32
+ background-color: #fff;
33
+
34
+ .ant-form-item {
35
+ margin-bottom: 20px;
44
36
  }
45
37
 
46
- .right {
47
- margin-top: 10px;
48
- justify-content: flex-end;
38
+ .ant-input-affix-wrapper {
39
+ border-radius: 4px;
40
+ }
41
+
42
+ .ant-btn {
43
+ height: 40px;
44
+ border-radius: 4px;
49
45
  }
50
46
  `
51
47
 
@@ -1,26 +1,148 @@
1
1
  import styled from 'styled-components'
2
2
 
3
3
  export const Container = styled.div`
4
+ .main-layout {
5
+ min-height: 100vh;
6
+ display: flex;
7
+ flex-direction: column;
8
+ }
9
+
4
10
  .header {
5
11
  position: relative;
12
+ display: flex;
13
+ align-items: center;
14
+ padding: 0 20px;
15
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
16
+ z-index: 10;
6
17
 
7
18
  .logo {
8
- float: left;
9
19
  width: 120px;
10
20
  height: 31px;
11
- // margin: 16px 24px 16px 0;
21
+ margin-right: 24px;
22
+ display: flex;
23
+ align-items: center;
12
24
  }
13
25
 
14
- .site-layout-background {
15
- background: #fff;
26
+ .main-menu {
27
+ flex: 1;
16
28
  }
17
29
 
18
- .user {
19
- position: absolute;
20
- right: 10px;
21
- top: 0;
22
- color: white;
30
+ .user-actions {
31
+ display: flex;
32
+ align-items: center;
33
+ margin-left: auto;
34
+ height: 100%;
35
+
36
+ .ant-space {
37
+ display: flex;
38
+ align-items: center;
39
+ height: 100%;
40
+ }
41
+
42
+ .action-icon {
43
+ color: rgba(255, 255, 255, 0.85);
44
+ font-size: 20px;
45
+ cursor: pointer;
46
+ transition: color 0.3s;
47
+ display: flex;
48
+ align-items: center;
49
+ justify-content: center;
50
+ height: 32px;
51
+ width: 32px;
52
+
53
+ &:hover {
54
+ color: #fff;
55
+ }
56
+ }
57
+
58
+ .user-dropdown {
59
+ cursor: pointer;
60
+ padding: 0 8px;
61
+ display: flex;
62
+ align-items: center;
63
+
64
+ .username {
65
+ color: rgba(255, 255, 255, 0.85);
66
+ margin-left: 8px;
67
+ }
68
+ }
69
+ }
70
+ }
71
+
72
+ .sidebar {
73
+ box-shadow: 2px 0 8px 0 rgba(29, 35, 41, 0.05);
74
+ background: #f5f7fa;
75
+ border-right: 1px solid #ebeef5;
76
+
77
+ .side-menu {
78
+ border-right: none;
79
+ background: #f5f7fa;
80
+
81
+ .ant-menu-item {
82
+ margin: 0;
83
+ border-radius: 0;
84
+
85
+ &:hover {
86
+ background-color: #e6f7ff;
87
+ }
88
+
89
+ &.ant-menu-item-selected {
90
+ background-color: #e6f7ff;
91
+ border-right: 3px solid #1890ff;
92
+ font-weight: 500;
93
+ }
94
+ }
95
+
96
+ .ant-menu-submenu-title {
97
+ &:hover {
98
+ background-color: #e6f7ff;
99
+ }
100
+ }
101
+
102
+ .ant-menu-submenu-selected > .ant-menu-submenu-title {
103
+ color: #1890ff;
104
+ font-weight: 500;
105
+ }
23
106
  }
24
107
  }
25
108
 
109
+ .content-layout {
110
+ padding: 0 24px 24px;
111
+ display: flex;
112
+ flex-direction: column;
113
+ flex: 1;
114
+ height: 100%;
115
+
116
+ .breadcrumb-container {
117
+ margin: 16px 0;
118
+ font-size: 14px;
119
+ }
120
+
121
+ .content-container {
122
+ padding: 24px;
123
+ margin: 0;
124
+ flex: 1;
125
+ min-height: 280px;
126
+ background: #fff;
127
+ border-radius: 4px;
128
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
129
+ display: flex;
130
+ flex-direction: column;
131
+ }
132
+ }
133
+
134
+ .site-layout-background {
135
+ background: #fff;
136
+ }
137
+
138
+ .ant-layout-sider-trigger {
139
+ background: #e6f7ff;
140
+ color: #1890ff;
141
+ border-top: 1px solid #ebeef5;
142
+ border-right: 1px solid #ebeef5;
143
+
144
+ &:hover {
145
+ background: #bae7ff;
146
+ }
147
+ }
26
148
  `
@@ -2,15 +2,76 @@ import styled from 'styled-components'
2
2
 
3
3
  export const Container = styled.div`
4
4
  margin: 20px;
5
+
6
+ .ant-table {
7
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
8
+ border-radius: 8px;
9
+ overflow: hidden;
10
+ transition: all 0.3s ease;
11
+
12
+ &:hover {
13
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
14
+ }
15
+ }
16
+
17
+ .table-row-light {
18
+ background-color: #ffffff;
19
+ }
20
+
21
+ .table-row-dark {
22
+ background-color: #f9f9f9;
23
+ }
24
+
25
+ .ant-table-thead > tr > th {
26
+ background-color: #f0f5ff;
27
+ color: #1890ff;
28
+ font-weight: 500;
29
+ padding: 12px 16px;
30
+ }
31
+
32
+ .ant-table-tbody > tr > td {
33
+ padding: 12px 16px;
34
+ transition: background-color 0.3s;
35
+ }
36
+
37
+ .page-title {
38
+ font-size: 24px;
39
+ font-weight: 500;
40
+ color: #1890ff;
41
+ margin-bottom: 20px;
42
+ padding-bottom: 10px;
43
+ border-bottom: 1px solid #f0f0f0;
44
+ position: relative;
45
+
46
+ &:after {
47
+ content: '';
48
+ position: absolute;
49
+ bottom: -1px;
50
+ left: 0;
51
+ width: 100px;
52
+ height: 3px;
53
+ background: linear-gradient(90deg, #1890ff, #69c0ff);
54
+ border-radius: 3px;
55
+ }
56
+ }
5
57
  `
6
58
 
7
59
  export const SearchRow = styled.div`
8
- margin: 10px;
60
+ margin: 10px 0 20px 0;
61
+ padding: 16px 20px;
9
62
  display: flex;
10
63
  flex: 1;
11
64
  flex-direction: row;
12
65
  justify-content: space-between;
13
66
  align-items: center;
67
+ background-color: #fff;
68
+ border-radius: 8px;
69
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
70
+ transition: all 0.3s ease;
71
+
72
+ &:hover {
73
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
74
+ }
14
75
  `
15
76
 
16
77
  export const ModalContainer = styled.div`
@@ -21,6 +82,7 @@ export const ModalContainer = styled.div`
21
82
  justify-content: flex-start;
22
83
  align-items: flex-start;
23
84
  height: 50px;
85
+ margin-bottom: 16px;
24
86
 
25
87
  label {
26
88
  display: flex;
@@ -29,11 +91,33 @@ export const ModalContainer = styled.div`
29
91
  align-items: flex-start;
30
92
  width: 80px;
31
93
  height: 32px;
32
- margin-right: 5px;
94
+ margin-right: 16px;
95
+ font-weight: 500;
96
+ color: #333;
97
+ position: relative;
98
+
99
+ &:after {
100
+ content: '';
101
+ position: absolute;
102
+ left: -8px;
103
+ top: 50%;
104
+ transform: translateY(-50%);
105
+ width: 3px;
106
+ height: 16px;
107
+ background: #1890ff;
108
+ border-radius: 3px;
109
+ }
33
110
  }
34
111
 
35
112
  input {
36
113
  flex: 1;
114
+ border-radius: 6px;
115
+ transition: all 0.3s ease;
116
+
117
+ &:hover, &:focus {
118
+ border-color: #40a9ff;
119
+ box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
120
+ }
37
121
  }
38
122
 
39
123
  .row {