nsgm-cli 2.1.5 → 2.1.7
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 +0 -2
- package/client/layout/index.tsx +169 -44
- package/client/redux/template/manage/actions.ts +1 -1
- package/client/service/template/manage.ts +11 -11
- package/client/styled/common.ts +18 -22
- package/client/styled/layout/index.ts +131 -9
- package/client/styled/template/manage.ts +86 -2
- package/client/utils/sso.ts +41 -41
- package/lib/tsconfig.build.tsbuildinfo +1 -1
- package/next.config.js +9 -4
- package/package.json +5 -5
- package/pages/_app.tsx +4 -4
- package/pages/_document.tsx +3 -1
- package/pages/index.tsx +84 -40
- package/pages/login.tsx +41 -15
- package/pages/template/manage.tsx +164 -58
- package/babel.config.js +0 -18
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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nsgm-cli",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.7",
|
|
4
4
|
"description": "A CLI tool to run Next/Style-components and Graphql/Mysql fullstack project",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -96,8 +96,8 @@
|
|
|
96
96
|
"mysql2": "3.14.2",
|
|
97
97
|
"next": "15.4.4",
|
|
98
98
|
"rc-util": "5.44.4",
|
|
99
|
-
"react": "
|
|
100
|
-
"react-dom": "
|
|
99
|
+
"react": "18.3.1",
|
|
100
|
+
"react-dom": "18.3.1",
|
|
101
101
|
"react-redux": "9.2.0",
|
|
102
102
|
"redux": "5.0.1",
|
|
103
103
|
"replace": "1.2.2",
|
|
@@ -128,8 +128,8 @@
|
|
|
128
128
|
"@types/mysql": "2.15.27",
|
|
129
129
|
"@types/next": "9.0.0",
|
|
130
130
|
"@types/node": "^24",
|
|
131
|
-
"@types/react": "
|
|
132
|
-
"@types/react-dom": "
|
|
131
|
+
"@types/react": "18.3.23",
|
|
132
|
+
"@types/react-dom": "18.3.7",
|
|
133
133
|
"@types/react-redux": "7.1.34",
|
|
134
134
|
"@types/shelljs": "0.8.17",
|
|
135
135
|
"@types/styled-components": "5.1.34",
|
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 />
|
package/pages/index.tsx
CHANGED
|
@@ -3,6 +3,10 @@ import _ from 'lodash'
|
|
|
3
3
|
import { Container } from '../client/styled/common'
|
|
4
4
|
import getConfig from 'next/config'
|
|
5
5
|
import React from 'react'
|
|
6
|
+
import { Card, Typography, Divider, Row, Col, Tag } from 'antd'
|
|
7
|
+
import { CodeOutlined, BookOutlined, DatabaseOutlined, SettingOutlined } from '@ant-design/icons'
|
|
8
|
+
|
|
9
|
+
const { Title, Paragraph, Text } = Typography
|
|
6
10
|
|
|
7
11
|
const md = new MarkdownIt({
|
|
8
12
|
html: true,
|
|
@@ -14,56 +18,96 @@ const nextConfig = getConfig()
|
|
|
14
18
|
const { publicRuntimeConfig } = nextConfig
|
|
15
19
|
const { env } = publicRuntimeConfig
|
|
16
20
|
|
|
17
|
-
const renderArr: any = []
|
|
18
|
-
|
|
19
|
-
renderArr.push('# NSGM CLI ' + env)
|
|
20
|
-
renderArr.push('- 技术栈: [Next](https://github.com/vercel/next.js), [Styled-components](https://github.com/styled-components/styled-components), [Graphql](https://graphql.org/), [Mysql](https://www.mysql.com/)')
|
|
21
|
-
renderArr.push('- 全栈架构,代码模板生成,快速开发')
|
|
22
|
-
renderArr.push('- 数据库采用 Mysql, 配置见 mysql.config.js')
|
|
23
|
-
renderArr.push('- 项目配置见 project.config.js')
|
|
24
|
-
renderArr.push('- Next 框架配置见 next.config.js')
|
|
25
|
-
|
|
26
|
-
renderArr.push('## 命令')
|
|
27
|
-
renderArr.push('- nsgm init 初始化项目')
|
|
28
|
-
renderArr.push('- nsgm upgrade 升级项目基础文件')
|
|
29
|
-
renderArr.push('- nsgm create 创建模板页面')
|
|
30
|
-
renderArr.push('- nsgm delete 删除模板页面')
|
|
31
|
-
renderArr.push('- nsgm deletedb 删除模板页面及数据库表')
|
|
32
|
-
renderArr.push('- nsgm dev 开发模式')
|
|
33
|
-
renderArr.push('- nsgm start 生产模式')
|
|
34
|
-
renderArr.push('- nsgm build 编译')
|
|
35
|
-
renderArr.push('- nsgm export 导出静态页面')
|
|
36
21
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
22
|
+
const Page = ({ html }) => {
|
|
23
|
+
return (
|
|
24
|
+
<Container>
|
|
25
|
+
<Typography style={{ padding: '24px' }}>
|
|
26
|
+
<Title level={1}>NSGM CLI</Title>
|
|
27
|
+
<Paragraph>
|
|
28
|
+
<Row gutter={[16, 16]}>
|
|
29
|
+
<Col><Tag color="blue">Next</Tag></Col>
|
|
30
|
+
<Col><Tag color="purple">Styled-components</Tag></Col>
|
|
31
|
+
<Col><Tag color="magenta">Graphql</Tag></Col>
|
|
32
|
+
<Col><Tag color="green">Mysql</Tag></Col>
|
|
33
|
+
</Row>
|
|
34
|
+
</Paragraph>
|
|
35
|
+
<Paragraph>
|
|
36
|
+
全栈架构,代码模板生成,快速开发
|
|
37
|
+
</Paragraph>
|
|
41
38
|
|
|
39
|
+
<Card style={{ marginBottom: '24px' }}>
|
|
40
|
+
<Row gutter={[24, 16]}>
|
|
41
|
+
<Col xs={24} md={8}>
|
|
42
|
+
<Card type="inner" title={<><DatabaseOutlined /> 数据库配置</>}>
|
|
43
|
+
数据库采用 Mysql, 配置见 mysql.config.js
|
|
44
|
+
</Card>
|
|
45
|
+
</Col>
|
|
46
|
+
<Col xs={24} md={8}>
|
|
47
|
+
<Card type="inner" title={<><SettingOutlined /> 项目配置</>}>
|
|
48
|
+
项目配置见 project.config.js
|
|
49
|
+
</Card>
|
|
50
|
+
</Col>
|
|
51
|
+
<Col xs={24} md={8}>
|
|
52
|
+
<Card type="inner" title={<><CodeOutlined /> 框架配置</>}>
|
|
53
|
+
Next 框架配置见 next.config.js
|
|
54
|
+
</Card>
|
|
55
|
+
</Col>
|
|
56
|
+
</Row>
|
|
57
|
+
</Card>
|
|
42
58
|
|
|
43
|
-
|
|
59
|
+
<Title level={2}><BookOutlined /> 命令</Title>
|
|
60
|
+
<Divider />
|
|
44
61
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
62
|
+
<Row gutter={[16, 16]}>
|
|
63
|
+
<Col xs={24} md={8}>
|
|
64
|
+
<Card hoverable>
|
|
65
|
+
<Title level={4}>项目管理</Title>
|
|
66
|
+
<ul>
|
|
67
|
+
<li><Text strong>nsgm init</Text> - 初始化项目</li>
|
|
68
|
+
<li><Text strong>nsgm upgrade</Text> - 升级项目基础文件</li>
|
|
69
|
+
</ul>
|
|
70
|
+
</Card>
|
|
71
|
+
</Col>
|
|
72
|
+
<Col xs={24} md={8}>
|
|
73
|
+
<Card hoverable>
|
|
74
|
+
<Title level={4}>模板操作</Title>
|
|
75
|
+
<ul>
|
|
76
|
+
<li><Text strong>nsgm create</Text> - 创建模板页面</li>
|
|
77
|
+
<li><Text strong>nsgm delete</Text> - 删除模板页面</li>
|
|
78
|
+
<li><Text strong>nsgm deletedb</Text> - 删除模板页面及数据库表</li>
|
|
79
|
+
</ul>
|
|
80
|
+
</Card>
|
|
81
|
+
</Col>
|
|
82
|
+
<Col xs={24} md={8}>
|
|
83
|
+
<Card hoverable>
|
|
84
|
+
<Title level={4}>运行与构建</Title>
|
|
85
|
+
<ul>
|
|
86
|
+
<li><Text strong>nsgm dev</Text> - 开发模式</li>
|
|
87
|
+
<li><Text strong>nsgm start</Text> - 生产模式</li>
|
|
88
|
+
<li><Text strong>nsgm build</Text> - 编译</li>
|
|
89
|
+
<li><Text strong>nsgm export</Text> - 导出静态页面</li>
|
|
90
|
+
</ul>
|
|
91
|
+
</Card>
|
|
92
|
+
</Col>
|
|
93
|
+
</Row>
|
|
50
94
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
95
|
+
<Title level={2} style={{ marginTop: '24px' }}>参数</Title>
|
|
96
|
+
<Divider />
|
|
97
|
+
<Card>
|
|
98
|
+
<ul>
|
|
99
|
+
<li><Text strong>dictionary:</Text> 在 export/init 的时候使用, 默认 webapp, 譬如: nsgm export/init dictionary=webapp 或者 nsgm export/init webapp</li>
|
|
100
|
+
<li><Text strong>controller:</Text> 在 create/delete 的时候使用, 必须有。譬如:nsgm create/delete math</li>
|
|
101
|
+
<li><Text strong>action:</Text> 在 create/delete 的时候使用, 默认 manage, 跟在 controller 后面, 譬如 nsgm create/delete math test</li>
|
|
102
|
+
</ul>
|
|
103
|
+
</Card>
|
|
104
|
+
</Typography>
|
|
54
105
|
</Container>
|
|
55
106
|
)
|
|
56
107
|
}
|
|
57
108
|
|
|
58
109
|
Page.getInitialProps = () => {
|
|
59
|
-
|
|
60
|
-
_.each(renderArr, (item, index) => {
|
|
61
|
-
html += md.render(item)
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
html
|
|
66
|
-
}
|
|
110
|
+
return {}
|
|
67
111
|
}
|
|
68
112
|
|
|
69
113
|
export default Page
|
package/pages/login.tsx
CHANGED
|
@@ -4,6 +4,8 @@ import { LoginContainer } from '../client/styled/common'
|
|
|
4
4
|
// import getConfig from 'next/config'
|
|
5
5
|
import React, { useState } from 'react'
|
|
6
6
|
import { handleXSS } from '../client/utils/common'
|
|
7
|
+
import { Input, Button, Form, Typography, message } from 'antd'
|
|
8
|
+
import { UserOutlined, LockOutlined } from '@ant-design/icons'
|
|
7
9
|
|
|
8
10
|
const md = new MarkdownIt({
|
|
9
11
|
html: true,
|
|
@@ -31,11 +33,18 @@ const Page = ({ html }) => {
|
|
|
31
33
|
|
|
32
34
|
const doLogin = () => {
|
|
33
35
|
if (typeof window !== "undefined") {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
if (userName === '') {
|
|
37
|
+
message.error('请输入用户名');
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (userPassword === '') {
|
|
41
|
+
message.error('请输入密码');
|
|
42
|
+
return;
|
|
38
43
|
}
|
|
44
|
+
|
|
45
|
+
let locationHref = window.location.origin + "?ticket=XXX"
|
|
46
|
+
locationHref += "&name=" + btoa(handleXSS(userName + "," + userPassword))
|
|
47
|
+
window.location.href = locationHref
|
|
39
48
|
}
|
|
40
49
|
}
|
|
41
50
|
|
|
@@ -50,17 +59,34 @@ const Page = ({ html }) => {
|
|
|
50
59
|
return (
|
|
51
60
|
<LoginContainer>
|
|
52
61
|
<div dangerouslySetInnerHTML={createMarkup()} />
|
|
53
|
-
<
|
|
54
|
-
<
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
<Typography.Title level={3} style={{ textAlign: 'center', marginBottom: 24 }}>系统登录</Typography.Title>
|
|
63
|
+
<Form layout="vertical" style={{ width: '100%' }}>
|
|
64
|
+
<Form.Item>
|
|
65
|
+
<Input
|
|
66
|
+
prefix={<UserOutlined style={{ color: 'rgba(0,0,0,.25)' }} />}
|
|
67
|
+
placeholder="用户名"
|
|
68
|
+
size="large"
|
|
69
|
+
value={userName}
|
|
70
|
+
onChange={doChangeName}
|
|
71
|
+
autoComplete="off"
|
|
72
|
+
/>
|
|
73
|
+
</Form.Item>
|
|
74
|
+
<Form.Item>
|
|
75
|
+
<Input.Password
|
|
76
|
+
prefix={<LockOutlined style={{ color: 'rgba(0,0,0,.25)' }} />}
|
|
77
|
+
placeholder="密码"
|
|
78
|
+
size="large"
|
|
79
|
+
value={userPassword}
|
|
80
|
+
onChange={doChangePassword}
|
|
81
|
+
autoComplete="off"
|
|
82
|
+
/>
|
|
83
|
+
</Form.Item>
|
|
84
|
+
<Form.Item>
|
|
85
|
+
<Button type="primary" onClick={doLogin} size="large" block>
|
|
86
|
+
登录
|
|
87
|
+
</Button>
|
|
88
|
+
</Form.Item>
|
|
89
|
+
</Form>
|
|
64
90
|
</LoginContainer>
|
|
65
91
|
)
|
|
66
92
|
}
|
|
@@ -1,14 +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
|
+
import styled from 'styled-components'
|
|
4
5
|
import { useDispatch, useSelector } from 'react-redux'
|
|
5
|
-
import { getTemplate, addTemplate, modTemplate, delTemplate, updateSSRTemplate, searchTemplate, batchDelTemplate } from '
|
|
6
|
-
import { getTemplateService } from '
|
|
7
|
-
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'
|
|
8
9
|
import _ from 'lodash'
|
|
9
10
|
import dayjs from 'dayjs'
|
|
10
11
|
import locale from 'antd/lib/locale/zh_CN'
|
|
11
|
-
import { handleXSS, checkModalObj } from '
|
|
12
|
+
import { handleXSS, checkModalObj } from '@/utils/common'
|
|
12
13
|
import { UploadOutlined } from '@ant-design/icons'
|
|
13
14
|
import ExcelJS from 'exceljs'
|
|
14
15
|
import { saveAs } from 'file-saver'
|
|
@@ -16,12 +17,76 @@ import { saveAs } from 'file-saver'
|
|
|
16
17
|
const pageSize = 100
|
|
17
18
|
const dateFormat = 'YYYY-MM-DD'
|
|
18
19
|
const currentDate = dayjs().format(dateFormat)
|
|
19
|
-
console.log('currentDate', currentDate)
|
|
20
20
|
|
|
21
21
|
const keyTitles = {
|
|
22
22
|
name: '名称'
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
// styled-components
|
|
26
|
+
const StyledButton = styled(Button) <{ $primary?: boolean; $export?: boolean; $import?: boolean; $danger?: boolean }>`
|
|
27
|
+
display: flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
border-radius: 6px;
|
|
30
|
+
box-shadow: 0 2px 0 rgba(0, 0, 0, 0.045);
|
|
31
|
+
${props => props.$export && `
|
|
32
|
+
background-color: #f6ffed;
|
|
33
|
+
color: #52c41a;
|
|
34
|
+
border-color: #b7eb8f;
|
|
35
|
+
box-shadow: 0 2px 0 rgba(0, 0, 0, 0.015);
|
|
36
|
+
transition: all 0.3s ease;
|
|
37
|
+
`}
|
|
38
|
+
${props => props.$import && `
|
|
39
|
+
background-color: #e6f7ff;
|
|
40
|
+
color: #1890ff;
|
|
41
|
+
border-color: #91d5ff;
|
|
42
|
+
box-shadow: 0 2px 0 rgba(0, 0, 0, 0.015);
|
|
43
|
+
transition: all 0.3s ease;
|
|
44
|
+
`}
|
|
45
|
+
${props => props.$danger && `
|
|
46
|
+
background-color: #fff1f0;
|
|
47
|
+
border-color: #ffa39e;
|
|
48
|
+
box-shadow: 0 2px 0 rgba(0, 0, 0, 0.015);
|
|
49
|
+
transition: all 0.3s ease;
|
|
50
|
+
`}
|
|
51
|
+
`
|
|
52
|
+
const StyledInput = styled(Input)`
|
|
53
|
+
width: 200px;
|
|
54
|
+
border-radius: 6px;
|
|
55
|
+
box-shadow: 0 2px 0 rgba(0, 0, 0, 0.015);
|
|
56
|
+
`
|
|
57
|
+
const StyledTable = styled(Table)`
|
|
58
|
+
margin-top: 16px;
|
|
59
|
+
border-radius: 8px;
|
|
60
|
+
overflow: hidden;
|
|
61
|
+
|
|
62
|
+
.styled-pagination {
|
|
63
|
+
margin-top: 16px;
|
|
64
|
+
margin-bottom: 16px;
|
|
65
|
+
}
|
|
66
|
+
`
|
|
67
|
+
const ModalTitle = styled.div`
|
|
68
|
+
color: #1890ff;
|
|
69
|
+
font-weight: 500;
|
|
70
|
+
`
|
|
71
|
+
const ModalInput = styled(Input)`
|
|
72
|
+
border-radius: 4px;
|
|
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
|
+
`
|
|
89
|
+
|
|
25
90
|
const Page = ({ template }) => {
|
|
26
91
|
const dispatch = useDispatch()
|
|
27
92
|
const [isModalVisiable, setIsModalVisible] = useState(false)
|
|
@@ -36,14 +101,12 @@ const Page = ({ template }) => {
|
|
|
36
101
|
|
|
37
102
|
const state = useSelector((state: RootState) => state)
|
|
38
103
|
const { templateManage }: any = state
|
|
39
|
-
console.log('templateManage', templateManage)
|
|
40
104
|
|
|
41
105
|
if (!templateManage.firstLoadFlag) {
|
|
42
106
|
template = templateManage.template
|
|
43
107
|
}
|
|
44
108
|
|
|
45
109
|
const { totalCounts, items: templateItems } = _.cloneDeep(template)
|
|
46
|
-
console.log('template', template)
|
|
47
110
|
|
|
48
111
|
_.each(templateItems, (item, index) => {
|
|
49
112
|
const { id } = item
|
|
@@ -58,7 +121,9 @@ const Page = ({ template }) => {
|
|
|
58
121
|
key: 'id',
|
|
59
122
|
sorter: (a: any, b: any) => a.id - b.id,
|
|
60
123
|
sortDirections: ['descend', 'ascend'],
|
|
61
|
-
showSorterTooltip: false
|
|
124
|
+
showSorterTooltip: false,
|
|
125
|
+
width: '15%',
|
|
126
|
+
align: 'center'
|
|
62
127
|
},
|
|
63
128
|
{
|
|
64
129
|
title: keyTitles.name,
|
|
@@ -66,23 +131,25 @@ const Page = ({ template }) => {
|
|
|
66
131
|
key: 'name',
|
|
67
132
|
sorter: (a: any, b: any) => a.name.length - b.name.length,
|
|
68
133
|
sortDirections: ['descend', 'ascend'],
|
|
69
|
-
showSorterTooltip: false
|
|
134
|
+
showSorterTooltip: false,
|
|
135
|
+
width: '60%',
|
|
136
|
+
ellipsis: true
|
|
70
137
|
},
|
|
71
138
|
{
|
|
72
139
|
title: '操作',
|
|
73
140
|
dataIndex: '',
|
|
141
|
+
width: '25%',
|
|
142
|
+
align: 'center',
|
|
74
143
|
render: (_: any, record: any) => {
|
|
75
144
|
return (
|
|
76
|
-
<Space>
|
|
77
|
-
<
|
|
78
|
-
console.log('record', record)
|
|
145
|
+
<Space size="small">
|
|
146
|
+
<RoundedButton type="primary" size="small" onClick={() => {
|
|
79
147
|
updateTemplate(record)
|
|
80
|
-
}}>修改</
|
|
81
|
-
<
|
|
82
|
-
console.log('record', record)
|
|
148
|
+
}}>修改</RoundedButton>
|
|
149
|
+
<RoundedButton danger size="small" onClick={() => {
|
|
83
150
|
const { id } = record
|
|
84
151
|
deleteTemplate(id)
|
|
85
|
-
}}>删除</
|
|
152
|
+
}}>删除</RoundedButton>
|
|
86
153
|
</Space>
|
|
87
154
|
)
|
|
88
155
|
}
|
|
@@ -91,7 +158,7 @@ const Page = ({ template }) => {
|
|
|
91
158
|
|
|
92
159
|
const rowSelection = {
|
|
93
160
|
onChange: (selectedRowKeys: any, selectedRows: any) => {
|
|
94
|
-
|
|
161
|
+
//
|
|
95
162
|
setBatchDelIds(selectedRowKeys)
|
|
96
163
|
}
|
|
97
164
|
}
|
|
@@ -138,7 +205,7 @@ const Page = ({ template }) => {
|
|
|
138
205
|
const modalObj = {
|
|
139
206
|
name: handleXSS(modalName)
|
|
140
207
|
}
|
|
141
|
-
|
|
208
|
+
//
|
|
142
209
|
|
|
143
210
|
const checkResult = checkModalObj(modalObj)
|
|
144
211
|
|
|
@@ -192,8 +259,8 @@ const Page = ({ template }) => {
|
|
|
192
259
|
wb.xlsx.writeBuffer().then((data) => {
|
|
193
260
|
const blob = new Blob([data], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
|
|
194
261
|
saveAs(blob, "Template.xlsx")
|
|
195
|
-
}).catch((
|
|
196
|
-
|
|
262
|
+
}).catch(() => {
|
|
263
|
+
// 导出失败
|
|
197
264
|
})
|
|
198
265
|
} else {
|
|
199
266
|
message.info("没有数据无需导出")
|
|
@@ -204,9 +271,7 @@ const Page = ({ template }) => {
|
|
|
204
271
|
name: 'file',
|
|
205
272
|
action: '/rest/template/import',
|
|
206
273
|
onChange(info: any) {
|
|
207
|
-
|
|
208
|
-
console.log(info.file, info.fileList)
|
|
209
|
-
}
|
|
274
|
+
//
|
|
210
275
|
|
|
211
276
|
if (info.file.status === 'done') {
|
|
212
277
|
message.success(`${info.file.name} 文件上传成功`)
|
|
@@ -236,43 +301,87 @@ const Page = ({ template }) => {
|
|
|
236
301
|
|
|
237
302
|
return (
|
|
238
303
|
<Container>
|
|
304
|
+
<GlobalStyle />
|
|
305
|
+
<div className="page-title">Template 管理</div>
|
|
239
306
|
<ConfigProvider locale={locale}>
|
|
240
307
|
<SearchRow>
|
|
241
|
-
<Space>
|
|
242
|
-
<
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
308
|
+
<Space size="middle" wrap>
|
|
309
|
+
<Space size="small">
|
|
310
|
+
<StyledButton type="primary" onClick={createTemplate} $primary>
|
|
311
|
+
<IconWrapper className="fa fa-plus"></IconWrapper>
|
|
312
|
+
新增
|
|
313
|
+
</StyledButton>
|
|
314
|
+
<StyledInput
|
|
315
|
+
value={searchName}
|
|
316
|
+
placeholder="请输入名称搜索"
|
|
317
|
+
allowClear
|
|
318
|
+
onChange={(e) => setSearchName(e.target.value)}
|
|
319
|
+
onPressEnter={doSearch}
|
|
320
|
+
/>
|
|
321
|
+
<StyledButton type="primary" onClick={doSearch} $primary>
|
|
322
|
+
<IconWrapper className="fa fa-search"></IconWrapper>
|
|
323
|
+
搜索
|
|
324
|
+
</StyledButton>
|
|
325
|
+
</Space>
|
|
326
|
+
<Space size="small">
|
|
327
|
+
<StyledButton onClick={exportTemplate} icon={<UploadOutlined rev={undefined} rotate={180} />} $export>
|
|
328
|
+
导出
|
|
329
|
+
</StyledButton>
|
|
330
|
+
<Upload {...uploadProps}>
|
|
331
|
+
<StyledButton icon={<UploadOutlined rev={undefined} />} $import>
|
|
332
|
+
导入
|
|
333
|
+
</StyledButton>
|
|
334
|
+
</Upload>
|
|
335
|
+
<StyledButton danger onClick={batchDeleteTemplate} $danger>
|
|
336
|
+
批量删除
|
|
337
|
+
</StyledButton>
|
|
338
|
+
</Space>
|
|
258
339
|
</Space>
|
|
259
340
|
</SearchRow>
|
|
260
|
-
<
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
341
|
+
<StyledTable
|
|
342
|
+
rowSelection={{
|
|
343
|
+
type: 'checkbox',
|
|
344
|
+
...rowSelection,
|
|
345
|
+
}}
|
|
346
|
+
dataSource={dataSource}
|
|
347
|
+
columns={columns}
|
|
348
|
+
bordered
|
|
349
|
+
rowClassName={(record, index) => index % 2 === 0 ? 'table-row-light' : 'table-row-dark'}
|
|
350
|
+
pagination={{
|
|
351
|
+
total: totalCounts,
|
|
352
|
+
pageSize: pageSize,
|
|
353
|
+
showSizeChanger: false,
|
|
354
|
+
showQuickJumper: true,
|
|
355
|
+
showTotal: (total) => `共 ${total} 条记录`,
|
|
356
|
+
onChange: (page, pageSize) => {
|
|
357
|
+
dispatch(searchTemplate(page - 1, pageSize, { name: handleXSS(searchName) }))
|
|
358
|
+
},
|
|
359
|
+
className: "styled-pagination"
|
|
360
|
+
}}
|
|
361
|
+
/>
|
|
362
|
+
<Modal
|
|
363
|
+
title={<ModalTitle>{(modalId == 0 ? "新增" : "修改") + " Template"}</ModalTitle>}
|
|
364
|
+
open={isModalVisiable}
|
|
365
|
+
onOk={handleOk}
|
|
366
|
+
onCancel={handleCancel}
|
|
367
|
+
okText="确认"
|
|
368
|
+
cancelText="取消"
|
|
369
|
+
centered
|
|
370
|
+
maskClosable={false}
|
|
371
|
+
destroyOnClose
|
|
372
|
+
okButtonProps={{ className: 'rounded-button' }}
|
|
373
|
+
cancelButtonProps={{ className: 'rounded-button' }}
|
|
374
|
+
>
|
|
272
375
|
<ModalContainer>
|
|
273
376
|
<div className="line">
|
|
274
|
-
<label>{keyTitles.name}
|
|
275
|
-
<
|
|
377
|
+
<label>{keyTitles.name}:</label>
|
|
378
|
+
<ModalInput
|
|
379
|
+
value={modalName}
|
|
380
|
+
placeholder="请输入名称"
|
|
381
|
+
allowClear
|
|
382
|
+
autoFocus
|
|
383
|
+
onChange={(e) => setModalName(e.target.value)}
|
|
384
|
+
/>
|
|
276
385
|
</div>
|
|
277
386
|
</ModalContainer>
|
|
278
387
|
</Modal>
|
|
@@ -285,13 +394,10 @@ Page.getInitialProps = async () => {
|
|
|
285
394
|
let template = null
|
|
286
395
|
|
|
287
396
|
await getTemplateService(0, pageSize).then((res: any) => {
|
|
288
|
-
console.log('res', res)
|
|
289
397
|
const { data } = res
|
|
290
398
|
template = data.template
|
|
291
399
|
})
|
|
292
400
|
|
|
293
|
-
console.log('template-getInitialProps', template)
|
|
294
|
-
|
|
295
401
|
return {
|
|
296
402
|
template
|
|
297
403
|
}
|