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/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.5",
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": "^19",
100
- "react-dom": "^19",
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": "^19",
132
- "@types/react-dom": "^19",
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 '../client/redux/store'
5
- import { GlobalStyle, Loading } from '../client/styled/common'
6
- import LayoutComponent from '../client/layout'
7
- import { login } from '../client/utils/sso'
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
 
@@ -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
- renderArr.push('## 参数')
38
- renderArr.push('- dictionary: 在 export/init 的时候使用, 默认 webapp, 譬如: nsgm export/init dictionary=webapp 或者 nsgm export/init webapp')
39
- renderArr.push('- controller: 在 create/delete 的时候使用, 必须有。譬如:nsgm create/delete math')
40
- renderArr.push('- action: create/delete 的时候使用, 默认 manage, 跟在 controller 后面, 譬如 nsgm create/delete math test')
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
- const Page = ({ html }) => {
59
+ <Title level={2}><BookOutlined /> 命令</Title>
60
+ <Divider />
44
61
 
45
- const createMarkup = () => {
46
- return {
47
- __html: html
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
- return (
52
- <Container>
53
- <div dangerouslySetInnerHTML={createMarkup()} />
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
- let html = ''
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
- let locationHref = window.location.origin + "?ticket=XXX"
35
- if (userName !== '') {
36
- locationHref += "&name=" + btoa(handleXSS(userName + "," + userPassword))
37
- window.location.href = locationHref
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
- <input type="text" style={{ opacity: 0, position: "absolute", width: 0, height: 0 }}></input>
54
- <input type="password" style={{ opacity: 0, position: "absolute", width: 0, height: 0 }}></input>
55
- <div className='row'>
56
- <input type="text" name="user-name" className='user-input' autoComplete='off' onChange={doChangeName} value={userName}></input>
57
- </div>
58
- <div className='row'>
59
- <input type="password" name="user-password" className='user-input' autoComplete='off' onChange={doChangePassword} value={userPassword}></input>
60
- </div>
61
- <div className='row right'>
62
- <button onClick={doLogin}>login</button>
63
- </div>
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 '../../client/styled/template/manage'
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 '../../client/redux/template/manage/actions'
6
- import { getTemplateService } from '../../client/service/template/manage'
7
- import { RootState } from '../../client/redux/store'
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 '../../client/utils/common'
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
- <Button onClick={() => {
78
- console.log('record', record)
145
+ <Space size="small">
146
+ <RoundedButton type="primary" size="small" onClick={() => {
79
147
  updateTemplate(record)
80
- }}>修改</Button>
81
- <Button onClick={() => {
82
- console.log('record', record)
148
+ }}>修改</RoundedButton>
149
+ <RoundedButton danger size="small" onClick={() => {
83
150
  const { id } = record
84
151
  deleteTemplate(id)
85
- }}>删除</Button>
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
- console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows)
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
- console.log('handleOk', modalObj)
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((error) => {
196
- console.error('导出失败', error?.message)
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
- if (info.file.status !== 'uploading') {
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
- <Button type="primary" onClick={createTemplate}>
243
- 新增
244
- </Button>
245
- <Input value={searchName} placeholder="" onChange={(e) => setSearchName(e.target.value)} />
246
- <Button type="primary" onClick={doSearch}>
247
- 搜索
248
- </Button>
249
- <Button type="primary" onClick={exportTemplate}>
250
- 导出
251
- </Button>
252
- <Upload {...uploadProps}>
253
- <Button icon={<UploadOutlined rev={undefined} />}>导入</Button>
254
- </Upload>
255
- <Button type="primary" onClick={batchDeleteTemplate}>
256
- 批量删除
257
- </Button>
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
- <Table rowSelection={{
261
- type: 'checkbox',
262
- ...rowSelection,
263
- }} dataSource={dataSource} columns={columns} pagination={{
264
- total: totalCounts,
265
- pageSize: pageSize,
266
- onChange: (page, pageSize) => {
267
- console.log('onChange', page, pageSize)
268
- dispatch(searchTemplate(page - 1, pageSize, { name: handleXSS(searchName) }))
269
- }
270
- }} />
271
- <Modal title={(modalId == 0 ? "新增" : "修改") + " template"} open={isModalVisiable} onOk={handleOk} onCancel={handleCancel} okText="确认" cancelText="取消">
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}</label>
275
- <Input value={modalName} placeholder="" onChange={(e) => setModalName(e.target.value)} />
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
  }