whistle.mockbubu 2.1.1 → 2.1.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.
|
@@ -27,10 +27,7 @@ const pluginModeManager = require('../plugin-mode-manager')
|
|
|
27
27
|
module.exports = (server, options) => {
|
|
28
28
|
console.log('[mockbubu] 🚀 server.js 模块已加载!')
|
|
29
29
|
const { storage } = options
|
|
30
|
-
|
|
31
|
-
// 使用 StorageAdapter 包装 Whistle storage
|
|
32
|
-
const actualBaseDir = options.config.baseDir
|
|
33
|
-
const storageAdapter = new StorageAdapter({ baseDir: actualBaseDir })
|
|
30
|
+
const storageAdapter = new StorageAdapter(options)
|
|
34
31
|
|
|
35
32
|
// 初始化组管理器(使用适配器)
|
|
36
33
|
const groupManager = new GroupManager(storageAdapter)
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
*
|
|
16
16
|
* 使用示例:
|
|
17
17
|
* ```javascript
|
|
18
|
-
* const adapter = new StorageAdapter(
|
|
18
|
+
* const adapter = new StorageAdapter(options)
|
|
19
19
|
* await adapter.init()
|
|
20
20
|
* await adapter.writeFile('default/https://api.test.com', '{"data": {...}}')
|
|
21
21
|
* const content = await adapter.readFile('default/https://api.test.com')
|
|
@@ -37,29 +37,25 @@ class StorageAdapter {
|
|
|
37
37
|
* 构造函数
|
|
38
38
|
*
|
|
39
39
|
* @param {Object} options - 配置选项
|
|
40
|
-
* @param {string} options.
|
|
40
|
+
* @param {string} options.pluginBaseDir - 插件存储目录路径
|
|
41
41
|
*
|
|
42
42
|
* @example
|
|
43
|
-
* const adapter = new StorageAdapter(
|
|
44
|
-
* baseDir: '~/.whistle'
|
|
45
|
-
* })
|
|
43
|
+
* const adapter = new StorageAdapter(options)
|
|
46
44
|
*/
|
|
47
45
|
constructor(options) {
|
|
48
46
|
// 初始化 logger
|
|
49
47
|
this.logger = createLogger('storage-adapter')
|
|
50
48
|
|
|
51
|
-
//
|
|
49
|
+
// 兜底存储目录路径
|
|
52
50
|
let baseDir = path.join(
|
|
53
51
|
process.env.HOME,
|
|
54
52
|
'.WhistleAppData/.whistle/.plugins/whistle.mockbubu',
|
|
55
53
|
)
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
// 实际存储目录路径
|
|
55
|
+
if (options?.config?.pluginBaseDir) {
|
|
56
|
+
baseDir = options.config.pluginBaseDir
|
|
58
57
|
}
|
|
59
58
|
|
|
60
|
-
// 记录基础目录(生产环境可保留,便于问题排查)
|
|
61
|
-
this.logger.log('基础目录:', baseDir)
|
|
62
|
-
|
|
63
59
|
// 初始化 V3 存储实例
|
|
64
60
|
this.v3Storage = new FileSystemStorage(baseDir)
|
|
65
61
|
this.currentGroupId = 'default'
|
package/lib/uiServer/index.js
CHANGED
|
@@ -13,16 +13,8 @@ const MAX_AGE = 1000 * 60 * 5
|
|
|
13
13
|
|
|
14
14
|
module.exports = (server, options) => {
|
|
15
15
|
const app = new Koa()
|
|
16
|
-
const { storage } = options
|
|
17
|
-
|
|
18
16
|
console.log('[mockbubu] 插件开始初始化...')
|
|
19
|
-
|
|
20
|
-
// 使用 StorageAdapter 包装 Whistle storage
|
|
21
|
-
// Whistle storage 对象直接有 baseDir 属性
|
|
22
|
-
const actualBaseDir = options.config.baseDir
|
|
23
|
-
console.log('[mockbubu] 🔍 UI Server storage.baseDir:', storage.baseDir)
|
|
24
|
-
console.log('[mockbubu] 🔍 UI Server 使用 baseDir:', actualBaseDir)
|
|
25
|
-
const storageAdapter = new StorageAdapter({ baseDir: actualBaseDir })
|
|
17
|
+
const storageAdapter = new StorageAdapter(options)
|
|
26
18
|
|
|
27
19
|
// 同步初始化:确保初始化完成后再处理请求
|
|
28
20
|
let isInitialized = false
|
package/package.json
CHANGED
package/public/js/app.js
CHANGED
|
@@ -1613,8 +1613,6 @@ const __default__ = {
|
|
|
1613
1613
|
|
|
1614
1614
|
// 解析 payload 为 JSON 对象供 jsoneditor 使用
|
|
1615
1615
|
const parsedPayloadData = (0,vue__WEBPACK_IMPORTED_MODULE_6__.computed)(() => {
|
|
1616
|
-
console.log('%c [ parsedPayloadData 计算属性触发 ]-126', 'font-size:13px; background:yellow; color:black;', 'computed 被调用');
|
|
1617
|
-
console.log('%c [ props.currentRow ]-131', 'font-size:13px; background:pink; color:#bf2c9f;', props.currentRow);
|
|
1618
1616
|
if (!props.currentRow?.payload) {
|
|
1619
1617
|
return null;
|
|
1620
1618
|
}
|
|
@@ -1965,6 +1963,8 @@ const __default__ = {
|
|
|
1965
1963
|
const currentFile = (0,vue__WEBPACK_IMPORTED_MODULE_9__.ref)({
|
|
1966
1964
|
content: {}
|
|
1967
1965
|
});
|
|
1966
|
+
const hasJsonError = (0,vue__WEBPACK_IMPORTED_MODULE_9__.ref)(false); // JSON 格式错误标志
|
|
1967
|
+
const hasFullScreenJsonError = (0,vue__WEBPACK_IMPORTED_MODULE_9__.ref)(false); // 全屏编辑器 JSON 格式错误标志
|
|
1968
1968
|
const versionModal = (0,vue__WEBPACK_IMPORTED_MODULE_9__.reactive)({
|
|
1969
1969
|
visible: false,
|
|
1970
1970
|
status: 'create',
|
|
@@ -2502,6 +2502,12 @@ const __default__ = {
|
|
|
2502
2502
|
element_ui_lib_message__WEBPACK_IMPORTED_MODULE_2___default().warning('原始响应数据为只读,不可修改');
|
|
2503
2503
|
return;
|
|
2504
2504
|
}
|
|
2505
|
+
|
|
2506
|
+
// 如果 JSON 格式错误,禁止保存
|
|
2507
|
+
if (hasJsonError.value) {
|
|
2508
|
+
element_ui_lib_message__WEBPACK_IMPORTED_MODULE_2___default().error('JSON 格式错误,请修正后再保存');
|
|
2509
|
+
return;
|
|
2510
|
+
}
|
|
2505
2511
|
if (currentFile.value.type === 'history') {
|
|
2506
2512
|
updateHistory();
|
|
2507
2513
|
} else {
|
|
@@ -2564,6 +2570,8 @@ const __default__ = {
|
|
|
2564
2570
|
const handleFullScreen = () => {
|
|
2565
2571
|
// 深拷贝当前内容到全屏编辑器
|
|
2566
2572
|
fullScreenModal.content = JSON.parse(JSON.stringify(currentFile.value.content));
|
|
2573
|
+
// 重置错误状态
|
|
2574
|
+
hasFullScreenJsonError.value = false;
|
|
2567
2575
|
fullScreenModal.visible = true;
|
|
2568
2576
|
};
|
|
2569
2577
|
|
|
@@ -2576,6 +2584,8 @@ const __default__ = {
|
|
|
2576
2584
|
const handleFullScreenClosed = () => {
|
|
2577
2585
|
// 弹窗关闭后清空内容
|
|
2578
2586
|
fullScreenModal.content = {};
|
|
2587
|
+
// 重置错误状态
|
|
2588
|
+
hasFullScreenJsonError.value = false;
|
|
2579
2589
|
};
|
|
2580
2590
|
|
|
2581
2591
|
// 全屏编辑器内容变化时同步到主编辑器
|
|
@@ -2645,6 +2655,12 @@ const __default__ = {
|
|
|
2645
2655
|
return;
|
|
2646
2656
|
}
|
|
2647
2657
|
|
|
2658
|
+
// 如果 JSON 格式错误,禁止保存
|
|
2659
|
+
if (hasFullScreenJsonError.value) {
|
|
2660
|
+
element_ui_lib_message__WEBPACK_IMPORTED_MODULE_2___default().error('JSON 格式错误,请修正后再保存');
|
|
2661
|
+
return;
|
|
2662
|
+
}
|
|
2663
|
+
|
|
2648
2664
|
// 确保内容已同步
|
|
2649
2665
|
currentFile.value.content = JSON.parse(JSON.stringify(fullScreenModal.content));
|
|
2650
2666
|
|
|
@@ -2735,6 +2751,8 @@ const __default__ = {
|
|
|
2735
2751
|
versionNameInput,
|
|
2736
2752
|
responseList,
|
|
2737
2753
|
currentFile,
|
|
2754
|
+
hasJsonError,
|
|
2755
|
+
hasFullScreenJsonError,
|
|
2738
2756
|
versionModal,
|
|
2739
2757
|
fullScreenModal,
|
|
2740
2758
|
name,
|
|
@@ -4492,6 +4510,7 @@ var render = function render() {
|
|
|
4492
4510
|
}, [_c("i", {
|
|
4493
4511
|
staticClass: "el-icon-lock"
|
|
4494
4512
|
}), _c("span", [_vm._v("只读模式")])]) : _vm._e()], 1), _c(_setup.JsonEditor, {
|
|
4513
|
+
key: `editor-${_setup.currentFile.filename}-${_setup.isSourceReadonly}`,
|
|
4495
4514
|
ref: "editRef",
|
|
4496
4515
|
attrs: {
|
|
4497
4516
|
"show-btns": false,
|
|
@@ -4504,6 +4523,12 @@ var render = function render() {
|
|
|
4504
4523
|
on: {
|
|
4505
4524
|
input: function ($event) {
|
|
4506
4525
|
return _setup.handleFileChange();
|
|
4526
|
+
},
|
|
4527
|
+
"has-error": function ($event) {
|
|
4528
|
+
_setup.hasJsonError = true;
|
|
4529
|
+
},
|
|
4530
|
+
"json-change": function ($event) {
|
|
4531
|
+
_setup.hasJsonError = false;
|
|
4507
4532
|
}
|
|
4508
4533
|
},
|
|
4509
4534
|
nativeOn: {
|
|
@@ -4526,12 +4551,15 @@ var render = function render() {
|
|
|
4526
4551
|
}
|
|
4527
4552
|
}), !_setup.isSourceReadonly && _setup.currentFile.effect && (_setup.currentFile.type === "history" || _vm.api.mock) ? _c("div", {
|
|
4528
4553
|
staticClass: "response-panel__save"
|
|
4529
|
-
}, [_c("span", {
|
|
4554
|
+
}, [_setup.hasJsonError ? _c("span", {
|
|
4555
|
+
staticClass: "response-panel__error-text"
|
|
4556
|
+
}, [_vm._v("JSON 格式错误,无法保存")]) : _c("span", {
|
|
4530
4557
|
staticClass: "response-panel__effect-icon"
|
|
4531
4558
|
}), _c("el-button", {
|
|
4532
4559
|
attrs: {
|
|
4533
4560
|
size: "small",
|
|
4534
|
-
type: "primary"
|
|
4561
|
+
type: "primary",
|
|
4562
|
+
disabled: _setup.hasJsonError
|
|
4535
4563
|
},
|
|
4536
4564
|
on: {
|
|
4537
4565
|
click: _setup.handleUpdate
|
|
@@ -4727,6 +4755,7 @@ var render = function render() {
|
|
|
4727
4755
|
}, [_c("i", {
|
|
4728
4756
|
staticClass: "el-icon-info"
|
|
4729
4757
|
}), _setup.isSourceReadonly ? _c("span", [_vm._v("快捷键: Ctrl/Cmd + F 查找 | ESC 关闭")]) : _c("span", [_vm._v("快捷键: Ctrl/Cmd + S 保存 | Ctrl/Cmd + F 查找 | ESC 关闭")])])], 1), _c(_setup.JsonEditor, {
|
|
4758
|
+
key: `fullscreen-editor-${_setup.currentFile.filename}-${_setup.isSourceReadonly}`,
|
|
4730
4759
|
ref: "fullScreenEditorRef",
|
|
4731
4760
|
attrs: {
|
|
4732
4761
|
"show-btns": false,
|
|
@@ -4737,7 +4766,13 @@ var render = function render() {
|
|
|
4737
4766
|
lang: "zh"
|
|
4738
4767
|
},
|
|
4739
4768
|
on: {
|
|
4740
|
-
input: _setup.handleFullScreenChange
|
|
4769
|
+
input: _setup.handleFullScreenChange,
|
|
4770
|
+
"has-error": function ($event) {
|
|
4771
|
+
_setup.hasFullScreenJsonError = true;
|
|
4772
|
+
},
|
|
4773
|
+
"json-change": function ($event) {
|
|
4774
|
+
_setup.hasFullScreenJsonError = false;
|
|
4775
|
+
}
|
|
4741
4776
|
},
|
|
4742
4777
|
nativeOn: {
|
|
4743
4778
|
keydown: [function ($event) {
|
|
@@ -4778,6 +4813,7 @@ var render = function render() {
|
|
|
4778
4813
|
}, [_vm._v(" 关闭 ")]), !_setup.isSourceReadonly ? _c("el-button", {
|
|
4779
4814
|
attrs: {
|
|
4780
4815
|
type: "primary",
|
|
4816
|
+
disabled: _setup.hasFullScreenJsonError,
|
|
4781
4817
|
size: "medium"
|
|
4782
4818
|
},
|
|
4783
4819
|
on: {
|
|
@@ -6080,7 +6116,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
6080
6116
|
|
|
6081
6117
|
var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
|
|
6082
6118
|
// Module
|
|
6083
|
-
___CSS_LOADER_EXPORT___.push([module.id, ".mock-container[data-v-d97322d2] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n.mock-container__content[data-v-d97322d2] {\n display: flex;\n flex: 1;\n border: 1px solid #ccc;\n border-left: none;\n overflow: hidden;\n}\n", ""]);
|
|
6119
|
+
___CSS_LOADER_EXPORT___.push([module.id, ".mock-container[data-v-d97322d2] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n.mock-container__content[data-v-d97322d2] {\n padding-bottom: 16px;\n background-image: linear-gradient(0deg, #3f9eff 0, #3f9eff 16px, transparent 100%);\n display: flex;\n flex: 1;\n border: 1px solid #ccc;\n border-left: none;\n overflow: hidden;\n}\n", ""]);
|
|
6084
6120
|
// Exports
|
|
6085
6121
|
/* harmony default export */ __webpack_exports__["default"] = (___CSS_LOADER_EXPORT___);
|
|
6086
6122
|
|
|
@@ -6176,7 +6212,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
6176
6212
|
|
|
6177
6213
|
var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
|
|
6178
6214
|
// Module
|
|
6179
|
-
___CSS_LOADER_EXPORT___.push([module.id, ".response-panel[data-v-c23cd6a6] {\n position: relative;\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n.response-panel__header[data-v-c23cd6a6] {\n display: flex;\n flex-wrap: wrap;\n}\n.response-panel__tab[data-v-c23cd6a6] {\n position: relative;\n cursor: pointer;\n height: 24px;\n padding: 0px 10px;\n font-size: 12px;\n line-height: 24px;\n color: #333333;\n font-weight: 500;\n border-right: 1px solid #ccc;\n border-bottom: 1px solid #ccc;\n}\n.response-panel__tab--selected[data-v-c23cd6a6] {\n background-color: #e0e3e6;\n}\n.response-panel__source-tab[data-v-c23cd6a6] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n color: #e6a23c;\n font-weight: 600;\n}\n.response-panel__source-tab i[data-v-c23cd6a6] {\n font-size: 14px;\n}\n.response-panel__tab-text[data-v-c23cd6a6] {\n display: inline-block;\n max-width: 120px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n vertical-align: middle;\n}\n.response-panel__edit-btn[data-v-c23cd6a6] {\n margin-left: 8px;\n color: #909399;\n}\n.response-panel__edit-btn[data-v-c23cd6a6]:hover {\n color: #409eff;\n}\n.response-panel__delete-btn[data-v-c23cd6a6] {\n margin-left: 8px;\n color: #909399;\n}\n.response-panel__delete-btn[data-v-c23cd6a6]:hover {\n color: #f46c6b;\n}\n.response-panel__add-btn[data-v-c23cd6a6] {\n cursor: pointer;\n line-height: 24px;\n padding: 0px 10px;\n color: #333333;\n font-weight: 500;\n}\n.response-panel__content[data-v-c23cd6a6] {\n position: relative;\n flex: 1;\n overflow: hidden;\n}\n.response-panel__toolbar[data-v-c23cd6a6] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background-color: #f5f7fa;\n border-bottom: 1px solid #e4e7ed;\n}\n.response-panel__toolbar .el-button[data-v-c23cd6a6] {\n margin: 0;\n}\n.response-panel__readonly-badge[data-v-c23cd6a6] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n margin-left: auto;\n padding: 4px 12px;\n background-color: #f0f2f5;\n border-radius: 4px;\n font-size: 12px;\n color: #909399;\n font-weight: 500;\n}\n.response-panel__readonly-badge i[data-v-c23cd6a6] {\n font-size: 12px;\n}\n.response-panel__alert[data-v-c23cd6a6] {\n position: absolute;\n top: 8px;\n right: 10px;\n font-size: 12px;\n font-weight: 600;\n color: #e6a23c;\n}\n.response-panel__save[data-v-c23cd6a6] {\n position: absolute;\n top: 100px;\n right: 20px;\n}\n.response-panel__effect-icon[data-v-c23cd6a6] {\n position: absolute;\n top: -5px;\n right: -5px;\n display: block;\n width: 6px;\n height: 6px;\n border-radius: 6px;\n background-color: #f46c6b;\n}\n.response-panel__dialog[data-v-c23cd6a6] {\n display: flex;\n align-items: center;\n}\n.response-panel__dialog-label[data-v-c23cd6a6] {\n white-space: nowrap;\n}\n", ""]);
|
|
6215
|
+
___CSS_LOADER_EXPORT___.push([module.id, ".response-panel[data-v-c23cd6a6] {\n position: relative;\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n.response-panel__header[data-v-c23cd6a6] {\n display: flex;\n flex-wrap: wrap;\n}\n.response-panel__tab[data-v-c23cd6a6] {\n position: relative;\n cursor: pointer;\n height: 24px;\n padding: 0px 10px;\n font-size: 12px;\n line-height: 24px;\n color: #333333;\n font-weight: 500;\n border-right: 1px solid #ccc;\n border-bottom: 1px solid #ccc;\n}\n.response-panel__tab--selected[data-v-c23cd6a6] {\n background-color: #e0e3e6;\n}\n.response-panel__source-tab[data-v-c23cd6a6] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n color: #e6a23c;\n font-weight: 600;\n}\n.response-panel__source-tab i[data-v-c23cd6a6] {\n font-size: 14px;\n}\n.response-panel__tab-text[data-v-c23cd6a6] {\n display: inline-block;\n max-width: 120px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n vertical-align: middle;\n}\n.response-panel__edit-btn[data-v-c23cd6a6] {\n margin-left: 8px;\n color: #909399;\n}\n.response-panel__edit-btn[data-v-c23cd6a6]:hover {\n color: #409eff;\n}\n.response-panel__delete-btn[data-v-c23cd6a6] {\n margin-left: 8px;\n color: #909399;\n}\n.response-panel__delete-btn[data-v-c23cd6a6]:hover {\n color: #f46c6b;\n}\n.response-panel__add-btn[data-v-c23cd6a6] {\n cursor: pointer;\n line-height: 24px;\n padding: 0px 10px;\n color: #333333;\n font-weight: 500;\n}\n.response-panel__content[data-v-c23cd6a6] {\n position: relative;\n flex: 1;\n overflow: hidden;\n}\n.response-panel__toolbar[data-v-c23cd6a6] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background-color: #f5f7fa;\n border-bottom: 1px solid #e4e7ed;\n}\n.response-panel__toolbar .el-button[data-v-c23cd6a6] {\n margin: 0;\n}\n.response-panel__readonly-badge[data-v-c23cd6a6] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n margin-left: auto;\n padding: 4px 12px;\n background-color: #f0f2f5;\n border-radius: 4px;\n font-size: 12px;\n color: #909399;\n font-weight: 500;\n}\n.response-panel__readonly-badge i[data-v-c23cd6a6] {\n font-size: 12px;\n}\n.response-panel__alert[data-v-c23cd6a6] {\n position: absolute;\n top: 8px;\n right: 10px;\n font-size: 12px;\n font-weight: 600;\n color: #e6a23c;\n}\n.response-panel__save[data-v-c23cd6a6] {\n position: absolute;\n top: 100px;\n right: 20px;\n}\n.response-panel__effect-icon[data-v-c23cd6a6] {\n position: absolute;\n top: -5px;\n right: -5px;\n display: block;\n width: 6px;\n height: 6px;\n border-radius: 6px;\n background-color: #f46c6b;\n}\n.response-panel__error-text[data-v-c23cd6a6] {\n position: absolute;\n top: -30px;\n right: 0;\n color: #f56c6c;\n font-size: 12px;\n white-space: nowrap;\n}\n.response-panel__dialog[data-v-c23cd6a6] {\n display: flex;\n align-items: center;\n}\n.response-panel__dialog-label[data-v-c23cd6a6] {\n white-space: nowrap;\n}\n", ""]);
|
|
6180
6216
|
// Exports
|
|
6181
6217
|
/* harmony default export */ __webpack_exports__["default"] = (___CSS_LOADER_EXPORT___);
|
|
6182
6218
|
|
|
@@ -9141,4 +9177,236 @@ function createSingletonHook(hook) {
|
|
|
9141
9177
|
/******/
|
|
9142
9178
|
/******/ })()
|
|
9143
9179
|
;
|
|
9144
|
-
//# sourceMappingURL=app.js.
|
|
9180
|
+
//# sourceMappingURL=app.js.mapult().name), (element_ui_lib_radio__WEBPACK_IMPORTED_MODULE_32___default()));\nvue__WEBPACK_IMPORTED_MODULE_59__[\"default\"].component((element_ui_lib_tabs__WEBPACK_IMPORTED_MODULE_30___default().name), (element_ui_lib_tabs__WEBPACK_IMPORTED_MODULE_30___default()));\nvue__WEBPACK_IMPORTED_MODULE_59__[\"default\"].component((element_ui_lib_tab_pane__WEBPACK_IMPORTED_MODULE_28___default().name), (element_ui_lib_tab_pane__WEBPACK_IMPORTED_MODULE_28___default()));\nvue__WEBPACK_IMPORTED_MODULE_59__[\"default\"].component((element_ui_lib_alert__WEBPACK_IMPORTED_MODULE_26___default().name), (element_ui_lib_alert__WEBPACK_IMPORTED_MODULE_26___default()));\nvue__WEBPACK_IMPORTED_MODULE_59__[\"default\"].component((element_ui_lib_dropdown__WEBPACK_IMPORTED_MODULE_24___default().name), (element_ui_lib_dropdown__WEBPACK_IMPORTED_MODULE_24___default()));\nvue__WEBPACK_IMPORTED_MODULE_59__[\"default\"].component((element_ui_lib_dropdown_item__WEBPACK_IMPORTED_MODULE_22___default().name), (element_ui_lib_dropdown_item__WEBPACK_IMPORTED_MODULE_22___default()));\nvue__WEBPACK_IMPORTED_MODULE_59__[\"default\"].component((element_ui_lib_dropdown_menu__WEBPACK_IMPORTED_MODULE_20___default().name), (element_ui_lib_dropdown_menu__WEBPACK_IMPORTED_MODULE_20___default()));\nvue__WEBPACK_IMPORTED_MODULE_59__[\"default\"].component((element_ui_lib_form__WEBPACK_IMPORTED_MODULE_18___default().name), (element_ui_lib_form__WEBPACK_IMPORTED_MODULE_18___default()));\nvue__WEBPACK_IMPORTED_MODULE_59__[\"default\"].component((element_ui_lib_form_item__WEBPACK_IMPORTED_MODULE_16___default().name), (element_ui_lib_form_item__WEBPACK_IMPORTED_MODULE_16___default()));\nvue__WEBPACK_IMPORTED_MODULE_59__[\"default\"].component((element_ui_lib_progress__WEBPACK_IMPORTED_MODULE_14___default().name), (element_ui_lib_progress__WEBPACK_IMPORTED_MODULE_14___default()));\nvue__WEBPACK_IMPORTED_MODULE_59__[\"default\"].component((element_ui_lib_badge__WEBPACK_IMPORTED_MODULE_12___default().name), (element_ui_lib_badge__WEBPACK_IMPORTED_MODULE_12___default()));\nvue__WEBPACK_IMPORTED_MODULE_59__[\"default\"].component((element_ui_lib_checkbox__WEBPACK_IMPORTED_MODULE_10___default().name), (element_ui_lib_checkbox__WEBPACK_IMPORTED_MODULE_10___default()));\nvue__WEBPACK_IMPORTED_MODULE_59__[\"default\"].component((element_ui_lib_checkbox_group__WEBPACK_IMPORTED_MODULE_8___default().name), (element_ui_lib_checkbox_group__WEBPACK_IMPORTED_MODULE_8___default()));\nvue__WEBPACK_IMPORTED_MODULE_59__[\"default\"].use((element_ui_lib_loading__WEBPACK_IMPORTED_MODULE_6___default().directive));\nvue__WEBPACK_IMPORTED_MODULE_59__[\"default\"].prototype.$loading = (element_ui_lib_loading__WEBPACK_IMPORTED_MODULE_6___default().service);\nvue__WEBPACK_IMPORTED_MODULE_59__[\"default\"].prototype.$message = (element_ui_lib_message__WEBPACK_IMPORTED_MODULE_4___default());\nvue__WEBPACK_IMPORTED_MODULE_59__[\"default\"].prototype.$msgbox = (element_ui_lib_message_box__WEBPACK_IMPORTED_MODULE_2___default());\nvue__WEBPACK_IMPORTED_MODULE_59__[\"default\"].prototype.$confirm = (element_ui_lib_message_box__WEBPACK_IMPORTED_MODULE_2___default().confirm);\nvue__WEBPACK_IMPORTED_MODULE_59__[\"default\"].config.productionTip = false;\nnew vue__WEBPACK_IMPORTED_MODULE_59__[\"default\"]({\n render: h => h(_App_vue__WEBPACK_IMPORTED_MODULE_60__[\"default\"])\n}).$mount('#app');\n\n//# sourceURL=webpack://web/./src/main.js?\n}");
|
|
9181
|
+
|
|
9182
|
+
/***/ }),
|
|
9183
|
+
|
|
9184
|
+
/***/ "./src/service/index.js":
|
|
9185
|
+
/*!******************************!*\
|
|
9186
|
+
!*** ./src/service/index.js ***!
|
|
9187
|
+
\******************************/
|
|
9188
|
+
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
9189
|
+
|
|
9190
|
+
"use strict";
|
|
9191
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ addVersion: function() { return /* binding */ addVersion; },\n/* harmony export */ batchDelete: function() { return /* binding */ batchDelete; },\n/* harmony export */ batchDeleteByNames: function() { return /* binding */ batchDeleteByNames; },\n/* harmony export */ batchUpdateMock: function() { return /* binding */ batchUpdateMock; },\n/* harmony export */ check: function() { return /* binding */ check; },\n/* harmony export */ copyGroup: function() { return /* binding */ copyGroup; },\n/* harmony export */ createGroup: function() { return /* binding */ createGroup; },\n/* harmony export */ deleteApi: function() { return /* binding */ deleteApi; },\n/* harmony export */ deleteGroup: function() { return /* binding */ deleteGroup; },\n/* harmony export */ deleteVersion: function() { return /* binding */ deleteVersion; },\n/* harmony export */ exportGroupsArchive: function() { return /* binding */ exportGroupsArchive; },\n/* harmony export */ getActiveRules: function() { return /* binding */ getActiveRules; },\n/* harmony export */ getApiData: function() { return /* binding */ getApiData; },\n/* harmony export */ getCurrentGroup: function() { return /* binding */ getCurrentGroup; },\n/* harmony export */ getGroups: function() { return /* binding */ getGroups; },\n/* harmony export */ getMemoryStats: function() { return /* binding */ getMemoryStats; },\n/* harmony export */ getSavedFiles: function() { return /* binding */ getSavedFiles; },\n/* harmony export */ getStorageStats: function() { return /* binding */ getStorageStats; },\n/* harmony export */ getVersions: function() { return /* binding */ getVersions; },\n/* harmony export */ importGroupsArchive: function() { return /* binding */ importGroupsArchive; },\n/* harmony export */ init: function() { return /* binding */ init; },\n/* harmony export */ saveFile: function() { return /* binding */ saveFile; },\n/* harmony export */ search: function() { return /* binding */ search; },\n/* harmony export */ setMockVersion: function() { return /* binding */ setMockVersion; },\n/* harmony export */ switchGroup: function() { return /* binding */ switchGroup; },\n/* harmony export */ updateApiData: function() { return /* binding */ updateApiData; },\n/* harmony export */ updateApiLock: function() { return /* binding */ updateApiLock; },\n/* harmony export */ updateApiMock: function() { return /* binding */ updateApiMock; },\n/* harmony export */ updateGroup: function() { return /* binding */ updateGroup; },\n/* harmony export */ updateVersionContent: function() { return /* binding */ updateVersionContent; },\n/* harmony export */ updateVersionMeta: function() { return /* binding */ updateVersionMeta; },\n/* harmony export */ updateVersionName: function() { return /* binding */ updateVersionName; }\n/* harmony export */ });\n/**\n * 获取已保存文件列表(首屏加载)\n *\n * @returns {Promise<Object>} 响应数据\n */\nfunction getSavedFiles() {\n return fetch('/cgi-bin/mockbubu/api-list-saved', {\n method: 'post',\n body: JSON.stringify({}),\n headers: {\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-cache, no-store, must-revalidate',\n Pragma: 'no-cache'\n },\n cache: 'no-store'\n }).then(response => {\n return response.json();\n });\n}\n\n/**\n * 增量轮询查询(只返回暂存区数据)\n *\n * @param {Object} params - 查询参数\n * @param {number} params.startTime - 轮询起始时间戳(0=首次轮询,>0=增量轮询)\n * @param {string} params.keyword - 可选,搜索关键词\n * @param {boolean} params.mock - 可选,筛选 mock 状态\n * @param {boolean} params.locked - 可选,筛选锁定状态\n * @returns {Promise<Object>} 响应数据\n */\nfunction search(params) {\n return fetch('/cgi-bin/mockbubu/api-list?_=' + Date.now(), {\n method: 'post',\n body: JSON.stringify(params),\n headers: {\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-cache, no-store, must-revalidate',\n Pragma: 'no-cache'\n },\n cache: 'no-store'\n }).then(response => {\n return response.json();\n });\n}\nfunction check() {\n return fetch('/cgi-bin/mockbubu/check-api-list?_=' + Date.now(), {\n headers: {\n 'Cache-Control': 'no-cache, no-store, must-revalidate',\n Pragma: 'no-cache'\n },\n cache: 'no-store'\n }).then(response => {\n return response.json();\n });\n}\nfunction init() {\n return fetch('/cgi-bin/init?_=' + Date.now(), {\n method: 'get',\n referrer: location.origin\n }).then(response => {\n return response.json();\n });\n}\nfunction getApiData(name) {\n return fetch('/cgi-bin/mockbubu/get-api-data?_=' + Date.now(), {\n method: 'post',\n body: JSON.stringify({\n name\n }),\n headers: {\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-cache, no-store, must-revalidate',\n Pragma: 'no-cache'\n },\n cache: 'no-store'\n }).then(response => {\n return response.json();\n });\n}\nfunction updateApiData(name, data) {\n return fetch('/cgi-bin/mockbubu/update-api-data', {\n method: 'post',\n body: JSON.stringify({\n name,\n data\n }),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction updateApiMock(name, mock) {\n return fetch('/cgi-bin/mockbubu/update-api-mock', {\n method: 'post',\n body: JSON.stringify({\n name,\n mock\n }),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction updateApiLock(name, locked) {\n return fetch('/cgi-bin/mockbubu/update-api-lock', {\n method: 'post',\n body: JSON.stringify({\n name,\n locked\n }),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction deleteApi(name) {\n return fetch('/cgi-bin/mockbubu/delete-api', {\n method: 'post',\n body: JSON.stringify({\n name\n }),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction batchDelete(params) {\n return fetch('/cgi-bin/mockbubu/batch-delete-api', {\n method: 'post',\n body: JSON.stringify(params),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction getVersions(params) {\n return fetch('/cgi-bin/mockbubu/get-versions', {\n method: 'post',\n body: JSON.stringify(params),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction addVersion(params) {\n return fetch('/cgi-bin/mockbubu/add-new-version', {\n method: 'post',\n body: JSON.stringify(params),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction deleteVersion(params) {\n return fetch('/cgi-bin/mockbubu/delete-version', {\n method: 'post',\n body: JSON.stringify(params),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction updateVersionContent(params) {\n return fetch('/cgi-bin/mockbubu/update-version-content', {\n method: 'post',\n body: JSON.stringify(params),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction updateVersionName(params) {\n return fetch('/cgi-bin/mockbubu/update-version-name', {\n method: 'post',\n body: JSON.stringify(params),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction setMockVersion(params) {\n return fetch('/cgi-bin/mockbubu/set-mock-version', {\n method: 'post',\n body: JSON.stringify(params),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction updateVersionMeta(params) {\n return fetch('/cgi-bin/mockbubu/update-version-meta', {\n method: 'post',\n body: JSON.stringify(params),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction batchUpdateMock(params) {\n return fetch('/cgi-bin/mockbubu/batch-update-mock', {\n method: 'post',\n body: JSON.stringify(params),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction batchDeleteByNames(params) {\n return fetch('/cgi-bin/mockbubu/batch-delete-by-names', {\n method: 'post',\n body: JSON.stringify(params),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\n\n// ============ 导入导出 API(压缩包) ============\n\n// 导出多个组为压缩包\nfunction exportGroupsArchive(groupIds) {\n return fetch('/cgi-bin/mockbubu/export-groups-archive', {\n method: 'post',\n body: JSON.stringify({\n groupIds\n }),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(async response => {\n // 先检查 Content-Type,判断是 JSON 错误还是二进制文件\n const contentType = response.headers.get('Content-Type');\n if (contentType && contentType.includes('application/json')) {\n // 后端返回了 JSON,说明出错了\n const errorData = await response.json();\n throw new Error(errorData.msg || '导出失败');\n }\n if (!response.ok) {\n throw new Error('导出失败: HTTP ' + response.status);\n }\n return response.blob();\n });\n}\n\n// 导入多个组的压缩包\nfunction importGroupsArchive(file) {\n const formData = new FormData();\n formData.append('file', file);\n return fetch('/cgi-bin/mockbubu/import-groups-archive', {\n method: 'post',\n body: formData\n }).then(response => {\n return response.json();\n });\n}\n\n// ============ 组管理 API ============\n\nfunction getGroups() {\n return fetch('/cgi-bin/mockbubu/groups/list', {\n method: 'post',\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction getCurrentGroup() {\n return fetch('/cgi-bin/mockbubu/groups/current', {\n method: 'post',\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction createGroup(params) {\n return fetch('/cgi-bin/mockbubu/groups/create', {\n method: 'post',\n body: JSON.stringify(params),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction updateGroup(groupId, params) {\n return fetch('/cgi-bin/mockbubu/groups/update', {\n method: 'post',\n body: JSON.stringify({\n groupId,\n ...params\n }),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction deleteGroup(groupId) {\n return fetch('/cgi-bin/mockbubu/groups/delete', {\n method: 'post',\n body: JSON.stringify({\n groupId\n }),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction switchGroup(groupId) {\n return fetch('/cgi-bin/mockbubu/groups/switch', {\n method: 'post',\n body: JSON.stringify({\n groupId\n }),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\nfunction copyGroup(sourceGroupId, params) {\n return fetch('/cgi-bin/mockbubu/groups/copy', {\n method: 'post',\n body: JSON.stringify({\n sourceGroupId,\n ...params\n }),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n return response.json();\n });\n}\n\n// ============ 存储管理 API ============\n\n// 获取存储统计信息\nfunction getStorageStats() {\n return fetch('cgi-bin/mockbubu/storage-stats', {\n method: 'get',\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n return response.json();\n });\n}\n\n// 获取生效的 Whistle 规则\nfunction getActiveRules() {\n return fetch('cgi-bin/mockbubu/active-rules', {\n method: 'get',\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n return response.json();\n });\n}\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n getSavedFiles,\n search,\n check,\n init,\n getApiData,\n updateApiData,\n updateApiMock,\n updateApiLock,\n deleteApi,\n batchDelete,\n getVersions,\n addVersion,\n deleteVersion,\n updateVersionContent,\n updateVersionName,\n setMockVersion,\n updateVersionMeta,\n batchUpdateMock,\n batchDeleteByNames,\n exportGroupsArchive,\n importGroupsArchive,\n getGroups,\n getCurrentGroup,\n createGroup,\n updateGroup,\n deleteGroup,\n switchGroup,\n copyGroup,\n getStorageStats,\n getMemoryStats,\n getActiveRules,\n saveFile\n});\nfunction getMemoryStats() {\n return fetch('/cgi-bin/mockbubu/memory-stats?_=' + Date.now(), {\n headers: {\n 'Cache-Control': 'no-cache, no-store, must-revalidate',\n Pragma: 'no-cache'\n },\n cache: 'no-store'\n }).then(response => {\n return response.json();\n });\n}\n\n/**\n * 首次保存文件(前端缓存 → 文件系统)\n *\n * @param {Object} params - 文件数据\n * @param {string} params.url - 请求URL\n * @param {string} params.method - HTTP方法\n * @param {number} params.status - 状态码\n * @param {Object} params.session - 完整会话数据\n * @returns {Promise<Object>} 响应数据\n */\nfunction saveFile(params) {\n console.log('[API] saveFile 被调用:', {\n url: params.url,\n method: params.method,\n hasSession: !!params.session\n });\n return fetch('/cgi-bin/mockbubu/file-save', {\n method: 'post',\n body: JSON.stringify(params),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(response => {\n console.log('[API] saveFile 响应:', response.status);\n return response.json();\n }).then(data => {\n console.log('[API] saveFile 返回数据:', data);\n return data;\n });\n}\n\n//# sourceURL=webpack://web/./src/service/index.js?\n}");
|
|
9192
|
+
|
|
9193
|
+
/***/ }),
|
|
9194
|
+
|
|
9195
|
+
/***/ "./src/util.js":
|
|
9196
|
+
/*!*********************!*\
|
|
9197
|
+
!*** ./src/util.js ***!
|
|
9198
|
+
\*********************/
|
|
9199
|
+
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
9200
|
+
|
|
9201
|
+
eval("{__webpack_require__(/*! core-js/modules/es.iterator.constructor.js */ \"./node_modules/core-js/modules/es.iterator.constructor.js\");\n__webpack_require__(/*! core-js/modules/es.iterator.filter.js */ \"./node_modules/core-js/modules/es.iterator.filter.js\");\n__webpack_require__(/*! core-js/modules/es.iterator.map.js */ \"./node_modules/core-js/modules/es.iterator.map.js\");\nexports.getActiveRules = (rules = '') => {\n return rules.split('\\n').map(i => i.trim()).filter(i => i[0] !== '#').filter(i => ~i.indexOf('mockbubu://')).map(i => i.trim()).map(i => i.replace(/\\s+/, ' '));\n};\n\n//# sourceURL=webpack://web/./src/util.js?\n}");
|
|
9202
|
+
|
|
9203
|
+
/***/ }),
|
|
9204
|
+
|
|
9205
|
+
/***/ "./src/utils/cache-manager.js":
|
|
9206
|
+
/*!************************************!*\
|
|
9207
|
+
!*** ./src/utils/cache-manager.js ***!
|
|
9208
|
+
\************************************/
|
|
9209
|
+
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
9210
|
+
|
|
9211
|
+
"use strict";
|
|
9212
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.iterator.constructor.js */ \"./node_modules/core-js/modules/es.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.iterator.for-each.js */ \"./node_modules/core-js/modules/es.iterator.for-each.js\");\n/* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\n/**\n * 前端缓存管理器\n *\n * 职责:\n * - 缓存所有捕获的请求数据(URL → session)\n * - URL 去重(已存在则跳过新数据,保留旧的)\n * - 容量管理(滑动窗口清理)\n * - 提供查询、过滤、删除等操作\n *\n * 核心规则:\n * - 完整数据生命周期管理(从捕获到保存/删除)\n * - URL 去重:已存在时跳过新数据(保留旧的)\n * - 容量上限:2000 条,超出触发滑动窗口清理\n */\n\n// 缓存容量配置\nconst CACHE_CONFIG = {\n MAX_SIZE: 2000,\n // 最大缓存容量\n CLEANUP_BATCH_SIZE: 200 // 滑动窗口清理批次大小\n};\nclass CacheManager {\n constructor() {\n // Key: url (完整 URL)\n // Value: { url, method, status, session, captureTime, groupId }\n this.cache = new Map();\n this.currentGroupId = null; // 当前激活的组ID\n }\n\n /**\n * 设置当前组ID\n *\n * @param {string} groupId - 组ID\n */\n setCurrentGroupId(groupId) {\n this.currentGroupId = groupId;\n console.log(`[CacheManager] 设置当前组ID: ${groupId}`);\n }\n\n /**\n * 切换组(清空旧组数据)\n *\n * @param {string} newGroupId - 新组ID\n */\n switchGroup(newGroupId) {\n if (this.currentGroupId === newGroupId) {\n console.log(`[CacheManager] 已经是当前组,无需切换: ${newGroupId}`);\n return;\n }\n console.log(`[CacheManager] 切换组: ${this.currentGroupId} -> ${newGroupId}`);\n\n // 清空旧组的所有缓存数据\n const oldSize = this.cache.size;\n this.cache.clear();\n console.log(`[CacheManager] 切换组时清空缓存,已清除 ${oldSize} 条`);\n\n // 更新当前组ID\n this.currentGroupId = newGroupId;\n }\n\n /**\n * 添加数据到缓存\n *\n * 去重规则:URL 已存在时跳过新数据(保留旧的)\n *\n * @param {Object} data - 捕获数据\n * @param {string} data.url - 请求URL\n * @param {string} data.method - HTTP方法\n * @param {number} data.status - 状态码\n * @param {Object} data.session - 完整会话数据\n * @param {string} data.groupId - 组ID(可选)\n * @param {boolean} skipCleanup - 是否跳过清理(批量添加时使用)\n * @returns {boolean} 是否成功添加(false 表示已存在被跳过)\n */\n add(data, skipCleanup = false) {\n const {\n url,\n method,\n status,\n session,\n captureTime,\n groupId\n } = data;\n\n // 参数校验\n if (!url || !method || !status || !session) {\n console.error('[CacheManager] add 参数不完整', {\n hasUrl: !!url,\n hasMethod: !!method,\n hasStatus: !!status,\n hasSession: !!session\n });\n return false;\n }\n\n // 去重:已存在则跳过(保留旧的)\n if (this.cache.has(url)) {\n console.log(`[CacheManager] 缓存已存在,跳过: ${url}`);\n return false;\n }\n\n // 新增到缓存\n this.cache.set(url, {\n url,\n method,\n status,\n session,\n captureTime: captureTime || Date.now(),\n groupId: groupId || this.currentGroupId // 记录组ID\n });\n console.log(`[CacheManager] 缓存新增: ${url} (组: ${groupId || this.currentGroupId}, 当前容量: ${this.cache.size})`);\n\n // 容量检查:超出上限触发滑动窗口清理(批量添加时跳过)\n if (!skipCleanup && this.cache.size > CACHE_CONFIG.MAX_SIZE) {\n this.slidingWindowCleanup();\n }\n return true;\n }\n\n /**\n * 批量添加数据\n *\n * 批量添加优化:先批量添加所有数据,最后统一清理\n * 避免每次添加都触发清理,提升性能\n *\n * @param {Array<Object>} dataList - 数据列表\n * @returns {number} 成功添加的数量\n */\n addBatch(dataList) {\n if (!Array.isArray(dataList)) {\n console.error('[CacheManager] addBatch 参数必须是数组');\n return 0;\n }\n let addedCount = 0;\n // 批量添加时跳过单次清理\n dataList.forEach(data => {\n if (this.add(data, true)) {\n addedCount++;\n }\n });\n console.log(`[CacheManager] 批量添加完成,新增 ${addedCount} 条,跳过 ${dataList.length - addedCount} 条`);\n\n // 批量添加后统一清理到合理容量\n if (this.cache.size > CACHE_CONFIG.MAX_SIZE) {\n const needCleanup = this.cache.size - CACHE_CONFIG.MAX_SIZE;\n const cleanupBatches = Math.ceil(needCleanup / CACHE_CONFIG.CLEANUP_BATCH_SIZE);\n console.log(`[CacheManager] 需要清理 ${needCleanup} 条,将执行 ${cleanupBatches} 次批量清理`);\n for (let i = 0; i < cleanupBatches; i++) {\n if (this.cache.size > CACHE_CONFIG.MAX_SIZE) {\n this.slidingWindowCleanup();\n }\n }\n }\n return addedCount;\n }\n\n /**\n * 获取所有缓存数据(数组形式)\n *\n * @returns {Array<Object>} 缓存数据列表\n */\n getAll() {\n return Array.from(this.cache.values());\n }\n\n /**\n * 根据 URL 获取数据\n *\n * @param {string} url - 请求URL\n * @returns {Object|null} 缓存数据\n */\n get(url) {\n return this.cache.get(url) || null;\n }\n\n /**\n * 检查 URL 是否存在\n *\n * @param {string} url - 请求URL\n * @returns {boolean}\n */\n has(url) {\n return this.cache.has(url);\n }\n\n /**\n * 删除指定 URL 的数据\n *\n * @param {string} url - 请求URL\n * @returns {boolean} 是否删除成功\n */\n remove(url) {\n const deleted = this.cache.delete(url);\n if (deleted) {\n console.log(`[CacheManager] 删除缓存: ${url} (剩余容量: ${this.cache.size})`);\n }\n return deleted;\n }\n\n /**\n * 批量删除\n *\n * @param {Array<string>} urls - URL 列表\n * @returns {number} 删除的数量\n */\n removeBatch(urls) {\n if (!Array.isArray(urls)) {\n console.error('[CacheManager] removeBatch 参数必须是数组');\n return 0;\n }\n let deletedCount = 0;\n urls.forEach(url => {\n if (this.remove(url)) {\n deletedCount++;\n }\n });\n console.log(`[CacheManager] 批量删除完成,删除 ${deletedCount} 条`);\n return deletedCount;\n }\n\n /**\n * 清空所有缓存\n */\n clear() {\n const oldSize = this.cache.size;\n this.cache.clear();\n console.log(`[CacheManager] 清空缓存,已清除 ${oldSize} 条`);\n }\n\n /**\n * 滑动窗口清理\n *\n * 清理策略:\n * - 按 captureTime 排序(最旧的在前)\n * - 删除最旧的 CLEANUP_BATCH_SIZE 条数据\n */\n slidingWindowCleanup() {\n const entries = Array.from(this.cache.entries());\n\n // 按时间排序(最旧的在前)\n entries.sort((a, b) => a[1].captureTime - b[1].captureTime);\n\n // 删除最旧的数据\n const toRemove = entries.slice(0, CACHE_CONFIG.CLEANUP_BATCH_SIZE);\n toRemove.forEach(([url]) => {\n this.cache.delete(url);\n });\n console.log(`[CacheManager] 滑动窗口清理 ${toRemove.length} 条 (剩余容量: ${this.cache.size})`);\n }\n\n /**\n * 获取统计信息\n *\n * @returns {Object} 统计信息\n */\n getStats() {\n return {\n size: this.cache.size,\n maxSize: CACHE_CONFIG.MAX_SIZE\n };\n }\n}\n\n// 导出单例实例\n/* harmony default export */ __webpack_exports__[\"default\"] = (new CacheManager());\n\n//# sourceURL=webpack://web/./src/utils/cache-manager.js?\n}");
|
|
9213
|
+
|
|
9214
|
+
/***/ }),
|
|
9215
|
+
|
|
9216
|
+
/***/ "./src/utils/createSingletonHook.js":
|
|
9217
|
+
/*!******************************************!*\
|
|
9218
|
+
!*** ./src/utils/createSingletonHook.js ***!
|
|
9219
|
+
\******************************************/
|
|
9220
|
+
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
9221
|
+
|
|
9222
|
+
"use strict";
|
|
9223
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ createSingletonHook: function() { return /* binding */ createSingletonHook; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm.js\");\n\n\n/**\n * @function createSingletonHook\n * @description 创建一个单例 Hook,用于确保某个 Hook 在组件树中只被初始化一次。\n * @param {Function} hook - 要包装为单例的 Hook 函数。\n * @returns {Function} 包装后的单例 Hook 函数。\n *\n * @example\n * // 定义一个普通 Hook\n * function useExampleHook(param) {\n * const state = ref(param)\n * return { state }\n * }\n *\n * // 创建单例 Hook\n * const useSingletonExampleHook = createSingletonHook(useExampleHook)\n *\n * // 在组件中使用\n * export default {\n * setup() {\n * const instance = useSingletonExampleHook('initial value')\n * return { instance }\n * }\n * }\n */\nfunction createSingletonHook(hook) {\n const key = Symbol(hook.name);\n return (...args) => {\n // 尝试获取已存在的实例\n const existing = (0,vue__WEBPACK_IMPORTED_MODULE_0__.inject)(key, null);\n if (existing) return existing;\n\n // 创建新实例\n const instance = hook(...args);\n\n // 注入单例\n (0,vue__WEBPACK_IMPORTED_MODULE_0__.provide)(key, instance);\n return instance;\n };\n}\n\n//# sourceURL=webpack://web/./src/utils/createSingletonHook.js?\n}");
|
|
9224
|
+
|
|
9225
|
+
/***/ })
|
|
9226
|
+
|
|
9227
|
+
/******/ });
|
|
9228
|
+
/************************************************************************/
|
|
9229
|
+
/******/ // The module cache
|
|
9230
|
+
/******/ var __webpack_module_cache__ = {};
|
|
9231
|
+
/******/
|
|
9232
|
+
/******/ // The require function
|
|
9233
|
+
/******/ function __webpack_require__(moduleId) {
|
|
9234
|
+
/******/ // Check if module is in cache
|
|
9235
|
+
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
|
9236
|
+
/******/ if (cachedModule !== undefined) {
|
|
9237
|
+
/******/ return cachedModule.exports;
|
|
9238
|
+
/******/ }
|
|
9239
|
+
/******/ // Create a new module (and put it into the cache)
|
|
9240
|
+
/******/ var module = __webpack_module_cache__[moduleId] = {
|
|
9241
|
+
/******/ id: moduleId,
|
|
9242
|
+
/******/ // no module.loaded needed
|
|
9243
|
+
/******/ exports: {}
|
|
9244
|
+
/******/ };
|
|
9245
|
+
/******/
|
|
9246
|
+
/******/ // Execute the module function
|
|
9247
|
+
/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
9248
|
+
/******/
|
|
9249
|
+
/******/ // Return the exports of the module
|
|
9250
|
+
/******/ return module.exports;
|
|
9251
|
+
/******/ }
|
|
9252
|
+
/******/
|
|
9253
|
+
/******/ // expose the modules object (__webpack_modules__)
|
|
9254
|
+
/******/ __webpack_require__.m = __webpack_modules__;
|
|
9255
|
+
/******/
|
|
9256
|
+
/************************************************************************/
|
|
9257
|
+
/******/ /* webpack/runtime/chunk loaded */
|
|
9258
|
+
/******/ !function() {
|
|
9259
|
+
/******/ var deferred = [];
|
|
9260
|
+
/******/ __webpack_require__.O = function(result, chunkIds, fn, priority) {
|
|
9261
|
+
/******/ if(chunkIds) {
|
|
9262
|
+
/******/ priority = priority || 0;
|
|
9263
|
+
/******/ for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
|
|
9264
|
+
/******/ deferred[i] = [chunkIds, fn, priority];
|
|
9265
|
+
/******/ return;
|
|
9266
|
+
/******/ }
|
|
9267
|
+
/******/ var notFulfilled = Infinity;
|
|
9268
|
+
/******/ for (var i = 0; i < deferred.length; i++) {
|
|
9269
|
+
/******/ var chunkIds = deferred[i][0];
|
|
9270
|
+
/******/ var fn = deferred[i][1];
|
|
9271
|
+
/******/ var priority = deferred[i][2];
|
|
9272
|
+
/******/ var fulfilled = true;
|
|
9273
|
+
/******/ for (var j = 0; j < chunkIds.length; j++) {
|
|
9274
|
+
/******/ if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every(function(key) { return __webpack_require__.O[key](chunkIds[j]); })) {
|
|
9275
|
+
/******/ chunkIds.splice(j--, 1);
|
|
9276
|
+
/******/ } else {
|
|
9277
|
+
/******/ fulfilled = false;
|
|
9278
|
+
/******/ if(priority < notFulfilled) notFulfilled = priority;
|
|
9279
|
+
/******/ }
|
|
9280
|
+
/******/ }
|
|
9281
|
+
/******/ if(fulfilled) {
|
|
9282
|
+
/******/ deferred.splice(i--, 1)
|
|
9283
|
+
/******/ var r = fn();
|
|
9284
|
+
/******/ if (r !== undefined) result = r;
|
|
9285
|
+
/******/ }
|
|
9286
|
+
/******/ }
|
|
9287
|
+
/******/ return result;
|
|
9288
|
+
/******/ };
|
|
9289
|
+
/******/ }();
|
|
9290
|
+
/******/
|
|
9291
|
+
/******/ /* webpack/runtime/compat get default export */
|
|
9292
|
+
/******/ !function() {
|
|
9293
|
+
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
9294
|
+
/******/ __webpack_require__.n = function(module) {
|
|
9295
|
+
/******/ var getter = module && module.__esModule ?
|
|
9296
|
+
/******/ function() { return module['default']; } :
|
|
9297
|
+
/******/ function() { return module; };
|
|
9298
|
+
/******/ __webpack_require__.d(getter, { a: getter });
|
|
9299
|
+
/******/ return getter;
|
|
9300
|
+
/******/ };
|
|
9301
|
+
/******/ }();
|
|
9302
|
+
/******/
|
|
9303
|
+
/******/ /* webpack/runtime/define property getters */
|
|
9304
|
+
/******/ !function() {
|
|
9305
|
+
/******/ // define getter functions for harmony exports
|
|
9306
|
+
/******/ __webpack_require__.d = function(exports, definition) {
|
|
9307
|
+
/******/ for(var key in definition) {
|
|
9308
|
+
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
|
9309
|
+
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
|
9310
|
+
/******/ }
|
|
9311
|
+
/******/ }
|
|
9312
|
+
/******/ };
|
|
9313
|
+
/******/ }();
|
|
9314
|
+
/******/
|
|
9315
|
+
/******/ /* webpack/runtime/global */
|
|
9316
|
+
/******/ !function() {
|
|
9317
|
+
/******/ __webpack_require__.g = (function() {
|
|
9318
|
+
/******/ if (typeof globalThis === 'object') return globalThis;
|
|
9319
|
+
/******/ try {
|
|
9320
|
+
/******/ return this || new Function('return this')();
|
|
9321
|
+
/******/ } catch (e) {
|
|
9322
|
+
/******/ if (typeof window === 'object') return window;
|
|
9323
|
+
/******/ }
|
|
9324
|
+
/******/ })();
|
|
9325
|
+
/******/ }();
|
|
9326
|
+
/******/
|
|
9327
|
+
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
|
9328
|
+
/******/ !function() {
|
|
9329
|
+
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
|
|
9330
|
+
/******/ }();
|
|
9331
|
+
/******/
|
|
9332
|
+
/******/ /* webpack/runtime/make namespace object */
|
|
9333
|
+
/******/ !function() {
|
|
9334
|
+
/******/ // define __esModule on exports
|
|
9335
|
+
/******/ __webpack_require__.r = function(exports) {
|
|
9336
|
+
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
9337
|
+
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
9338
|
+
/******/ }
|
|
9339
|
+
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
9340
|
+
/******/ };
|
|
9341
|
+
/******/ }();
|
|
9342
|
+
/******/
|
|
9343
|
+
/******/ /* webpack/runtime/publicPath */
|
|
9344
|
+
/******/ !function() {
|
|
9345
|
+
/******/ __webpack_require__.p = "/";
|
|
9346
|
+
/******/ }();
|
|
9347
|
+
/******/
|
|
9348
|
+
/******/ /* webpack/runtime/jsonp chunk loading */
|
|
9349
|
+
/******/ !function() {
|
|
9350
|
+
/******/ __webpack_require__.b = document.baseURI || self.location.href;
|
|
9351
|
+
/******/
|
|
9352
|
+
/******/ // object to store loaded and loading chunks
|
|
9353
|
+
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
|
|
9354
|
+
/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
|
|
9355
|
+
/******/ var installedChunks = {
|
|
9356
|
+
/******/ "app": 0
|
|
9357
|
+
/******/ };
|
|
9358
|
+
/******/
|
|
9359
|
+
/******/ // no chunk on demand loading
|
|
9360
|
+
/******/
|
|
9361
|
+
/******/ // no prefetching
|
|
9362
|
+
/******/
|
|
9363
|
+
/******/ // no preloaded
|
|
9364
|
+
/******/
|
|
9365
|
+
/******/ // no HMR
|
|
9366
|
+
/******/
|
|
9367
|
+
/******/ // no HMR manifest
|
|
9368
|
+
/******/
|
|
9369
|
+
/******/ __webpack_require__.O.j = function(chunkId) { return installedChunks[chunkId] === 0; };
|
|
9370
|
+
/******/
|
|
9371
|
+
/******/ // install a JSONP callback for chunk loading
|
|
9372
|
+
/******/ var webpackJsonpCallback = function(parentChunkLoadingFunction, data) {
|
|
9373
|
+
/******/ var chunkIds = data[0];
|
|
9374
|
+
/******/ var moreModules = data[1];
|
|
9375
|
+
/******/ var runtime = data[2];
|
|
9376
|
+
/******/ // add "moreModules" to the modules object,
|
|
9377
|
+
/******/ // then flag all "chunkIds" as loaded and fire callback
|
|
9378
|
+
/******/ var moduleId, chunkId, i = 0;
|
|
9379
|
+
/******/ if(chunkIds.some(function(id) { return installedChunks[id] !== 0; })) {
|
|
9380
|
+
/******/ for(moduleId in moreModules) {
|
|
9381
|
+
/******/ if(__webpack_require__.o(moreModules, moduleId)) {
|
|
9382
|
+
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
|
|
9383
|
+
/******/ }
|
|
9384
|
+
/******/ }
|
|
9385
|
+
/******/ if(runtime) var result = runtime(__webpack_require__);
|
|
9386
|
+
/******/ }
|
|
9387
|
+
/******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
|
|
9388
|
+
/******/ for(;i < chunkIds.length; i++) {
|
|
9389
|
+
/******/ chunkId = chunkIds[i];
|
|
9390
|
+
/******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
|
|
9391
|
+
/******/ installedChunks[chunkId][0]();
|
|
9392
|
+
/******/ }
|
|
9393
|
+
/******/ installedChunks[chunkId] = 0;
|
|
9394
|
+
/******/ }
|
|
9395
|
+
/******/ return __webpack_require__.O(result);
|
|
9396
|
+
/******/ }
|
|
9397
|
+
/******/
|
|
9398
|
+
/******/ var chunkLoadingGlobal = self["webpackChunkweb"] = self["webpackChunkweb"] || [];
|
|
9399
|
+
/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
|
|
9400
|
+
/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
|
|
9401
|
+
/******/ }();
|
|
9402
|
+
/******/
|
|
9403
|
+
/************************************************************************/
|
|
9404
|
+
/******/
|
|
9405
|
+
/******/ // startup
|
|
9406
|
+
/******/ // Load entry module and return exports
|
|
9407
|
+
/******/ // This entry module depends on other loaded chunks and execution need to be delayed
|
|
9408
|
+
/******/ var __webpack_exports__ = __webpack_require__.O(undefined, ["chunk-vendors"], function() { return __webpack_require__("./src/main.js"); })
|
|
9409
|
+
/******/ __webpack_exports__ = __webpack_require__.O(__webpack_exports__);
|
|
9410
|
+
/******/
|
|
9411
|
+
/******/ })()
|
|
9412
|
+
;
|