nsgm-cli 2.1.12 → 2.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/README.md +369 -163
  2. package/client/components/Button.tsx +3 -5
  3. package/client/components/__tests__/Button.test.tsx +10 -10
  4. package/client/layout/index.tsx +149 -137
  5. package/client/redux/reducers.ts +1 -1
  6. package/client/redux/store.ts +2 -1
  7. package/client/redux/template/manage/actions.ts +77 -88
  8. package/client/redux/template/manage/reducers.ts +25 -37
  9. package/client/redux/template/manage/types.ts +1 -1
  10. package/client/service/template/manage.ts +20 -21
  11. package/client/styled/common.ts +12 -13
  12. package/client/styled/layout/index.ts +19 -19
  13. package/client/styled/template/manage.ts +14 -13
  14. package/client/utils/common.ts +23 -21
  15. package/client/utils/cookie.ts +18 -19
  16. package/client/utils/fetch.ts +64 -100
  17. package/client/utils/menu.tsx +16 -3
  18. package/client/utils/sso.ts +74 -84
  19. package/eslint.config.js +38 -1
  20. package/generation/README.md +25 -18
  21. package/generation/__tests__/example.test.js +41 -0
  22. package/generation/client/utils/menu.tsx +9 -2
  23. package/generation/env.example +3 -0
  24. package/generation/eslint.config.js +112 -0
  25. package/generation/gitignore +6 -1
  26. package/generation/jest.config.js +40 -0
  27. package/generation/package.json +25 -4
  28. package/jest.config.js +23 -6
  29. package/lib/args.js +9 -1
  30. package/lib/cli/app.d.ts +28 -0
  31. package/lib/cli/app.js +99 -0
  32. package/lib/cli/commands/build.d.ts +2 -0
  33. package/lib/cli/commands/build.js +29 -0
  34. package/lib/cli/commands/create.d.ts +2 -0
  35. package/lib/cli/commands/create.js +113 -0
  36. package/lib/cli/commands/delete.d.ts +3 -0
  37. package/lib/cli/commands/delete.js +151 -0
  38. package/lib/cli/commands/export.d.ts +2 -0
  39. package/lib/cli/commands/export.js +42 -0
  40. package/lib/cli/commands/help.d.ts +2 -0
  41. package/lib/cli/commands/help.js +42 -0
  42. package/lib/cli/commands/init.d.ts +2 -0
  43. package/lib/cli/commands/init.js +115 -0
  44. package/lib/cli/commands/server.d.ts +3 -0
  45. package/lib/cli/commands/server.js +26 -0
  46. package/lib/cli/commands/upgrade.d.ts +2 -0
  47. package/lib/cli/commands/upgrade.js +38 -0
  48. package/lib/cli/commands/version.d.ts +2 -0
  49. package/lib/cli/commands/version.js +24 -0
  50. package/lib/cli/index.d.ts +16 -0
  51. package/lib/cli/index.js +33 -0
  52. package/lib/cli/parser.d.ts +22 -0
  53. package/lib/cli/parser.js +115 -0
  54. package/lib/cli/registry.d.ts +33 -0
  55. package/lib/cli/registry.js +81 -0
  56. package/lib/cli/types/project.d.ts +10 -0
  57. package/lib/cli/types/project.js +2 -0
  58. package/lib/cli/types.d.ts +31 -0
  59. package/lib/cli/types.js +20 -0
  60. package/lib/cli/utils/console.d.ts +62 -0
  61. package/lib/cli/utils/console.js +148 -0
  62. package/lib/cli/utils/index.d.ts +2 -0
  63. package/lib/cli/utils/index.js +7 -0
  64. package/lib/cli/utils/prompt.d.ts +83 -0
  65. package/lib/cli/utils/prompt.js +368 -0
  66. package/lib/constants.d.ts +58 -0
  67. package/lib/constants.js +162 -0
  68. package/lib/generate.d.ts +25 -3
  69. package/lib/generate.js +97 -621
  70. package/lib/generate_create.d.ts +9 -0
  71. package/lib/generate_create.js +326 -0
  72. package/lib/generate_delete.d.ts +8 -0
  73. package/lib/generate_delete.js +156 -0
  74. package/lib/generate_init.d.ts +50 -0
  75. package/lib/generate_init.js +492 -0
  76. package/lib/generators/base-generator.d.ts +47 -0
  77. package/lib/generators/base-generator.js +92 -0
  78. package/lib/generators/generator-factory.d.ts +20 -0
  79. package/lib/generators/generator-factory.js +25 -0
  80. package/lib/generators/page-generator.d.ts +41 -0
  81. package/lib/generators/page-generator.js +552 -0
  82. package/lib/generators/resolver-generator.d.ts +12 -0
  83. package/lib/generators/resolver-generator.js +303 -0
  84. package/lib/generators/schema-generator.d.ts +7 -0
  85. package/lib/generators/schema-generator.js +57 -0
  86. package/lib/generators/service-generator.d.ts +7 -0
  87. package/lib/generators/service-generator.js +119 -0
  88. package/lib/generators/sql-generator.d.ts +8 -0
  89. package/lib/generators/sql-generator.js +52 -0
  90. package/lib/index.d.ts +1 -1
  91. package/lib/index.js +14 -193
  92. package/lib/server/csrf.js +9 -16
  93. package/lib/server/db.js +6 -7
  94. package/lib/server/graphql.js +5 -6
  95. package/lib/server/plugins/date.js +1 -1
  96. package/lib/server/utils/graphql-cache.js +3 -3
  97. package/lib/tsconfig.build.tsbuildinfo +1 -1
  98. package/lib/utils/project-config.d.ts +5 -0
  99. package/lib/utils/project-config.js +145 -0
  100. package/lib/utils.js +1 -1
  101. package/next.config.js +12 -8
  102. package/package.json +10 -7
  103. package/pages/_app.tsx +23 -28
  104. package/pages/_document.tsx +39 -19
  105. package/pages/index.tsx +84 -39
  106. package/pages/login.tsx +21 -21
  107. package/pages/template/manage.tsx +114 -89
  108. package/public/fonts/font-awesome.min.css +4 -0
  109. package/public/fonts/fontawesome-webfont.woff +0 -0
  110. package/public/fonts/fontawesome-webfont.woff2 +0 -0
  111. package/public/slbhealthcheck.html +1 -1
  112. package/server/apis/template.js +0 -2
  113. package/generation/eslintrc.js +0 -16
@@ -0,0 +1,41 @@
1
+ import { BaseGenerator } from './base-generator';
2
+ /**
3
+ * 页面生成器
4
+ * 基于现有的 pages/template/manage.tsx 模板生成页面组件
5
+ */
6
+ export declare class PageGenerator extends BaseGenerator {
7
+ generate(): string;
8
+ /**
9
+ * 生成键值标题映射
10
+ */
11
+ private generateKeyTitles;
12
+ /**
13
+ * 生成模态框状态变量
14
+ */
15
+ private generateModalStates;
16
+ /**
17
+ * 生成记录解构
18
+ */
19
+ private generateRecordDestructuring;
20
+ /**
21
+ * 生成模态框重置状态
22
+ */
23
+ private generateModalResetStates;
24
+ /**
25
+ * 生成模态框设置状态
26
+ */
27
+ private generateModalSetStates;
28
+ /**
29
+ * 生成模态框对象
30
+ */
31
+ private generateModalObj;
32
+ /**
33
+ * 生成模态框字段
34
+ */
35
+ private generateModalFields;
36
+ /**
37
+ * 生成Excel列配置
38
+ */
39
+ private generateExcelColumns;
40
+ private generateTableColumns;
41
+ }
@@ -0,0 +1,552 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PageGenerator = void 0;
4
+ const base_generator_1 = require("./base-generator");
5
+ /**
6
+ * 页面生成器
7
+ * 基于现有的 pages/template/manage.tsx 模板生成页面组件
8
+ */
9
+ class PageGenerator extends base_generator_1.BaseGenerator {
10
+ generate() {
11
+ const capitalizedController = this.getCapitalizedController();
12
+ const capitalizedAction = this.getCapitalizedAction();
13
+ // 获取各种字段类型
14
+ const listFields = this.getDisplayFields();
15
+ const formFields = this.getFormFields();
16
+ const searchFields = this.getSearchableFields();
17
+ // 生成键值标题映射
18
+ const keyTitles = this.generateKeyTitles();
19
+ // 生成表格列定义
20
+ const tableColumns = this.generateTableColumns(listFields);
21
+ // 生成表单字段
22
+ const modalFields = this.generateModalFields(formFields);
23
+ // 生成搜索字段(取第一个可搜索字段作为主要搜索)
24
+ const mainSearchField = searchFields.length > 0 ? searchFields[0] : null;
25
+ return `import React, { useState, useEffect } from 'react'
26
+ import { ConfigProvider, Table, Modal, Button, Input, Space, Upload, message } from 'antd'
27
+ import { Container, SearchRow, ModalContainer } from '@/styled/${this.controller}/${this.action}'
28
+ import styled from 'styled-components'
29
+ import { useDispatch, useSelector } from 'react-redux'
30
+ import {
31
+ add${capitalizedController},
32
+ mod${capitalizedController},
33
+ del${capitalizedController},
34
+ updateSSR${capitalizedController},
35
+ search${capitalizedController},
36
+ batchDel${capitalizedController}
37
+ } from '@/redux/${this.controller}/${this.action}/actions'
38
+ import { get${capitalizedController}Service } from '@/service/${this.controller}/${this.action}'
39
+ import { RootState, AppDispatch } from '@/redux/store'
40
+ import _ from 'lodash'
41
+ import locale from 'antd/lib/locale/zh_CN'
42
+ import { handleXSS, checkModalObj } from '@/utils/common'
43
+ import { UploadOutlined } from '@ant-design/icons'
44
+ import ExcelJS from 'exceljs'
45
+ import { saveAs } from 'file-saver'
46
+ import { createCSRFUploadProps } from '@/utils/fetch'
47
+
48
+ const pageSize = 100
49
+
50
+ const keyTitles = {
51
+ ${keyTitles}
52
+ }
53
+
54
+ // styled-components
55
+ const StyledButton = styled(Button)<{ $primary?: boolean; $export?: boolean; $import?: boolean; $danger?: boolean }>\`
56
+ display: flex;
57
+ align-items: center;
58
+ border-radius: 6px;
59
+ box-shadow: 0 2px 0 rgba(0, 0, 0, 0.045);
60
+ \${(props) =>
61
+ props.$export &&
62
+ \`
63
+ background-color: #f6ffed;
64
+ color: #52c41a;
65
+ border-color: #b7eb8f;
66
+ box-shadow: 0 2px 0 rgba(0, 0, 0, 0.015);
67
+ transition: all 0.3s ease;
68
+ \`}
69
+ \${(props) =>
70
+ props.$import &&
71
+ \`
72
+ background-color: #e6f7ff;
73
+ color: #1890ff;
74
+ border-color: #91d5ff;
75
+ box-shadow: 0 2px 0 rgba(0, 0, 0, 0.015);
76
+ transition: all 0.3s ease;
77
+ \`}
78
+ \${(props) =>
79
+ props.$danger &&
80
+ \`
81
+ background-color: #fff1f0;
82
+ border-color: #ffa39e;
83
+ box-shadow: 0 2px 0 rgba(0, 0, 0, 0.015);
84
+ transition: all 0.3s ease;
85
+ \`}
86
+ \`${mainSearchField
87
+ ? `
88
+ const StyledInput = styled(Input)\`
89
+ width: 200px;
90
+ border-radius: 6px;
91
+ box-shadow: 0 2px 0 rgba(0, 0, 0, 0.015);
92
+ \``
93
+ : ''}
94
+ const StyledTable = styled(Table)\`
95
+ margin-top: 16px;
96
+ border-radius: 8px;
97
+ overflow: hidden;
98
+
99
+ .styled-pagination {
100
+ margin-top: 16px;
101
+ margin-bottom: 16px;
102
+ }
103
+ \`
104
+ const ModalTitle = styled.div\`
105
+ color: #1890ff;
106
+ font-weight: 500;
107
+ \`
108
+ const ModalInput = styled(Input)\`
109
+ border-radius: 4px;
110
+ \`
111
+ const IconWrapper = styled.i\`
112
+ margin-right: 5px;
113
+ \`
114
+ const RoundedButton = styled(Button)\`
115
+ border-radius: 4px;
116
+ \`
117
+ const GlobalStyle = styled.div\`
118
+ .rounded-button {
119
+ border-radius: 4px;
120
+ }
121
+ \`
122
+
123
+ const Page = ({ ${this.controller} }) => {
124
+ const dispatch = useDispatch<AppDispatch>()
125
+ const [isModalVisiable, setIsModalVisible] = useState(false)
126
+ const [modalId, setModalId] = useState(0)
127
+ ${this.generateModalStates()}${mainSearchField ? "\n const [searchKeyword, setSearchKeyword] = useState('')" : ''}
128
+ const [batchDelIds, setBatchDelIds] = useState([])
129
+
130
+ useEffect(() => {
131
+ dispatch(updateSSR${capitalizedController}(${this.controller}))
132
+ }, [dispatch])
133
+
134
+ const ${this.controller}${capitalizedAction} = useSelector((state: RootState) => state.${this.controller}${capitalizedAction})
135
+
136
+ if (!${this.controller}${capitalizedAction}.firstLoadFlag) {
137
+ ${this.controller} = ${this.controller}${capitalizedAction}.${this.controller}
138
+ }
139
+
140
+ const { totalCounts, items: ${this.controller}Items } = _.cloneDeep(${this.controller})
141
+
142
+ _.each(${this.controller}Items, (item) => {
143
+ const { id } = item
144
+ item.key = id
145
+ })
146
+
147
+ const dataSource = ${this.controller}Items
148
+ const columns: any = [
149
+ ${tableColumns},
150
+ {
151
+ title: '操作',
152
+ dataIndex: '',
153
+ width: '25%',
154
+ align: 'center',
155
+ render: (_: any, record: any) => {
156
+ return (
157
+ <Space size="small">
158
+ <RoundedButton
159
+ type="primary"
160
+ size="small"
161
+ onClick={() => {
162
+ update${capitalizedController}(record)
163
+ }}
164
+ >
165
+ 修改
166
+ </RoundedButton>
167
+ <RoundedButton
168
+ danger
169
+ size="small"
170
+ onClick={() => {
171
+ const { id } = record
172
+ delete${capitalizedController}(id)
173
+ }}
174
+ >
175
+ 删除
176
+ </RoundedButton>
177
+ </Space>
178
+ )
179
+ }
180
+ }
181
+ ]
182
+
183
+ const rowSelection = {
184
+ onChange: (selectedRowKeys: any) => {
185
+ setBatchDelIds(selectedRowKeys)
186
+ }
187
+ }
188
+
189
+ const create${capitalizedController} = () => {
190
+ setModalId(0)
191
+ ${this.generateModalResetStates()}
192
+ showModal()
193
+ }
194
+
195
+ const update${capitalizedController} = (record: any) => {
196
+ const { id${this.generateRecordDestructuring()} } = record
197
+
198
+ setModalId(id)
199
+ ${this.generateModalSetStates()}
200
+ showModal()
201
+ }
202
+
203
+ const delete${capitalizedController} = (id: number) => {
204
+ Modal.confirm({
205
+ title: '提示',
206
+ content: '确认删除吗',
207
+ okText: '确认',
208
+ cancelText: '取消',
209
+ onOk: () => {
210
+ dispatch(del${capitalizedController}(id))
211
+ Modal.destroyAll()
212
+ }
213
+ })
214
+ }
215
+
216
+ const showModal = () => {
217
+ setIsModalVisible(true)
218
+ }
219
+
220
+ const getMessageTitle = (key: string) => {
221
+ let result = keyTitles[key]
222
+ if (result == undefined) result = key
223
+ return result
224
+ }
225
+
226
+ const handleOk = () => {
227
+ const modalObj = {
228
+ ${this.generateModalObj()}
229
+ }
230
+
231
+ const checkResult = checkModalObj(modalObj)
232
+
233
+ if (!checkResult) {
234
+ if (modalId == 0) {
235
+ // 新增
236
+ dispatch(add${capitalizedController}(modalObj))
237
+ } else {
238
+ dispatch(mod${capitalizedController}(modalId, modalObj))
239
+ }
240
+
241
+ setIsModalVisible(false)
242
+ } else {
243
+ message.info(getMessageTitle(checkResult.key) + checkResult.reason)
244
+ }
245
+ }
246
+
247
+ const handleCancel = () => {
248
+ setIsModalVisible(false)
249
+ }
250
+
251
+ const doSearch = () => {
252
+ ${mainSearchField
253
+ ? `const searchData = { ${mainSearchField.name}: handleXSS(searchKeyword) }`
254
+ : 'const searchData = {}'}
255
+ dispatch(search${capitalizedController}(0, pageSize, searchData))
256
+ }
257
+
258
+ const export${capitalizedController} = () => {
259
+ if (${this.controller}Items.length > 0) {
260
+ const wb = new ExcelJS.Workbook()
261
+ const ws = wb.addWorksheet('${capitalizedController}')
262
+ const jsonData = _.map(${this.controller}Items, (item) => _.omit(item, ['key']))
263
+
264
+ // 提取表头
265
+ const headers = Object.keys(jsonData[0])
266
+
267
+ // 将 JSON 数据转换为二维数组
268
+ const data = [headers, ...jsonData.map((item) => headers.map((header) => item[header]))]
269
+
270
+ // 将数据写入工作表
271
+ ws.addRows(data)
272
+
273
+ // 设置表头样式加粗
274
+ ws.getRow(1).eachCell((cell) => {
275
+ cell.font = { bold: true }
276
+ })
277
+
278
+ // 设置列宽
279
+ ws.columns = [
280
+ ${this.generateExcelColumns()}
281
+ ]
282
+
283
+ wb.xlsx
284
+ .writeBuffer()
285
+ .then((data) => {
286
+ const blob = new Blob([data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
287
+ saveAs(blob, '${capitalizedController}.xlsx')
288
+ })
289
+ .catch(() => {
290
+ // 导出失败
291
+ })
292
+ } else {
293
+ message.info('没有数据无需导出')
294
+ }
295
+ }
296
+
297
+ const uploadProps = createCSRFUploadProps('/rest/${this.controller}/import', {
298
+ name: 'file',
299
+ onSuccess: (fileName) => {
300
+ message.success(\`\${fileName} 文件上传成功\`)
301
+ window.location.reload()
302
+ },
303
+ onError: (fileName) => {
304
+ message.error(\`\${fileName} 文件上传失败\`)
305
+ },
306
+ beforeUpload: (file) => {
307
+ const isExcel =
308
+ file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ||
309
+ file.type === 'application/vnd.ms-excel'
310
+ if (!isExcel) {
311
+ message.error('只能上传 Excel 文件!')
312
+ return false
313
+ }
314
+ const isLt2M = file.size / 1024 / 1024 < 2
315
+ if (!isLt2M) {
316
+ message.error('文件大小不能超过 2MB!')
317
+ return false
318
+ }
319
+ return true
320
+ }
321
+ })
322
+
323
+ const batchDelete${capitalizedController} = () => {
324
+ if (batchDelIds.length > 0) {
325
+ Modal.confirm({
326
+ title: '提示',
327
+ content: '确认批量删除吗',
328
+ okText: '确认',
329
+ cancelText: '取消',
330
+ onOk: () => {
331
+ dispatch(batchDel${capitalizedController}(batchDelIds))
332
+ Modal.destroyAll()
333
+ }
334
+ })
335
+ } else {
336
+ message.info('没有数据不能批量删除')
337
+ }
338
+ }
339
+
340
+ return (
341
+ <Container>
342
+ <GlobalStyle />
343
+ <div className="page-title">${capitalizedController} 管理</div>
344
+ <ConfigProvider locale={locale}>
345
+ <SearchRow>
346
+ <Space size="middle" wrap>
347
+ <Space size="small">
348
+ <StyledButton type="primary" onClick={create${capitalizedController}} $primary>
349
+ <IconWrapper className="fa fa-plus"></IconWrapper>
350
+ 新增
351
+ </StyledButton>
352
+ ${mainSearchField
353
+ ? `<StyledInput
354
+ value={searchKeyword}
355
+ placeholder="请输入${mainSearchField.comment || mainSearchField.name}搜索"
356
+ allowClear
357
+ onChange={(e) => setSearchKeyword(e.target.value)}
358
+ onPressEnter={doSearch}
359
+ />`
360
+ : ''}
361
+ <StyledButton type="primary" onClick={doSearch} $primary>
362
+ <IconWrapper className="fa fa-search"></IconWrapper>
363
+ 搜索
364
+ </StyledButton>
365
+ </Space>
366
+ <Space size="small">
367
+ <StyledButton onClick={export${capitalizedController}} icon={<UploadOutlined rotate={180} />} $export>
368
+ 导出
369
+ </StyledButton>
370
+ <Upload {...uploadProps}>
371
+ <StyledButton icon={<UploadOutlined />} $import>
372
+ 导入
373
+ </StyledButton>
374
+ </Upload>
375
+ <StyledButton danger onClick={batchDelete${capitalizedController}} $danger>
376
+ 批量删除
377
+ </StyledButton>
378
+ </Space>
379
+ </Space>
380
+ </SearchRow>
381
+ <StyledTable
382
+ rowSelection={{
383
+ type: 'checkbox',
384
+ ...rowSelection
385
+ }}
386
+ dataSource={dataSource}
387
+ columns={columns}
388
+ bordered
389
+ rowClassName={(_, index) => (index % 2 === 0 ? 'table-row-light' : 'table-row-dark')}
390
+ pagination={{
391
+ total: totalCounts,
392
+ pageSize: pageSize,
393
+ showSizeChanger: false,
394
+ showQuickJumper: true,
395
+ showTotal: (total) => \`共 \${total} 条记录\`,
396
+ onChange: (page, pageSize) => {
397
+ ${mainSearchField
398
+ ? `const searchData = { ${mainSearchField.name}: handleXSS(searchKeyword) }`
399
+ : 'const searchData = {}'}
400
+ dispatch(search${capitalizedController}(page - 1, pageSize, searchData))
401
+ },
402
+ className: 'styled-pagination'
403
+ }}
404
+ />
405
+ <Modal
406
+ title={<ModalTitle>{\`\${modalId == 0 ? '新增' : '修改'} ${capitalizedController}\`}</ModalTitle>}
407
+ open={isModalVisiable}
408
+ onOk={handleOk}
409
+ onCancel={handleCancel}
410
+ okText="确认"
411
+ cancelText="取消"
412
+ centered
413
+ maskClosable={false}
414
+ destroyOnHidden
415
+ okButtonProps={{ className: 'rounded-button' }}
416
+ cancelButtonProps={{ className: 'rounded-button' }}
417
+ >
418
+ <ModalContainer>
419
+ ${modalFields}
420
+ </ModalContainer>
421
+ </Modal>
422
+ </ConfigProvider>
423
+ </Container>
424
+ )
425
+ }
426
+
427
+ Page.getInitialProps = async () => {
428
+ let ${this.controller} = null
429
+
430
+ await get${capitalizedController}Service(0, pageSize).then((res: any) => {
431
+ const { data } = res
432
+ ${this.controller} = data.${this.controller}
433
+ })
434
+
435
+ return {
436
+ ${this.controller}
437
+ }
438
+ }
439
+
440
+ export default Page`;
441
+ }
442
+ /**
443
+ * 生成键值标题映射
444
+ */
445
+ generateKeyTitles() {
446
+ return this.getFormFields()
447
+ .map((field) => {
448
+ return ` ${field.name}: '${field.comment || field.name}'`;
449
+ })
450
+ .join(',\n');
451
+ }
452
+ /**
453
+ * 生成模态框状态变量
454
+ */
455
+ generateModalStates() {
456
+ return this.getFormFields()
457
+ .map((field) => {
458
+ const capitalizedName = field.name.charAt(0).toUpperCase() + field.name.slice(1);
459
+ return ` const [modal${capitalizedName}, setModal${capitalizedName}] = useState('')`;
460
+ })
461
+ .join('\n');
462
+ }
463
+ /**
464
+ * 生成记录解构
465
+ */
466
+ generateRecordDestructuring() {
467
+ const fields = this.getFormFields().map((field) => field.name);
468
+ return fields.length > 0 ? `, ${fields.join(', ')}` : '';
469
+ }
470
+ /**
471
+ * 生成模态框重置状态
472
+ */
473
+ generateModalResetStates() {
474
+ return this.getFormFields()
475
+ .map((field) => {
476
+ const capitalizedName = field.name.charAt(0).toUpperCase() + field.name.slice(1);
477
+ return ` setModal${capitalizedName}('')`;
478
+ })
479
+ .join('\n');
480
+ }
481
+ /**
482
+ * 生成模态框设置状态
483
+ */
484
+ generateModalSetStates() {
485
+ return this.getFormFields()
486
+ .map((field) => {
487
+ const capitalizedName = field.name.charAt(0).toUpperCase() + field.name.slice(1);
488
+ return ` setModal${capitalizedName}(${field.name})`;
489
+ })
490
+ .join('\n');
491
+ }
492
+ /**
493
+ * 生成模态框对象
494
+ */
495
+ generateModalObj() {
496
+ return this.getFormFields()
497
+ .map((field) => {
498
+ const capitalizedName = field.name.charAt(0).toUpperCase() + field.name.slice(1);
499
+ return ` ${field.name}: handleXSS(modal${capitalizedName})`;
500
+ })
501
+ .join(',\n');
502
+ }
503
+ /**
504
+ * 生成模态框字段
505
+ */
506
+ generateModalFields(fields) {
507
+ return fields
508
+ .map((field) => {
509
+ const capitalizedName = field.name.charAt(0).toUpperCase() + field.name.slice(1);
510
+ return ` <div className="line">
511
+ <label>{keyTitles.${field.name}}:</label>
512
+ <ModalInput
513
+ value={modal${capitalizedName}}
514
+ placeholder="请输入${field.comment || field.name}"
515
+ allowClear
516
+ ${field === fields[0] ? 'autoFocus' : ''}
517
+ onChange={(e) => setModal${capitalizedName}(e.target.value)}
518
+ />
519
+ </div>`;
520
+ })
521
+ .join('\n');
522
+ }
523
+ /**
524
+ * 生成Excel列配置
525
+ */
526
+ generateExcelColumns() {
527
+ const displayFields = this.getDisplayFields();
528
+ return displayFields
529
+ .map((field, index) => {
530
+ const width = field.type === 'text' ? 50 : field.type === 'integer' ? 15 : 30;
531
+ return ` { header: '${(field.comment || field.name).toUpperCase()}', key: 'header${index + 1}', width: ${width} }`;
532
+ })
533
+ .join(',\n');
534
+ }
535
+ generateTableColumns(fields) {
536
+ return fields
537
+ .map((field) => {
538
+ let column = ` {\n title: '${field.comment || field.name}',\n dataIndex: '${field.name}',\n key: '${field.name}'`;
539
+ // 根据字段类型设置特定属性
540
+ if (field.type === 'timestamp' || field.type === 'date' || field.type === 'datetime') {
541
+ column += `,\n render: (text: string) => text ? new Date(text).toLocaleString() : '-'`;
542
+ }
543
+ else if (field.type === 'integer' || field.type === 'decimal') {
544
+ column += `,\n align: 'right' as const`;
545
+ }
546
+ column += '\n }';
547
+ return column;
548
+ })
549
+ .join(',\n');
550
+ }
551
+ }
552
+ exports.PageGenerator = PageGenerator;
@@ -0,0 +1,12 @@
1
+ import { BaseGenerator } from './base-generator';
2
+ /**
3
+ * Resolver生成器
4
+ */
5
+ export declare class ResolverGenerator extends BaseGenerator {
6
+ generate(): string;
7
+ private generateSearchConditions;
8
+ private generateValidateFunctions;
9
+ private generateValidationCalls;
10
+ private generateBatchValidationCalls;
11
+ private generateUpdateValidationCalls;
12
+ }