nsgm-cli 2.1.13 → 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 +370 -155
  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 -6
  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 +24 -3
  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 -173
  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
@@ -2,38 +2,38 @@ import styled from 'styled-components'
2
2
 
3
3
  export const Container = styled.div`
4
4
  margin: 20px;
5
-
5
+
6
6
  .ant-table {
7
7
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
8
8
  border-radius: 8px;
9
9
  overflow: hidden;
10
10
  transition: all 0.3s ease;
11
-
11
+
12
12
  &:hover {
13
13
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
14
14
  }
15
15
  }
16
-
16
+
17
17
  .table-row-light {
18
18
  background-color: #ffffff;
19
19
  }
20
-
20
+
21
21
  .table-row-dark {
22
22
  background-color: #f9f9f9;
23
23
  }
24
-
24
+
25
25
  .ant-table-thead > tr > th {
26
26
  background-color: #f0f5ff;
27
27
  color: #1890ff;
28
28
  font-weight: 500;
29
29
  padding: 12px 16px;
30
30
  }
31
-
31
+
32
32
  .ant-table-tbody > tr > td {
33
33
  padding: 12px 16px;
34
34
  transition: background-color 0.3s;
35
35
  }
36
-
36
+
37
37
  .page-title {
38
38
  font-size: 24px;
39
39
  font-weight: 500;
@@ -42,7 +42,7 @@ export const Container = styled.div`
42
42
  padding-bottom: 10px;
43
43
  border-bottom: 1px solid #f0f0f0;
44
44
  position: relative;
45
-
45
+
46
46
  &:after {
47
47
  content: '';
48
48
  position: absolute;
@@ -68,7 +68,7 @@ export const SearchRow = styled.div`
68
68
  border-radius: 8px;
69
69
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
70
70
  transition: all 0.3s ease;
71
-
71
+
72
72
  &:hover {
73
73
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
74
74
  }
@@ -95,7 +95,7 @@ export const ModalContainer = styled.div`
95
95
  font-weight: 500;
96
96
  color: #333;
97
97
  position: relative;
98
-
98
+
99
99
  &:after {
100
100
  content: '';
101
101
  position: absolute;
@@ -113,8 +113,9 @@ export const ModalContainer = styled.div`
113
113
  flex: 1;
114
114
  border-radius: 6px;
115
115
  transition: all 0.3s ease;
116
-
117
- &:hover, &:focus {
116
+
117
+ &:hover,
118
+ &:focus {
118
119
  border-color: #40a9ff;
119
120
  box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
120
121
  }
@@ -133,4 +134,4 @@ export const ModalContainer = styled.div`
133
134
  }
134
135
  }
135
136
  }
136
- `
137
+ `
@@ -1,7 +1,7 @@
1
1
  import getConfig from 'next/config'
2
2
  import _ from 'lodash'
3
3
 
4
- export const getLocalEnv = () => {
4
+ export const getLocalEnv = () => {
5
5
  const nextConfig = getConfig()
6
6
  const { publicRuntimeConfig } = nextConfig
7
7
  let { env = 'uat' } = publicRuntimeConfig
@@ -12,75 +12,77 @@ export const getLocalEnv = () => {
12
12
  export const getLocalApiPrefix = () => {
13
13
  const nextConfig = getConfig()
14
14
  const { publicRuntimeConfig } = nextConfig
15
- let { protocol, host, port, prefix, isExport } = publicRuntimeConfig
15
+ let { protocol, host, port } = publicRuntimeConfig
16
+ const { prefix, isExport } = publicRuntimeConfig
16
17
 
17
18
  let localApiPrefix = ''
18
-
19
- if(!isExport){
20
- if (typeof window !== 'undefined') {
19
+
20
+ if (!isExport) {
21
+ if (typeof window !== 'undefined') {
21
22
  // 客户端:使用当前页面的 location
22
23
  const location = window.location
23
24
 
24
25
  protocol = location.protocol
25
- if (protocol.indexOf(':') != -1) {
26
+ if (protocol.indexOf(':') != -1) {
26
27
  protocol = protocol.split(':')[0]
27
28
  }
28
29
  host = location.hostname
29
- port = location.port || (protocol.indexOf('https') !== -1 ? "443" : "80")
30
+ port = location.port || (protocol.indexOf('https') !== -1 ? '443' : '80')
30
31
  }
31
32
  // 服务器端:直接使用配置中的值,无需额外处理
32
- }
33
+ }
33
34
 
34
- localApiPrefix = protocol + '://' + host + ':' + port + prefix
35
+ localApiPrefix = `${protocol}://${host}:${port}${prefix}`
35
36
  return localApiPrefix
36
37
  }
37
38
 
38
39
  export const handleXSS = (content: string) => {
39
40
  content = content || ''
40
- return content.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;').replace(/\'/g, '&#x27;')
41
+ return content.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;')
41
42
  }
42
43
 
43
44
  export const checkModalObj = (modalObj: {}, ignoreKeys: any = []) => {
44
45
  let result: any = null
45
46
  _.each(modalObj, (value: any, key: string) => {
46
- // console.log('checkModalObj', ignoreKeys, key, ignoreKeys.join('.').indexOf(key))
47
47
  if (ignoreKeys.length === 0 || (ignoreKeys.length !== 0 && ignoreKeys.join('.').indexOf(key) === -1)) {
48
48
  if (_.trim(value) === '') {
49
49
  result = {
50
50
  key,
51
- reason: '不能为空'
51
+ reason: '不能为空',
52
52
  }
53
53
  return false
54
54
  }
55
55
  }
56
+ return true
56
57
  })
57
58
  return result
58
59
  }
59
60
 
60
- export const getUrlParamByKey = (key: string) => {
61
+ export const getUrlParamByKey = (key: string) => {
61
62
  let result = ''
62
63
  if (typeof window !== 'undefined') {
63
64
  const locationHref = window.location.href
64
- if (locationHref.indexOf('?') !== -1) {
65
+ if (locationHref.indexOf('?') !== -1) {
65
66
  const locationHrefArr = locationHref.split('?')
66
- if (locationHrefArr.length > 1) {
67
+ if (locationHrefArr.length > 1) {
67
68
  const paramsStr = locationHrefArr[1]
68
69
 
69
- let params:any = []
70
+ let params: any = []
70
71
  if (paramsStr.indexOf('&') !== -1) {
71
72
  params = paramsStr.split('&')
72
- } else {
73
+ } else {
73
74
  params.push(paramsStr)
74
75
  }
75
-
76
- _.each(params, (item, index) => {
77
- if (item.indexOf('=') !== -1) {
76
+
77
+ _.each(params, (item) => {
78
+ if (item.indexOf('=') !== -1) {
78
79
  const itemArr = item.split('=')
79
- if (itemArr[0] === key) {
80
+ if (itemArr[0] === key) {
80
81
  result = itemArr[1]
81
82
  return false
82
83
  }
83
84
  }
85
+ return true
84
86
  })
85
87
  }
86
88
  }
@@ -1,52 +1,51 @@
1
1
  import _ from 'lodash'
2
2
 
3
- export const setCookie = (name: string, value:string, cookieExpire:any) => {
3
+ export const setCookie = (name: string, value: string, cookieExpire: any) => {
4
4
  const currentDate = new Date()
5
5
  const currentTime = currentDate.getTime()
6
- let expiresTime = currentDate
6
+ const expiresTime = new Date()
7
7
  expiresTime.setTime(currentTime + 60 * 1000 * 60 * 24 * 30)
8
8
 
9
9
  if (typeof document !== 'undefined') {
10
- let cookie = name + '=' + window.btoa(encodeURIComponent(value))
10
+ let cookie = `${name}=${window.btoa(encodeURIComponent(value))}`
11
11
  // let cookie = name + '=' + encodeURIComponent(value)
12
12
  if (cookieExpire) {
13
- cookie += ";expires=" + cookieExpire
14
- } else {
15
- cookie += ";expires=" + expiresTime.toUTCString()
13
+ cookie += `;expires=${cookieExpire}`
14
+ } else {
15
+ cookie += `;expires=${expiresTime.toUTCString()}`
16
16
  }
17
17
 
18
- cookie += ";path=/"
18
+ cookie += ';path=/'
19
19
  document.cookie = cookie
20
20
  }
21
21
  }
22
22
 
23
- export const getCookie = (name: string) => {
23
+ export const getCookie = (name: string) => {
24
24
  let result = ''
25
- if (typeof document !== 'undefined') {
25
+ if (typeof document !== 'undefined') {
26
26
  const cookie = document.cookie
27
- // console.log('cookie', cookie)
28
27
 
29
- const cookieArr = cookie.split("; ")
30
-
31
- _.each(cookieArr, (item, index) => {
32
- const itemArr = item.split("=")
28
+ const cookieArr = cookie.split('; ')
29
+
30
+ _.each(cookieArr, (item) => {
31
+ const itemArr = item.split('=')
33
32
  if (name === itemArr[0]) {
34
33
  result = decodeURIComponent(window.atob(itemArr[1]))
35
- // result = decodeURIComponent(itemArr[1])
36
34
  return false
37
35
  }
36
+ return true
38
37
  })
39
38
  }
40
39
  return result
41
40
  }
42
41
 
43
- export const delCookie = (name: string) => {
42
+ export const delCookie = (name: string) => {
44
43
  const currentDate = new Date()
45
44
  const currentTime = currentDate.getTime()
46
- let expiresTime = currentDate
45
+ const expiresTime = new Date()
47
46
  expiresTime.setTime(currentTime - 1)
48
47
 
49
48
  if (typeof document !== 'undefined') {
50
- document.cookie = name + "=;expires=" + expiresTime.toUTCString() + ";path=/"
49
+ document.cookie = `${name}=;expires=${expiresTime.toUTCString()};path=/`
51
50
  }
52
- }
51
+ }
@@ -11,38 +11,38 @@ axios.defaults.withCredentials = true
11
11
  export const GRAPHQL_CONFIG = {
12
12
  // GraphQL 端点
13
13
  endpoint: '/graphql',
14
-
14
+
15
15
  // 默认请求头
16
16
  defaultHeaders: {
17
17
  'Content-Type': 'application/json',
18
- 'Accept': 'application/json'
18
+ Accept: 'application/json',
19
19
  },
20
-
20
+
21
21
  // 缓存配置
22
22
  cache: {
23
23
  defaultTTL: 5 * 60 * 1000, // 5分钟
24
24
  maxSize: 100,
25
- enabled: true
25
+ enabled: true,
26
26
  },
27
-
27
+
28
28
  // CSRF 配置
29
29
  csrf: {
30
30
  enabled: true,
31
31
  tokenHeader: 'X-CSRF-Token',
32
- cookieName: 'csrfToken'
32
+ cookieName: 'csrfToken',
33
33
  },
34
-
34
+
35
35
  // 开发模式配置
36
36
  development: {
37
- enableDebugLogs: process.env.NODE_ENV === 'development'
38
- }
37
+ enableDebugLogs: process.env.NODE_ENV === 'development',
38
+ },
39
39
  }
40
40
 
41
41
  // GraphQL 操作类型
42
42
  export enum GraphQLOperationType {
43
43
  QUERY = 'query',
44
44
  MUTATION = 'mutation',
45
- SUBSCRIPTION = 'subscription'
45
+ SUBSCRIPTION = 'subscription',
46
46
  }
47
47
 
48
48
  // GraphQL 工具函数
@@ -54,20 +54,20 @@ export const GraphQLUtils = {
54
54
  if (trimmed.startsWith('subscription')) return GraphQLOperationType.SUBSCRIPTION
55
55
  return GraphQLOperationType.QUERY
56
56
  },
57
-
57
+
58
58
  // 提取操作名称
59
59
  getOperationName(query: string): string | null {
60
60
  const match = query.match(/(?:query|mutation|subscription)\s+(\w+)/)
61
61
  return match ? match[1] : null
62
62
  },
63
-
63
+
64
64
  // 生成缓存键
65
65
  generateCacheKey(query: string, variables?: any): string {
66
66
  const operationName = this.getOperationName(query) || 'anonymous'
67
67
  const variablesHash = variables ? JSON.stringify(variables) : ''
68
68
  return `${operationName}_${btoa(variablesHash)}`
69
69
  },
70
-
70
+
71
71
  // 验证 GraphQL 查询语法
72
72
  isValidQuery(query: string): boolean {
73
73
  try {
@@ -81,7 +81,7 @@ export const GraphQLUtils = {
81
81
  } catch {
82
82
  return false
83
83
  }
84
- }
84
+ },
85
85
  }
86
86
 
87
87
  // ==================== CSRF 工具 ====================
@@ -92,14 +92,14 @@ export const GraphQLUtils = {
92
92
  */
93
93
  export const getCSRFToken = async (): Promise<string> => {
94
94
  try {
95
- const response = await axios.get(getLocalApiPrefix() + '/csrf-token', {
96
- withCredentials: true
95
+ const response = await axios.get(`${getLocalApiPrefix()}/csrf-token`, {
96
+ withCredentials: true,
97
97
  })
98
-
99
- if (!response.data || !response.data.csrfToken) {
98
+
99
+ if (!response.data?.csrfToken) {
100
100
  throw new Error('服务器返回的 CSRF token 为空')
101
101
  }
102
-
102
+
103
103
  return response.data.csrfToken
104
104
  } catch (error) {
105
105
  console.error('获取 CSRF token 错误:', error)
@@ -108,46 +108,27 @@ export const getCSRFToken = async (): Promise<string> => {
108
108
  }
109
109
 
110
110
  // ==================== GraphQL 客户端 ====================
111
-
112
- // GraphQL 查询缓存
113
- const queryCache = new Map<string, { data: any; timestamp: number }>()
114
- const CACHE_DURATION = GRAPHQL_CONFIG.cache.defaultTTL
115
-
116
111
  /**
117
112
  * GraphQL 客户端主函数
118
113
  * 自动处理 CSRF 保护、缓存、错误重试
119
114
  */
120
- export const getLocalGraphql = async (query: string, variables: any = {}, useCache = false) => {
115
+ export const getLocalGraphql = async (query: string, variables: any = {}) => {
121
116
  // 验证查询语法
122
117
  if (!GraphQLUtils.isValidQuery(query)) {
123
118
  throw new Error('Invalid GraphQL query syntax')
124
119
  }
125
-
126
- // 生成缓存键
127
- const cacheKey = GraphQLUtils.generateCacheKey(query, variables)
128
-
129
- // 检查缓存
130
- if (useCache && queryCache.has(cacheKey)) {
131
- const cached = queryCache.get(cacheKey)!
132
- if (Date.now() - cached.timestamp < CACHE_DURATION) {
133
- if (GRAPHQL_CONFIG.development.enableDebugLogs) {
134
- console.log('GraphQL cache hit:', cacheKey)
135
- }
136
- return cached.data
137
- }
138
- }
139
-
120
+
140
121
  try {
141
122
  // 检测操作类型
142
123
  const operationType = GraphQLUtils.getOperationType(query)
143
124
  const isMutation = operationType === GraphQLOperationType.MUTATION
144
-
125
+
145
126
  const headers: Record<string, string> = {
146
- ...GRAPHQL_CONFIG.defaultHeaders
127
+ ...GRAPHQL_CONFIG.defaultHeaders,
147
128
  }
148
-
129
+
149
130
  let response
150
-
131
+
151
132
  if (isMutation) {
152
133
  // Mutation 使用 POST 方法并需要 CSRF token
153
134
  if (GRAPHQL_CONFIG.csrf.enabled) {
@@ -158,16 +139,16 @@ export const getLocalGraphql = async (query: string, variables: any = {}, useCac
158
139
  console.warn('获取 CSRF token 失败,继续执行 GraphQL 请求:', csrfError)
159
140
  }
160
141
  }
161
-
142
+
162
143
  response = await axios.post(
163
- getLocalApiPrefix() + '/graphql',
144
+ `${getLocalApiPrefix()}/graphql`,
164
145
  {
165
146
  query,
166
- variables
147
+ variables,
167
148
  },
168
149
  {
169
150
  headers,
170
- withCredentials: true
151
+ withCredentials: true,
171
152
  }
172
153
  )
173
154
  } else {
@@ -177,27 +158,16 @@ export const getLocalGraphql = async (query: string, variables: any = {}, useCac
177
158
  if (variables && Object.keys(variables).length > 0) {
178
159
  params.append('variables', JSON.stringify(variables))
179
160
  }
180
-
181
- response = await axios.get(
182
- getLocalApiPrefix() + '/graphql?' + params.toString(),
183
- {
184
- headers: {
185
- 'Accept': 'application/json'
186
- },
187
- withCredentials: true
188
- }
189
- )
161
+
162
+ response = await axios.get(`${getLocalApiPrefix()}/graphql?${params.toString()}`, {
163
+ headers: {
164
+ Accept: 'application/json',
165
+ },
166
+ withCredentials: true,
167
+ })
190
168
  }
191
169
 
192
- if (response && response.data) {
193
- // 缓存查询结果
194
- if (useCache && !isMutation) {
195
- queryCache.set(cacheKey, {
196
- data: response.data,
197
- timestamp: Date.now()
198
- })
199
- }
200
-
170
+ if (response?.data) {
201
171
  return response.data
202
172
  } else {
203
173
  throw new Error('GraphQL response is empty')
@@ -206,7 +176,7 @@ export const getLocalGraphql = async (query: string, variables: any = {}, useCac
206
176
  // 只为 mutation 检查 CSRF 错误 (403),因为 query 使用 GET 不需要 CSRF token
207
177
  if (axios.isAxiosError(error) && error.response?.status === 403) {
208
178
  const operationType = GraphQLUtils.getOperationType(query)
209
-
179
+
210
180
  if (operationType === GraphQLOperationType.MUTATION) {
211
181
  console.warn('🔄 CSRF token 可能已过期,尝试重试 mutation...')
212
182
  try {
@@ -214,15 +184,15 @@ export const getLocalGraphql = async (query: string, variables: any = {}, useCac
214
184
  const newCsrfToken = await getCSRFToken()
215
185
  const retryHeaders = {
216
186
  ...GRAPHQL_CONFIG.defaultHeaders,
217
- [GRAPHQL_CONFIG.csrf.tokenHeader]: newCsrfToken
187
+ [GRAPHQL_CONFIG.csrf.tokenHeader]: newCsrfToken,
218
188
  }
219
-
189
+
220
190
  const retryResponse = await axios.post(
221
- getLocalApiPrefix() + '/graphql',
191
+ `${getLocalApiPrefix()}/graphql`,
222
192
  { query, variables },
223
193
  { headers: retryHeaders, withCredentials: true }
224
194
  )
225
-
195
+
226
196
  return retryResponse.data
227
197
  } catch (retryError) {
228
198
  console.error('❌ CSRF mutation 重试失败:', retryError)
@@ -230,7 +200,7 @@ export const getLocalGraphql = async (query: string, variables: any = {}, useCac
230
200
  }
231
201
  }
232
202
  }
233
-
203
+
234
204
  console.error('GraphQL request failed:', error)
235
205
  throw error
236
206
  }
@@ -252,22 +222,14 @@ export const createCSRFUploadProps = (
252
222
  multiple?: boolean
253
223
  } = {}
254
224
  ) => {
255
- const {
256
- name = 'file',
257
- onSuccess,
258
- onError,
259
- beforeUpload: customBeforeUpload,
260
- accept,
261
- multiple = false
262
- } = options
263
-
264
- return {
225
+ const { name = 'file', onSuccess, onError, beforeUpload: customBeforeUpload, accept, multiple = false } = options
226
+
227
+ const uploadProps: any = {
265
228
  name,
266
229
  action,
267
- accept,
268
230
  multiple,
269
231
  customRequest: async (options: any) => {
270
- const { onProgress, onError: onUploadError, onSuccess: onUploadSuccess, file } = options
232
+ const { onError: onUploadError, onSuccess: onUploadSuccess, file } = options
271
233
 
272
234
  try {
273
235
  // 获取 CSRF token
@@ -284,9 +246,9 @@ export const createCSRFUploadProps = (
284
246
  const uploadUrl = action.startsWith('http') ? action : getLocalApiPrefix() + action
285
247
  const response = await axios.post(uploadUrl, formData, {
286
248
  headers: {
287
- [GRAPHQL_CONFIG.csrf.tokenHeader]: csrfToken
249
+ [GRAPHQL_CONFIG.csrf.tokenHeader]: csrfToken,
288
250
  },
289
- withCredentials: true
251
+ withCredentials: true,
290
252
  })
291
253
 
292
254
  if (response.status >= 200 && response.status < 300) {
@@ -330,8 +292,15 @@ export const createCSRFUploadProps = (
330
292
  onError(fileName)
331
293
  }
332
294
  }
333
- }
295
+ },
334
296
  }
297
+
298
+ // 只有当 accept 有值时才添加该属性
299
+ if (accept) {
300
+ uploadProps.accept = accept
301
+ }
302
+
303
+ return uploadProps
335
304
  }
336
305
 
337
306
  /**
@@ -343,41 +312,36 @@ export const validateCSRFForUpload = async (): Promise<{ valid: boolean; token?:
343
312
  if (!csrfToken) {
344
313
  return {
345
314
  valid: false,
346
- error: 'CSRF Token 获取失败,请刷新页面重试'
315
+ error: 'CSRF Token 获取失败,请刷新页面重试',
347
316
  }
348
317
  }
349
318
  return {
350
319
  valid: true,
351
- token: csrfToken
320
+ token: csrfToken,
352
321
  }
353
322
  } catch (error) {
354
323
  return {
355
324
  valid: false,
356
- error: error instanceof Error ? error.message : '获取 CSRF Token 时发生未知错误'
325
+ error: error instanceof Error ? error.message : '获取 CSRF Token 时发生未知错误',
357
326
  }
358
327
  }
359
328
  }
360
329
 
361
330
  // ==================== 工具函数 ====================
362
331
 
363
- // 清除缓存
364
- export const clearGraphqlCache = () => {
365
- queryCache.clear()
366
- }
367
-
368
332
  // GraphQL 查询辅助函数
369
- export const graphqlQuery = async (query: string, variables?: any, useCache = true) => {
370
- return getLocalGraphql(query, variables, useCache)
333
+ export const graphqlQuery = async (query: string, variables?: any) => {
334
+ return getLocalGraphql(query, variables)
371
335
  }
372
336
 
373
337
  // GraphQL 变更辅助函数 (Mutation)
374
338
  export const graphqlMutation = async (mutation: string, variables?: any) => {
375
- return getLocalGraphql(mutation, variables, false) // 变更操作不使用缓存
339
+ return getLocalGraphql(mutation, variables)
376
340
  }
377
341
 
378
342
  // 检查 GraphQL 响应是否有错误
379
343
  export const hasGraphqlErrors = (response: any): boolean => {
380
- return response && response.errors && response.errors.length > 0
344
+ return response?.errors && response.errors.length > 0
381
345
  }
382
346
 
383
347
  // 获取 GraphQL 错误信息
@@ -5,13 +5,26 @@ let key = 1
5
5
 
6
6
  export default [
7
7
  {
8
- key: key.toString(),
8
+ key: (++key).toString(),
9
9
  text: '介绍',
10
10
  url: '/',
11
11
  icon: <BookOutlined rev={undefined} />,
12
- subMenus: null
12
+ subMenus: null,
13
13
  },
14
14
  {
15
+ key: (++key).toString(),
16
+ text: '模板',
17
+ url: '/template/manage',
18
+ icon: <SolutionOutlined rev={undefined} />,
19
+ subMenus: [
20
+ {
21
+ key: `${key}_1`,
22
+ text: '模板1',
23
+ url: '/template/manage',
24
+ },
25
+ ],
26
+ },
27
+ /*{
15
28
  key: (++key).toString(),
16
29
  text: '模板',
17
30
  url: '/template/manage',
@@ -23,5 +36,5 @@ export default [
23
36
  url: '/template/manage'
24
37
  }
25
38
  ]
26
- }
39
+ }*/
27
40
  ]