koishi-plugin-jscn-aaaquery 1.0.1 → 1.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/lib/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export interface Config {
4
4
  loginName: string;
5
5
  password: string;
6
6
  baseUrl: string;
7
+ radiusApiUrl?: string;
7
8
  }
8
9
  export declare const Config: Schema<Config>;
9
10
  export declare function apply(ctx: Context, config: Config): void;
package/lib/index.js CHANGED
@@ -28,13 +28,106 @@ module.exports = __toCommonJS(src_exports);
28
28
  var import_koishi = require("koishi");
29
29
  var name = "jscn-aaaquery";
30
30
  var Config = import_koishi.Schema.object({
31
- loginName: import_koishi.Schema.string().required().description("运维系统登录账号"),
32
- password: import_koishi.Schema.string().required().description("运维系统登录密码"),
33
- baseUrl: import_koishi.Schema.string().default("http://172.16.251.75:8090/nms/api").description("运维系统API地址")
31
+ loginName: import_koishi.Schema.string().required().description("运维系统登录账号").default("admin"),
32
+ password: import_koishi.Schema.string().required().description("运维系统登录密码").default("admin"),
33
+ baseUrl: import_koishi.Schema.string().default("http://172.16.251.75:8090/nms/api").description("运维系统API地址"),
34
+ // 添加RADIUS API的配置项
35
+ radiusApiUrl: import_koishi.Schema.string().description("RADIUS API基础URL").default("http://111.208.114.248:28210/api/radius")
34
36
  });
35
37
  function apply(ctx, config) {
36
38
  let currentToken = null;
37
39
  let tokenExpireTime = 0;
40
+ const requestQueue = {};
41
+ const cache = {};
42
+ const CACHE_EXPIRE_TIME = 5 * 60 * 1e3;
43
+ const CACHE_CLEAN_INTERVAL = 60 * 1e3;
44
+ const QUEUE_EXPIRE_TIME = 10 * 60 * 1e3;
45
+ const QUEUE_CLEAN_INTERVAL = 5 * 60 * 1e3;
46
+ const MAX_CONCURRENT_REQUESTS = 10;
47
+ let currentConcurrentRequests = 0;
48
+ const requestWaitQueue = [];
49
+ function getCacheKey(type, params) {
50
+ return `${type}:${JSON.stringify(params)}`;
51
+ }
52
+ __name(getCacheKey, "getCacheKey");
53
+ function getFromCache(type, params) {
54
+ const key = getCacheKey(type, params);
55
+ const item = cache[key];
56
+ if (item && Date.now() - item.timestamp <= CACHE_EXPIRE_TIME) {
57
+ return item.data;
58
+ }
59
+ return null;
60
+ }
61
+ __name(getFromCache, "getFromCache");
62
+ function setCache(type, params, data) {
63
+ const key = getCacheKey(type, params);
64
+ cache[key] = {
65
+ data,
66
+ timestamp: Date.now()
67
+ };
68
+ }
69
+ __name(setCache, "setCache");
70
+ setInterval(() => {
71
+ const now = Date.now();
72
+ for (const key in cache) {
73
+ if (now - cache[key].timestamp > CACHE_EXPIRE_TIME) {
74
+ delete cache[key];
75
+ }
76
+ }
77
+ }, CACHE_CLEAN_INTERVAL);
78
+ setInterval(() => {
79
+ const now = Date.now();
80
+ for (const key in requestQueue) {
81
+ if (now - requestQueue[key].timestamp > QUEUE_EXPIRE_TIME) {
82
+ delete requestQueue[key];
83
+ }
84
+ }
85
+ }, QUEUE_CLEAN_INTERVAL);
86
+ function getQueueKey(type, params) {
87
+ return `${type}:${JSON.stringify(params)}`;
88
+ }
89
+ __name(getQueueKey, "getQueueKey");
90
+ async function waitForRequestSlot() {
91
+ if (currentConcurrentRequests < MAX_CONCURRENT_REQUESTS) {
92
+ currentConcurrentRequests++;
93
+ return;
94
+ }
95
+ return new Promise((resolve) => {
96
+ requestWaitQueue.push(() => {
97
+ currentConcurrentRequests++;
98
+ resolve();
99
+ });
100
+ });
101
+ }
102
+ __name(waitForRequestSlot, "waitForRequestSlot");
103
+ function releaseRequestSlot() {
104
+ currentConcurrentRequests--;
105
+ if (requestWaitQueue.length > 0) {
106
+ const nextRequest = requestWaitQueue.shift();
107
+ if (nextRequest) {
108
+ nextRequest();
109
+ }
110
+ }
111
+ }
112
+ __name(releaseRequestSlot, "releaseRequestSlot");
113
+ async function addToQueue(type, params, fn) {
114
+ const key = getQueueKey(type, params);
115
+ if (requestQueue[key]) {
116
+ return requestQueue[key].promise;
117
+ }
118
+ await waitForRequestSlot();
119
+ const promise = fn();
120
+ requestQueue[key] = {
121
+ promise,
122
+ timestamp: Date.now()
123
+ };
124
+ promise.finally(() => {
125
+ delete requestQueue[key];
126
+ releaseRequestSlot();
127
+ });
128
+ return promise;
129
+ }
130
+ __name(addToQueue, "addToQueue");
38
131
  function formatMacAddress(mac) {
39
132
  return mac.replace(/[:-\s.]/g, "").toLowerCase();
40
133
  }
@@ -44,6 +137,14 @@ function apply(ctx, config) {
44
137
  return /^[0-9a-f]{12}$/i.test(cleanMac);
45
138
  }
46
139
  __name(isValidMacAddress, "isValidMacAddress");
140
+ function formatAccount(account) {
141
+ return account.toUpperCase();
142
+ }
143
+ __name(formatAccount, "formatAccount");
144
+ function isAccountResponseComplete(data) {
145
+ return !!(data.accessUserName && data.onlineStatus && data.isPass && data.userIp && data.mac && data.maxUpSpeed !== void 0 && data.maxDownSpeed !== void 0 && data.accessDomain && data.startTime && data.startTimeSum !== void 0 && data.nickName);
146
+ }
147
+ __name(isAccountResponseComplete, "isAccountResponseComplete");
47
148
  async function getToken() {
48
149
  const now = Date.now();
49
150
  if (currentToken && now < tokenExpireTime) {
@@ -52,10 +153,7 @@ function apply(ctx, config) {
52
153
  }
53
154
  try {
54
155
  console.log("开始登录请求...");
55
- console.log("请求参数:", {
56
- loginName: config.loginName,
57
- pwd: config.password
58
- });
156
+ await waitForRequestSlot();
59
157
  const response = await ctx.http.post(
60
158
  `${config.baseUrl}/admin/login`,
61
159
  `loginName=${encodeURIComponent(config.loginName)}&pwd=${encodeURIComponent(config.password)}`,
@@ -80,41 +178,56 @@ function apply(ctx, config) {
80
178
  console.error("错误响应:", error.response.data);
81
179
  }
82
180
  throw error;
181
+ } finally {
182
+ releaseRequestSlot();
83
183
  }
84
184
  }
85
185
  __name(getToken, "getToken");
86
186
  async function queryAccount(account) {
87
- try {
88
- console.log("开始查询账号信息...");
89
- const token = await getToken();
90
- const response = await ctx.http.get(`${config.baseUrl}/fttx/aaa/aaaCertification`, {
91
- params: { accessUserName: account },
92
- headers: {
93
- "Authorization": token,
94
- "Accept": "application/json",
95
- "Content-Type": "application/json"
187
+ const formattedAccount = formatAccount(account);
188
+ const cachedData = getFromCache("account", { account: formattedAccount });
189
+ if (cachedData) {
190
+ console.log("使用缓存的账号信息");
191
+ return cachedData;
192
+ }
193
+ return addToQueue("account", { account: formattedAccount }, async () => {
194
+ try {
195
+ console.log("开始查询账号信息...");
196
+ const token = await getToken();
197
+ const response = await ctx.http.get(`${config.baseUrl}/fttx/aaa/aaaCertification`, {
198
+ params: { accessUserName: formattedAccount },
199
+ headers: {
200
+ "Authorization": token,
201
+ "Accept": "application/json",
202
+ "Content-Type": "application/json"
203
+ }
204
+ });
205
+ console.log("查询响应:", JSON.stringify(response, null, 2));
206
+ if (response.status === 200 && response.data) {
207
+ if (!isAccountResponseComplete(response.data)) {
208
+ throw new Error("账号信息有误,请检查账号是否正确");
209
+ }
210
+ setCache("account", { account: formattedAccount }, response.data);
211
+ return response.data;
96
212
  }
97
- });
98
- console.log("查询响应:", JSON.stringify(response, null, 2));
99
- if (response.status === 200 && response.data) {
100
- return response.data;
101
- }
102
- throw new Error(`查询失败:${response.message || "未知错误"}`);
103
- } catch (error) {
104
- console.error("查询错误详情:", error);
105
- if (error.response) {
106
- console.error("错误响应:", error.response.data);
213
+ throw new Error(`查询失败:${response.message || "未知错误"}`);
214
+ } catch (error) {
215
+ console.error("查询错误详情:", error);
216
+ if (error.response) {
217
+ console.error("错误响应:", error.response.data);
218
+ }
219
+ throw error;
107
220
  }
108
- throw error;
109
- }
221
+ });
110
222
  }
111
223
  __name(queryAccount, "queryAccount");
112
224
  async function queryAccountDetail(account) {
225
+ const formattedAccount = formatAccount(account);
113
226
  try {
114
227
  console.log("开始查询账号详情记录...");
115
228
  const token = await getToken();
116
229
  const response = await ctx.http.get(`${config.baseUrl}/fttx/aaa/getMoreRecord`, {
117
- params: { accessUserName: account },
230
+ params: { accessUserName: formattedAccount },
118
231
  headers: {
119
232
  "Authorization": token,
120
233
  "Accept": "application/json",
@@ -136,266 +249,407 @@ function apply(ctx, config) {
136
249
  }
137
250
  __name(queryAccountDetail, "queryAccountDetail");
138
251
  async function queryOnuList(mac) {
139
- try {
140
- console.log("开始查询MAC设备信息...");
141
- const token = await getToken();
142
- const response = await ctx.http.get(`${config.baseUrl}/fttx/onu/searchOnuList`, {
143
- params: { mac, limit: 50, page: 1 },
144
- // 增加limit以获取更多结果
145
- headers: {
146
- "Authorization": token,
147
- "Accept": "application/json",
148
- "Content-Type": "application/json"
252
+ const cachedData = getFromCache("onuList", { mac });
253
+ if (cachedData) {
254
+ console.log("使用缓存的设备信息");
255
+ return cachedData;
256
+ }
257
+ return addToQueue("onuList", { mac }, async () => {
258
+ try {
259
+ console.log("开始查询MAC设备信息...");
260
+ const token = await getToken();
261
+ const response = await ctx.http.get(`${config.baseUrl}/fttx/onu/searchOnuList`, {
262
+ params: { mac, limit: 10, page: 1 },
263
+ headers: {
264
+ "Authorization": token,
265
+ "Accept": "application/json",
266
+ "Content-Type": "application/json"
267
+ }
268
+ });
269
+ console.log("查询响应:", JSON.stringify(response, null, 2));
270
+ if (response.status === 200 && response.data && response.data.rows && response.data.rows.length > 0) {
271
+ const activeOnu = response.data.rows.find((row) => row.status === 1);
272
+ if (activeOnu) {
273
+ console.log("找到在线设备:", activeOnu);
274
+ setCache("onuList", { mac }, activeOnu);
275
+ return activeOnu;
276
+ }
277
+ const lastOnu = response.data.rows[response.data.rows.length - 1];
278
+ console.log("没有在线设备,返回最后一条记录:", lastOnu);
279
+ setCache("onuList", { mac }, lastOnu);
280
+ return lastOnu;
149
281
  }
150
- });
151
- console.log("查询响应:", JSON.stringify(response, null, 2));
152
- if (response.status === 200 && response.data && response.data.rows && response.data.rows.length > 0) {
153
- const activeOnu = response.data.rows.find((row) => row.status === 1);
154
- if (activeOnu) {
155
- console.log("找到在线设备:", activeOnu);
156
- return activeOnu;
282
+ throw new Error(`查询失败:${response.message || "未找到设备信息"}`);
283
+ } catch (error) {
284
+ console.error("查询错误详情:", error);
285
+ if (error.response) {
286
+ console.error("错误响应:", error.response.data);
157
287
  }
158
- const lastOnu = response.data.rows[response.data.rows.length - 1];
159
- console.log("没有在线设备,返回最后一条记录:", lastOnu);
160
- return lastOnu;
161
- }
162
- throw new Error(`查询失败:${response.message || "未找到设备信息"}`);
163
- } catch (error) {
164
- console.error("查询错误详情:", error);
165
- if (error.response) {
166
- console.error("错误响应:", error.response.data);
288
+ throw error;
167
289
  }
168
- throw error;
169
- }
290
+ });
170
291
  }
171
292
  __name(queryOnuList, "queryOnuList");
172
293
  async function queryOnuDetailInfo(onuId) {
173
- try {
174
- console.log("开始查询MAC详细信息...");
175
- const token = await getToken();
176
- const response = await ctx.http.get(`${config.baseUrl}/fttx/onu/onuDetailInfo`, {
177
- params: { onuId },
178
- headers: {
179
- "Authorization": token,
180
- "Accept": "application/json",
181
- "Content-Type": "application/json"
182
- }
183
- });
184
- console.log("查询响应:", JSON.stringify(response, null, 2));
185
- if (response.status === 200 && response.data) {
186
- if (response.data.status === 1 && (response.data.onuReceivePower === "0" || response.data.onuSendPower === "0")) {
187
- console.log("设备在线但光功率为0,尝试刷新光功率...");
188
- try {
189
- const powerResponse = await ctx.http.get(
190
- `${config.baseUrl}/fttx/onu/refreshOnuPower`,
191
- {
192
- params: {
193
- cid: response.data.cid,
194
- gponIndex: response.data.gponIndex,
195
- onuIndex: response.data.onuIndex
196
- },
197
- headers: {
198
- "Authorization": token,
199
- "Accept": "application/json",
200
- "Content-Type": "application/json"
294
+ const cachedData = getFromCache("onuDetail", { onuId });
295
+ if (cachedData) {
296
+ console.log("使用缓存的设备详细信息");
297
+ return cachedData;
298
+ }
299
+ return addToQueue("onuDetail", { onuId }, async () => {
300
+ try {
301
+ console.log("开始查询MAC详细信息...");
302
+ const token = await getToken();
303
+ const response = await ctx.http.get(`${config.baseUrl}/fttx/onu/onuDetailInfo`, {
304
+ params: { onuId },
305
+ headers: {
306
+ "Authorization": token,
307
+ "Accept": "application/json",
308
+ "Content-Type": "application/json"
309
+ }
310
+ });
311
+ console.log("查询响应:", JSON.stringify(response, null, 2));
312
+ if (response.status === 200 && response.data) {
313
+ if (response.data.status === 1 && (response.data.onuReceivePower === "0" || response.data.onuSendPower === "0")) {
314
+ console.log("设备在线但光功率为0,尝试刷新光功率...");
315
+ try {
316
+ const powerResponse = await ctx.http.get(
317
+ `${config.baseUrl}/fttx/onu/refreshOnuPower`,
318
+ {
319
+ params: {
320
+ cid: response.data.cid,
321
+ gponIndex: response.data.gponIndex,
322
+ onuIndex: response.data.onuIndex
323
+ },
324
+ headers: {
325
+ "Authorization": token,
326
+ "Accept": "application/json",
327
+ "Content-Type": "application/json"
328
+ }
201
329
  }
330
+ );
331
+ if (powerResponse.status === 200 && powerResponse.data) {
332
+ console.log("光功率刷新成功:", powerResponse.data);
333
+ response.data.onuReceivePower = powerResponse.data.onuReceivePower;
334
+ response.data.onuSendPower = powerResponse.data.onuSendPower;
335
+ response.data.statusHealth = powerResponse.data.statusHealth;
202
336
  }
203
- );
204
- if (powerResponse.status === 200 && powerResponse.data) {
205
- console.log("光功率刷新成功:", powerResponse.data);
206
- response.data.onuReceivePower = powerResponse.data.onuReceivePower;
207
- response.data.onuSendPower = powerResponse.data.onuSendPower;
208
- response.data.statusHealth = powerResponse.data.statusHealth;
337
+ } catch (error) {
338
+ console.error("刷新光功率失败:", error);
209
339
  }
210
- } catch (error) {
211
- console.error("刷新光功率失败:", error);
212
340
  }
341
+ setCache("onuDetail", { onuId }, response.data);
342
+ return response.data;
213
343
  }
214
- return response.data;
215
- }
216
- throw new Error(`查询失败:${response.message || "未知错误"}`);
217
- } catch (error) {
218
- console.error("查询错误详情:", error);
219
- if (error.response) {
220
- console.error("错误响应:", error.response.data);
344
+ throw new Error(`查询失败:${response.message || "未知错误"}`);
345
+ } catch (error) {
346
+ console.error("查询错误详情:", error);
347
+ if (error.response) {
348
+ console.error("错误响应:", error.response.data);
349
+ }
350
+ throw error;
221
351
  }
222
- throw error;
223
- }
352
+ });
224
353
  }
225
354
  __name(queryOnuDetailInfo, "queryOnuDetailInfo");
226
355
  async function queryCCName(mac) {
227
- try {
228
- console.log("开始查询CCNAME...");
229
- const token = await getToken();
230
- const response = await ctx.http.get(`${config.baseUrl}/fttx/onu/getCCname`, {
231
- params: { mac },
232
- headers: {
233
- "Authorization": token,
234
- "Accept": "application/json",
235
- "Content-Type": "application/json"
356
+ const cachedData = getFromCache("ccname", { mac });
357
+ if (cachedData) {
358
+ console.log("使用缓存的CCNAME");
359
+ return cachedData;
360
+ }
361
+ return addToQueue("ccname", { mac }, async () => {
362
+ try {
363
+ console.log("开始查询CCNAME...");
364
+ const token = await getToken();
365
+ const response = await ctx.http.get(`${config.baseUrl}/fttx/onu/getCCname`, {
366
+ params: { mac },
367
+ headers: {
368
+ "Authorization": token,
369
+ "Accept": "application/json",
370
+ "Content-Type": "application/json"
371
+ }
372
+ });
373
+ console.log("查询响应:", JSON.stringify(response, null, 2));
374
+ if (response.status === 200 && response.data && response.data.ccname) {
375
+ setCache("ccname", { mac }, response.data.ccname);
376
+ return response.data.ccname;
236
377
  }
237
- });
238
- console.log("查询响应:", JSON.stringify(response, null, 2));
239
- if (response.status === 200 && response.data && response.data.ccname) {
240
- return response.data.ccname;
378
+ return "无CCName";
379
+ } catch (error) {
380
+ console.error("查询错误详情:", error);
381
+ return "无CCName";
241
382
  }
242
- return "无CCName";
243
- } catch (error) {
244
- console.error("查询错误详情:", error);
245
- return "无CCName";
246
- }
383
+ });
247
384
  }
248
385
  __name(queryCCName, "queryCCName");
249
386
  async function queryOnuOrder(onuDetail) {
250
- try {
251
- console.log("开始查询工单信息...");
252
- const token = await getToken();
253
- const response = await ctx.http.get(`${config.baseUrl}/fttx/onu/onuOrderList`, {
254
- params: {
255
- cid: onuDetail.cid,
256
- gponIndex: onuDetail.gponIndex,
257
- onuIndex: onuDetail.onuIndex,
258
- serial: onuDetail.serial
259
- },
260
- headers: {
261
- "Authorization": token,
262
- "Accept": "application/json",
263
- "Content-Type": "application/json"
387
+ const cacheKey = {
388
+ cid: onuDetail.cid,
389
+ gponIndex: onuDetail.gponIndex,
390
+ onuIndex: onuDetail.onuIndex,
391
+ serial: onuDetail.serial
392
+ };
393
+ const cachedData = getFromCache("onuOrder", cacheKey);
394
+ if (cachedData) {
395
+ console.log("使用缓存的工单信息");
396
+ return cachedData;
397
+ }
398
+ return addToQueue("onuOrder", cacheKey, async () => {
399
+ try {
400
+ console.log("开始查询工单信息...");
401
+ const token = await getToken();
402
+ const response = await ctx.http.get(`${config.baseUrl}/fttx/onu/onuOrderList`, {
403
+ params: {
404
+ cid: onuDetail.cid,
405
+ gponIndex: onuDetail.gponIndex,
406
+ onuIndex: onuDetail.onuIndex,
407
+ serial: onuDetail.serial
408
+ },
409
+ headers: {
410
+ "Authorization": token,
411
+ "Accept": "application/json",
412
+ "Content-Type": "application/json"
413
+ }
414
+ });
415
+ console.log("查询响应:", JSON.stringify(response, null, 2));
416
+ if (response.status === 200 && response.data && response.data.length > 0) {
417
+ setCache("onuOrder", cacheKey, response.data[0]);
418
+ return response.data[0];
264
419
  }
265
- });
266
- console.log("查询响应:", JSON.stringify(response, null, 2));
267
- if (response.status === 200 && response.data && response.data.length > 0) {
268
- return response.data[0];
420
+ return null;
421
+ } catch (error) {
422
+ console.error("查询错误详情:", error);
423
+ return null;
269
424
  }
270
- return null;
271
- } catch (error) {
272
- console.error("查询错误详情:", error);
273
- return null;
274
- }
425
+ });
275
426
  }
276
427
  __name(queryOnuOrder, "queryOnuOrder");
277
428
  async function queryOnuDetailVlanInfo(onuId) {
278
- try {
279
- console.log("开始查询业务配置信息...");
280
- const token = await getToken();
281
- const response = await ctx.http.get(`${config.baseUrl}/fttx/onu/onuDetailVlanInfo`, {
282
- params: { onuId },
283
- headers: {
284
- "Authorization": token,
285
- "Accept": "application/json",
286
- "Content-Type": "application/json"
287
- }
288
- });
289
- console.log("查询响应:", JSON.stringify(response, null, 2));
290
- return response;
291
- } catch (error) {
292
- console.error("查询错误详情:", error);
293
- return [];
429
+ const cachedData = getFromCache("onuVlan", { onuId });
430
+ if (cachedData) {
431
+ console.log("使用缓存的业务配置信息");
432
+ return cachedData;
294
433
  }
434
+ return addToQueue("onuVlan", { onuId }, async () => {
435
+ try {
436
+ console.log("开始查询业务配置信息...");
437
+ const token = await getToken();
438
+ const response = await ctx.http.get(`${config.baseUrl}/fttx/onu/onuDetailVlanInfo`, {
439
+ params: { onuId },
440
+ headers: {
441
+ "Authorization": token,
442
+ "Accept": "application/json",
443
+ "Content-Type": "application/json"
444
+ }
445
+ });
446
+ console.log("查询响应:", JSON.stringify(response, null, 2));
447
+ setCache("onuVlan", { onuId }, response);
448
+ return response;
449
+ } catch (error) {
450
+ console.error("查询错误详情:", error);
451
+ return [];
452
+ }
453
+ });
295
454
  }
296
455
  __name(queryOnuDetailVlanInfo, "queryOnuDetailVlanInfo");
297
456
  async function queryOrderLog(mac, startTime, endTime) {
298
- try {
299
- console.log("开始查询工单日志...");
300
- const token = await getToken();
301
- const formattedMac = formatMacAddress(mac);
302
- console.log("处理后的MAC地址:", formattedMac);
303
- const response = await ctx.http.get(`${config.baseUrl}/fttx/orderAnalyBlock/selectorderAnalyBlockOneList`, {
304
- params: {
305
- mac: formattedMac,
306
- startTime,
307
- endTime
308
- },
309
- headers: {
310
- "Authorization": token,
311
- "Accept": "application/json",
312
- "Content-Type": "application/json"
313
- }
314
- });
315
- console.log("查询响应:", JSON.stringify(response, null, 2));
316
- return response;
317
- } catch (error) {
318
- console.error("查询错误详情:", error);
319
- return [];
457
+ const cacheKey = { mac, startTime, endTime };
458
+ const cachedData = getFromCache("orderLog", cacheKey);
459
+ if (cachedData) {
460
+ console.log("使用缓存的工单日志");
461
+ return cachedData;
320
462
  }
321
- }
322
- __name(queryOrderLog, "queryOrderLog");
323
- ctx.middleware(async (session, next) => {
324
- const input = session.content.trim();
325
- if (input.includes(" ") || /[\u4e00-\u9fa5]/.test(input)) {
326
- return next();
327
- }
328
- const cleanInput = formatMacAddress(input);
329
- console.log("处理后的内容:", cleanInput);
330
- if (isValidMacAddress(cleanInput)) {
463
+ return addToQueue("orderLog", cacheKey, async () => {
331
464
  try {
332
- const onuList = await queryOnuList(cleanInput);
333
- if (!onuList) {
334
- return "未找到该MAC地址的设备信息";
335
- }
336
- const onuDetail = await queryOnuDetailInfo(onuList.id);
337
- const ccname = await queryCCName(cleanInput);
338
- const order = await queryOnuOrder(onuDetail);
339
- const vlanInfo = await queryOnuDetailVlanInfo(onuList.id);
340
- const messages = [
341
- "📊 终端基本信息",
342
- "--------------------------------",
343
- `MAC地址: ${cleanInput}`,
344
- `状态:${onuDetail.status === 1 ? "在线" : "不在线"}`,
345
- `机房: ${onuDetail.roomName}`,
346
- `设备名称: ${onuDetail.deviceName}`,
347
- `OLT IP: ${onuDetail.oltIp}`,
348
- `PON端口: ${onuDetail.portName}`,
349
- `端口逻辑号: ${onuDetail.logicId}`,
350
- `发射光功率: ${onuDetail.onuSendPower}dBm`,
351
- `接收光功率: ${onuDetail.onuReceivePower}dBm`,
352
- `CCName: ${ccname}`,
353
- "",
354
- "📝 工单信息",
355
- "--------------------------------",
356
- order ? [
357
- `工单编号: ${order.orderId}`,
358
- `创建时间: ${order.createDate}`,
359
- `更新时间: ${order.updateDate}`
360
- ].join("\n") : "无工单信息",
361
- "",
362
- "🔧 业务配置信息",
363
- "--------------------------------"
364
- ];
365
- vlanInfo.forEach((info) => {
366
- messages.push(
367
- `端口 ${info.LAN}:`,
368
- ` VLAN: ${info.actualVlan}`
369
- );
465
+ console.log("开始查询工单日志...");
466
+ const token = await getToken();
467
+ const formattedMac = formatMacAddress(mac);
468
+ console.log("处理后的MAC地址:", formattedMac);
469
+ const response = await ctx.http.get(`${config.baseUrl}/fttx/orderAnalyBlock/selectorderAnalyBlockOneList`, {
470
+ params: {
471
+ mac: formattedMac,
472
+ startTime,
473
+ endTime
474
+ },
475
+ headers: {
476
+ "Authorization": token,
477
+ "Accept": "application/json",
478
+ "Content-Type": "application/json"
479
+ }
370
480
  });
371
- return messages.join("\n");
481
+ console.log("查询响应:", JSON.stringify(response, null, 2));
482
+ setCache("orderLog", cacheKey, response);
483
+ return response;
372
484
  } catch (error) {
373
- console.error("查询过程出错:", error);
374
- return "查询失败,请稍后重试";
485
+ console.error("查询错误详情:", error);
486
+ return [];
375
487
  }
376
- } else {
488
+ });
489
+ }
490
+ __name(queryOrderLog, "queryOrderLog");
491
+ async function queryRadiusUser(account) {
492
+ const cachedData = getFromCache("radiusUser", { account });
493
+ if (cachedData) {
494
+ console.log("使用缓存的RADIUS用户信息");
495
+ return cachedData;
496
+ }
497
+ return addToQueue("radiusUser", { account }, async () => {
377
498
  try {
378
- const accountInfo = await queryAccount(input);
379
- const message = [
380
- "📊 账号查询结果",
381
- "--------------------------------",
382
- `账号: ${accountInfo.accessUserName}`,
383
- `状态: ${accountInfo.onlineStatus}`,
384
- `认证: ${accountInfo.isPass}`,
385
- `IP地址: ${accountInfo.userIp}`,
386
- `MAC地址: ${accountInfo.mac}`,
387
- `最大上行: ${accountInfo.maxUpSpeed}Mbps`,
388
- `最大下行: ${accountInfo.maxDownSpeed}Mbps`,
389
- `接入域: ${accountInfo.accessDomain}`,
390
- `开始时间: ${accountInfo.startTime}`,
391
- `在线时长: ${accountInfo.startTimeSum}分钟`,
392
- `设备名称: ${accountInfo.nickName}`
393
- ].join("\n");
394
- return message;
499
+ console.log("开始查询RADIUS用户信息...");
500
+ const response = await ctx.http.post(
501
+ `${config.radiusApiUrl}/userquery`,
502
+ {
503
+ login_name: account,
504
+ org_code: "403",
505
+ // 固定值
506
+ channel: "ALL"
507
+ // 固定值
508
+ },
509
+ {
510
+ headers: {
511
+ "Content-Type": "application/json",
512
+ "Accept": "application/json"
513
+ }
514
+ }
515
+ );
516
+ console.log("查询响应:", JSON.stringify(response, null, 2));
517
+ setCache("radiusUser", { account }, response);
518
+ return response;
395
519
  } catch (error) {
396
- console.error("查询过程出错:", error);
397
- return "查询失败,请稍后重试";
520
+ console.error("查询RADIUS用户错误详情:", error);
521
+ if (error.response) {
522
+ console.error("错误响应:", error.response.data);
523
+ }
524
+ throw error;
398
525
  }
526
+ });
527
+ }
528
+ __name(queryRadiusUser, "queryRadiusUser");
529
+ function formatRadiusTime(timeString) {
530
+ if (!timeString || timeString.length < 14) return "未知时间";
531
+ const year = timeString.substring(0, 4);
532
+ const month = timeString.substring(4, 6);
533
+ const day = timeString.substring(6, 8);
534
+ const hour = timeString.substring(8, 10);
535
+ const minute = timeString.substring(10, 12);
536
+ const second = timeString.substring(12, 14);
537
+ return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
538
+ }
539
+ __name(formatRadiusTime, "formatRadiusTime");
540
+ function translateOrderStatus(status) {
541
+ switch (status) {
542
+ case "active":
543
+ return "有效";
544
+ case "inactive":
545
+ return "无效";
546
+ case "suspend":
547
+ return "暂停";
548
+ default:
549
+ return status;
550
+ }
551
+ }
552
+ __name(translateOrderStatus, "translateOrderStatus");
553
+ function translateUserStatus(status) {
554
+ switch (status) {
555
+ case "active":
556
+ return "正常";
557
+ case "inactive":
558
+ return "停用";
559
+ case "suspend":
560
+ return "暂停";
561
+ default:
562
+ return status;
563
+ }
564
+ }
565
+ __name(translateUserStatus, "translateUserStatus");
566
+ ctx.middleware(async (session, next) => {
567
+ console.log("原始消息:", session.content);
568
+ const input = session.content.trim();
569
+ console.log("接收到消息:", input);
570
+ try {
571
+ if (input.includes(" ") || /[\u4e00-\u9fa5]/.test(input)) {
572
+ console.log("消息包含空格或中文,跳过智能查询");
573
+ return next();
574
+ }
575
+ const cleanInput = formatMacAddress(input);
576
+ console.log("处理后的内容:", cleanInput);
577
+ if (isValidMacAddress(cleanInput)) {
578
+ console.log("内容是合法的MAC地址,开始查询");
579
+ try {
580
+ const onuList = await queryOnuList(cleanInput);
581
+ if (!onuList) {
582
+ return "未找到该MAC地址的设备信息";
583
+ }
584
+ const onuDetail = await queryOnuDetailInfo(onuList.id);
585
+ const ccname = await queryCCName(cleanInput);
586
+ const order = await queryOnuOrder(onuDetail);
587
+ const vlanInfo = await queryOnuDetailVlanInfo(onuList.id);
588
+ const messages = [
589
+ "📊 终端基本信息",
590
+ "--------------------------------",
591
+ `MAC地址: ${cleanInput}`,
592
+ `状态:${onuDetail.status === 1 ? "在线" : "不在线"}`,
593
+ `机房: ${onuDetail.roomName}`,
594
+ `设备名称: ${onuDetail.deviceName}`,
595
+ `OLT IP: ${onuDetail.oltIp}`,
596
+ `PON端口: ${onuDetail.portName}`,
597
+ `端口逻辑号: ${onuDetail.logicId}`,
598
+ `发射光功率: ${onuDetail.onuSendPower}dBm`,
599
+ `接收光功率: ${onuDetail.onuReceivePower}dBm`,
600
+ `CCName: ${ccname}`,
601
+ "",
602
+ "📝 工单信息",
603
+ "--------------------------------",
604
+ order ? [
605
+ `工单编号: ${order.orderId}`,
606
+ `创建时间: ${order.createDate}`,
607
+ `更新时间: ${order.updateDate}`
608
+ ].join("\n") : "无工单信息",
609
+ "",
610
+ "🔧 业务配置信息",
611
+ "--------------------------------"
612
+ ];
613
+ vlanInfo.forEach((info) => {
614
+ messages.push(
615
+ `端口 ${info.LAN}:`,
616
+ ` VLAN: ${info.actualVlan}`
617
+ );
618
+ });
619
+ return messages.join("\n");
620
+ } catch (error) {
621
+ console.error("查询MAC地址过程出错:", error);
622
+ return "查询失败,请稍后重试";
623
+ }
624
+ } else {
625
+ console.log("内容不是MAC地址,尝试作为账号查询");
626
+ try {
627
+ const accountInfo = await queryAccount(input);
628
+ const message = [
629
+ "📊 账号查询结果",
630
+ "--------------------------------",
631
+ `账号: ${accountInfo.accessUserName}`,
632
+ `状态: ${accountInfo.onlineStatus}`,
633
+ `认证: ${accountInfo.isPass}`,
634
+ `IP地址: ${accountInfo.userIp}`,
635
+ `MAC地址: ${accountInfo.mac}`,
636
+ `最大上行: ${accountInfo.maxUpSpeed}Mbps`,
637
+ `最大下行: ${accountInfo.maxDownSpeed}Mbps`,
638
+ `接入域: ${accountInfo.accessDomain}`,
639
+ `开始时间: ${accountInfo.startTime}`,
640
+ `在线时长: ${accountInfo.startTimeSum}分钟`,
641
+ `设备名称: ${accountInfo.nickName}`
642
+ ].join("\n");
643
+ return message;
644
+ } catch (error) {
645
+ console.error("查询账号过程出错:", error);
646
+ console.log("账号查询失败,交给其他中间件处理");
647
+ return next();
648
+ }
649
+ }
650
+ } catch (error) {
651
+ console.error("智能查询过程出错:", error);
652
+ return next();
399
653
  }
400
654
  });
401
655
  ctx.command("账号查询 <account:string>", "查询宽带账号状态").action(async (_, account) => {
@@ -420,7 +674,7 @@ function apply(ctx, config) {
420
674
  return message;
421
675
  } catch (error) {
422
676
  console.error("查询过程出错:", error);
423
- return "查询失败,请稍后重试";
677
+ return error.message || "查询失败,请检查账号是否正确";
424
678
  }
425
679
  });
426
680
  ctx.command("账号详情 <account:string>", "查询宽带账号详细记录").action(async (_, account) => {
@@ -445,7 +699,7 @@ function apply(ctx, config) {
445
699
  return messages.join("\n\n");
446
700
  } catch (error) {
447
701
  console.error("查询过程出错:", error);
448
- return "查询失败,请稍后重试";
702
+ return error.message || "查询失败,请稍后重试";
449
703
  }
450
704
  });
451
705
  ctx.command("终端查询 <mac:string>", "查询终端基本信息").action(async (_, mac) => {
@@ -665,6 +919,50 @@ function apply(ctx, config) {
665
919
  return "查询失败,请稍后重试";
666
920
  }
667
921
  });
922
+ ctx.command("用户查询 <account:string>", "查询RADIUS用户信息").action(async (_, account) => {
923
+ if (!account) return "请输入要查询的账号";
924
+ try {
925
+ const radiusUserInfo = await queryRadiusUser(account);
926
+ if (radiusUserInfo.code !== "000000" || !radiusUserInfo.data) {
927
+ return `查询失败: ${radiusUserInfo.message || "未知错误"}`;
928
+ }
929
+ const { user, orders } = radiusUserInfo.data;
930
+ const messages = [
931
+ "📊 RADIUS用户信息",
932
+ "--------------------------------",
933
+ `账号: ${user.login_name}`,
934
+ `密码: ${user.password}`,
935
+ `状态: ${translateUserStatus(user.user_status)}`,
936
+ `漫游状态: ${user.roam_status === "0" ? "允许漫游" : "禁止漫游"}`,
937
+ `分公司标识: ${user.org_code}`,
938
+ `BOSS分公司标识: ${user.boss_org_code}`,
939
+ `用户VLAN: ${user.user_vlan}`,
940
+ "",
941
+ "📝 订购信息",
942
+ "--------------------------------"
943
+ ];
944
+ if (orders && orders.length > 0) {
945
+ orders.forEach((order, index) => {
946
+ messages.push(
947
+ `订购 #${index + 1}:`,
948
+ ` 订购序列号: ${order.order_id}`,
949
+ ` 订购状态: ${translateOrderStatus(order.order_status)}`,
950
+ ` 服务名称: ${order.service_name}`,
951
+ ` 并发数: ${order.online_num}`,
952
+ ` 生效时间: ${formatRadiusTime(order.valid_date)}`,
953
+ ` 失效时间: ${formatRadiusTime(order.expire_date)}`,
954
+ ""
955
+ );
956
+ });
957
+ } else {
958
+ messages.push("无订购信息");
959
+ }
960
+ return messages.join("\n");
961
+ } catch (error) {
962
+ console.error("查询过程出错:", error);
963
+ return error.message || "查询失败,请稍后重试";
964
+ }
965
+ });
668
966
  }
669
967
  __name(apply, "apply");
670
968
  // Annotate the CommonJS export names for ESM import in node:
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-jscn-aaaquery",
3
3
  "description": "江苏有线无锡分公司宽带信息查询插件",
4
- "version": "1.0.1",
4
+ "version": "1.0.3",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [