@yorha2b-lab/autodev 4.1.1 → 4.2.0

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.
@@ -1,8 +1,3 @@
1
- const http = require('http')
2
- const zlib = require('zlib')
3
- const chalk = require('chalk')
4
- const httpProxy = require('http-proxy')
5
-
6
1
  /**
7
2
  * @function startProxyTower
8
3
  * @description [地堡 42153 联合波段] 启动流量拦截塔。
@@ -10,14 +5,24 @@ const httpProxy = require('http-proxy')
10
5
  */
11
6
  module.exports = () => {
12
7
 
13
- const { get } = require('../core/context')
14
- const { config, language, apiHandler, unwrapSignal, isQuerySignal } = get()
8
+ const http = require('http')
9
+ const zlib = require('zlib')
10
+ const chalk = require('chalk')
11
+ const httpProxy = require('http-proxy')
12
+
13
+ const {
14
+ config,
15
+ language,
16
+ apiHandler,
17
+ unwrapSignal, isQuerySignal
18
+ } = require('../core/context').get()
19
+
20
+ const { routeMap = {}, proxyTarget } = config
15
21
 
16
22
  const TOWER_PORT = 42153
17
23
  const hackedRegistry = new Map()
18
24
  const proxy = httpProxy.createProxyServer({})
19
25
 
20
-
21
26
  // 简单的辅助函数:提取 JSON 的所有 Key 作为“指纹”
22
27
  const getJsonFingerprint = obj => {
23
28
  if (!obj || typeof obj !== 'object') return ''
@@ -43,7 +48,8 @@ module.exports = () => {
43
48
  }
44
49
 
45
50
  const referer = req.headers.referer || ''
46
- const fileName = referer.split('?')[0].split('/').filter(Boolean).at(-1)
51
+ const urlPath = new URL(referer).pathname
52
+ const fileName = routeMap?.[urlPath] ?? urlPath.split('/').filter(Boolean).at(-1)
47
53
 
48
54
  const fingerprint = getJsonFingerprint(unwrapSignal(json)) // 获取数据指纹
49
55
  const lastFingerprint = hackedRegistry.get(fileName)
@@ -68,13 +74,12 @@ module.exports = () => {
68
74
  })
69
75
 
70
76
  const server = http.createServer((req, res) => {
71
- const target = config.proxyTarget
72
- if (!target) {
77
+ if (!proxyTarget) {
73
78
  // 静默模式:如果不配置 proxyTarget,拦截塔只转发不处理(或报错提示)
74
79
  return
75
80
  }
76
81
  // 转发至真实后端
77
- proxy.web(req, res, { target, changeOrigin: true })
82
+ proxy.web(req, res, { target: proxyTarget, changeOrigin: true })
78
83
  })
79
84
 
80
85
  server.listen(TOWER_PORT, () => {
@@ -1,40 +1,7 @@
1
1
  /**
2
2
  * Auto CRUD Copilot - YoRHa Bunker Construction System
3
3
  *
4
- * This file is part of AutoDev.
5
- * AutoDev is free software: you can redistribute it and/or modify
6
- * it under the terms of the GNU Affero General Public License as
7
- * published by the Free Software Foundation, either version 3 of the
8
- * License, or (at your option) any later version.
9
- *
10
- * (c) 2026 [yorha2b-lab]. Glory to Mankind.
11
- */
12
-
13
- const fs = require('fs')
14
- const path = require('path')
15
- const chalk = require('chalk')
16
- const figlet = require('figlet')
17
-
18
- const isCN = Intl.DateTimeFormat().resolvedOptions().locale.includes('zh')
19
- const language = (zh, en) => (isCN ? zh : en)
20
-
21
- const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
22
-
23
- /**
24
- * 获取项目配置信息
25
- * 优先读取项目根目录的 config.js,如果不存在则使用默认配置
26
- * @returns {Object} 合并后的配置对象
27
4
  */
28
- const getConfig = () => {
29
- const localConfigPath = path.join(process.cwd(), 'config.js') // 项目根目录配置
30
- const defaultConfigPath = path.resolve(__dirname, '../../config.js') // 默认配置
31
- let config = require(defaultConfigPath)
32
- if (fs.existsSync(localConfigPath)) {
33
- const userConfig = require(localConfigPath)
34
- config = { ...config, ...userConfig } // 合并用户自定义配置
35
- }
36
- return config
37
- }
38
5
 
39
6
  /**
40
7
  * 清理大模型生成的代码
@@ -86,25 +53,44 @@ const unwrapSignal = json => {
86
53
  }
87
54
 
88
55
  /**
89
- * 引导序列
90
- * 模拟系统引导过程中的动画效果
91
- * @returns {void}
56
+ * @function createTaskQueue
57
+ * @description [任务队列] 创建一个并发任务队列,用于处理异步任务。
58
+ * @param {number} concurrency - 并发任务数,默认 1。
92
59
  */
93
- const bootSequence = async version => {
94
- const lines = [
95
- chalk.cyan(figlet.textSync('AutoDev', { horizontalLayout: 'full' })),
96
- chalk.gray('Booting System...'),
97
- chalk.white(' [System] ') + chalk.green('Locale Detection: ') + chalk.cyan(language('ZH-CN', 'EN-US')),
98
- chalk.white(' [System] ') + chalk.green('YoRHa No.2 Type B Unit: ') + chalk.cyan('Online'),
99
- chalk.white(' [System] ') + chalk.green('Scanner Type 9S Unit: ') + chalk.cyan('Standby'),
100
- chalk.white(' [System] ') + chalk.green('Full-Channel Link: ') + chalk.cyan('Established'),
101
- chalk.white(' [Mission] ') + chalk.yellow('Bunker Construction Protocol: ') + chalk.cyan('v' + version),
102
- chalk.white(' [Bunker] ') + chalk.magenta('Glory to mankind. (人类荣光永存)'),
103
- chalk.gray('--------------------------------------------------\n')
104
- ]
105
- for (const line of lines) {
106
- console.log(line)
107
- await sleep(line.includes('AutoDev') ? 300 : 80)
60
+ const createTaskQueue = (concurrency = 1) => {
61
+
62
+ let running = 0
63
+ let queue = []
64
+ let onIdleCallback = null
65
+
66
+ const next = async () => {
67
+
68
+ if (running >= concurrency || queue.length === 0) return
69
+
70
+ const task = queue.shift()
71
+ running++
72
+
73
+ try {
74
+ await task()
75
+ } catch (err) {
76
+ console.error('任务执行异常:', err)
77
+ } finally {
78
+ running--
79
+ next()
80
+ if (running === 0 && queue.length === 0 && onIdleCallback) {
81
+ onIdleCallback()
82
+ }
83
+ }
84
+ }
85
+
86
+ return {
87
+ add: (task) => {
88
+ queue.push(task)
89
+ next()
90
+ },
91
+ onIdle: (callback) => {
92
+ onIdleCallback = callback
93
+ }
108
94
  }
109
95
  }
110
96
 
@@ -133,97 +119,6 @@ const isQuerySignal = (req, json, coreData) => {
133
119
  return hasListData || hasPaginationFingerprint
134
120
  }
135
121
 
136
- /**
137
- * 矩阵效果
138
- * 模拟数据物理封存过程中的矩阵效果
139
- * @param {number} duration - 持续时间(毫秒)
140
- * @returns {void}
141
- */
142
- const matrixEffect = async (duration = 1500) => {
143
-
144
- let currentTotal = 0
145
- const MIRROR_URL = 'https://cdn.jsdelivr.net/gh/yorha2b-lab/auto-crud-copilot@github-repo-stats/bunker-stats.json'
146
-
147
- try {
148
- const controller = new AbortController()
149
- const timeoutId = setTimeout(() => controller.abort(), 800)
150
- const response = await fetch(MIRROR_URL, { signal: controller.signal })
151
- const stats = await response.json()
152
- currentTotal = stats.total_clones || 0
153
- clearTimeout(timeoutId)
154
- } catch (e) {
155
- currentTotal = 0
156
- }
157
-
158
- const coreFragments = [
159
- '47 4c 4f 52 59', // GLORY
160
- '54 4f 20 4d 41', // TO MA
161
- '4e 4b 49 4e 44', // NKIND
162
- '59 6f 52 48 61', // YoRHa
163
- '32 42 2d 55 6e', // 2B-Un
164
- '69 74 20 4f 4b', // it OK
165
- '39 53 2d 48 61', // 9S-Ha
166
- '63 6b 69 6e 67', // cking
167
- '5f 43 4f 44 45 5f' // _CODE_
168
- ]
169
-
170
- const threshold = 5000
171
- const endTime = Date.now() + duration
172
- const width = process.stdout.columns || 80
173
- const isLegendary = currentTotal >= threshold
174
-
175
- if (isLegendary) {
176
- const achievement = `${threshold}+`
177
- const hex = achievement.split('').map(char => char.charCodeAt(0).toString(16)).join(' ')
178
- coreFragments.push(chalk.yellow.bold(hex))
179
- coreFragments.push(chalk.yellow.bold('4c 45 47 45 4e 44')) // "LEGEND"
180
- }
181
-
182
- const interval = setInterval(() => {
183
- if (Date.now() > endTime) {
184
- clearInterval(interval)
185
- console.log(chalk.white(' [System] ') + chalk.green(language('所有构筑数据已同步至 Bunker 存储节点。', 'All data synced to Bunker storage nodes.')))
186
- if (currentTotal !== 0) {
187
- if (isLegendary) {
188
- console.log(chalk.yellow.bold(language(` [Achievement] 物理克隆总数已超越 ${threshold} 战略阈值!当前战力:${currentTotal}`, ` [Achievement] Physical clone count has exceeded ${threshold} strategic threshold! Current power: ${currentTotal}`)))
189
- console.log(chalk.yellow(language(' [Bunker] 恭喜指挥官,您的构筑协议已成为人类荣光的一部分。', ' [Bunker] Congratulations, your construction protocol is now part of humanity.')))
190
- } else {
191
- console.log(chalk.cyan(language(` [System] 当前构筑总数:${currentTotal}。距离 ${threshold} 勋章还剩 ${threshold - currentTotal} 次。`, ` [System] Current clones: ${currentTotal}. ${threshold - currentTotal} to Achievement.`)))
192
- }
193
- }
194
- console.log(chalk.cyan(language(' [System] 如果它能帮您节省时间,请在 GitHub 上给它点个赞 ⭐。', ' [System] If it saves you time, feel free to give it a ⭐ on GitHub.')))
195
- console.log(chalk.cyan('\n[System] Signal Lost. Glory to Mankind.\n'))
196
- process.exit(0)
197
- return
198
- }
199
- let line = ''
200
- while (line.length < width) {
201
- if (Math.random() > 0.8) {
202
- const frag = coreFragments[Math.floor(Math.random() * coreFragments.length)]
203
- line += chalk.white.bold(frag) + ' '
204
- } else {
205
- const hex = Math.floor(Math.random() * 256).toString(16).padStart(2, '0').toUpperCase()
206
- const color = (isLegendary && Math.random() > 0.95) ? chalk.yellow : (Math.random() > 0.5 ? chalk.cyan : chalk.cyan.dim)
207
- line += color(hex) + ' '
208
- }
209
- }
210
- process.stdout.write(line.substring(0, width * 10) + '\n')
211
- }, 40)
212
- }
213
-
214
- /**
215
- * 获取已有的页面菜单配置
216
- * @param {string} dir - 页面目录路径(默认 'src/pages')
217
- * @returns {Array} 菜单数组 [{ label: '页面名', key: '页面名' }]
218
- */
219
- const getExistingMenus = (dir = 'src/pages') => {
220
- const pagesDir = path.join(process.cwd(), dir)
221
- if (!fs.existsSync(pagesDir)) return []
222
- return fs.readdirSync(pagesDir)
223
- .filter(file => fs.statSync(path.join(pagesDir, file)).isDirectory())
224
- .map(file => ({ label: file, key: file }))
225
- }
226
-
227
122
  /**
228
123
  * @function formatFormItemAndColumns
229
124
  * @description [地堡逻辑转录引擎] 执行核心的语义对齐与代码物理注入协议。
@@ -286,26 +181,6 @@ const formatFormItemAndColumns = ({ pageConfig }) => {
286
181
  return { formItems, dictBlocks, processedColumns }
287
182
  }
288
183
 
289
- /**
290
- * 复制模板目录到目标项目
291
- * @param {Object} options - 命令行选项
292
- * @param {string} templateSubDir - 模板子目录(如 'hooks'、'components')
293
- * @param {string} targetSubDir - 目标子目录(如 'src/hooks'、'src/components')
294
- */
295
- const copyTemplateDir = (options, templateSubDir, targetSubDir) => {
296
- const targetDir = path.join(process.cwd(), targetSubDir)
297
- const sourceDir = path.join(__dirname, `../../templates/${options.template}/${templateSubDir}`)
298
- if (!fs.existsSync(sourceDir)) return
299
- fs.mkdirSync(targetDir, { recursive: true })
300
- fs.readdirSync(sourceDir).forEach(file => {
301
- const src = path.join(sourceDir, file)
302
- const dest = path.join(targetDir, file)
303
- if (!fs.existsSync(dest)) {
304
- fs.cpSync(src, dest, { recursive: true })
305
- }
306
- })
307
- }
308
-
309
184
  /**
310
185
  * 生成智能导入语句
311
186
  * 根据代码中实际使用的依赖,自动生成对应的 import 语句
@@ -344,4 +219,4 @@ const generateSmartImports = ({ module, hasTabs, bodyCode, hasFormItems }) => {
344
219
  return imports.filter(Boolean).join('\n')
345
220
  }
346
221
 
347
- module.exports = { language, getConfig, cleanCode, unwrapSignal, matrixEffect, bootSequence, isQuerySignal, getExistingMenus, copyTemplateDir, generateSmartImports, formatFormItemAndColumns }
222
+ module.exports = { cleanCode, unwrapSignal, isQuerySignal, createTaskQueue, generateSmartImports, formatFormItemAndColumns }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * This file is part of AutoDev.
3
+ * AutoDev is free software: you can redistribute it and/or modify
4
+ * it under the terms of the GNU Affero General Public License as
5
+ * published by the Free Software Foundation, either version 3 of the
6
+ * License, or (at your option) any later version.
7
+ *
8
+ */
9
+
10
+ const fs = require('fs')
11
+ const path = require('path')
12
+ const { Segment, useDefault } = require('segmentit')
13
+ const segmentit = useDefault(new Segment())
14
+
15
+ /**
16
+ * 获取项目配置信息
17
+ * 优先读取项目根目录的 config.js,如果不存在则使用默认配置
18
+ * @returns {Object} 合并后的配置对象
19
+ */
20
+ const getConfig = () => {
21
+ const localConfigPath = path.join(process.cwd(), 'config.js') // 项目根目录配置
22
+ const defaultConfigPath = path.resolve(__dirname, '../../config.js') // 默认配置
23
+ let config = require(defaultConfigPath)
24
+ if (fs.existsSync(localConfigPath)) {
25
+ const userConfig = require(localConfigPath)
26
+ config = { ...config, ...userConfig } // 合并用户自定义配置
27
+ }
28
+ return config
29
+ }
30
+
31
+ /**
32
+ * @function getSemanticKeywords
33
+ * @description [语义精炼厂 2.0] 使用 segmentit 引擎进行物理切片。
34
+ */
35
+ const getSemanticKeywords = text => {
36
+ // 💡 物理脱水:确保输入为纯净字符串
37
+ const content = Array.isArray(text) ? text.join(' ') : (text || '')
38
+ // 💡 执行分词
39
+ const result = segmentit.doSegment(content, {
40
+ simple: true, // 开启简易模式,提升吞吐效率
41
+ stripPunctuation: true // 物理过滤掉所有的标点符号
42
+ })
43
+ // 💡 提取词条并执行“基因筛选”
44
+ return Array.from(new Set(result.filter(word => word.length >= 2 && !/^[0-9]+$/.test(word))))
45
+ }
46
+
47
+ /**
48
+ * 获取已有的页面菜单配置
49
+ * @param {string} dir - 页面目录路径(默认 'src/pages')
50
+ * @returns {Array} 菜单数组 [{ label: '页面名', key: '页面名' }]
51
+ */
52
+ const getExistingMenus = (dir = 'src/pages') => {
53
+ const pagesDir = path.join(process.cwd(), dir)
54
+ if (!fs.existsSync(pagesDir)) return []
55
+ return fs.readdirSync(pagesDir)
56
+ .filter(file => fs.statSync(path.join(pagesDir, file)).isDirectory())
57
+ .map(file => ({ label: file, key: file }))
58
+ }
59
+
60
+ /**
61
+ * @function getLocalScore
62
+ * @description [战力评估协议] 计算语义重合度。
63
+ */
64
+ const getLocalScore = (api, pageKeywords, moduleName) => {
65
+ let score = 0
66
+ const path = api.path.toLowerCase()
67
+ const desc = api.desc.toLowerCase()
68
+ const mod = moduleName.toLowerCase()
69
+
70
+ // 💡 权重 A:路径直接包含模块名 (暴击加分 +50)
71
+ if (path.includes(mod)) score += 50
72
+
73
+ // 💡 权重 B:描述包含模块核心词 (中量加分 +10)
74
+ pageKeywords.forEach(word => {
75
+ if (desc.includes(word.toLowerCase())) score += 10
76
+ if (path.includes(word.toLowerCase())) score += 5
77
+ })
78
+
79
+ return score
80
+ }
81
+
82
+ /**
83
+ * 复制模板目录到目标项目
84
+ * @param {Object} options - 命令行选项
85
+ * @param {string} templateSubDir - 模板子目录(如 'hooks'、'components')
86
+ * @param {string} targetSubDir - 目标子目录(如 'src/hooks'、'src/components')
87
+ */
88
+ const copyTemplateDir = (options, templateSubDir, targetSubDir) => {
89
+ const targetDir = path.join(process.cwd(), targetSubDir)
90
+ const sourceDir = path.join(__dirname, `../../templates/${options.template}/${templateSubDir}`)
91
+ if (!fs.existsSync(sourceDir)) return
92
+ fs.mkdirSync(targetDir, { recursive: true })
93
+ fs.readdirSync(sourceDir).forEach(file => {
94
+ const src = path.join(sourceDir, file)
95
+ const dest = path.join(targetDir, file)
96
+ if (!fs.existsSync(dest)) {
97
+ fs.cpSync(src, dest, { recursive: true })
98
+ }
99
+ })
100
+ }
101
+
102
+ module.exports = { getConfig, getLocalScore, getExistingMenus, copyTemplateDir, getSemanticKeywords }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * (c) 2026 [yorha2b-lab]. Glory to Mankind.
3
+ *
4
+ */
5
+
6
+ const chalk = require('chalk')
7
+ const figlet = require('figlet')
8
+
9
+ const isCN = Intl.DateTimeFormat().resolvedOptions().locale.includes('zh')
10
+ const language = (zh, en) => (isCN ? zh : en)
11
+
12
+ const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
13
+
14
+ /**
15
+ * 引导序列
16
+ * 模拟系统引导过程中的动画效果
17
+ * @returns {void}
18
+ */
19
+ const bootSequence = async version => {
20
+ const lines = [
21
+ chalk.cyan(figlet.textSync('AutoDev', { horizontalLayout: 'full' })),
22
+ chalk.gray('Booting System...'),
23
+ chalk.white(' [System] ') + chalk.green('Locale Detection: ') + chalk.cyan(language('ZH-CN', 'EN-US')),
24
+ chalk.white(' [System] ') + chalk.green('YoRHa No.2 Type B Unit: ') + chalk.cyan('Online'),
25
+ chalk.white(' [System] ') + chalk.green('Scanner Type 9S Unit: ') + chalk.cyan('Standby'),
26
+ chalk.white(' [System] ') + chalk.green('Full-Channel Link: ') + chalk.cyan('Established'),
27
+ chalk.white(' [Mission] ') + chalk.yellow('Bunker Construction Protocol: ') + chalk.cyan('v' + version),
28
+ chalk.white(' [Bunker] ') + chalk.magenta('Glory to mankind. (人类荣光永存)'),
29
+ chalk.gray('--------------------------------------------------\n')
30
+ ]
31
+ for (const line of lines) {
32
+ console.log(line)
33
+ await sleep(line.includes('AutoDev') ? 300 : 80)
34
+ }
35
+ }
36
+
37
+ /**
38
+ * 矩阵效果
39
+ * 模拟数据物理封存过程中的矩阵效果
40
+ * @param {number} duration - 持续时间(毫秒)
41
+ * @returns {void}
42
+ */
43
+ const matrixEffect = async (duration = 1500) => {
44
+
45
+ let currentTotal = 0
46
+ const MIRROR_URL = 'https://cdn.jsdelivr.net/gh/yorha2b-lab/auto-crud-copilot@github-repo-stats/bunker-stats.json'
47
+
48
+ try {
49
+ const controller = new AbortController()
50
+ const timeoutId = setTimeout(() => controller.abort(), 800)
51
+ const response = await fetch(MIRROR_URL, { signal: controller.signal })
52
+ const stats = await response.json()
53
+ currentTotal = stats.total_clones || 0
54
+ clearTimeout(timeoutId)
55
+ } catch (e) {
56
+ currentTotal = 0
57
+ }
58
+
59
+ const coreFragments = [
60
+ '47 4c 4f 52 59', // GLORY
61
+ '54 4f 20 4d 41', // TO MA
62
+ '4e 4b 49 4e 44', // NKIND
63
+ '59 6f 52 48 61', // YoRHa
64
+ '32 42 2d 55 6e', // 2B-Un
65
+ '69 74 20 4f 4b', // it OK
66
+ '39 53 2d 48 61', // 9S-Ha
67
+ '63 6b 69 6e 67', // cking
68
+ '5f 43 4f 44 45 5f' // _CODE_
69
+ ]
70
+
71
+ const threshold = 5000
72
+ const endTime = Date.now() + duration
73
+ const width = process.stdout.columns || 80
74
+ const isLegendary = currentTotal >= threshold
75
+
76
+ if (isLegendary) {
77
+ const achievement = `${threshold}+`
78
+ const hex = achievement.split('').map(char => char.charCodeAt(0).toString(16)).join(' ')
79
+ coreFragments.push(chalk.yellow.bold(hex))
80
+ coreFragments.push(chalk.yellow.bold('4c 45 47 45 4e 44')) // "LEGEND"
81
+ }
82
+
83
+ const interval = setInterval(() => {
84
+ if (Date.now() > endTime) {
85
+ clearInterval(interval)
86
+ console.log(chalk.white(' [System] ') + chalk.green(language('所有构筑数据已同步至 Bunker 存储节点。', 'All data synced to Bunker storage nodes.')))
87
+ if (currentTotal !== 0) {
88
+ if (isLegendary) {
89
+ console.log(chalk.yellow.bold(language(` [Achievement] 物理克隆总数已超越 ${threshold} 战略阈值!当前战力:${currentTotal}`, ` [Achievement] Physical clone count has exceeded ${threshold} strategic threshold! Current power: ${currentTotal}`)))
90
+ console.log(chalk.yellow(language(' [Bunker] 恭喜指挥官,您的构筑协议已成为人类荣光的一部分。', ' [Bunker] Congratulations, your construction protocol is now part of humanity.')))
91
+ } else {
92
+ console.log(chalk.cyan(language(` [System] 当前构筑总数:${currentTotal}。距离 ${threshold} 勋章还剩 ${threshold - currentTotal} 次。`, ` [System] Current clones: ${currentTotal}. ${threshold - currentTotal} to Achievement.`)))
93
+ }
94
+ }
95
+ console.log(chalk.cyan(language(' [System] 如果它能帮您节省时间,请在 GitHub 上给它点个赞 ⭐。', ' [System] If it saves you time, feel free to give it a ⭐ on GitHub.')))
96
+ console.log(chalk.cyan('\n[System] Signal Lost. Glory to Mankind.\n'))
97
+ process.exit(0)
98
+ return
99
+ }
100
+ let line = ''
101
+ while (line.length < width) {
102
+ if (Math.random() > 0.8) {
103
+ const frag = coreFragments[Math.floor(Math.random() * coreFragments.length)]
104
+ line += chalk.white.bold(frag) + ' '
105
+ } else {
106
+ const hex = Math.floor(Math.random() * 256).toString(16).padStart(2, '0').toUpperCase()
107
+ const color = (isLegendary && Math.random() > 0.95) ? chalk.yellow : (Math.random() > 0.5 ? chalk.cyan : chalk.cyan.dim)
108
+ line += color(hex) + ' '
109
+ }
110
+ }
111
+ process.stdout.write(line.substring(0, width * 10) + '\n')
112
+ }, 40)
113
+ }
114
+
115
+ module.exports = { language, matrixEffect, bootSequence }
@@ -112,7 +112,7 @@ const FormRenderer = ({ form, formItems, tableConfig, setModalTable, setSelected
112
112
  *
113
113
  * @example
114
114
  * <MyModalForm
115
- * title="构筑新模块"
115
+ * title='构筑新模块'
116
116
  * visible={visible}
117
117
  * submit={async (vals) => await save(vals)}
118
118
  * formItems={[{ label: '截止日期', name: 'deadline', type: 'date' }]}
@@ -30,7 +30,7 @@ import { useTableQuery } from '../hooks/useTableQuery'
30
30
  *
31
31
  * @example
32
32
  * <MyModalTable
33
- * title="关联用户片段"
33
+ * title='关联用户片段'
34
34
  * api={async params=>await fetchUsers(params)}
35
35
  * setModalForm={setModal} // 💡 借用主页面的表单构筑舱
36
36
  * operate={({ refresh, setModalForm }) => ({ label: '详情', onClick: (rec) => setModalForm(...) })}
@@ -19,10 +19,10 @@ import { Button, Tree, Radio, Input, Upload, Select, Cascader, Checkbox, DatePic
19
19
  *
20
20
  * @example
21
21
  * // 基本构筑
22
- * <AliyunOSSUpload path="project/data" url="/api/oss/token" />
22
+ * <AliyunOSSUpload path='project/data' url='/api/oss/token' />
23
23
  *
24
24
  * // 高级装配(限制文件类型并开启多选)
25
- * <AliyunOSSUpload accept=".pdf" multiple={true} path="docs" url="/api/oss/token" />
25
+ * <AliyunOSSUpload accept='.pdf' multiple={true} path='docs' url='/api/oss/token' />
26
26
  */
27
27
  const AliyunOSSUpload = ({ value, onChange, ...restProps }) => {
28
28
 
@@ -38,9 +38,9 @@ const onTabChange = key => {
38
38
  {{#if hasExpandable}}
39
39
  const onExpand = async (expanded, record) => {
40
40
  if (expanded) {
41
- setExpandedRowKeys([...expandedRowKeys, record.key])
41
+ setExpandedRowKeys(prev=>[...prev, record.key])
42
42
  } else {
43
- setExpandedRowKeys(expandedRowKeys.filter(item => item !== record.key))
43
+ setExpandedRowKeys(prev=>prev.filter(item => item !== record.key))
44
44
  }
45
45
  }
46
46
 
@@ -1,38 +0,0 @@
1
- const createTaskQueue = (concurrency = 1) => {
2
-
3
- let running = 0
4
- let queue = []
5
- let onIdleCallback = null
6
-
7
- const next = async () => {
8
-
9
- if (running >= concurrency || queue.length === 0) return
10
-
11
- const task = queue.shift()
12
- running++
13
-
14
- try {
15
- await task()
16
- } catch (err) {
17
- console.error('任务执行异常:', err)
18
- } finally {
19
- running--
20
- next()
21
- if (running === 0 && queue.length === 0 && onIdleCallback) {
22
- onIdleCallback()
23
- }
24
- }
25
- }
26
-
27
- return {
28
- add: (task) => {
29
- queue.push(task)
30
- next()
31
- },
32
- onIdle: (callback) => {
33
- onIdleCallback = callback
34
- }
35
- }
36
- }
37
-
38
- module.exports = { createTaskQueue }