whistle.mockbubu 1.0.0-dev.4 → 2.0.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.
- package/.gitignore +4 -0
- package/CHANGELOG_GROUP_FEATURE.md +468 -0
- package/CHANGELOG_P0_FIXES.md +412 -0
- package/CHANGELOG_P1_OPTIMIZATIONS.md +292 -0
- package/CLAUDE.md +436 -0
- package/GROUP_FEATURE_DESIGN.md +520 -0
- package/lib/const.js +19 -0
- package/lib/group-manager.js +491 -0
- package/lib/server.js +173 -33
- package/lib/uiServer/index.js +46 -4
- package/lib/uiServer/router/group-router.js +218 -0
- package/lib/uiServer/router/index.js +1393 -38
- package/lib/uiServer/router/version-router.js +131 -53
- package/lib/uiServer/util.js +64 -10
- package/lib/uiServer/validator.js +105 -0
- package/lib/utils.js +149 -27
- package/package.json +1 -1
- package/public/js/app.js +4541 -747
- package/public/js/app.js.map +1 -1
- package/public/js/chunk-vendors.js +12194 -6869
- package/public/js/chunk-vendors.js.map +1 -1
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock 数据分组管理器
|
|
3
|
+
* 负责管理多个 Mock 数据组,每个组有独立的 mock 配置
|
|
4
|
+
*/
|
|
5
|
+
class GroupManager {
|
|
6
|
+
constructor(storage) {
|
|
7
|
+
this.storage = storage
|
|
8
|
+
this.GROUPS_KEY = '__groups__'
|
|
9
|
+
this.DEFAULT_GROUP_ID = 'default'
|
|
10
|
+
this.DEFAULT_GROUP_NAME = '默认组'
|
|
11
|
+
|
|
12
|
+
// 初始化:确保默认组存在
|
|
13
|
+
this.ensureDefaultGroup()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 确保默认组存在
|
|
18
|
+
*/
|
|
19
|
+
ensureDefaultGroup() {
|
|
20
|
+
const groupsData = this.getGroupsData()
|
|
21
|
+
if (!groupsData || !groupsData.groups || groupsData.groups.length === 0) {
|
|
22
|
+
// 首次使用,创建默认组
|
|
23
|
+
const defaultGroup = {
|
|
24
|
+
id: this.DEFAULT_GROUP_ID,
|
|
25
|
+
name: this.DEFAULT_GROUP_NAME,
|
|
26
|
+
description: '系统默认分组',
|
|
27
|
+
createTime: Date.now(),
|
|
28
|
+
updateTime: Date.now(),
|
|
29
|
+
isDefault: true,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
this.storage.setProperty(this.GROUPS_KEY, {
|
|
33
|
+
groups: [defaultGroup],
|
|
34
|
+
currentGroupId: this.DEFAULT_GROUP_ID,
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 获取组列表数据(内部方法)
|
|
41
|
+
*/
|
|
42
|
+
getGroupsData() {
|
|
43
|
+
return this.storage.getProperty(this.GROUPS_KEY) || {
|
|
44
|
+
groups: [],
|
|
45
|
+
currentGroupId: this.DEFAULT_GROUP_ID,
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 保存组列表数据(内部方法)
|
|
51
|
+
*/
|
|
52
|
+
setGroupsData(data) {
|
|
53
|
+
this.storage.setProperty(this.GROUPS_KEY, data)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 获取所有组
|
|
58
|
+
*/
|
|
59
|
+
getGroups() {
|
|
60
|
+
const data = this.getGroupsData()
|
|
61
|
+
return data.groups || []
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 获取当前组ID
|
|
66
|
+
*/
|
|
67
|
+
getCurrentGroupId() {
|
|
68
|
+
const data = this.getGroupsData()
|
|
69
|
+
return data.currentGroupId || this.DEFAULT_GROUP_ID
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* 获取当前组信息
|
|
74
|
+
*/
|
|
75
|
+
getCurrentGroup() {
|
|
76
|
+
const currentId = this.getCurrentGroupId()
|
|
77
|
+
const groups = this.getGroups()
|
|
78
|
+
return groups.find(g => g.id === currentId) || groups[0]
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* 设置当前组
|
|
83
|
+
*/
|
|
84
|
+
setCurrentGroup(groupId) {
|
|
85
|
+
const groups = this.getGroups()
|
|
86
|
+
const group = groups.find(g => g.id === groupId)
|
|
87
|
+
|
|
88
|
+
if (!group) {
|
|
89
|
+
throw new Error(`组不存在: ${groupId}`)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const data = this.getGroupsData()
|
|
93
|
+
data.currentGroupId = groupId
|
|
94
|
+
this.setGroupsData(data)
|
|
95
|
+
|
|
96
|
+
return group
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* 生成唯一组ID
|
|
101
|
+
*/
|
|
102
|
+
generateGroupId() {
|
|
103
|
+
return 'group_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* 创建新组
|
|
108
|
+
* @param {Object} params
|
|
109
|
+
* @param {string} params.name - 组名
|
|
110
|
+
* @param {string} params.description - 组描述
|
|
111
|
+
* @param {string} params.copyFromGroupId - 从哪个组复制(可选)
|
|
112
|
+
*/
|
|
113
|
+
createGroup({ name, description = '', copyFromGroupId = null }) {
|
|
114
|
+
if (!name || !name.trim()) {
|
|
115
|
+
throw new Error('组名不能为空')
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const groups = this.getGroups()
|
|
119
|
+
|
|
120
|
+
// 检查组名是否重复
|
|
121
|
+
if (groups.some(g => g.name === name)) {
|
|
122
|
+
throw new Error('组名已存在')
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 检查组数量限制(最多10个)
|
|
126
|
+
if (groups.length >= 10) {
|
|
127
|
+
throw new Error('组数量已达上限(10个)')
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const newGroup = {
|
|
131
|
+
id: this.generateGroupId(),
|
|
132
|
+
name: name.trim(),
|
|
133
|
+
description: description.trim(),
|
|
134
|
+
createTime: Date.now(),
|
|
135
|
+
updateTime: Date.now(),
|
|
136
|
+
isDefault: false,
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// 如果指定了复制源,复制配置
|
|
140
|
+
if (copyFromGroupId) {
|
|
141
|
+
this.copyGroupConfigs(copyFromGroupId, newGroup.id)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// 保存新组
|
|
145
|
+
const data = this.getGroupsData()
|
|
146
|
+
data.groups.push(newGroup)
|
|
147
|
+
this.setGroupsData(data)
|
|
148
|
+
|
|
149
|
+
return newGroup
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 更新组信息
|
|
154
|
+
*/
|
|
155
|
+
updateGroup(groupId, { name, description }) {
|
|
156
|
+
const groups = this.getGroups()
|
|
157
|
+
const groupIndex = groups.findIndex(g => g.id === groupId)
|
|
158
|
+
|
|
159
|
+
if (groupIndex === -1) {
|
|
160
|
+
throw new Error(`组不存在: ${groupId}`)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// 检查新名称是否与其他组重复
|
|
164
|
+
if (name && groups.some((g, idx) => idx !== groupIndex && g.name === name)) {
|
|
165
|
+
throw new Error('组名已存在')
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const group = groups[groupIndex]
|
|
169
|
+
if (name) group.name = name.trim()
|
|
170
|
+
if (description !== undefined) group.description = description.trim()
|
|
171
|
+
group.updateTime = Date.now()
|
|
172
|
+
|
|
173
|
+
const data = this.getGroupsData()
|
|
174
|
+
data.groups[groupIndex] = group
|
|
175
|
+
this.setGroupsData(data)
|
|
176
|
+
|
|
177
|
+
return group
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* 删除组
|
|
182
|
+
*/
|
|
183
|
+
deleteGroup(groupId) {
|
|
184
|
+
if (groupId === this.DEFAULT_GROUP_ID) {
|
|
185
|
+
throw new Error('不能删除默认组')
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const groups = this.getGroups()
|
|
189
|
+
const groupIndex = groups.findIndex(g => g.id === groupId)
|
|
190
|
+
|
|
191
|
+
if (groupIndex === -1) {
|
|
192
|
+
throw new Error(`组不存在: ${groupId}`)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// 删除组的所有配置
|
|
196
|
+
this.deleteGroupConfigs(groupId)
|
|
197
|
+
|
|
198
|
+
// 从列表中移除
|
|
199
|
+
groups.splice(groupIndex, 1)
|
|
200
|
+
|
|
201
|
+
const data = this.getGroupsData()
|
|
202
|
+
data.groups = groups
|
|
203
|
+
|
|
204
|
+
// 如果删除的是当前组,切换到默认组
|
|
205
|
+
if (data.currentGroupId === groupId) {
|
|
206
|
+
data.currentGroupId = this.DEFAULT_GROUP_ID
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
this.setGroupsData(data)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* 获取组的配置键名
|
|
214
|
+
*/
|
|
215
|
+
getGroupConfigKey(groupId, filename) {
|
|
216
|
+
return `group.${groupId}.${filename}`
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* 获取组的文件配置
|
|
221
|
+
*/
|
|
222
|
+
getGroupFileConfig(groupId, filename) {
|
|
223
|
+
const key = this.getGroupConfigKey(groupId, filename)
|
|
224
|
+
const config = this.storage.getProperty(key)
|
|
225
|
+
|
|
226
|
+
return config || {
|
|
227
|
+
mock: false,
|
|
228
|
+
locked: false,
|
|
229
|
+
mockVersion: null,
|
|
230
|
+
mockTime: null,
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* 设置组的文件配置
|
|
236
|
+
* 注意:直接使用 storage.setProperty 而不是 setProperty 工具函数
|
|
237
|
+
* 因为 setProperty 会使用 Object.assign 合并对象,而我们需要完全替换
|
|
238
|
+
*/
|
|
239
|
+
setGroupFileConfig(groupId, filename, config) {
|
|
240
|
+
const key = this.getGroupConfigKey(groupId, filename)
|
|
241
|
+
// 直接设置,不使用 Object.assign 合并
|
|
242
|
+
this.storage.setProperty(key, config)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* 复制组配置(从源组到目标组)
|
|
247
|
+
*/
|
|
248
|
+
copyGroupConfigs(sourceGroupId, targetGroupId) {
|
|
249
|
+
// 获取所有文件名
|
|
250
|
+
const fileList = this.storage.getFileList()
|
|
251
|
+
|
|
252
|
+
fileList.forEach(item => {
|
|
253
|
+
const filename = item.name
|
|
254
|
+
const sourceKey = this.getGroupConfigKey(sourceGroupId, filename)
|
|
255
|
+
const sourceConfig = this.storage.getProperty(sourceKey)
|
|
256
|
+
|
|
257
|
+
if (sourceConfig) {
|
|
258
|
+
const targetKey = this.getGroupConfigKey(targetGroupId, filename)
|
|
259
|
+
// 深拷贝配置
|
|
260
|
+
this.storage.setProperty(targetKey, JSON.parse(JSON.stringify(sourceConfig)))
|
|
261
|
+
}
|
|
262
|
+
})
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* 删除组的所有配置
|
|
267
|
+
*/
|
|
268
|
+
deleteGroupConfigs(groupId) {
|
|
269
|
+
// 完全隔离架构:删除该组所有文件的配置
|
|
270
|
+
const fileList = this.storage.getFileList()
|
|
271
|
+
const prefix = `${groupId}/`
|
|
272
|
+
|
|
273
|
+
// 过滤出属于该组的文件
|
|
274
|
+
const groupFiles = fileList.filter(item => item.name.startsWith(prefix))
|
|
275
|
+
|
|
276
|
+
groupFiles.forEach(item => {
|
|
277
|
+
// 提取纯文件名(移除 groupId/ 前缀)
|
|
278
|
+
const filename = item.name.replace(prefix, '')
|
|
279
|
+
const key = this.getGroupConfigKey(groupId, filename)
|
|
280
|
+
// 检查该属性是否存在,存在则删除
|
|
281
|
+
if (this.storage.getProperty(key)) {
|
|
282
|
+
this.storage.removeProperty(key)
|
|
283
|
+
}
|
|
284
|
+
})
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* 迁移现有数据到默认组
|
|
289
|
+
* 将旧版本的配置迁移到默认组
|
|
290
|
+
*/
|
|
291
|
+
migrateExistingData() {
|
|
292
|
+
console.log('[mockbubu] 开始数据迁移检查...')
|
|
293
|
+
|
|
294
|
+
// 不进行自动迁移!旧数据可能包含超大文件导致内存溢出
|
|
295
|
+
// 用户如果需要迁移旧数据,应该手动删除 properties 文件中的旧配置
|
|
296
|
+
console.log('[mockbubu] 跳过自动迁移,避免内存溢出')
|
|
297
|
+
console.log('[mockbubu] 如需迁移旧数据,请手动删除 properties 中的超大文件')
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* 检查组是否有文件配置
|
|
302
|
+
*/
|
|
303
|
+
hasGroupConfig(groupId, filename) {
|
|
304
|
+
const key = this.getGroupConfigKey(groupId, filename)
|
|
305
|
+
return this.storage.hasProperty(key)
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* 删除组的文件配置(仅删除 Layer 3)
|
|
310
|
+
* 不删除原始数据和全局元数据
|
|
311
|
+
* @param {string} groupId - 组ID
|
|
312
|
+
* @param {string} filename - 文件名
|
|
313
|
+
*/
|
|
314
|
+
removeGroupFileConfig(groupId, filename) {
|
|
315
|
+
const key = this.getGroupConfigKey(groupId, filename)
|
|
316
|
+
this.storage.removeProperty(key)
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* ❌ 废弃:完全隔离架构下不再需要此函数
|
|
321
|
+
* 原因:每个组有独立的物理文件存储(groupId/filename),删除时直接删除即可
|
|
322
|
+
*
|
|
323
|
+
* @deprecated 将在 Phase 2 完成后移除此函数及其所有调用
|
|
324
|
+
*
|
|
325
|
+
* 检查文件是否被其他组使用
|
|
326
|
+
* @param {string} currentGroupId - 当前组ID
|
|
327
|
+
* @param {string} filename - 文件名
|
|
328
|
+
* @returns {boolean} - 永远返回 false(完全隔离架构下无需判断)
|
|
329
|
+
*/
|
|
330
|
+
isFileUsedByOtherGroups(currentGroupId, filename) {
|
|
331
|
+
// ⚠️ 临时实现:返回 false,因为完全隔离架构下每个组文件独立
|
|
332
|
+
// 在 Phase 2.4 更新所有调用方后,此函数将被完全移除
|
|
333
|
+
return false
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* ❌ 废弃:完全隔离架构下不再需要此函数
|
|
338
|
+
* 原因:每个组有独立的物理文件,无需跨组查询
|
|
339
|
+
*
|
|
340
|
+
* @deprecated 将在 Phase 2 完成后移除(仅用于已废弃的批量删除预览接口)
|
|
341
|
+
*
|
|
342
|
+
* 获取所有使用该文件的组列表
|
|
343
|
+
* @param {string} filename - 文件名
|
|
344
|
+
* @returns {Array<Object>} - 空数组(完全隔离架构下无意义)
|
|
345
|
+
*/
|
|
346
|
+
getGroupsUsingFile(filename) {
|
|
347
|
+
// ⚠️ 临时实现:返回空数组
|
|
348
|
+
// 此函数仅被已废弃的 batchDeletePreview 接口使用
|
|
349
|
+
return []
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* 获取组的版本列表
|
|
354
|
+
*/
|
|
355
|
+
getGroupVersions(groupId, filename) {
|
|
356
|
+
const config = this.getGroupFileConfig(groupId, filename)
|
|
357
|
+
const list = []
|
|
358
|
+
|
|
359
|
+
Object.keys(config).forEach((key) => {
|
|
360
|
+
const matchs = key.match(/^version\.(.+)/)
|
|
361
|
+
if (matchs && matchs[1]) {
|
|
362
|
+
const versionName = matchs[1]
|
|
363
|
+
const metaKey = `versionMeta.${versionName}`
|
|
364
|
+
const meta = config[metaKey] || {}
|
|
365
|
+
|
|
366
|
+
list.push({
|
|
367
|
+
filename: versionName,
|
|
368
|
+
content: config[key],
|
|
369
|
+
description: meta.description || '',
|
|
370
|
+
createTime: meta.createTime || 0,
|
|
371
|
+
updateTime: meta.updateTime || 0,
|
|
372
|
+
})
|
|
373
|
+
}
|
|
374
|
+
})
|
|
375
|
+
|
|
376
|
+
// 按修改时间倒序
|
|
377
|
+
return list.sort((a, b) => b.updateTime - a.updateTime)
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* 添加组的版本
|
|
382
|
+
*/
|
|
383
|
+
addGroupVersion(groupId, filename, versionName, content, description = '') {
|
|
384
|
+
const config = this.getGroupFileConfig(groupId, filename)
|
|
385
|
+
|
|
386
|
+
// 检查版本数量限制
|
|
387
|
+
const versions = this.getGroupVersions(groupId, filename)
|
|
388
|
+
if (versions.length >= 10) {
|
|
389
|
+
throw new Error('版本数量已达上限(10个),请删除旧版本后再创建')
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const versionKey = `version.${versionName}`
|
|
393
|
+
const metaKey = `versionMeta.${versionName}`
|
|
394
|
+
const now = Date.now()
|
|
395
|
+
|
|
396
|
+
config[versionKey] = content
|
|
397
|
+
config[metaKey] = {
|
|
398
|
+
description,
|
|
399
|
+
createTime: now,
|
|
400
|
+
updateTime: now,
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
this.setGroupFileConfig(groupId, filename, config)
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* 更新组的版本内容
|
|
408
|
+
*/
|
|
409
|
+
updateGroupVersionContent(groupId, filename, versionName, content) {
|
|
410
|
+
const config = this.getGroupFileConfig(groupId, filename)
|
|
411
|
+
const versionKey = `version.${versionName}`
|
|
412
|
+
const metaKey = `versionMeta.${versionName}`
|
|
413
|
+
|
|
414
|
+
config[versionKey] = content
|
|
415
|
+
if (config[metaKey]) {
|
|
416
|
+
config[metaKey].updateTime = Date.now()
|
|
417
|
+
} else {
|
|
418
|
+
config[metaKey] = {
|
|
419
|
+
description: '',
|
|
420
|
+
createTime: Date.now(),
|
|
421
|
+
updateTime: Date.now(),
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
this.setGroupFileConfig(groupId, filename, config)
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* 获取组的版本内容
|
|
430
|
+
*/
|
|
431
|
+
getGroupVersionContent(groupId, filename, versionName) {
|
|
432
|
+
const config = this.getGroupFileConfig(groupId, filename)
|
|
433
|
+
const versionKey = `version.${versionName}`
|
|
434
|
+
return config[versionKey]
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* 删除组的版本
|
|
439
|
+
*/
|
|
440
|
+
deleteGroupVersion(groupId, filename, versionName) {
|
|
441
|
+
const config = this.getGroupFileConfig(groupId, filename)
|
|
442
|
+
const versionKey = `version.${versionName}`
|
|
443
|
+
const metaKey = `versionMeta.${versionName}`
|
|
444
|
+
|
|
445
|
+
delete config[versionKey]
|
|
446
|
+
delete config[metaKey]
|
|
447
|
+
|
|
448
|
+
this.setGroupFileConfig(groupId, filename, config)
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* 更新组的版本元信息
|
|
453
|
+
*/
|
|
454
|
+
updateGroupVersionMeta(groupId, filename, versionName, newVersionName, description) {
|
|
455
|
+
const config = this.getGroupFileConfig(groupId, filename)
|
|
456
|
+
const oldVersionKey = `version.${versionName}`
|
|
457
|
+
const oldMetaKey = `versionMeta.${versionName}`
|
|
458
|
+
const content = config[oldVersionKey]
|
|
459
|
+
const oldMeta = config[oldMetaKey] || {}
|
|
460
|
+
|
|
461
|
+
if (!content) {
|
|
462
|
+
throw new Error('版本不存在')
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// 如果版本名变了
|
|
466
|
+
if (versionName !== newVersionName) {
|
|
467
|
+
delete config[oldVersionKey]
|
|
468
|
+
delete config[oldMetaKey]
|
|
469
|
+
|
|
470
|
+
const newVersionKey = `version.${newVersionName}`
|
|
471
|
+
const newMetaKey = `versionMeta.${newVersionName}`
|
|
472
|
+
config[newVersionKey] = content
|
|
473
|
+
config[newMetaKey] = {
|
|
474
|
+
...oldMeta,
|
|
475
|
+
description,
|
|
476
|
+
updateTime: Date.now(),
|
|
477
|
+
}
|
|
478
|
+
} else {
|
|
479
|
+
// 只更新元数据
|
|
480
|
+
config[oldMetaKey] = {
|
|
481
|
+
...oldMeta,
|
|
482
|
+
description,
|
|
483
|
+
updateTime: Date.now(),
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
this.setGroupFileConfig(groupId, filename, config)
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
module.exports = GroupManager
|