whistle.mock-plugins 1.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.
Files changed (68) hide show
  1. package/API.md +247 -0
  2. package/README.md +91 -0
  3. package/app/cgi-bin/features.js +285 -0
  4. package/app/cgi-bin/index.js +31 -0
  5. package/app/cgi-bin/interfaces.js +409 -0
  6. package/app/cgi-bin/logs.js +151 -0
  7. package/app/cgi-bin/test-interface.js +152 -0
  8. package/app/public/index.html +1 -0
  9. package/app/public/js/index.js +2 -0
  10. package/app/public/js/index.js.LICENSE.txt +150 -0
  11. package/app/util/index.js +24 -0
  12. package/index.html +52 -0
  13. package/initialize.js +32 -0
  14. package/lib/dataManager.js +500 -0
  15. package/lib/index.js +3 -0
  16. package/lib/models.js +64 -0
  17. package/lib/routes/features.js +213 -0
  18. package/lib/routes/interfaces.js +304 -0
  19. package/lib/routes/proxy.js +239 -0
  20. package/lib/ruleManager.js +551 -0
  21. package/lib/rules-server.js +267 -0
  22. package/lib/server.js +805 -0
  23. package/lib/storage.js +16 -0
  24. package/lib/ui-server.js +68 -0
  25. package/package.json +51 -0
  26. package/public/bundle.js +2 -0
  27. package/public/bundle.js.LICENSE.txt +38 -0
  28. package/public/index.html +1 -0
  29. package/public/plugin.mock-plugin.html +14 -0
  30. package/rules.txt +22 -0
  31. package/test/rulesServer.test.js +120 -0
  32. package/ui/src/App.css +173 -0
  33. package/ui/src/App.js +24 -0
  34. package/ui/src/components/AppLayout.js +149 -0
  35. package/ui/src/components/FeatureCard.js +53 -0
  36. package/ui/src/components/Layout.js +94 -0
  37. package/ui/src/components/MainNav.js +42 -0
  38. package/ui/src/components/PageContainer.js +16 -0
  39. package/ui/src/index.html +11 -0
  40. package/ui/src/index.js +43 -0
  41. package/ui/src/pages/FileProxy.js +235 -0
  42. package/ui/src/pages/FilesPage.js +292 -0
  43. package/ui/src/pages/Home.js +128 -0
  44. package/ui/src/pages/HomePage.js +195 -0
  45. package/ui/src/pages/InterfaceManagement.js +829 -0
  46. package/ui/src/pages/InterfacePage.js +342 -0
  47. package/ui/src/pages/MockData.js +472 -0
  48. package/ui/src/pages/Settings.js +192 -0
  49. package/ui/src/pages/SettingsPage.js +165 -0
  50. package/ui/src/pages/UrlRedirect.js +225 -0
  51. package/ui/src/pages/Welcome.js +155 -0
  52. package/ui/src/services/api.js +186 -0
  53. package/ui/src/styles/app-layout.css +337 -0
  54. package/ui/src/styles/feature-card.css +172 -0
  55. package/ui/src/styles/file-proxy.css +301 -0
  56. package/ui/src/styles/global.css +224 -0
  57. package/ui/src/styles/home.css +123 -0
  58. package/ui/src/styles/index.css +419 -0
  59. package/ui/src/styles/interface-management.css +694 -0
  60. package/ui/src/styles/layout.css +159 -0
  61. package/ui/src/styles/logs-page.css +427 -0
  62. package/ui/src/styles/main-nav.css +52 -0
  63. package/ui/src/styles/mock-data.css +850 -0
  64. package/ui/src/styles/page-container.css +11 -0
  65. package/ui/src/styles/settings.css +208 -0
  66. package/ui/src/styles/url-redirect.css +279 -0
  67. package/ui/src/styles/welcome.css +282 -0
  68. package/webpack.config.js +49 -0
package/API.md ADDED
@@ -0,0 +1,247 @@
1
+ # whistle.mock-plugin API 文档
2
+
3
+ 本文档描述了 whistle.mock-plugin 插件的 API 接口和数据模型。
4
+
5
+ ## 数据模型
6
+
7
+ ### 功能模块 (Feature)
8
+
9
+ 功能模块是接口的分组,用于组织和管理相关的接口。
10
+
11
+ | 字段 | 类型 | 描述 |
12
+ | --- | --- | --- |
13
+ | id | string | 功能模块唯一标识符 |
14
+ | name | string | 功能模块名称 |
15
+ | description | string | 功能模块描述 |
16
+ | interfaceCount | number | 该功能模块下的接口数量 |
17
+ | active | boolean | 功能模块是否启用 |
18
+ | createdAt | string | 创建时间,ISO 字符串格式 |
19
+ | updatedAt | string | 最后更新时间,ISO 字符串格式 |
20
+
21
+ ### 接口 (Interface)
22
+
23
+ 接口定义了匹配规则和响应内容,用于模拟 API 响应。
24
+
25
+ | 字段 | 类型 | 描述 |
26
+ | --- | --- | --- |
27
+ | id | string | 接口唯一标识符 |
28
+ | featureId | string | 所属功能模块 ID |
29
+ | name | string | 接口名称 |
30
+ | urlPattern | string | URL 匹配规则,支持精确匹配、通配符和正则表达式 |
31
+ | proxyType | string | 代理类型,可选值: 'response'(数据模板), 'redirect'(URL重定向), 'file'(文件代理) |
32
+ | responseContent | string | 响应内容,使用 Mock.js 语法 |
33
+ | targetUrl | string | 重定向目标 URL,仅在 proxyType='redirect' 时有效 |
34
+ | filePath | string | 文件路径,仅在 proxyType='file' 时有效 |
35
+ | httpStatus | number | HTTP 状态码 |
36
+ | responseDelay | number | 响应延迟,单位毫秒 |
37
+ | httpMethod | string | HTTP 方法,可选值: 'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS', 'ALL' |
38
+ | active | boolean | 接口是否启用 |
39
+ | contentType | string | 响应内容类型 |
40
+ | headers | object | 自定义响应头 |
41
+ | createdAt | string | 创建时间,ISO 字符串格式 |
42
+ | updatedAt | string | 最后更新时间,ISO 字符串格式 |
43
+
44
+ ### API 响应 (ApiResponse)
45
+
46
+ 所有 API 接口的标准响应格式。
47
+
48
+ | 字段 | 类型 | 描述 |
49
+ | --- | --- | --- |
50
+ | code | number | 状态码,0 表示成功,其他值表示错误 |
51
+ | message | string | 状态消息 |
52
+ | data | any | 响应数据,具体结构根据接口而定 |
53
+
54
+ ## API 接口
55
+
56
+ ### 功能模块
57
+
58
+ #### 获取所有功能模块
59
+
60
+ ```
61
+ GET /cgi-bin/features
62
+ ```
63
+
64
+ 请求参数:无
65
+
66
+ 响应示例:
67
+
68
+ ```json
69
+ {
70
+ "code": 0,
71
+ "message": "成功",
72
+ "data": [
73
+ {
74
+ "id": "1",
75
+ "name": "用户管理",
76
+ "description": "用户相关接口",
77
+ "interfaceCount": 3,
78
+ "active": true,
79
+ "createdAt": "2023-01-01T00:00:00.000Z",
80
+ "updatedAt": "2023-01-01T00:00:00.000Z"
81
+ }
82
+ ]
83
+ }
84
+ ```
85
+
86
+ #### 获取指定功能模块的接口列表
87
+
88
+ ```
89
+ GET /cgi-bin/interfaces?featureId={featureId}
90
+ ```
91
+
92
+ 请求参数:
93
+
94
+ | 参数 | 类型 | 必填 | 描述 |
95
+ | --- | --- | --- | --- |
96
+ | featureId | string | 是 | 功能模块 ID |
97
+
98
+ 响应示例:
99
+
100
+ ```json
101
+ {
102
+ "code": 0,
103
+ "message": "成功",
104
+ "data": [
105
+ {
106
+ "id": "1",
107
+ "featureId": "1",
108
+ "name": "获取用户信息",
109
+ "urlPattern": "/api/users/*",
110
+ "proxyType": "response",
111
+ "responseContent": "{\"code\":0,\"data\":{\"id\":1,\"name\":\"test\"}}",
112
+ "httpStatus": 200,
113
+ "contentType": "application/json; charset=utf-8",
114
+ "active": true
115
+ }
116
+ ]
117
+ }
118
+ ```
119
+
120
+ ### 接口
121
+
122
+ #### 创建接口
123
+
124
+ ```
125
+ POST /cgi-bin/interfaces
126
+ ```
127
+
128
+ 请求参数:
129
+
130
+ | 参数 | 类型 | 必填 | 描述 |
131
+ | --- | --- | --- | --- |
132
+ | name | string | 是 | 接口名称 |
133
+ | featureId | string | 是 | 功能模块 ID |
134
+ | urlPattern | string | 是 | URL 匹配规则 |
135
+ | proxyType | string | 否 | 代理类型,默认 'response' |
136
+ | responseContent | string | 否 | 响应内容 |
137
+ | httpStatus | number | 否 | HTTP 状态码,默认 200 |
138
+ | contentType | string | 否 | 响应内容类型 |
139
+ | active | boolean | 否 | 是否启用,默认 true |
140
+
141
+ 响应示例:
142
+
143
+ ```json
144
+ {
145
+ "code": 0,
146
+ "message": "接口创建成功",
147
+ "data": {
148
+ "id": "1",
149
+ "featureId": "1",
150
+ "name": "获取用户信息",
151
+ "urlPattern": "/api/users/*",
152
+ "proxyType": "response",
153
+ "responseContent": "{\"code\":0,\"data\":{\"id\":1,\"name\":\"test\"}}",
154
+ "httpStatus": 200,
155
+ "contentType": "application/json; charset=utf-8",
156
+ "active": true
157
+ }
158
+ }
159
+ ```
160
+
161
+ #### 更新接口
162
+
163
+ ```
164
+ PUT /cgi-bin/interfaces?id={id}
165
+ ```
166
+
167
+ 请求参数:
168
+
169
+ | 参数 | 类型 | 必填 | 描述 |
170
+ | --- | --- | --- | --- |
171
+ | id | string | 是 | 接口 ID (URL参数) |
172
+ | name | string | 否 | 接口名称 |
173
+ | urlPattern | string | 否 | URL 匹配规则 |
174
+ | proxyType | string | 否 | 代理类型 |
175
+ | responseContent | string | 否 | 响应内容 |
176
+ | httpStatus | number | 否 | HTTP 状态码 |
177
+ | contentType | string | 否 | 响应内容类型 |
178
+ | active | boolean | 否 | 是否启用 |
179
+
180
+ 响应示例:
181
+
182
+ ```json
183
+ {
184
+ "code": 0,
185
+ "message": "接口更新成功",
186
+ "data": {
187
+ "id": "1",
188
+ "featureId": "1",
189
+ "name": "获取用户信息",
190
+ "urlPattern": "/api/users/*",
191
+ "proxyType": "response",
192
+ "responseContent": "{\"code\":0,\"data\":{\"id\":1,\"name\":\"updated\"}}",
193
+ "httpStatus": 200,
194
+ "contentType": "application/json; charset=utf-8",
195
+ "active": true
196
+ }
197
+ }
198
+ ```
199
+
200
+ #### 删除接口
201
+
202
+ ```
203
+ DELETE /cgi-bin/interfaces?id={id}
204
+ ```
205
+
206
+ 请求参数:
207
+
208
+ | 参数 | 类型 | 必填 | 描述 |
209
+ | --- | --- | --- | --- |
210
+ | id | string | 是 | 接口 ID (URL参数) |
211
+
212
+ 响应示例:
213
+
214
+ ```json
215
+ {
216
+ "code": 0,
217
+ "message": "接口删除成功",
218
+ "data": null
219
+ }
220
+ ```
221
+
222
+ #### 测试接口
223
+
224
+ ```
225
+ POST /cgi-bin/test-interface
226
+ ```
227
+
228
+ 请求参数:
229
+
230
+ | 参数 | 类型 | 必填 | 描述 |
231
+ | --- | --- | --- | --- |
232
+ | url | string | 是 | 测试 URL |
233
+ | interfaceId | string | 是 | 接口 ID |
234
+
235
+ 响应示例:
236
+
237
+ ```json
238
+ {
239
+ "code": 0,
240
+ "message": "成功",
241
+ "data": {
242
+ "statusCode": 200,
243
+ "contentType": "application/json; charset=utf-8",
244
+ "responseBody": "{\"code\":0,\"data\":{\"id\":1,\"name\":\"test\"}}"
245
+ }
246
+ }
247
+ ```
package/README.md ADDED
@@ -0,0 +1,91 @@
1
+ # Whistle Mock Plugin
2
+
3
+ 一个用于Whistle的mock数据插件,帮助前端开发者管理和模拟API接口响应。
4
+
5
+ ## 核心功能
6
+
7
+ ### 1. 功能模块管理
8
+
9
+ - **创建功能模块**:用户可以创建多个功能模块,每个模块代表一组相关的API接口
10
+ - **启用/禁用功能模块**:整体控制一组接口的启用状态
11
+ - **管理功能模块**:编辑、删除功能模块及其描述信息
12
+
13
+ ### 2. 接口代理配置
14
+
15
+ 在每个功能模块下,用户可以添加多个接口代理配置,支持以下代理方式:
16
+
17
+ - **URL重定向**:将请求重定向到另一个URL地址
18
+ - **本地文件代理**:返回本地文件的内容作为响应
19
+ - **响应内容直接配置**:直接编辑JSON、HTML等响应内容
20
+
21
+ ### 3. 代理规则控制
22
+
23
+ - **每个接口可独立启用/禁用**:精细控制每个接口的代理状态
24
+ - **匹配规则配置**:支持精确匹配、通配符、正则表达式等多种匹配方式
25
+ - **请求方法过滤**:可限定特定HTTP方法(GET, POST等)的请求被代理
26
+
27
+ ### 4. 高级功能
28
+
29
+ - **响应延迟模拟**:模拟网络延迟,可针对接口设置响应时间
30
+ - **状态码与响应头配置**:自定义HTTP状态码和响应头
31
+ - **请求日志记录**:记录被代理的请求,便于调试和回溯
32
+
33
+ ## 使用场景
34
+
35
+ 1. **前后端分离开发**:前端开发不依赖后端接口进度
36
+ 2. **复杂场景测试**:模拟各种API响应状态和错误情况
37
+ 3. **演示环境搭建**:快速构建演示环境,无需部署完整后端
38
+ 4. **接口联调**:在本地环境联调多个微服务接口
39
+
40
+ ## 项目结构
41
+
42
+ ```
43
+ whistle.mock-plugin/
44
+ ├── app/ # 插件服务端代码
45
+ │ ├── index.js # 插件入口文件
46
+ │ └── public/ # 插件UI静态资源
47
+ ├── ui/ # 插件UI源代码
48
+ │ ├── src/ # React源代码
49
+ │ ├── package.json # UI依赖配置
50
+ │ └── webpack.config.js # 构建配置
51
+ ├── package.json # 插件依赖配置
52
+ └── README.md # 项目说明文档
53
+ ```
54
+
55
+ ## 页面结构
56
+
57
+ ### 1. 首页/概览
58
+
59
+ - 显示插件使用统计信息
60
+ - 快速入门指南和使用提示
61
+ - 最近活动记录
62
+
63
+ ### 2. 功能模块管理页面
64
+
65
+ - 功能模块列表展示
66
+ - 添加/编辑/删除功能模块
67
+ - 功能模块启用/禁用控制
68
+ - 每个功能模块的接口数量统计
69
+
70
+ ### 3. 接口管理页面
71
+
72
+ - 特定功能模块下的接口列表
73
+ - 添加/编辑/删除接口配置
74
+ - 接口启用/禁用控制
75
+ - 接口详细配置:
76
+ - URL匹配规则
77
+ - 代理方式选择(URL重定向/本地文件/直接响应)
78
+ - 响应配置(状态码、头信息、延迟)
79
+
80
+ ### 4. 系统设置页面
81
+
82
+ - 全局插件设置
83
+ - 日志记录设置
84
+ - 默认响应行为配置
85
+
86
+ ## 技术实现
87
+
88
+ - 前端:React框架构建UI界面
89
+ - 构建:使用Webpack打包前端资源
90
+ - 插件通信:利用Whistle插件API与主程序通信
91
+ - 数据存储:使用本地文件系统存储配置信息
@@ -0,0 +1,285 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+
4
+ module.exports = function(req, res) {
5
+ const dataDir = this.dataDir;
6
+ const featuresFile = path.join(dataDir, 'features.json');
7
+ const interfacesFile = path.join(dataDir, 'interfaces.json');
8
+
9
+ try {
10
+ // 确保配置文件存在并包含有效结构
11
+ if (!fs.existsSync(featuresFile)) {
12
+ fs.writeJsonSync(featuresFile, { features: [] }, { spaces: 2 });
13
+ } else {
14
+ // 读取文件验证结构
15
+ try {
16
+ const fileData = fs.readJsonSync(featuresFile);
17
+ if (!fileData || !fileData.features) {
18
+ // 如果文件存在但结构无效,重新初始化
19
+ fs.writeJsonSync(featuresFile, { features: [] }, { spaces: 2 });
20
+ console.log('修复了损坏的features文件结构');
21
+ }
22
+ } catch (e) {
23
+ // JSON解析错误时重新初始化文件
24
+ fs.writeJsonSync(featuresFile, { features: [] }, { spaces: 2 });
25
+ console.log('修复了无法解析的features文件');
26
+ }
27
+ }
28
+
29
+ // 处理GET请求 - 获取所有功能模块
30
+ if (req.method === 'GET') {
31
+ let featuresData;
32
+ try {
33
+ featuresData = fs.readJsonSync(featuresFile);
34
+ if (!featuresData.features) {
35
+ featuresData.features = [];
36
+ }
37
+ } catch (err) {
38
+ // 读取出错时返回空数组
39
+ console.error('读取功能列表错误:', err);
40
+ featuresData = { features: [] };
41
+ }
42
+
43
+ // 计算每个功能模块的接口数量
44
+ if (fs.existsSync(interfacesFile)) {
45
+ try {
46
+ const interfacesData = fs.readJsonSync(interfacesFile);
47
+ const interfaces = interfacesData.interfaces || [];
48
+
49
+ // 统计接口数量
50
+ for (const feature of featuresData.features) {
51
+ feature.interfaceCount = interfaces.filter(item => item.featureId === feature.id).length;
52
+ }
53
+ } catch (err) {
54
+ console.error('读取接口列表错误:', err);
55
+ // 读取接口出错时不影响功能列表返回
56
+ }
57
+ }
58
+
59
+ return res.json({
60
+ code: 0,
61
+ message: '成功',
62
+ data: featuresData.features
63
+ });
64
+ }
65
+
66
+ // 处理POST请求 - 添加或更新功能模块
67
+ if (req.method === 'POST') {
68
+ const featureData = req.body;
69
+ let featuresData;
70
+
71
+ try {
72
+ featuresData = fs.readJsonSync(featuresFile);
73
+ if (!featuresData.features) {
74
+ featuresData = { features: [] };
75
+ }
76
+ } catch (err) {
77
+ // 读取出错时初始化
78
+ console.error('读取功能列表错误:', err);
79
+ featuresData = { features: [] };
80
+ }
81
+
82
+ // 参数验证
83
+ if (!featureData.name) {
84
+ return res.status(400).json({
85
+ code: 400,
86
+ message: '功能名称不能为空',
87
+ data: null
88
+ });
89
+ }
90
+
91
+ // 如果有ID则更新,否则创建新功能
92
+ if (featureData.id) {
93
+ // 更新现有功能
94
+ const index = featuresData.features.findIndex(item => item.id === featureData.id);
95
+
96
+ if (index === -1) {
97
+ return res.status(404).json({
98
+ code: 404,
99
+ message: '功能模块不存在',
100
+ data: null
101
+ });
102
+ }
103
+
104
+ // 更新功能
105
+ featuresData.features[index] = {
106
+ ...featuresData.features[index],
107
+ name: featureData.name,
108
+ description: featureData.description,
109
+ active: featureData.active
110
+ };
111
+
112
+ fs.writeJsonSync(featuresFile, featuresData, { spaces: 2 });
113
+
114
+ return res.json({
115
+ code: 0,
116
+ message: '功能模块更新成功',
117
+ data: featuresData.features[index]
118
+ });
119
+ } else {
120
+ // 创建新功能
121
+ const newFeature = {
122
+ id: Date.now().toString(),
123
+ name: featureData.name,
124
+ description: featureData.description || '',
125
+ active: featureData.active !== false,
126
+ createdAt: new Date().toISOString().split('T')[0]
127
+ };
128
+
129
+ // 确保features数组存在
130
+ if (!Array.isArray(featuresData.features)) {
131
+ featuresData.features = [];
132
+ }
133
+
134
+ featuresData.features.push(newFeature);
135
+ fs.writeJsonSync(featuresFile, featuresData, { spaces: 2 });
136
+
137
+ return res.json({
138
+ code: 0,
139
+ message: '功能模块创建成功',
140
+ data: newFeature
141
+ });
142
+ }
143
+ }
144
+
145
+ // 处理DELETE请求 - 删除功能模块
146
+ if (req.method === 'DELETE') {
147
+ const { id } = req.query;
148
+
149
+ if (!id) {
150
+ return res.status(400).json({
151
+ code: 400,
152
+ message: '功能ID不能为空',
153
+ data: null
154
+ });
155
+ }
156
+
157
+ let featuresData;
158
+ try {
159
+ featuresData = fs.readJsonSync(featuresFile);
160
+ if (!featuresData.features) {
161
+ featuresData = { features: [] };
162
+ }
163
+ } catch (err) {
164
+ // 读取出错时初始化
165
+ console.error('读取功能列表错误:', err);
166
+ featuresData = { features: [] };
167
+ }
168
+
169
+ const index = featuresData.features.findIndex(item => item.id === id);
170
+
171
+ if (index === -1) {
172
+ return res.status(404).json({
173
+ code: 404,
174
+ message: '功能模块不存在',
175
+ data: null
176
+ });
177
+ }
178
+
179
+ // 删除功能
180
+ const deletedFeature = featuresData.features.splice(index, 1)[0];
181
+ fs.writeJsonSync(featuresFile, featuresData, { spaces: 2 });
182
+
183
+ // 同时删除该功能的所有接口
184
+ if (fs.existsSync(interfacesFile)) {
185
+ try {
186
+ const interfacesData = fs.readJsonSync(interfacesFile);
187
+ if (interfacesData && Array.isArray(interfacesData.interfaces)) {
188
+ interfacesData.interfaces = interfacesData.interfaces.filter(item => item.featureId !== id);
189
+ fs.writeJsonSync(interfacesFile, interfacesData, { spaces: 2 });
190
+ }
191
+ } catch (err) {
192
+ console.error('处理接口文件错误:', err);
193
+ }
194
+ }
195
+
196
+ return res.json({
197
+ code: 0,
198
+ message: '功能模块删除成功',
199
+ data: deletedFeature
200
+ });
201
+ }
202
+
203
+ // 处理PATCH请求 - 部分更新功能模块
204
+ if (req.method === 'PATCH') {
205
+ const { id } = req.query;
206
+ const updateData = req.body;
207
+
208
+ if (!id) {
209
+ return res.status(400).json({
210
+ code: 400,
211
+ message: '功能ID不能为空',
212
+ data: null
213
+ });
214
+ }
215
+
216
+ let featuresData;
217
+ try {
218
+ featuresData = fs.readJsonSync(featuresFile);
219
+ if (!featuresData.features) {
220
+ featuresData = { features: [] };
221
+ }
222
+ } catch (err) {
223
+ console.error('读取功能列表错误:', err);
224
+ return res.status(500).json({
225
+ code: 500,
226
+ message: '读取功能列表失败',
227
+ data: null
228
+ });
229
+ }
230
+
231
+ const index = featuresData.features.findIndex(item => item.id === id);
232
+
233
+ if (index === -1) {
234
+ return res.status(404).json({
235
+ code: 404,
236
+ message: '功能模块不存在',
237
+ data: null
238
+ });
239
+ }
240
+
241
+ // 更新部分字段
242
+ const updatedFeature = {
243
+ ...featuresData.features[index]
244
+ };
245
+
246
+ // 只更新提供的字段
247
+ if (updateData.name !== undefined) {
248
+ updatedFeature.name = updateData.name;
249
+ }
250
+
251
+ if (updateData.description !== undefined) {
252
+ updatedFeature.description = updateData.description;
253
+ }
254
+
255
+ if (updateData.active !== undefined) {
256
+ updatedFeature.active = updateData.active;
257
+ }
258
+
259
+ updatedFeature.updatedAt = new Date().toISOString();
260
+
261
+ featuresData.features[index] = updatedFeature;
262
+ fs.writeJsonSync(featuresFile, featuresData, { spaces: 2 });
263
+
264
+ return res.json({
265
+ code: 0,
266
+ message: '功能模块更新成功',
267
+ data: updatedFeature
268
+ });
269
+ }
270
+
271
+ // 其他请求方法
272
+ return res.status(405).json({
273
+ code: 405,
274
+ message: '不支持的请求方法',
275
+ data: null
276
+ });
277
+ } catch (err) {
278
+ console.error('处理功能模块请求出错:', err);
279
+ return res.status(500).json({
280
+ code: 500,
281
+ message: '服务器内部错误: ' + err.message,
282
+ data: null
283
+ });
284
+ }
285
+ };
@@ -0,0 +1,31 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+
4
+ module.exports = function(req, res) {
5
+ const dataDir = this.dataDir;
6
+ const featuresFile = path.join(dataDir, 'features.json');
7
+ const interfacesFile = path.join(dataDir, 'interfaces.json');
8
+
9
+ // 确保配置文件存在
10
+ if (!fs.existsSync(featuresFile)) {
11
+ fs.writeJsonSync(featuresFile, { features: [] }, { spaces: 2 });
12
+ }
13
+ if (!fs.existsSync(interfacesFile)) {
14
+ fs.writeJsonSync(interfacesFile, { interfaces: [] }, { spaces: 2 });
15
+ }
16
+
17
+ res.json({
18
+ code: 0,
19
+ message: '成功',
20
+ data: {
21
+ version: '0.2.0',
22
+ name: 'whistle.mock-plugin',
23
+ features: [
24
+ '支持Mock.js语法',
25
+ '支持自定义响应头',
26
+ '支持延迟响应',
27
+ '支持条件匹配'
28
+ ]
29
+ }
30
+ });
31
+ };