nsgm-cli 2.1.6 → 2.1.8
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 +106 -58
- package/client/layout/index.tsx +80 -29
- package/client/redux/template/manage/actions.ts +1 -1
- package/client/service/template/manage.ts +11 -11
- package/client/utils/sso.ts +41 -41
- package/generation/README.md +147 -16
- package/next.config.js +9 -4
- package/package.json +1 -1
- package/pages/_app.tsx +4 -4
- package/pages/_document.tsx +3 -1
- package/pages/template/manage.tsx +37 -16
- package/babel.config.js +0 -18
package/README.md
CHANGED
|
@@ -1,28 +1,62 @@
|
|
|
1
1
|
# NSGM CLI
|
|
2
|
-
|
|
3
|
-
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
2
|
+
|
|
3
|
+
A full-stack development framework with code template generation capabilities, helping developers efficiently build web applications.
|
|
4
|
+
|
|
5
|
+
## Tech Stack
|
|
6
|
+
|
|
7
|
+
- [Next.js](https://github.com/vercel/next.js) - React framework
|
|
8
|
+
- [Styled-components](https://github.com/styled-components/styled-components) - CSS-in-JS solution
|
|
9
|
+
- [GraphQL](https://graphql.org/) - API query language
|
|
10
|
+
- [MySQL](https://www.mysql.com/) - Relational database
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- Full-stack architecture design
|
|
15
|
+
- Automatic code template generation
|
|
16
|
+
- Rapid development workflow
|
|
17
|
+
- Integrated GraphQL API
|
|
18
|
+
- MySQL database support
|
|
19
|
+
|
|
20
|
+
## Command Line Tools
|
|
21
|
+
|
|
22
|
+
### Basic Commands
|
|
23
|
+
|
|
24
|
+
| Command | Description |
|
|
25
|
+
|------|------|
|
|
26
|
+
| `nsgm init` | Initialize project |
|
|
27
|
+
| `nsgm upgrade` | Upgrade project base files |
|
|
28
|
+
| `nsgm create` | Create template page |
|
|
29
|
+
| `nsgm delete` | Delete template page |
|
|
30
|
+
| `nsgm deletedb` | Delete template page and database table |
|
|
31
|
+
| `nsgm dev` | Development mode |
|
|
32
|
+
| `nsgm start` | Production mode |
|
|
33
|
+
| `nsgm build` | Build project |
|
|
34
|
+
| `nsgm export` | Export static pages |
|
|
35
|
+
|
|
36
|
+
### Parameter Description
|
|
37
|
+
|
|
38
|
+
- **dictionary**: Used with `export`/`init` commands, default value is `webapp`
|
|
39
|
+
```
|
|
40
|
+
nsgm init dictionary=webapp
|
|
41
|
+
# or simplified as
|
|
42
|
+
nsgm init webapp
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
- **controller**: Used with `create`/`delete` commands, required parameter
|
|
46
|
+
```
|
|
47
|
+
nsgm create math
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
- **action**: Used with `create`/`delete` commands, default value is `manage`, follows the controller
|
|
51
|
+
```
|
|
52
|
+
nsgm create math test
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Project Configuration
|
|
56
|
+
|
|
57
|
+
### next.config.js
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
26
60
|
const { nextConfig } = require('nsgm-cli')
|
|
27
61
|
const projectConfig = require('./project.config')
|
|
28
62
|
|
|
@@ -37,8 +71,9 @@ module.exports = (phase, defaultConfig) => {
|
|
|
37
71
|
}
|
|
38
72
|
```
|
|
39
73
|
|
|
40
|
-
|
|
41
|
-
|
|
74
|
+
### mysql.config.js
|
|
75
|
+
|
|
76
|
+
```javascript
|
|
42
77
|
const { mysqlConfig } = require('nsgm-cli')
|
|
43
78
|
const { mysqlOptions } = mysqlConfig
|
|
44
79
|
const { user, password, host, port, database } = mysqlOptions
|
|
@@ -54,8 +89,9 @@ module.exports = {
|
|
|
54
89
|
}
|
|
55
90
|
```
|
|
56
91
|
|
|
57
|
-
|
|
58
|
-
|
|
92
|
+
### project.config.js
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
59
95
|
const { projectConfig } = require('nsgm-cli')
|
|
60
96
|
const pkg = require('./package.json')
|
|
61
97
|
|
|
@@ -71,34 +107,44 @@ module.exports = {
|
|
|
71
107
|
}
|
|
72
108
|
```
|
|
73
109
|
|
|
74
|
-
##
|
|
75
|
-
- apis 存放 Rest Api
|
|
76
|
-
- modules 存放 graphql 的 resolver 和 schema
|
|
77
|
-
- plugins 存放 graphql 的 plugin
|
|
78
|
-
- *.js 举例: test.js => 用于响应 /test/*, ${prefix}/test/* 请求
|
|
110
|
+
## Server Directory Structure
|
|
79
111
|
|
|
80
|
-
|
|
81
|
-
const express = require('express')
|
|
82
|
-
const moment = require('moment')
|
|
112
|
+
The `server` folder in the project root contains the following:
|
|
83
113
|
|
|
84
|
-
|
|
114
|
+
### Directory Description
|
|
85
115
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
})
|
|
116
|
+
- `apis/` - Stores REST API interfaces
|
|
117
|
+
- `modules/` - Stores GraphQL resolvers and schemas
|
|
118
|
+
- `plugins/` - Stores GraphQL plugins
|
|
119
|
+
- `*.js` - Route files, e.g., `test.js` handles requests to `/test/*` and `${prefix}/test/*`
|
|
91
120
|
|
|
92
|
-
|
|
93
|
-
res.statusCode = 200
|
|
94
|
-
res.json({ name: 'TEST' })
|
|
95
|
-
})
|
|
121
|
+
### Example Code
|
|
96
122
|
|
|
97
|
-
|
|
98
|
-
```
|
|
123
|
+
#### Route File Example (server/test.js)
|
|
99
124
|
|
|
100
|
-
|
|
125
|
+
```javascript
|
|
126
|
+
const express = require('express')
|
|
127
|
+
const moment = require('moment')
|
|
128
|
+
|
|
129
|
+
const router = express.Router()
|
|
130
|
+
|
|
131
|
+
router.use((req, res, next) => {
|
|
132
|
+
const fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl
|
|
133
|
+
console.log(moment().format('YYYY-MM-DD HH:mm:ss') + ' ' + fullUrl)
|
|
134
|
+
next()
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
router.get('/*', (req, res) => {
|
|
138
|
+
res.statusCode = 200
|
|
139
|
+
res.json({ name: 'TEST' })
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
module.exports = router
|
|
101
143
|
```
|
|
144
|
+
|
|
145
|
+
#### REST API Example (server/apis/hello.js)
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
102
148
|
const express = require('express')
|
|
103
149
|
const router = express.Router()
|
|
104
150
|
|
|
@@ -110,8 +156,9 @@ router.get('/*', (req, res) => {
|
|
|
110
156
|
module.exports = router
|
|
111
157
|
```
|
|
112
158
|
|
|
113
|
-
|
|
114
|
-
|
|
159
|
+
#### GraphQL Schema Example (server/modules/link/schema.js)
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
115
162
|
module.exports = {
|
|
116
163
|
query: `
|
|
117
164
|
link: String
|
|
@@ -124,15 +171,16 @@ module.exports = {
|
|
|
124
171
|
}
|
|
125
172
|
```
|
|
126
173
|
|
|
127
|
-
|
|
128
|
-
|
|
174
|
+
#### GraphQL Resolver Example (server/modules/link/resolver.js)
|
|
175
|
+
|
|
176
|
+
```javascript
|
|
129
177
|
let localLink = ''
|
|
130
178
|
|
|
131
179
|
module.exports = {
|
|
132
180
|
link: () => {
|
|
133
181
|
return localLink
|
|
134
182
|
},
|
|
135
|
-
linkUpdate: ({ link }) =>{
|
|
183
|
+
linkUpdate: ({ link }) => {
|
|
136
184
|
console.log('link', link)
|
|
137
185
|
localLink = link
|
|
138
186
|
return localLink
|
|
@@ -140,8 +188,9 @@ module.exports = {
|
|
|
140
188
|
}
|
|
141
189
|
```
|
|
142
190
|
|
|
143
|
-
|
|
144
|
-
|
|
191
|
+
#### GraphQL Plugin Example (server/plugins/date.js)
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
145
194
|
const moment = require('moment')
|
|
146
195
|
const { Kind } = require('graphql/language')
|
|
147
196
|
const { GraphQLScalarType } = require('graphql')
|
|
@@ -157,5 +206,4 @@ const customScalarDate = new GraphQLScalarType({
|
|
|
157
206
|
})
|
|
158
207
|
|
|
159
208
|
module.exports = { Date: customScalarDate }
|
|
160
|
-
```
|
|
161
|
-
|
|
209
|
+
```
|
package/client/layout/index.tsx
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react'
|
|
2
|
-
import { Layout, Menu, Breadcrumb, Image, Select,
|
|
3
|
-
import { Container } from '
|
|
2
|
+
import { Layout, Menu, Breadcrumb, Image, Select, Dropdown, Space, Tooltip } from 'antd'
|
|
3
|
+
import { Container } from '@/styled/layout'
|
|
4
4
|
import styled from 'styled-components'
|
|
5
5
|
import { useRouter } from 'next/router'
|
|
6
6
|
import _ from 'lodash'
|
|
7
|
-
import menuConfig from '
|
|
8
|
-
import { logout } from '
|
|
7
|
+
import menuConfig from '@/utils/menu'
|
|
8
|
+
import { logout } from '@/utils/sso'
|
|
9
9
|
import getConfig from 'next/config'
|
|
10
|
-
import {
|
|
10
|
+
import { LogoutOutlined, SettingOutlined, BellOutlined, UserOutlined } from '@ant-design/icons'
|
|
11
11
|
|
|
12
12
|
const { Option } = Select
|
|
13
13
|
const { SubMenu } = Menu
|
|
@@ -25,24 +25,80 @@ const FlexLayout = styled(Layout)`
|
|
|
25
25
|
const StyledSider = styled(Sider)`
|
|
26
26
|
display: flex;
|
|
27
27
|
flex-direction: column;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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;
|
|
28
|
+
box-shadow: 2px 0 8px -4px rgba(0, 0, 0, 0.1);
|
|
29
|
+
z-index: 5;
|
|
30
|
+
position: relative;
|
|
37
31
|
`
|
|
32
|
+
|
|
38
33
|
const SideMenu = styled(Menu)`
|
|
39
34
|
height: 100%;
|
|
40
35
|
border-right: 0;
|
|
36
|
+
padding: 8px 0;
|
|
41
37
|
`
|
|
38
|
+
|
|
42
39
|
const ContentLayout = styled(Layout)`
|
|
43
40
|
display: flex;
|
|
44
41
|
flex-direction: column;
|
|
45
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;
|
|
46
102
|
`
|
|
47
103
|
|
|
48
104
|
const getLocationKey = () => {
|
|
@@ -208,9 +264,9 @@ const LayoutComponent = ({ user, children }) => {
|
|
|
208
264
|
return (
|
|
209
265
|
<Layout className="main-layout">
|
|
210
266
|
<Container>
|
|
211
|
-
<
|
|
267
|
+
<StyledHeader>
|
|
212
268
|
<div className="logo">
|
|
213
|
-
<Image width={
|
|
269
|
+
<Image width={120} src={prefix + "/images/zhizuotu_1.png"} preview={false} />
|
|
214
270
|
</div>
|
|
215
271
|
<Menu
|
|
216
272
|
theme="dark"
|
|
@@ -221,7 +277,7 @@ const LayoutComponent = ({ user, children }) => {
|
|
|
221
277
|
className="main-menu"
|
|
222
278
|
/>
|
|
223
279
|
<div className="user-actions">
|
|
224
|
-
<Space size={
|
|
280
|
+
<Space size={20} align="center">
|
|
225
281
|
<Tooltip title="通知">
|
|
226
282
|
<BellOutlined className="action-icon" />
|
|
227
283
|
</Tooltip>
|
|
@@ -259,10 +315,10 @@ const LayoutComponent = ({ user, children }) => {
|
|
|
259
315
|
</Dropdown>
|
|
260
316
|
</Space>
|
|
261
317
|
</div>
|
|
262
|
-
</
|
|
318
|
+
</StyledHeader>
|
|
263
319
|
<FlexLayout>
|
|
264
320
|
<StyledSider
|
|
265
|
-
width={
|
|
321
|
+
width={220}
|
|
266
322
|
className="site-layout-background sidebar"
|
|
267
323
|
collapsible
|
|
268
324
|
collapsed={collapsed}
|
|
@@ -279,12 +335,9 @@ const LayoutComponent = ({ user, children }) => {
|
|
|
279
335
|
className="side-menu"
|
|
280
336
|
/>
|
|
281
337
|
</div>
|
|
282
|
-
<SiderFooter collapsed={collapsed}>
|
|
283
|
-
{collapsed ? '©' : '© 2025 NSGM'}
|
|
284
|
-
</SiderFooter>
|
|
285
338
|
</StyledSider>
|
|
286
339
|
<ContentLayout className="content-layout">
|
|
287
|
-
<
|
|
340
|
+
<StyledBreadcrumb>
|
|
288
341
|
{_.map(menuConfig, (item, index) => {
|
|
289
342
|
const { key, text, subMenus } = item
|
|
290
343
|
|
|
@@ -294,7 +347,7 @@ const LayoutComponent = ({ user, children }) => {
|
|
|
294
347
|
const { key: subKey, text: subText } = subItem
|
|
295
348
|
if (subKey === topMenuKey + '_' + sliderMenuKey) {
|
|
296
349
|
subContent.push(<Breadcrumb.Item key={'breadcrumb' + subIndex}>{text}</Breadcrumb.Item>)
|
|
297
|
-
subContent.push(<Breadcrumb.Item key={'breadcrumb' + subIndex}>{subText}</Breadcrumb.Item>)
|
|
350
|
+
subContent.push(<Breadcrumb.Item key={'breadcrumb' + subIndex + '_sub'}>{subText}</Breadcrumb.Item>)
|
|
298
351
|
return false
|
|
299
352
|
}
|
|
300
353
|
})
|
|
@@ -305,12 +358,10 @@ const LayoutComponent = ({ user, children }) => {
|
|
|
305
358
|
}
|
|
306
359
|
}
|
|
307
360
|
})}
|
|
308
|
-
</
|
|
309
|
-
<
|
|
310
|
-
className="site-layout-background content-container"
|
|
311
|
-
>
|
|
361
|
+
</StyledBreadcrumb>
|
|
362
|
+
<StyledContent>
|
|
312
363
|
{children}
|
|
313
|
-
</
|
|
364
|
+
</StyledContent>
|
|
314
365
|
</ContentLayout>
|
|
315
366
|
</FlexLayout>
|
|
316
367
|
</Container>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as types from './types'
|
|
2
|
-
import { getTemplateService, addTemplateService, updateTemplateService, deleteTemplateService, searchTemplateService, batchDeleteTemplateService } from '
|
|
2
|
+
import { getTemplateService, addTemplateService, updateTemplateService, deleteTemplateService, searchTemplateService, batchDeleteTemplateService } from '@/service/template/manage'
|
|
3
3
|
|
|
4
4
|
export const getTemplate = (page=0, pageSize=10) => (
|
|
5
5
|
dispatch: (arg0: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { getLocalGraphql } from '
|
|
1
|
+
import { getLocalGraphql } from '@/utils/fetch'
|
|
2
2
|
import _ from 'lodash'
|
|
3
3
|
|
|
4
|
-
export const getTemplateService = (page=0, pageSize=10) => {
|
|
4
|
+
export const getTemplateService = (page = 0, pageSize = 10) => {
|
|
5
5
|
const getTemplateQuery = `query ($page: Int, $pageSize: Int) { template(page: $page, pageSize: $pageSize) {
|
|
6
6
|
totalCounts items {
|
|
7
7
|
id name
|
|
@@ -9,10 +9,10 @@ export const getTemplateService = (page=0, pageSize=10) => {
|
|
|
9
9
|
}
|
|
10
10
|
}`
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
return getLocalGraphql(getTemplateQuery, {
|
|
13
|
+
page,
|
|
14
|
+
pageSize
|
|
15
|
+
})
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export const searchTemplateByIdService = (id: number) => {
|
|
@@ -39,7 +39,7 @@ export const searchTemplateService = (page = 0, pageSize = 10, data: any) => {
|
|
|
39
39
|
}`
|
|
40
40
|
|
|
41
41
|
return getLocalGraphql(searchTemplateQuery, {
|
|
42
|
-
page,
|
|
42
|
+
page,
|
|
43
43
|
pageSize,
|
|
44
44
|
data: {
|
|
45
45
|
name
|
|
@@ -47,7 +47,7 @@ export const searchTemplateService = (page = 0, pageSize = 10, data: any) => {
|
|
|
47
47
|
})
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
export const addTemplateService = (data: any) => {
|
|
50
|
+
export const addTemplateService = (data: any) => {
|
|
51
51
|
const { name } = data
|
|
52
52
|
|
|
53
53
|
const addTemplateQuery = `mutation ($data: TemplateAddInput) { templateAdd(data: $data) }`
|
|
@@ -59,7 +59,7 @@ export const addTemplateService = (data: any) => {
|
|
|
59
59
|
})
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
export const updateTemplateService = (id: number, data: any) => {
|
|
62
|
+
export const updateTemplateService = (id: number, data: any) => {
|
|
63
63
|
const { name } = data
|
|
64
64
|
|
|
65
65
|
const updateTemplateQuery = `mutation ($id: Int, $data: TemplateAddInput) { templateUpdate(id: $id, data: $data) }`
|
|
@@ -72,7 +72,7 @@ export const updateTemplateService = (id: number, data: any) => {
|
|
|
72
72
|
})
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
export const deleteTemplateService = (id: number) => {
|
|
75
|
+
export const deleteTemplateService = (id: number) => {
|
|
76
76
|
const deleteTemplateQuery = `mutation ($id: Int) { templateDelete(id: $id) }`
|
|
77
77
|
|
|
78
78
|
return getLocalGraphql(deleteTemplateQuery, {
|
|
@@ -88,7 +88,7 @@ export const batchAddTemplateService = (datas: any) => {
|
|
|
88
88
|
})
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
export const batchDeleteTemplateService = (ids: any) => {
|
|
91
|
+
export const batchDeleteTemplateService = (ids: any) => {
|
|
92
92
|
const batchDeleteTemplateQuery = `mutation ($ids: [Int]) { templateBatchDelete(ids: $ids) }`
|
|
93
93
|
|
|
94
94
|
return getLocalGraphql(batchDeleteTemplateQuery, {
|
package/client/utils/sso.ts
CHANGED
|
@@ -8,17 +8,17 @@ const env = getLocalEnv()
|
|
|
8
8
|
const LOGIN_COOKIE_ID = env + '_cas_nsgm'
|
|
9
9
|
const LOGIN_COOKIE_USER = env + '_nsgm_user'
|
|
10
10
|
|
|
11
|
-
const getPrincipalUrl = () => {
|
|
11
|
+
const getPrincipalUrl = () => {
|
|
12
12
|
const url = getLocalApiPrefix() + '/rest/sso/sessionCheck'
|
|
13
13
|
return url
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
const getValidateUrl = () => {
|
|
16
|
+
const getValidateUrl = () => {
|
|
17
17
|
const url = getLocalApiPrefix() + '/rest/sso/ticketCheck'
|
|
18
18
|
return url
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
const handleLocationHref = () => {
|
|
21
|
+
const handleLocationHref = () => {
|
|
22
22
|
let newHref = ''
|
|
23
23
|
if (typeof window !== 'undefined') {
|
|
24
24
|
const locationHref = window.location.href
|
|
@@ -27,12 +27,12 @@ const handleLocationHref = () => {
|
|
|
27
27
|
const locationHrefArrLen = locationHrefArr.length
|
|
28
28
|
|
|
29
29
|
let newParamStr = ''
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
if (locationHrefArrLen > 1) {
|
|
32
32
|
const paramStr = locationHrefArr[1]
|
|
33
33
|
if (paramStr.indexOf('&') !== -1) {
|
|
34
34
|
const paramArr = paramStr.split('&')
|
|
35
|
-
|
|
35
|
+
|
|
36
36
|
_.each(paramArr, (item, index) => {
|
|
37
37
|
if (item.indexOf('=') !== -1) {
|
|
38
38
|
const itemArr = item.split('=')
|
|
@@ -42,7 +42,7 @@ const handleLocationHref = () => {
|
|
|
42
42
|
let value = ''
|
|
43
43
|
if (itemArrLen > 1)
|
|
44
44
|
value = itemArr[1]
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
if ('ticket' !== key) {
|
|
47
47
|
newParamStr += key + '=' + value + '&'
|
|
48
48
|
}
|
|
@@ -58,11 +58,11 @@ const handleLocationHref = () => {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
const locationHrefArrFirst = locationHrefArr[0]
|
|
61
|
-
if(newParamStr !== '')
|
|
61
|
+
if (newParamStr !== '')
|
|
62
62
|
newHref = locationHrefArrFirst + '?' + newParamStr
|
|
63
63
|
else
|
|
64
64
|
newHref = locationHrefArrFirst
|
|
65
|
-
} else {
|
|
65
|
+
} else {
|
|
66
66
|
newHref = locationHref
|
|
67
67
|
}
|
|
68
68
|
}
|
|
@@ -71,43 +71,43 @@ const handleLocationHref = () => {
|
|
|
71
71
|
return encodeURIComponent(newHref)
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
const jumpToLogin = () => {
|
|
74
|
+
const jumpToLogin = () => {
|
|
75
75
|
delCookie(LOGIN_COOKIE_ID)
|
|
76
76
|
delCookie(LOGIN_COOKIE_USER)
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
if (typeof window !== 'undefined') {
|
|
79
79
|
window.location.href = window.location.origin + '/login'
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
const jumpToLogout = () => {
|
|
83
|
+
const jumpToLogout = () => {
|
|
84
84
|
delCookie(LOGIN_COOKIE_ID)
|
|
85
85
|
delCookie(LOGIN_COOKIE_USER)
|
|
86
|
-
|
|
86
|
+
|
|
87
87
|
if (typeof window !== 'undefined') {
|
|
88
88
|
window.location.href = window.location.origin
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
const principalLogin = (cookie:string, callback:any) => {
|
|
92
|
+
const principalLogin = (cookie: string, callback: any) => {
|
|
93
93
|
let url = getPrincipalUrl()
|
|
94
94
|
|
|
95
95
|
if (typeof window !== 'undefined') {
|
|
96
96
|
url += '?cookieValue=' + cookie + '&redirectUrl=' + handleLocationHref()
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
console.log('principalLogin_url', url)
|
|
100
|
-
axios.get(url, { params: { credentials: 'include' } }).then((res:any) => {
|
|
101
|
-
console.log('principalLogin_res', res)
|
|
99
|
+
// console.log('principalLogin_url', url)
|
|
100
|
+
axios.get(url, { params: { credentials: 'include' } }).then((res: any) => {
|
|
101
|
+
// console.log('principalLogin_res', res)
|
|
102
102
|
const { data } = res
|
|
103
103
|
if (data) {
|
|
104
104
|
const { returnCode, userAttr } = data
|
|
105
105
|
if (returnCode !== 0) {
|
|
106
106
|
jumpToLogin()
|
|
107
|
-
} else {
|
|
107
|
+
} else {
|
|
108
108
|
storeLoginUser(userAttr, callback)
|
|
109
109
|
}
|
|
110
|
-
} else {
|
|
110
|
+
} else {
|
|
111
111
|
jumpToLogin()
|
|
112
112
|
}
|
|
113
113
|
}).catch((e) => {
|
|
@@ -116,42 +116,42 @@ const principalLogin = (cookie:string, callback:any) => {
|
|
|
116
116
|
})
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
const storeLoginUser = (userAttr:any, callback:any) => {
|
|
120
|
-
console.log('storeLoginUser', userAttr)
|
|
119
|
+
const storeLoginUser = (userAttr: any, callback: any) => {
|
|
120
|
+
// console.log('storeLoginUser', userAttr)
|
|
121
121
|
|
|
122
122
|
if (userAttr) {
|
|
123
123
|
const user = JSON.stringify(userAttr, ['city', 'company', 'department', 'displayName', 'employee', 'mail', 'name', 'sn'])
|
|
124
124
|
setCookie(LOGIN_COOKIE_USER, user, null)
|
|
125
125
|
callback && callback(JSON.parse(user))
|
|
126
|
-
} else {
|
|
126
|
+
} else {
|
|
127
127
|
callback && callback()
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
const storeLogin = (cookie:any, cookieExpire:any, userAttr:any, callback:any) => {
|
|
132
|
-
console.log('storeLogin_cookie', cookie)
|
|
131
|
+
const storeLogin = (cookie: any, cookieExpire: any, userAttr: any, callback: any) => {
|
|
132
|
+
// console.log('storeLogin_cookie', cookie)
|
|
133
133
|
|
|
134
|
-
if (cookie) {
|
|
134
|
+
if (cookie) {
|
|
135
135
|
setCookie(LOGIN_COOKIE_ID, cookie, cookieExpire)
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
storeLoginUser(userAttr, callback)
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
const validateLogin = (ticket:string, name:string = '', callback:any) => {
|
|
141
|
+
const validateLogin = (ticket: string, name: string = '', callback: any) => {
|
|
142
142
|
let url = getValidateUrl()
|
|
143
143
|
|
|
144
144
|
if (typeof window !== 'undefined') {
|
|
145
145
|
url += '?ticket=' + ticket
|
|
146
146
|
|
|
147
|
-
if(name !== ''){
|
|
147
|
+
if (name !== '') {
|
|
148
148
|
url += '&name=' + name
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
|
-
|
|
152
|
-
console.log('validateLogin_url', url)
|
|
153
|
-
axios.get(url, { params: { credentials: 'include' } }).then((res:any) => {
|
|
154
|
-
console.log('validateLogin_res', res)
|
|
151
|
+
|
|
152
|
+
// console.log('validateLogin_url', url)
|
|
153
|
+
axios.get(url, { params: { credentials: 'include' } }).then((res: any) => {
|
|
154
|
+
// console.log('validateLogin_res', res)
|
|
155
155
|
|
|
156
156
|
if (res) {
|
|
157
157
|
const { data } = res
|
|
@@ -159,13 +159,13 @@ const validateLogin = (ticket:string, name:string = '', callback:any) => {
|
|
|
159
159
|
const { cookieValue, cookieExpire, returnCode, userAttr } = data
|
|
160
160
|
if (returnCode === 0) {
|
|
161
161
|
storeLogin(cookieValue, cookieExpire, userAttr, callback)
|
|
162
|
-
} else {
|
|
162
|
+
} else {
|
|
163
163
|
jumpToLogin()
|
|
164
164
|
}
|
|
165
|
-
} else {
|
|
165
|
+
} else {
|
|
166
166
|
jumpToLogin()
|
|
167
167
|
}
|
|
168
|
-
} else {
|
|
168
|
+
} else {
|
|
169
169
|
jumpToLogin()
|
|
170
170
|
}
|
|
171
171
|
}).catch((e) => {
|
|
@@ -173,25 +173,25 @@ const validateLogin = (ticket:string, name:string = '', callback:any) => {
|
|
|
173
173
|
})
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
export const login = (callback:any) => {
|
|
176
|
+
export const login = (callback: any) => {
|
|
177
177
|
const cookieLoginValue = getCookie(LOGIN_COOKIE_ID)
|
|
178
|
-
console.log('cookieLoginValue', cookieLoginValue)
|
|
178
|
+
// console.log('cookieLoginValue', cookieLoginValue)
|
|
179
179
|
|
|
180
|
-
if(typeof window !== 'undefined'){
|
|
180
|
+
if (typeof window !== 'undefined') {
|
|
181
181
|
const locationHref = window.location.href
|
|
182
182
|
|
|
183
|
-
if(locationHref.indexOf('/login') === -1){
|
|
183
|
+
if (locationHref.indexOf('/login') === -1) {
|
|
184
184
|
|
|
185
185
|
if (cookieLoginValue !== '') {
|
|
186
186
|
principalLogin(cookieLoginValue, callback)
|
|
187
|
-
} else {
|
|
187
|
+
} else {
|
|
188
188
|
const urlParamTicket = getUrlParamByKey('ticket')
|
|
189
189
|
const urlParamName = getUrlParamByKey('name')
|
|
190
|
-
console.log('urlParamTicket', urlParamTicket, urlParamName)
|
|
190
|
+
// console.log('urlParamTicket', urlParamTicket, urlParamName)
|
|
191
191
|
|
|
192
192
|
if (urlParamTicket !== '') {
|
|
193
193
|
validateLogin(urlParamTicket, urlParamName, callback)
|
|
194
|
-
} else {
|
|
194
|
+
} else {
|
|
195
195
|
jumpToLogin()
|
|
196
196
|
}
|
|
197
197
|
}
|
|
@@ -199,7 +199,7 @@ export const login = (callback:any) => {
|
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
-
export const logout = () => {
|
|
202
|
+
export const logout = () => {
|
|
203
203
|
jumpToLogout()
|
|
204
204
|
}
|
|
205
205
|
|
package/generation/README.md
CHANGED
|
@@ -1,16 +1,147 @@
|
|
|
1
|
-
# NSGM
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
# 欢迎使用 NSGM 项目
|
|
2
|
+
|
|
3
|
+
这是一个由 NSGM CLI 创建的全栈开发项目,集成了 Next.js、Styled-components、GraphQL 和 MySQL 技术栈。
|
|
4
|
+
|
|
5
|
+
## 技术栈
|
|
6
|
+
|
|
7
|
+
- [Next.js](https://github.com/vercel/next.js) - React 框架
|
|
8
|
+
- [Styled-components](https://github.com/styled-components/styled-components) - CSS-in-JS 解决方案
|
|
9
|
+
- [GraphQL](https://graphql.org/) - API 查询语言
|
|
10
|
+
- [MySQL](https://www.mysql.com/) - 关系型数据库
|
|
11
|
+
|
|
12
|
+
## 快速入门
|
|
13
|
+
|
|
14
|
+
### 开发命令
|
|
15
|
+
|
|
16
|
+
| 命令 | 说明 |
|
|
17
|
+
|---------|-------------|
|
|
18
|
+
| `npm run dev` | 开发模式 |
|
|
19
|
+
| `npm run start` | 生产模式 |
|
|
20
|
+
| `npm run build` | 编译项目 |
|
|
21
|
+
| `npm run export` | 导出静态页面 |
|
|
22
|
+
|
|
23
|
+
### 代码生成命令
|
|
24
|
+
|
|
25
|
+
| 命令 | 说明 |
|
|
26
|
+
|---------|-------------|
|
|
27
|
+
| `npm run create` | 创建模板页面 |
|
|
28
|
+
| `npm run delete` | 删除模板页面 |
|
|
29
|
+
|
|
30
|
+
### 项目维护命令
|
|
31
|
+
|
|
32
|
+
| 命令 | 说明 |
|
|
33
|
+
|---------|-------------|
|
|
34
|
+
| `npm run upgrade` | 升级项目基础文件 |
|
|
35
|
+
|
|
36
|
+
## 参数说明
|
|
37
|
+
|
|
38
|
+
### controller
|
|
39
|
+
- 用于 `create`/`delete` 命令
|
|
40
|
+
- 必填参数
|
|
41
|
+
- 示例:
|
|
42
|
+
```
|
|
43
|
+
npm run create math
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### action
|
|
47
|
+
- 用于 `create`/`delete` 命令
|
|
48
|
+
- 默认值为 `manage`
|
|
49
|
+
- 跟在 controller 参数后面
|
|
50
|
+
- 示例:
|
|
51
|
+
```
|
|
52
|
+
npm run create math test
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### dictionary
|
|
56
|
+
- 用于 `export` 命令
|
|
57
|
+
- 默认值为 `webapp`
|
|
58
|
+
- 示例:
|
|
59
|
+
```
|
|
60
|
+
npm run export dictionary=webapp
|
|
61
|
+
# 或简化为
|
|
62
|
+
npm run export webapp
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## 项目结构
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
├── components/ # 公共组件
|
|
69
|
+
├── pages/ # 页面文件
|
|
70
|
+
│ ├── api/ # API 路由
|
|
71
|
+
│ └── [controller]/ # 控制器页面
|
|
72
|
+
├── public/ # 静态资源
|
|
73
|
+
├── server/ # 服务端代码
|
|
74
|
+
│ ├── apis/ # REST API 接口
|
|
75
|
+
│ ├── modules/ # GraphQL 解析器和模式
|
|
76
|
+
│ └── plugins/ # GraphQL 插件
|
|
77
|
+
├── styles/ # 全局样式
|
|
78
|
+
├── next.config.js # Next.js 配置
|
|
79
|
+
├── mysql.config.js # MySQL 配置
|
|
80
|
+
└── project.config.js # 项目配置
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## 配置文件
|
|
84
|
+
|
|
85
|
+
### next.config.js
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
const { nextConfig } = require('nsgm-cli')
|
|
89
|
+
const projectConfig = require('./project.config')
|
|
90
|
+
|
|
91
|
+
const { version, prefix, protocol, host } = projectConfig
|
|
92
|
+
|
|
93
|
+
module.exports = (phase, defaultConfig) => {
|
|
94
|
+
let configObj = nextConfig(phase, defaultConfig, {
|
|
95
|
+
version, prefix, protocol, host
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
return configObj
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### mysql.config.js
|
|
103
|
+
|
|
104
|
+
```javascript
|
|
105
|
+
const { mysqlConfig } = require('nsgm-cli')
|
|
106
|
+
const { mysqlOptions } = mysqlConfig
|
|
107
|
+
const { user, password, host, port, database } = mysqlOptions
|
|
108
|
+
|
|
109
|
+
module.exports = {
|
|
110
|
+
mysqlOptions: {
|
|
111
|
+
user,
|
|
112
|
+
password,
|
|
113
|
+
host,
|
|
114
|
+
port,
|
|
115
|
+
database
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### project.config.js
|
|
121
|
+
|
|
122
|
+
```javascript
|
|
123
|
+
const { projectConfig } = require('nsgm-cli')
|
|
124
|
+
const pkg = require('./package.json')
|
|
125
|
+
|
|
126
|
+
const { prefix, protocol, host, port } = projectConfig
|
|
127
|
+
const { version } = pkg
|
|
128
|
+
|
|
129
|
+
module.exports = {
|
|
130
|
+
version,
|
|
131
|
+
prefix,
|
|
132
|
+
protocol,
|
|
133
|
+
host,
|
|
134
|
+
port
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## 开发指南
|
|
139
|
+
|
|
140
|
+
1. **创建新页面**:使用 `npm run create [controller] [action]` 命令
|
|
141
|
+
2. **启动开发服务器**:运行 `npm run dev`
|
|
142
|
+
3. **构建生产版本**:运行 `npm run build` 然后 `npm run start`
|
|
143
|
+
4. **导出静态网站**:运行 `npm run export`
|
|
144
|
+
|
|
145
|
+
## 更多资源
|
|
146
|
+
|
|
147
|
+
更多详细信息,请参考 [NSGM CLI 文档](https://github.com/erishen/nsgm-cli)。
|
package/next.config.js
CHANGED
|
@@ -63,12 +63,17 @@ module.exports = (phase, defaultConfig, options) => {
|
|
|
63
63
|
// Bundle 优化配置
|
|
64
64
|
experimental: {
|
|
65
65
|
optimizeCss: true, // 启用 CSS 优化(已安装 critters 依赖)
|
|
66
|
-
swcMinify: true, // 使用 SWC 压缩器
|
|
67
66
|
esmExternals: true // 支持 ESM 外部依赖
|
|
68
67
|
},
|
|
69
68
|
compiler: {
|
|
70
69
|
removeConsole: phase !== PHASE_DEVELOPMENT_SERVER,
|
|
71
70
|
},
|
|
71
|
+
allowedDevOrigins: [
|
|
72
|
+
'http://127.0.0.1:8080',
|
|
73
|
+
'http://localhost:8080',
|
|
74
|
+
'http://127.0.0.1:3000',
|
|
75
|
+
'http://localhost:3000'
|
|
76
|
+
],
|
|
72
77
|
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
|
|
73
78
|
// 启用压缩
|
|
74
79
|
if (!dev && !isServer) {
|
|
@@ -105,7 +110,7 @@ module.exports = (phase, defaultConfig, options) => {
|
|
|
105
110
|
},
|
|
106
111
|
minimize: true,
|
|
107
112
|
}
|
|
108
|
-
|
|
113
|
+
|
|
109
114
|
// 添加分析工具
|
|
110
115
|
if (process.env.ANALYZE === 'true') {
|
|
111
116
|
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
|
|
@@ -117,13 +122,13 @@ module.exports = (phase, defaultConfig, options) => {
|
|
|
117
122
|
)
|
|
118
123
|
}
|
|
119
124
|
}
|
|
120
|
-
|
|
125
|
+
|
|
121
126
|
// 优化模块解析
|
|
122
127
|
config.resolve.alias = {
|
|
123
128
|
...config.resolve.alias,
|
|
124
129
|
'@': path.resolve(__dirname, 'client'),
|
|
125
130
|
}
|
|
126
|
-
|
|
131
|
+
|
|
127
132
|
return config
|
|
128
133
|
},
|
|
129
134
|
generateBuildId: async () => {
|
package/package.json
CHANGED
package/pages/_app.tsx
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react'
|
|
2
2
|
import { Provider } from 'react-redux'
|
|
3
3
|
import { ThemeProvider } from 'styled-components'
|
|
4
|
-
import { useStore } from '
|
|
5
|
-
import { GlobalStyle, Loading } from '
|
|
6
|
-
import LayoutComponent from '
|
|
7
|
-
import { login } from '
|
|
4
|
+
import { useStore } from '@/redux/store'
|
|
5
|
+
import { GlobalStyle, Loading } from '@/styled/common'
|
|
6
|
+
import LayoutComponent from '@/layout'
|
|
7
|
+
import { login } from '@/utils/sso'
|
|
8
8
|
import { Spin } from 'antd'
|
|
9
9
|
import 'antd/dist/reset.css'
|
|
10
10
|
|
package/pages/_document.tsx
CHANGED
|
@@ -15,7 +15,9 @@ const MyDocument = () => {
|
|
|
15
15
|
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui" />
|
|
16
16
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
17
17
|
<meta charSet="utf-8" />
|
|
18
|
-
<Head
|
|
18
|
+
<Head>
|
|
19
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
|
|
20
|
+
</Head>
|
|
19
21
|
<body>
|
|
20
22
|
<Main />
|
|
21
23
|
<NextScript />
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react'
|
|
2
2
|
import { ConfigProvider, Table, Modal, Button, Input, Space, Upload, message } from 'antd'
|
|
3
|
-
import { Container, SearchRow, ModalContainer } from '
|
|
3
|
+
import { Container, SearchRow, ModalContainer } from '@/styled/template/manage'
|
|
4
4
|
import styled from 'styled-components'
|
|
5
5
|
import { useDispatch, useSelector } from 'react-redux'
|
|
6
|
-
import { getTemplate, addTemplate, modTemplate, delTemplate, updateSSRTemplate, searchTemplate, batchDelTemplate } from '
|
|
7
|
-
import { getTemplateService } from '
|
|
8
|
-
import { RootState } from '
|
|
6
|
+
import { getTemplate, addTemplate, modTemplate, delTemplate, updateSSRTemplate, searchTemplate, batchDelTemplate } from '@/redux/template/manage/actions'
|
|
7
|
+
import { getTemplateService } from '@/service/template/manage'
|
|
8
|
+
import { RootState } from '@/redux/store'
|
|
9
9
|
import _ from 'lodash'
|
|
10
10
|
import dayjs from 'dayjs'
|
|
11
11
|
import locale from 'antd/lib/locale/zh_CN'
|
|
12
|
-
import { handleXSS, checkModalObj } from '
|
|
12
|
+
import { handleXSS, checkModalObj } from '@/utils/common'
|
|
13
13
|
import { UploadOutlined } from '@ant-design/icons'
|
|
14
14
|
import ExcelJS from 'exceljs'
|
|
15
15
|
import { saveAs } from 'file-saver'
|
|
@@ -58,6 +58,11 @@ const StyledTable = styled(Table)`
|
|
|
58
58
|
margin-top: 16px;
|
|
59
59
|
border-radius: 8px;
|
|
60
60
|
overflow: hidden;
|
|
61
|
+
|
|
62
|
+
.styled-pagination {
|
|
63
|
+
margin-top: 16px;
|
|
64
|
+
margin-bottom: 16px;
|
|
65
|
+
}
|
|
61
66
|
`
|
|
62
67
|
const ModalTitle = styled.div`
|
|
63
68
|
color: #1890ff;
|
|
@@ -66,6 +71,21 @@ const ModalTitle = styled.div`
|
|
|
66
71
|
const ModalInput = styled(Input)`
|
|
67
72
|
border-radius: 4px;
|
|
68
73
|
`
|
|
74
|
+
const IconWrapper = styled.i`
|
|
75
|
+
margin-right: 5px;
|
|
76
|
+
`
|
|
77
|
+
const StyledPagination = styled.div`
|
|
78
|
+
margin-top: 16px;
|
|
79
|
+
margin-bottom: 16px;
|
|
80
|
+
`
|
|
81
|
+
const RoundedButton = styled(Button)`
|
|
82
|
+
border-radius: 4px;
|
|
83
|
+
`
|
|
84
|
+
const GlobalStyle = styled.div`
|
|
85
|
+
.rounded-button {
|
|
86
|
+
border-radius: 4px;
|
|
87
|
+
}
|
|
88
|
+
`
|
|
69
89
|
|
|
70
90
|
const Page = ({ template }) => {
|
|
71
91
|
const dispatch = useDispatch()
|
|
@@ -123,13 +143,13 @@ const Page = ({ template }) => {
|
|
|
123
143
|
render: (_: any, record: any) => {
|
|
124
144
|
return (
|
|
125
145
|
<Space size="small">
|
|
126
|
-
<
|
|
146
|
+
<RoundedButton type="primary" size="small" onClick={() => {
|
|
127
147
|
updateTemplate(record)
|
|
128
|
-
}}
|
|
129
|
-
<
|
|
148
|
+
}}>修改</RoundedButton>
|
|
149
|
+
<RoundedButton danger size="small" onClick={() => {
|
|
130
150
|
const { id } = record
|
|
131
151
|
deleteTemplate(id)
|
|
132
|
-
}}
|
|
152
|
+
}}>删除</RoundedButton>
|
|
133
153
|
</Space>
|
|
134
154
|
)
|
|
135
155
|
}
|
|
@@ -281,13 +301,14 @@ const Page = ({ template }) => {
|
|
|
281
301
|
|
|
282
302
|
return (
|
|
283
303
|
<Container>
|
|
284
|
-
<
|
|
304
|
+
<GlobalStyle />
|
|
305
|
+
<div className="page-title">Template 管理</div>
|
|
285
306
|
<ConfigProvider locale={locale}>
|
|
286
307
|
<SearchRow>
|
|
287
308
|
<Space size="middle" wrap>
|
|
288
309
|
<Space size="small">
|
|
289
310
|
<StyledButton type="primary" onClick={createTemplate} $primary>
|
|
290
|
-
<
|
|
311
|
+
<IconWrapper className="fa fa-plus"></IconWrapper>
|
|
291
312
|
新增
|
|
292
313
|
</StyledButton>
|
|
293
314
|
<StyledInput
|
|
@@ -298,7 +319,7 @@ const Page = ({ template }) => {
|
|
|
298
319
|
onPressEnter={doSearch}
|
|
299
320
|
/>
|
|
300
321
|
<StyledButton type="primary" onClick={doSearch} $primary>
|
|
301
|
-
<
|
|
322
|
+
<IconWrapper className="fa fa-search"></IconWrapper>
|
|
302
323
|
搜索
|
|
303
324
|
</StyledButton>
|
|
304
325
|
</Space>
|
|
@@ -335,11 +356,11 @@ const Page = ({ template }) => {
|
|
|
335
356
|
onChange: (page, pageSize) => {
|
|
336
357
|
dispatch(searchTemplate(page - 1, pageSize, { name: handleXSS(searchName) }))
|
|
337
358
|
},
|
|
338
|
-
|
|
359
|
+
className: "styled-pagination"
|
|
339
360
|
}}
|
|
340
361
|
/>
|
|
341
362
|
<Modal
|
|
342
|
-
title={<ModalTitle>{(modalId == 0 ? "新增" : "修改") + "
|
|
363
|
+
title={<ModalTitle>{(modalId == 0 ? "新增" : "修改") + " Template"}</ModalTitle>}
|
|
343
364
|
open={isModalVisiable}
|
|
344
365
|
onOk={handleOk}
|
|
345
366
|
onCancel={handleCancel}
|
|
@@ -348,8 +369,8 @@ const Page = ({ template }) => {
|
|
|
348
369
|
centered
|
|
349
370
|
maskClosable={false}
|
|
350
371
|
destroyOnClose
|
|
351
|
-
okButtonProps={{
|
|
352
|
-
cancelButtonProps={{
|
|
372
|
+
okButtonProps={{ className: 'rounded-button' }}
|
|
373
|
+
cancelButtonProps={{ className: 'rounded-button' }}
|
|
353
374
|
>
|
|
354
375
|
<ModalContainer>
|
|
355
376
|
<div className="line">
|
package/babel.config.js
DELETED