mm_machine 2.0.1 → 2.0.3

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/item.js CHANGED
@@ -1,13 +1,31 @@
1
+ require('mm_logs');
1
2
  const util = require('util');
2
3
  const conf = require('mm_config');
3
4
  const Mod = require('mm_hot_reload');
4
- $.mod = new Mod();
5
- $.require = function(file, func) {
5
+
6
+
7
+ // 初始化模块管理器
8
+ $.mod = $.mod || new Mod();
9
+
10
+ /**
11
+ * 增强require函数,支持热更新
12
+ * @param {String} file 文件路径
13
+ * @param {Function} func 回调函数
14
+ * @returns {Object} 加载的模块
15
+ */
16
+ $.require = function (file, func) {
6
17
  return $.mod.load(file, func);
7
- }
8
- $.loadJson = function(file, func) {
18
+ };
19
+
20
+ /**
21
+ * 增强JSON加载函数,支持热更新
22
+ * @param {String} file 文件路径
23
+ * @param {Function} func 回调函数
24
+ * @returns {Object} 解析的JSON对象
25
+ */
26
+ $.loadJson = function (file, func) {
9
27
  return $.mod.load(file, func);
10
- }
28
+ };
11
29
 
12
30
  /**
13
31
  * 驱动基础类
@@ -29,47 +47,48 @@ class Item {
29
47
  /**
30
48
  * 默认文件
31
49
  */
32
- this.default_file = "./sys.json";
50
+ this.default_file = './sys.json';
33
51
 
34
52
  // 当前文件
35
- this.filename;
53
+ this.filename = null;
54
+
36
55
  /* 通用项 */
37
56
  /**
38
57
  * 配置参数
39
58
  */
40
59
  this.config = {
41
60
  /**
42
- * 名称, 由中英文和下“_”组成, 用于卸载接口 例如: demo
61
+ * 名称, 由中英文和下"_"组成, 用于卸载接口 例如: demo
43
62
  */
44
- "name": "",
63
+ name: '',
45
64
  /**
46
65
  * 标题, 介绍作用
47
66
  */
48
- "title": "",
67
+ title: '',
49
68
  /**
50
69
  * 描述, 用于描述该有什么用的
51
70
  */
52
- "description": "",
71
+ description: '',
53
72
  /**
54
73
  * 文件路径, 当调用函数不存在时,会先从文件中加载
55
74
  */
56
- "func_file": "./index.js",
75
+ func_file: './index.js',
57
76
  /**
58
77
  * 回调函数名 用于决定调用脚本的哪个函数
59
78
  */
60
- "func_name": "",
79
+ func_name: '',
61
80
  /**
62
81
  * 排序
63
82
  */
64
- "sort": 10,
83
+ sort: 10,
65
84
  /**
66
85
  * 状态, 0表示未启用, 1表示启用
67
86
  */
68
- "state": 1,
87
+ state: 1,
69
88
  /**
70
89
  * 显示, 0表示不显示, 1表示显示
71
90
  */
72
- "show": 0
91
+ show: 0
73
92
  };
74
93
 
75
94
  /**
@@ -94,394 +113,462 @@ class Item {
94
113
 
95
114
  /**
96
115
  * 设置配置
97
- * @param {Object} config 配置
116
+ * @param {Object} config 配置对象
98
117
  */
99
- Item.prototype.set_config = function(config) {
100
- if (config && config.func_file !== this.config.func_file) {
118
+ Item.prototype.set_config = function (config) {
119
+ if (!config) return;
120
+
121
+ // 如果func_file改变,重置加载状态
122
+ if (config.func_file !== this.config.func_file) {
101
123
  this.complete = false;
102
124
  }
103
- this.config = conf(Object.assign({}, this.config, config || {}), this.filename);
104
- }
125
+
126
+ // 合并配置并应用配置处理
127
+ this.config = conf(Object.assign({}, this.config, config), this.filename);
128
+ };
105
129
 
106
130
  /**
107
- * 设置配置后
131
+ * 设置配置后钩子方法
108
132
  */
109
- Item.prototype.set_config_after = function() {
110
-
133
+ Item.prototype.set_config_after = function () {
134
+ // 空实现,供子类重写
111
135
  };
112
136
 
113
137
  /**
114
- * 新建脚本
115
- * @param {String} file
138
+ * 新建脚本文件
139
+ * @param {String} file 目标文件路径
116
140
  */
117
- Item.prototype.new_script = function(file) {
118
- var fl = this.dir_base + "/script.js";
119
- if (fl.hasFile()) {
120
- fl.copyFile(file);
141
+ Item.prototype.new_script = function (file) {
142
+ const templateFile = `${this.dir_base}/script.js`;
143
+ if (templateFile.hasFile()) {
144
+ templateFile.copyFile(file);
121
145
  }
122
146
  };
123
147
 
124
148
  /**
125
149
  * 移除模块
126
- * @param {Object} m
150
+ * @param {Object|String} module 模块对象或路径
127
151
  */
128
- Item.prototype.remove_module = function(m) {
129
- if (this.mode === 3 || this.mode === 4) {
130
- // 移除模块和监听
131
- $.mod.unload(m);
132
- } else {
133
- // 移除模块
134
- var filename = require.resolve(m);
135
- require.cache[filename] = null;
136
- delete require.cache[filename];
152
+ Item.prototype.remove_module = function (module) {
153
+ if (!module) return;
154
+
155
+ try {
156
+ if (this.mode === 3 || this.mode === 4) {
157
+ // 移除模块和监听
158
+ $.mod.unload(module);
159
+ } else {
160
+ // 移除模块缓存
161
+ const filename = require.resolve(module);
162
+ if (require.cache[filename]) {
163
+ require.cache[filename] = null;
164
+ delete require.cache[filename];
165
+ }
166
+ }
167
+ } catch (err) {
168
+ $.log.error(`移除模块失败: ${err.message}`);
137
169
  }
138
170
  };
139
171
 
140
172
  /**
141
173
  * 卸载脚本
142
- * @param {String} file 文件
174
+ * @param {String} file 文件路径
143
175
  */
144
- Item.prototype.unload_script = function(file) {
176
+ Item.prototype.unload_script = function (file) {
145
177
  if (!file) {
146
- var f = this.config.func_file;
147
- if (f) {
148
- file = f.fullname(this.dir)
178
+ const funcFile = this.config.func_file;
179
+ if (funcFile) {
180
+ file = funcFile.fullname(this.dir);
149
181
  }
150
182
  }
183
+
151
184
  if (file) {
152
185
  this.remove_module(file);
153
186
  }
187
+
154
188
  this.complete = false;
155
- }
189
+ };
156
190
 
157
191
  /**
158
192
  * 重载脚本
159
- * @param {String} file 文件
160
193
  */
161
- Item.prototype.reload_script = function() {
194
+ Item.prototype.reload_script = function () {
162
195
  this.unload_script();
163
196
  this.load_script();
164
- }
197
+ };
165
198
 
166
199
  /**
167
- * 卸载
200
+ * 卸载钩子方法
168
201
  */
169
- Item.prototype.unload = async function() {
170
-
171
- }
202
+ Item.prototype.unload = async function () {
203
+ // 空实现,供子类重写
204
+ };
172
205
 
173
206
  /**
174
- * 卸载之后
207
+ * 卸载之后处理
175
208
  * @param {Boolean} remove 是否删除文件
176
209
  */
177
- Item.prototype.unload_after = async function(remove) {
210
+ Item.prototype.unload_after = async function (remove) {
178
211
  // 删除脚本
179
212
  this.unload_script();
180
213
  if (remove) {
181
214
  this.remove_file();
182
215
  }
183
- }
216
+ };
184
217
 
185
218
  /**
186
219
  * 加载脚本
187
- * @param {String} file 文件
220
+ * @param {String} file 文件路径
188
221
  * @param {String} name 函数名
189
- * @returns {Object} 返回加载的模块对象
222
+ * @returns {Object|null} 返回加载的模块对象
190
223
  */
191
- Item.prototype.load_script = function(file, name = "") {
224
+ Item.prototype.load_script = function (file, name = '') {
192
225
  if (!file) {
193
- var f = this.config.func_file;
194
- if (f) {
195
- file = f.fullname(this.dir);
226
+ const funcFile = this.config.func_file;
227
+ if (funcFile) {
228
+ file = funcFile.fullname(this.dir);
196
229
  if (!file.hasFile()) {
197
230
  this.new_script(file);
198
231
  }
199
232
  } else {
200
- return;
233
+ return null;
201
234
  }
202
235
  }
236
+
203
237
  if (!name) {
204
238
  name = this.config.func_name;
205
239
  }
206
- var cs;
207
- if (this.mode === 3 || this.mode === 4) {
208
- cs = $.require(file, (cs, way) => {
209
- if (way == "change" && cs) {
210
- if (name) {
211
- if (cs[name]) {
212
- this.main = cs[name];
240
+
241
+ let cs;
242
+ try {
243
+ if (this.mode === 3 || this.mode === 4) {
244
+ cs = $.require(file, (loadedModule, changeType) => {
245
+ if (changeType === 'change' && loadedModule) {
246
+ if (name) {
247
+ if (loadedModule[name]) {
248
+ this.main = loadedModule[name];
249
+ }
250
+ } else if ($.push) {
251
+ $.push(this, loadedModule, true);
213
252
  }
214
- } else {
215
- $.push(this, cs, true);
216
253
  }
217
- }
218
- });
219
- } else {
220
- cs = require(file);
221
- }
222
- if (cs) {
223
- if (name) {
224
- if (cs[name]) {
225
- this.main = cs[name];
226
- }
254
+ });
227
255
  } else {
228
- $.push(this, cs, true);
256
+ cs = require(file);
229
257
  }
258
+
259
+ if (cs) {
260
+ if (name) {
261
+ if (cs[name]) {
262
+ this.main = cs[name];
263
+ }
264
+ } else if ($.push) {
265
+ $.push(this, cs, true);
266
+ }
267
+ }
268
+
269
+ return cs;
270
+ } catch (err) {
271
+ $.log.error(`加载脚本失败: ${err.message}`);
272
+ return null;
230
273
  }
231
- return cs;
232
- }
274
+ };
233
275
 
234
276
  /**
235
- * 新建配置
236
- * @param {String} file
277
+ * 新建配置文件
278
+ * @param {String} file 目标文件路径
237
279
  */
238
- Item.prototype.new_config = function(file) {
239
- var fl = this.dir_base + "/config.tpl.json";
240
- fl.copyFile(file);
280
+ Item.prototype.new_config = function (file) {
281
+ const templateFile = `${this.dir_base}/config.tpl.json`;
282
+ templateFile.copyFile(file);
241
283
  };
242
284
 
243
285
  /**
244
286
  * 加载配置文件
245
287
  * @param {String} file 文件路径
246
288
  * @param {String} name 配置项名称
247
- * @return {Object} 配置对象
289
+ * @return {Object|null} 配置对象
248
290
  */
249
- Item.prototype.load_file = function(file, name) {
250
- var config;
251
- var f = file.fullname(this.dir);
252
- var text = f.loadText();
253
- if (!text) {
254
- this.new_config(f);
255
- }
256
- if (text) {
257
- if (this.mode === 2 || this.mode === 3 || this.mode === 4) {
258
- config = $.loadJson(f, (conf, way) => {
259
- if (way == "change" && conf) {
260
- if (Array.isArray(conf)) {
261
- var list = conf;
262
- for (var i = 0; i < list.length; i++) {
263
- var o = list[i];
264
- if (this.config.name === o.name) {
265
- this.set_config(o);
291
+ Item.prototype.load_file = function (file, name) {
292
+ let config = null;
293
+ try {
294
+ const fullPath = file.fullname(this.dir);
295
+ let text = fullPath.loadText();
296
+
297
+ // 如果文件不存在,创建新的配置文件
298
+ if (!text) {
299
+ this.new_config(fullPath);
300
+ text = fullPath.loadText();
301
+ }
302
+
303
+ if (text) {
304
+ // 根据模式决定是否使用热更新加载
305
+ if (this.mode === 2 || this.mode === 3 || this.mode === 4) {
306
+ config = $.loadJson(fullPath, function (loadedConfig, changeType) {
307
+ if (changeType === 'change' && loadedConfig) {
308
+ try {
309
+ if (Array.isArray(loadedConfig)) {
310
+ // 在数组中查找匹配的配置项
311
+ const targetConfig = loadedConfig.find(item => item.name === this.config.name);
312
+ if (targetConfig) {
313
+ this.set_config(targetConfig);
314
+ this.set_config_after();
315
+ // 根据模式决定是否重新加载脚本
316
+ if (this.mode === 3 || this.mode === 4) {
317
+ this.reload_script();
318
+ }
319
+ }
320
+ } else {
321
+ this.set_config(loadedConfig);
266
322
  this.set_config_after();
267
323
  if (this.mode === 3 || this.mode === 4) {
268
324
  this.reload_script();
269
325
  }
270
- break;
271
326
  }
272
- }
273
- } else {
274
- this.set_config(conf);
275
- this.set_config_after();
276
- if (this.mode === 3 || this.mode === 4) {
277
- this.reload_script();
327
+ } catch (err) {
328
+ $.log.error(`配置热更新失败: ${err.message}`);
278
329
  }
279
330
  }
280
- }
281
- });
282
- } else {
283
- config = f.loadJson();
284
- }
331
+ }.bind(this));
332
+ } else {
333
+ config = fullPath.loadJson();
334
+ }
285
335
 
286
- if (name) {
287
- if (Array.isArray(config)) {
288
- var list = config;
289
- for (var i = 0; i < list.length; i++) {
290
- var o = list[i];
291
- if (name === o.name) {
292
- config = o;
293
- break;
294
- }
295
- }
336
+ // 如果指定了名称且配置是数组,查找匹配项
337
+ if (name && Array.isArray(config)) {
338
+ config = config.find(item => item.name === name) || null;
296
339
  }
297
340
  }
341
+
342
+ // 更新目录和文件名引用
343
+ this.dir = fullPath.dirname();
344
+ this.filename = fullPath;
345
+ return config;
346
+ } catch (err) {
347
+ $.log.error(`加载配置文件失败: ${err.message}`);
348
+ return null;
298
349
  }
299
- this.dir = f.dirname();
300
- this.filename = f;
301
- return config;
302
350
  };
303
351
 
304
352
  /**
305
- * 删除文件
353
+ * 删除目录
306
354
  */
307
- Item.prototype.del_dir = function() {
308
- var f = this.config.func_file;
309
- if (f) {
355
+ Item.prototype.del_dir = function () {
356
+ const funcFile = this.config.func_file;
357
+ if (funcFile && $.dir && $.dir.del) {
310
358
  $.dir.del(this.dir);
311
359
  }
312
360
  };
313
361
 
314
362
  /**
315
363
  * 删除配置和脚本文件
316
- * @param {Object} item 项目
364
+ * @returns {String|null} 错误消息,如果没有错误则返回null
317
365
  */
318
- Item.prototype.remove_file = function() {
319
- var name = this.config.name;
320
- var file = this.filename;
321
-
322
- var msg = null;
323
- if (file.hasFile()) {
324
- var text = file.loadText();
325
- if (text) {
326
- var jarr = text.toJson();
327
- if (jarr.constructor == Array) {
328
- for (var i = 0; i < jarr.length; i++) {
329
- var o = jarr[i];
330
- if (name === o.name) {
366
+ Item.prototype.remove_file = function () {
367
+ const name = this.config.name;
368
+ const file = this.filename;
369
+
370
+ let errorMessage = null;
371
+ try {
372
+ if (file && file.hasFile) {
373
+ if (file.hasFile()) {
374
+ const text = file.loadText();
375
+ if (text) {
376
+ const config = text.toJson();
377
+ if (Array.isArray(config)) {
378
+ // 在数组配置中查找并删除指定项
379
+ const index = config.findIndex(item => item.name === name);
380
+ if (index !== -1) {
381
+ this.del_dir();
382
+ config.splice(index, 1);
383
+ }
384
+ // 根据剩余配置决定保存或删除文件
385
+ if (config.length > 0) {
386
+ file.saveText(JSON.stringify(config, null, 4));
387
+ } else if (file.delFile) {
388
+ file.delFile();
389
+ }
390
+ } else {
391
+ // 单个配置直接删除目录
331
392
  this.del_dir();
332
- jarr.splice(i, 1);
333
- break;
334
393
  }
335
- }
336
- if (jarr.length) {
337
- file.saveText(JSON.stringify(jarr, null, 4));
338
394
  } else {
339
- file.delFile();
395
+ this.del_dir();
340
396
  }
341
397
  } else {
342
- this.del_dir();
398
+ errorMessage = '配置文件不存在';
343
399
  }
344
- } else {
345
- this.del_dir();
346
400
  }
347
- } else {
348
- msg = "配置文件不存在";
401
+ } catch (err) {
402
+ $.log.error(`删除文件失败: ${err.message}`);
403
+ errorMessage = `删除失败: ${err.message}`;
349
404
  }
350
- return msg;
405
+ return errorMessage;
351
406
  };
352
407
 
353
408
  /**
354
409
  * 载入配置
355
- * @param {Object|String} conf 配置对象或配置路径
410
+ * @param {Object|String} configData 配置对象或配置路径
356
411
  * @param {String} name 配置名称
357
412
  */
358
- Item.prototype.load_config = function(conf, name) {
359
- var config;
360
- if (conf) {
361
- if (typeof(conf) === "string") {
362
- config = this.load_file(conf, name);
413
+ Item.prototype.load_config = function (configData, name) {
414
+ let config;
415
+ try {
416
+ if (configData) {
417
+ if (typeof configData === 'string') {
418
+ config = this.load_file(configData, name);
419
+ } else {
420
+ config = configData;
421
+ }
363
422
  } else {
364
- config = conf;
423
+ config = this.load_file(this.filename, name);
365
424
  }
366
- } else {
367
- config = this.load_file(this.filename, name);
425
+
426
+ this.set_config(config);
427
+ this.set_config_after();
428
+ } catch (err) {
429
+ $.log.error(`载入配置失败: ${err.message}`);
368
430
  }
369
- this.set_config(config);
370
- this.set_config_after();
371
431
  };
372
432
 
373
433
  /**
374
- * 加载前
434
+ * 加载前处理
375
435
  */
376
- Item.prototype.load_before = async function() {
377
- var cs = this.load_script();
378
- if (cs) {
379
- this.complete = true;
436
+ Item.prototype.load_before = async function () {
437
+ try {
438
+ const module = this.load_script();
439
+ if (module) {
440
+ this.complete = true;
441
+ }
442
+ } catch (err) {
443
+ $.log.error(`加载前处理失败: ${err.message}`);
444
+ this.complete = false;
380
445
  }
381
- }
446
+ };
382
447
 
383
448
  /**
384
- * 加载
449
+ * 加载处理
385
450
  */
386
- Item.prototype.load = async function() {
387
- // 加载前
388
- }
451
+ Item.prototype.load = async function () {
452
+ // 空实现,供子类重写
453
+ };
389
454
 
390
455
  /**
391
456
  * 重载配置和脚本
392
457
  */
393
- Item.prototype.reload = async function() {
458
+ Item.prototype.reload = async function () {
394
459
  await this.run('unload');
395
460
  await this.run('load');
396
- }
461
+ };
397
462
 
398
463
  /**
399
464
  * 保存配置
400
465
  */
401
- Item.prototype.save = function() {
402
- var f = this.filename.fullname(this.dir);
403
- var text = f.loadText();
404
- if (text) {
405
- if (text.trim().startsWith('[')) {
406
- var jarr = text.toJson();
407
- for (var i = 0; i < jarr.length; i++) {
408
- if (jarr[i].name === this.config.name) {
409
- jarr[i] = this.config;
410
- break;
466
+ Item.prototype.save = function () {
467
+ try {
468
+ if (!this.filename) return;
469
+
470
+ const fullPath = this.filename.fullname(this.dir);
471
+ const text = fullPath.loadText();
472
+
473
+ if (text && text.trim().startsWith('[')) {
474
+ // 数组格式配置
475
+ const configArray = text.toJson();
476
+ if (Array.isArray(configArray)) {
477
+ // 查找并更新现有配置项
478
+ const existingIndex = configArray.findIndex(item => item.name === this.config.name);
479
+ if (existingIndex !== -1) {
480
+ configArray[existingIndex] = this.config;
481
+ } else {
482
+ // 如果不存在,添加新配置项
483
+ configArray.push(this.config);
411
484
  }
485
+ fullPath.saveText(JSON.stringify(configArray, null, 4));
486
+ return;
412
487
  }
413
- var txt = JSON.stringify(jarr, null, 4);
414
- f.saveText(txt);
415
- return;
416
488
  }
489
+
490
+ // 单对象格式配置,直接保存
491
+ fullPath.saveText(JSON.stringify(this.config, null, 4));
492
+ } catch (err) {
493
+ $.log.error(`保存配置失败: ${err.message}`);
417
494
  }
418
- var txt = JSON.stringify(this.config, null, 4);
419
- f.saveText(txt);
420
495
  };
421
496
 
422
497
  /**
423
498
  * 主要执行函数
424
- * @param {Object} params 参数集合
499
+ * @param {*} params 参数集合
500
+ * @returns {Promise<any>} 执行结果
425
501
  */
426
- Item.prototype.main = async function(...params) {
427
- // console.log("未实现", params);
502
+ Item.prototype.main = async function (...params) {
503
+ // 空实现,供子类重写
428
504
  return null;
429
505
  };
430
506
 
431
507
  /**
432
- * 运行
433
- * @param {Object} params 参数集合
508
+ * 运行主函数
509
+ * @param {*} params 参数集合
510
+ * @returns {Promise<any>} 执行结果
434
511
  */
435
- Item.prototype.run = async function(...params) {
436
- return await this.exec("main", ...params);
437
- }
512
+ Item.prototype.run = async function (...params) {
513
+ return await this.exec('main', ...params);
514
+ };
438
515
 
439
516
  /**
440
- * 调用函数
517
+ * 调用函数(核心执行方法)
441
518
  * @param {String} method 函数名
442
- * @param {Object} params 参数集合
443
- * @return {Object} 执行结果
519
+ * @param {*} params 参数集合
520
+ * @returns {Promise<any>} 执行结果
444
521
  */
445
- Item.prototype.exec = async function(method, ...params) {
446
- if (this[method]) {
447
- var ret;
448
- if (this[method + "_before"]) {
522
+ Item.prototype.exec = async function (method, ...params) {
523
+ if (!this[method]) {
524
+ return null;
525
+ }
526
+
527
+ let result;
528
+
529
+ try {
530
+ // 执行前置钩子
531
+ const beforeMethod = `${method}_before`;
532
+ if (this[beforeMethod]) {
449
533
  try {
450
- ret = this[method + "_before"](...params);
534
+ result = this[beforeMethod](...params);
535
+ if (util.types.isPromise(result)) {
536
+ result = await result;
537
+ }
451
538
  } catch (err) {
452
- $.log.error("执行前失败!", err);
539
+ $.log.error(`执行前置钩子 ${beforeMethod} 失败: ${err.message}`);
453
540
  }
454
- if (util.types.isPromise(ret)) {
455
- ret = await ret;
456
- }
457
- }
458
- try {
459
- ret = this[method](...params);
460
- } catch (err) {
461
- $.log.error("执行时失败!", err);
462
- }
463
- if (util.types.isPromise(ret)) {
464
- ret = await ret;
465
541
  }
466
- // console.log(this.config.name + "-" + method + "内容", ret);
467
- if (this[method + "_after"]) {
542
+
543
+ // 执行主方法
544
+ const methodResult = this[method](...params);
545
+ result = util.types.isPromise(methodResult) ? await methodResult : methodResult;
546
+
547
+ // 执行后置钩子
548
+ const afterMethod = `${method}_after`;
549
+ if (this[afterMethod]) {
468
550
  try {
469
- var result = this[method + "_after"](ret, ...params);
470
- if (util.types.isPromise(result)) {
471
- result = await result;
472
- }
473
- if (result) {
474
- ret = result;
551
+ const afterResult = this[afterMethod](result, ...params);
552
+ if (util.types.isPromise(afterResult)) {
553
+ const resolvedAfterResult = await afterResult;
554
+ if (resolvedAfterResult !== undefined) {
555
+ result = resolvedAfterResult;
556
+ }
557
+ } else if (afterResult !== undefined) {
558
+ result = afterResult;
475
559
  }
476
560
  } catch (err) {
477
- $.log.error("执行后失败!", err);
561
+ $.log.error(`执行后置钩子 ${afterMethod} 失败: ${err.message}`);
478
562
  }
479
563
  }
480
- return ret
564
+ } catch (err) {
565
+ $.log.error(`执行方法 ${method} 失败: ${err.message}`);
566
+ return null;
481
567
  }
568
+ return result;
482
569
  };
483
570
 
484
571
  /**
485
- * @module 导出Drive
572
+ * @module 导出Item
486
573
  */
487
574
  module.exports = Item;