koishi-plugin-jscn-aaaquery 1.0.3 → 1.0.5

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 (3) hide show
  1. package/lib/index.js +685 -371
  2. package/package.json +1 -1
  3. package/readme.md +120 -9
package/lib/index.js CHANGED
@@ -34,6 +34,23 @@ var Config = import_koishi.Schema.object({
34
34
  // 添加RADIUS API的配置项
35
35
  radiusApiUrl: import_koishi.Schema.string().description("RADIUS API基础URL").default("http://111.208.114.248:28210/api/radius")
36
36
  });
37
+ function evaluateOpticalPower(power) {
38
+ if (power === "设备不在线" || power === void 0 || power === null) {
39
+ return "";
40
+ }
41
+ const powerValue = parseFloat(power);
42
+ if (isNaN(powerValue)) {
43
+ return "";
44
+ }
45
+ if (powerValue >= -24 && powerValue <= -8) {
46
+ return "🟢正常";
47
+ } else if (powerValue > -8) {
48
+ return "🔴过高";
49
+ } else {
50
+ return "🔴过低";
51
+ }
52
+ }
53
+ __name(evaluateOpticalPower, "evaluateOpticalPower");
37
54
  function apply(ctx, config) {
38
55
  let currentToken = null;
39
56
  let tokenExpireTime = 0;
@@ -46,6 +63,11 @@ function apply(ctx, config) {
46
63
  const MAX_CONCURRENT_REQUESTS = 10;
47
64
  let currentConcurrentRequests = 0;
48
65
  const requestWaitQueue = [];
66
+ const messageQueue = [];
67
+ let isProcessingMessage = false;
68
+ const MESSAGE_TIMEOUT = 2 * 60 * 1e3;
69
+ const MESSAGE_CLEAN_INTERVAL = 60 * 1e3;
70
+ const MAX_QUEUE_LENGTH = 50;
49
71
  function getCacheKey(type, params) {
50
72
  return `${type}:${JSON.stringify(params)}`;
51
73
  }
@@ -129,7 +151,7 @@ function apply(ctx, config) {
129
151
  }
130
152
  __name(addToQueue, "addToQueue");
131
153
  function formatMacAddress(mac) {
132
- return mac.replace(/[:-\s.]/g, "").toLowerCase();
154
+ return mac.replace(/[:-\s.:。-|]/g, "").toLowerCase();
133
155
  }
134
156
  __name(formatMacAddress, "formatMacAddress");
135
157
  function isValidMacAddress(mac) {
@@ -142,7 +164,11 @@ function apply(ctx, config) {
142
164
  }
143
165
  __name(formatAccount, "formatAccount");
144
166
  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);
167
+ const hasBasicFields = !!(data.accessUserName && data.onlineStatus && data.isPass);
168
+ if (data.onlineStatus === "离线" || data.isPass === "原因未知") {
169
+ return hasBasicFields;
170
+ }
171
+ return hasBasicFields && !!(data.userIp && data.mac && data.maxUpSpeed !== void 0 && data.maxDownSpeed !== void 0 && data.accessDomain && data.startTime && data.startTimeSum !== void 0 && data.nickName);
146
172
  }
147
173
  __name(isAccountResponseComplete, "isAccountResponseComplete");
148
174
  async function getToken() {
@@ -204,6 +230,29 @@ function apply(ctx, config) {
204
230
  });
205
231
  console.log("查询响应:", JSON.stringify(response, null, 2));
206
232
  if (response.status === 200 && response.data) {
233
+ if (response.data.isPass === "上线失败") {
234
+ console.log("账号上线失败,将使用失败信息");
235
+ if (!response.data.startTimeSum) response.data.startTimeSum = 0;
236
+ if (!response.data.maxUpSpeed) response.data.maxUpSpeed = 0;
237
+ if (!response.data.maxDownSpeed) response.data.maxDownSpeed = 0;
238
+ if (!response.data.startTime) response.data.startTime = response.data.onlineFailTime || "未知";
239
+ if (!response.data.nickName) response.data.nickName = response.data.nickName || "未知";
240
+ setCache("account", { account: formattedAccount }, response.data);
241
+ return response.data;
242
+ }
243
+ if (response.data.onlineStatus === "离线" || response.data.isPass === "原因未知") {
244
+ console.log("账号离线或状态异常,将使用有限信息");
245
+ if (!response.data.startTimeSum) response.data.startTimeSum = 0;
246
+ if (!response.data.maxUpSpeed) response.data.maxUpSpeed = 0;
247
+ if (!response.data.maxDownSpeed) response.data.maxDownSpeed = 0;
248
+ if (!response.data.startTime) response.data.startTime = "未知";
249
+ if (!response.data.nickName) response.data.nickName = "未知";
250
+ if (!response.data.mac) response.data.mac = "未知";
251
+ if (!response.data.userIp) response.data.userIp = "未知";
252
+ if (!response.data.accessDomain) response.data.accessDomain = "未知";
253
+ setCache("account", { account: formattedAccount }, response.data);
254
+ return response.data;
255
+ }
207
256
  if (!isAccountResponseComplete(response.data)) {
208
257
  throw new Error("账号信息有误,请检查账号是否正确");
209
258
  }
@@ -310,32 +359,42 @@ function apply(ctx, config) {
310
359
  });
311
360
  console.log("查询响应:", JSON.stringify(response, null, 2));
312
361
  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
- }
362
+ console.log("尝试刷新设备光功率...");
363
+ try {
364
+ const powerResponse = await ctx.http.get(
365
+ `${config.baseUrl}/fttx/onu/refreshOnuPower`,
366
+ {
367
+ params: {
368
+ cid: response.data.cid,
369
+ gponIndex: response.data.gponIndex,
370
+ onuIndex: response.data.onuIndex
371
+ },
372
+ headers: {
373
+ "Authorization": token,
374
+ "Accept": "application/json",
375
+ "Content-Type": "application/json"
329
376
  }
330
- );
331
- if (powerResponse.status === 200 && powerResponse.data) {
332
- console.log("光功率刷新成功:", powerResponse.data);
377
+ }
378
+ );
379
+ if (powerResponse.status === 200 && powerResponse.data) {
380
+ console.log("光功率刷新结果:", powerResponse.data);
381
+ if (powerResponse.data.status !== void 0) {
382
+ response.data.status = powerResponse.data.status;
383
+ }
384
+ if (response.data.status !== 1 && (powerResponse.data.onuReceivePower === void 0 || powerResponse.data.onuSendPower === void 0)) {
385
+ response.data.onuReceivePower = "设备不在线";
386
+ response.data.onuSendPower = "设备不在线";
387
+ } else {
333
388
  response.data.onuReceivePower = powerResponse.data.onuReceivePower;
334
389
  response.data.onuSendPower = powerResponse.data.onuSendPower;
335
- response.data.statusHealth = powerResponse.data.statusHealth;
336
390
  }
337
- } catch (error) {
338
- console.error("刷新光功率失败:", error);
391
+ response.data.statusHealth = powerResponse.data.statusHealth;
392
+ }
393
+ } catch (error) {
394
+ console.error("刷新光功率过程中出错:", error);
395
+ if (response.data.status !== 1 && (response.data.onuReceivePower === void 0 || response.data.onuReceivePower === null || response.data.onuSendPower === void 0 || response.data.onuSendPower === null)) {
396
+ response.data.onuReceivePower = "设备不在线";
397
+ response.data.onuSendPower = "设备不在线";
339
398
  }
340
399
  }
341
400
  setCache("onuDetail", { onuId }, response.data);
@@ -453,7 +512,7 @@ function apply(ctx, config) {
453
512
  });
454
513
  }
455
514
  __name(queryOnuDetailVlanInfo, "queryOnuDetailVlanInfo");
456
- async function queryOrderLog(mac, startTime, endTime) {
515
+ async function queryOrderLog(mac, startTime, endTime, token) {
457
516
  const cacheKey = { mac, startTime, endTime };
458
517
  const cachedData = getFromCache("orderLog", cacheKey);
459
518
  if (cachedData) {
@@ -463,7 +522,6 @@ function apply(ctx, config) {
463
522
  return addToQueue("orderLog", cacheKey, async () => {
464
523
  try {
465
524
  console.log("开始查询工单日志...");
466
- const token = await getToken();
467
525
  const formattedMac = formatMacAddress(mac);
468
526
  console.log("处理后的MAC地址:", formattedMac);
469
527
  const response = await ctx.http.get(`${config.baseUrl}/fttx/orderAnalyBlock/selectorderAnalyBlockOneList`, {
@@ -563,43 +621,528 @@ function apply(ctx, config) {
563
621
  }
564
622
  }
565
623
  __name(translateUserStatus, "translateUserStatus");
566
- ctx.middleware(async (session, next) => {
567
- console.log("原始消息:", session.content);
568
- const input = session.content.trim();
569
- console.log("接收到消息:", input);
624
+ function processTimeRange(startTime, endTime) {
625
+ const formatDate = /* @__PURE__ */ __name((date) => {
626
+ const year = date.getFullYear();
627
+ const month = String(date.getMonth() + 1).padStart(2, "0");
628
+ const day = String(date.getDate()).padStart(2, "0");
629
+ return `${year}-${month}-${day}`;
630
+ }, "formatDate");
631
+ const parseDate = /* @__PURE__ */ __name((dateStr) => {
632
+ if (dateStr.includes(".") || dateStr.includes("/")) {
633
+ const parts = dateStr.split(/[./]/);
634
+ if (parts.length === 3) {
635
+ const [year, month, day] = parts.map(Number);
636
+ return new Date(year, month - 1, day);
637
+ } else if (parts.length === 2) {
638
+ const [month, day] = parts.map(Number);
639
+ const year = (/* @__PURE__ */ new Date()).getFullYear();
640
+ return new Date(year, month - 1, day);
641
+ }
642
+ }
643
+ const chineseMonthMap = {
644
+ "一": 1,
645
+ "二": 2,
646
+ "三": 3,
647
+ "四": 4,
648
+ "五": 5,
649
+ "六": 6,
650
+ "七": 7,
651
+ "八": 8,
652
+ "九": 9,
653
+ "十": 10,
654
+ "十一": 11,
655
+ "十二": 12
656
+ };
657
+ const chineseDayMap = {
658
+ "一": 1,
659
+ "二": 2,
660
+ "三": 3,
661
+ "四": 4,
662
+ "五": 5,
663
+ "六": 6,
664
+ "七": 7,
665
+ "八": 8,
666
+ "九": 9,
667
+ "十": 10,
668
+ "十一": 11,
669
+ "十二": 12,
670
+ "十三": 13,
671
+ "十四": 14,
672
+ "十五": 15,
673
+ "十六": 16,
674
+ "十七": 17,
675
+ "十八": 18,
676
+ "十九": 19,
677
+ "二十": 20,
678
+ "二十一": 21,
679
+ "二十二": 22,
680
+ "二十三": 23,
681
+ "二十四": 24,
682
+ "二十五": 25,
683
+ "二十六": 26,
684
+ "二十七": 27,
685
+ "二十八": 28,
686
+ "二十九": 29,
687
+ "三十": 30,
688
+ "三十一": 31
689
+ };
690
+ const monthMatch = dateStr.match(/[一二三四五六七八九十]+月/);
691
+ const dayMatch = dateStr.match(/[一二三四五六七八九十]+[号日]/);
692
+ if (monthMatch && dayMatch) {
693
+ const monthStr = monthMatch[0].replace("月", "");
694
+ const dayStr = dayMatch[0].replace(/[号日]/, "");
695
+ const year = (/* @__PURE__ */ new Date()).getFullYear();
696
+ const month = chineseMonthMap[monthStr];
697
+ const day = chineseDayMap[dayStr];
698
+ return new Date(year, month - 1, day);
699
+ }
700
+ throw new Error("不支持的日期格式");
701
+ }, "parseDate");
702
+ let formattedStartTime;
703
+ let formattedEndTime;
704
+ try {
705
+ if (startTime && endTime) {
706
+ formattedStartTime = formatDate(parseDate(startTime));
707
+ formattedEndTime = formatDate(parseDate(endTime));
708
+ } else if (startTime) {
709
+ const endDate = parseDate(startTime);
710
+ const startDate = new Date(endDate);
711
+ startDate.setDate(startDate.getDate() - 1);
712
+ formattedStartTime = formatDate(startDate);
713
+ formattedEndTime = formatDate(endDate);
714
+ } else {
715
+ const today = /* @__PURE__ */ new Date();
716
+ const yesterday = new Date(today);
717
+ yesterday.setDate(yesterday.getDate() - 1);
718
+ formattedStartTime = formatDate(yesterday);
719
+ formattedEndTime = formatDate(today);
720
+ }
721
+ } catch (error) {
722
+ throw new Error("日期格式错误,支持的格式:\n1. 2025.4.4 或 2025/4/4\n2. 4.7 或 4/7(自动补全当前年份)\n3. 四月五号\n4. 四月五日");
723
+ }
724
+ return { formattedStartTime, formattedEndTime };
725
+ }
726
+ __name(processTimeRange, "processTimeRange");
727
+ function isShortPrompt(message) {
728
+ return !message.includes("\n") && message.length < 30;
729
+ }
730
+ __name(isShortPrompt, "isShortPrompt");
731
+ function formatOutputMessage(message) {
732
+ if (isShortPrompt(message)) {
733
+ return message;
734
+ }
735
+ if (!message.trim().endsWith("--------------------------------")) {
736
+ message = message + "\n--------------------------------";
737
+ }
738
+ return "\n" + message;
739
+ }
740
+ __name(formatOutputMessage, "formatOutputMessage");
741
+ async function processMessageQueue() {
742
+ if (isProcessingMessage || messageQueue.length === 0) return;
743
+ isProcessingMessage = true;
570
744
  try {
571
- if (input.includes(" ") || /[\u4e00-\u9fa5]/.test(input)) {
572
- console.log("消息包含空格或中文,跳过智能查询");
573
- return next();
745
+ const task = messageQueue.shift();
746
+ if (!task) {
747
+ isProcessingMessage = false;
748
+ return;
749
+ }
750
+ if (Date.now() - task.timestamp > MESSAGE_TIMEOUT) {
751
+ console.log("消息处理任务超时,跳过处理");
752
+ isProcessingMessage = false;
753
+ setTimeout(processMessageQueue, 0);
754
+ return;
755
+ }
756
+ console.log("开始处理消息队列中的任务");
757
+ const result = await task.handler();
758
+ if (result && task.session?.send) {
759
+ const formattedResult = formatOutputMessage(result);
760
+ await task.session.send(formattedResult);
574
761
  }
575
- const cleanInput = formatMacAddress(input);
576
- console.log("处理后的内容:", cleanInput);
577
- if (isValidMacAddress(cleanInput)) {
578
- console.log("内容是合法的MAC地址,开始查询");
762
+ console.log("消息处理完成");
763
+ } catch (error) {
764
+ console.error("处理消息队列任务出错:", error);
765
+ } finally {
766
+ isProcessingMessage = false;
767
+ setTimeout(processMessageQueue, 100);
768
+ }
769
+ }
770
+ __name(processMessageQueue, "processMessageQueue");
771
+ function addToMessageQueue(session, handler) {
772
+ if (messageQueue.length >= MAX_QUEUE_LENGTH) {
773
+ const oldestTask = messageQueue.shift();
774
+ if (oldestTask?.session?.send) {
775
+ oldestTask.session.send("系统繁忙,请稍后再试").catch((error) => console.error("发送繁忙提示失败:", error));
776
+ }
777
+ }
778
+ messageQueue.push({
779
+ session,
780
+ handler,
781
+ timestamp: Date.now()
782
+ });
783
+ setTimeout(processMessageQueue, 0);
784
+ }
785
+ __name(addToMessageQueue, "addToMessageQueue");
786
+ setInterval(() => {
787
+ const now = Date.now();
788
+ let expiredCount = 0;
789
+ while (messageQueue.length > 0 && now - messageQueue[0].timestamp > MESSAGE_TIMEOUT) {
790
+ const expiredTask = messageQueue.shift();
791
+ if (expiredTask?.session?.send) {
792
+ expiredTask.session.send("处理超时,请稍后再试").catch((error) => console.error("发送超时提示失败:", error));
793
+ }
794
+ expiredCount++;
795
+ }
796
+ if (expiredCount > 0) {
797
+ console.log(`清理了 ${expiredCount} 个超时的消息任务`);
798
+ }
799
+ }, MESSAGE_CLEAN_INTERVAL);
800
+ ctx.middleware(async (session, next) => {
801
+ console.log("原始消息:", session.content);
802
+ const originalInput = session.stripped.content.trim();
803
+ let input = originalInput;
804
+ console.log("处理后的消息:", input);
805
+ if (!input) {
806
+ console.log("处理后的消息为空,跳过智能查询");
807
+ return next();
808
+ }
809
+ if (/[\u4e00-\u9fa5]/.test(input)) {
810
+ console.log("消息包含中文,跳过智能查询");
811
+ return next();
812
+ }
813
+ return new Promise((resolve) => {
814
+ addToMessageQueue(session, async () => {
815
+ try {
816
+ const cleanInput = formatMacAddress(input);
817
+ console.log("处理后的内容:", cleanInput);
818
+ if (isValidMacAddress(cleanInput)) {
819
+ console.log("内容是合法的MAC地址,开始查询");
820
+ try {
821
+ const onuList = await queryOnuList(cleanInput);
822
+ if (!onuList) {
823
+ return "未找到该MAC地址的设备信息";
824
+ }
825
+ const onuDetail = await queryOnuDetailInfo(onuList.id);
826
+ const ccname = await queryCCName(cleanInput);
827
+ const order = await queryOnuOrder(onuDetail);
828
+ const vlanInfo = await queryOnuDetailVlanInfo(onuList.id);
829
+ const messages = [
830
+ "🖥️ 终端基本信息",
831
+ "--------------------------------",
832
+ `MAC地址: ${cleanInput}`,
833
+ `状态:${onuDetail.status === 1 ? "在线 ✅" : "不在线 ❌"}`,
834
+ `机房: ${onuDetail.roomName}`,
835
+ `设备名称: `,
836
+ `${onuDetail.deviceName}`,
837
+ `OLT IP: ${onuDetail.oltIp}`,
838
+ `PON端口: ${onuDetail.portName}`,
839
+ `端口逻辑号: ${onuDetail.logicId}`,
840
+ `发射光功率: ${onuDetail.onuSendPower === "设备不在线" ? "设备不在线" : onuDetail.onuSendPower + "dBm"}`,
841
+ `接收光功率: ${onuDetail.onuReceivePower === "设备不在线" ? "设备不在线" : onuDetail.onuReceivePower + "dBm"}${onuDetail.onuReceivePower !== "设备不在线" ? " " + evaluateOpticalPower(onuDetail.onuReceivePower) : ""}`,
842
+ `CCName: ${ccname}`,
843
+ "",
844
+ "📃 工单信息",
845
+ "--------------------------------",
846
+ order ? [
847
+ `工单编号: ${order.orderId}`,
848
+ `创建时间: ${order.createDate}`,
849
+ `更新时间: ${order.updateDate}`
850
+ ].join("\n") : "无工单信息",
851
+ "",
852
+ "⚙️ 业务配置信息",
853
+ "--------------------------------"
854
+ ];
855
+ vlanInfo.forEach((info) => {
856
+ messages.push(
857
+ `端口 ${info.LAN}:`,
858
+ ` 端口VLAN: ${info.VLAN || "未配置"}`,
859
+ ` 工单VLAN: ${info.actualVlan || "未配置"}`
860
+ );
861
+ });
862
+ messages.push("--------------------------------");
863
+ return messages.join("\n");
864
+ } catch (error) {
865
+ console.error("查询MAC地址过程出错:", error);
866
+ return "查询失败,请稍后重试";
867
+ }
868
+ } else {
869
+ console.log("内容不是MAC地址,尝试作为账号查询");
870
+ try {
871
+ const radiusUserInfo = await queryRadiusUser(input);
872
+ if (radiusUserInfo.code !== "000000" || !radiusUserInfo.data) {
873
+ return "账号授权有误,请重新授权";
874
+ }
875
+ const { user, orders } = radiusUserInfo.data;
876
+ const accountInfo = await queryAccount(input);
877
+ const days = Math.floor(accountInfo.startTimeSum / (60 * 24));
878
+ const hours = Math.floor(accountInfo.startTimeSum % (60 * 24) / 60);
879
+ const minutes = accountInfo.startTimeSum % 60;
880
+ let durationText = "";
881
+ if (days > 0) {
882
+ durationText = `${days}天${hours > 0 ? hours + "小时" : ""}${minutes > 0 ? minutes + "分钟" : ""}`;
883
+ } else if (hours > 0) {
884
+ durationText = `${hours}小时${minutes > 0 ? minutes + "分钟" : ""}`;
885
+ } else {
886
+ durationText = `${minutes}分钟`;
887
+ }
888
+ const message = [
889
+ "🌐 账号查询结果",
890
+ "--------------------------------",
891
+ `账号: ${accountInfo.accessUserName}`,
892
+ // `RADIUS用户密码: ${user.password}`,
893
+ `RADIUS状态: ${translateUserStatus(user.user_status)} ${user.user_status === "active" ? "✅" : user.user_status === "suspend" ? "⚠️" : "❌"}`,
894
+ "",
895
+ `状态: ${accountInfo.onlineStatus} ${accountInfo.onlineStatus === "在线" ? "✅" : "❌"}`,
896
+ `认证: ${accountInfo.isPass} ${accountInfo.isPass.includes("成功") ? "✅" : "❌"}`
897
+ ];
898
+ if (accountInfo.isPass === "上线失败") {
899
+ message.push(
900
+ `MAC地址: ${accountInfo.mac || "未知"}`,
901
+ `失败时间: ${accountInfo.onlineFailTime || "未知"}`,
902
+ `失败原因: ${accountInfo.onlineFailReason || "未知"}`,
903
+ `回复消息: ${accountInfo.failReplyMessage || "未知"}`,
904
+ `原因分析: ${accountInfo.reasonAnaly || "未知"}`
905
+ );
906
+ } else if (accountInfo.onlineStatus === "离线" || accountInfo.isPass === "原因未知") {
907
+ message.push(
908
+ `MAC地址: ${accountInfo.mac || "未知"}`,
909
+ `最后IP: ${accountInfo.userIp || "未知"}`
910
+ );
911
+ if (accountInfo.startTime) {
912
+ message.push(`最后在线: ${accountInfo.startTime || "未知"}`);
913
+ }
914
+ } else {
915
+ message.push(
916
+ `IP地址: ${accountInfo.userIp}`,
917
+ `MAC地址: ${accountInfo.mac}`,
918
+ `最大上行: ${accountInfo.maxUpSpeed}Mbps`,
919
+ `最大下行: ${accountInfo.maxDownSpeed}Mbps`,
920
+ `开始时间: ${accountInfo.startTime}`,
921
+ `在线时长: ${durationText}`
922
+ );
923
+ }
924
+ message.push("");
925
+ if (orders && orders.length > 0) {
926
+ message.push("🛒 订购信息");
927
+ message.push("--------------------------------");
928
+ orders.forEach((order, index) => {
929
+ message.push(
930
+ `订购 #${index + 1}:`,
931
+ ` 订购状态: ${translateOrderStatus(order.order_status)}`,
932
+ ` 服务名称: ${order.service_name}`,
933
+ ` 生效时间: ${formatRadiusTime(order.valid_date)}`,
934
+ ` 失效时间: ${formatRadiusTime(order.expire_date)}`
935
+ );
936
+ if (index < orders.length - 1) {
937
+ message.push("");
938
+ }
939
+ });
940
+ }
941
+ message.push("--------------------------------");
942
+ return message.join("\n");
943
+ } catch (error) {
944
+ console.error("查询账号过程出错:", error);
945
+ resolve(next());
946
+ return null;
947
+ }
948
+ }
949
+ } catch (error) {
950
+ console.error("智能查询过程出错:", error);
951
+ resolve(next());
952
+ return null;
953
+ }
954
+ });
955
+ });
956
+ });
957
+ ctx.command("账号查询 <account:string>", "查询宽带账号状态").action(async ({ session }, account) => {
958
+ if (!account) return "请输入要查询的账号";
959
+ return new Promise((resolve) => {
960
+ addToMessageQueue(session, async () => {
961
+ try {
962
+ const radiusUserInfo = await queryRadiusUser(account);
963
+ if (radiusUserInfo.code !== "000000" || !radiusUserInfo.data) {
964
+ return "账号授权有误,请重新授权";
965
+ }
966
+ const { user, orders } = radiusUserInfo.data;
967
+ const accountInfo = await queryAccount(account);
968
+ const days = Math.floor(accountInfo.startTimeSum / (60 * 24));
969
+ const hours = Math.floor(accountInfo.startTimeSum % (60 * 24) / 60);
970
+ const minutes = accountInfo.startTimeSum % 60;
971
+ let durationText = "";
972
+ if (days > 0) {
973
+ durationText = `${days}天${hours > 0 ? hours + "小时" : ""}${minutes > 0 ? minutes + "分钟" : ""}`;
974
+ } else if (hours > 0) {
975
+ durationText = `${hours}小时${minutes > 0 ? minutes + "分钟" : ""}`;
976
+ } else {
977
+ durationText = `${minutes}分钟`;
978
+ }
979
+ const message = [
980
+ "🌐 账号查询结果",
981
+ "--------------------------------",
982
+ `账号: ${accountInfo.accessUserName}`,
983
+ // `RADIUS用户密码: ${user.password}`,
984
+ `RADIUS状态: ${translateUserStatus(user.user_status)} ${user.user_status === "active" ? "✅" : user.user_status === "suspend" ? "⚠️" : "❌"}`,
985
+ "",
986
+ `状态: ${accountInfo.onlineStatus} ${accountInfo.onlineStatus === "在线" ? "✅" : "❌"}`,
987
+ `认证: ${accountInfo.isPass} ${accountInfo.isPass.includes("成功") ? "✅" : "❌"}`
988
+ ];
989
+ if (accountInfo.isPass === "上线失败") {
990
+ message.push(
991
+ `MAC地址: ${accountInfo.mac || "未知"}`,
992
+ `失败时间: ${accountInfo.onlineFailTime || "未知"}`,
993
+ `失败原因: ${accountInfo.onlineFailReason || "未知"}`,
994
+ `回复消息: ${accountInfo.failReplyMessage || "未知"}`,
995
+ `原因分析: ${accountInfo.reasonAnaly || "未知"}`
996
+ );
997
+ } else if (accountInfo.onlineStatus === "离线" || accountInfo.isPass === "原因未知") {
998
+ message.push(
999
+ `MAC地址: ${accountInfo.mac || "未知"}`,
1000
+ `最后IP: ${accountInfo.userIp || "未知"}`
1001
+ );
1002
+ if (accountInfo.startTime) {
1003
+ message.push(`最后在线: ${accountInfo.startTime || "未知"}`);
1004
+ }
1005
+ } else {
1006
+ message.push(
1007
+ `IP地址: ${accountInfo.userIp}`,
1008
+ `MAC地址: ${accountInfo.mac}`,
1009
+ `最大上行: ${accountInfo.maxUpSpeed}Mbps`,
1010
+ `最大下行: ${accountInfo.maxDownSpeed}Mbps`,
1011
+ `开始时间: ${accountInfo.startTime}`,
1012
+ `在线时长: ${durationText}`
1013
+ );
1014
+ }
1015
+ message.push("");
1016
+ if (orders && orders.length > 0) {
1017
+ message.push("🛒 订购信息");
1018
+ message.push("--------------------------------");
1019
+ orders.forEach((order, index) => {
1020
+ message.push(
1021
+ `订购 #${index + 1}:`,
1022
+ ` 订购状态: ${translateOrderStatus(order.order_status)}`,
1023
+ ` 服务名称: ${order.service_name}`,
1024
+ ` 生效时间: ${formatRadiusTime(order.valid_date)}`,
1025
+ ` 失效时间: ${formatRadiusTime(order.expire_date)}`
1026
+ );
1027
+ if (index < orders.length - 1) {
1028
+ message.push("");
1029
+ }
1030
+ });
1031
+ }
1032
+ message.push("--------------------------------");
1033
+ return message.join("\n");
1034
+ } catch (error) {
1035
+ console.error("查询过程出错:", error);
1036
+ return error.message || "查询失败,请检查账号是否正确";
1037
+ }
1038
+ });
1039
+ resolve();
1040
+ });
1041
+ });
1042
+ ctx.command("账号详情 <account:string>", "查询宽带账号详细记录").action(async ({ session }, account) => {
1043
+ if (!account) return "请输入要查询的账号";
1044
+ return new Promise((resolve) => {
1045
+ addToMessageQueue(session, async () => {
1046
+ try {
1047
+ const records = await queryAccountDetail(account);
1048
+ if (records.length === 0) {
1049
+ return "未找到该账号的详细记录";
1050
+ }
1051
+ const messages = records.map((record, index) => [
1052
+ `📋 记录 #${index + 1}`,
1053
+ "--------------------------------",
1054
+ `账号: ${record.accessUserName}`,
1055
+ `记录类型: ${record.recordType}`,
1056
+ `设备名称: ${record.nickName}`,
1057
+ `IP地址: ${record.ip}`,
1058
+ `MAC地址: ${record.mac}`,
1059
+ `登录时间: ${record.userLoginInTime}`,
1060
+ `登出时间: ${record.userLoginOutTime}`,
1061
+ `原因: ${record.reason || "无"}`
1062
+ ].join("\n"));
1063
+ let result = messages.join("\n\n");
1064
+ result += "\n--------------------------------";
1065
+ return result;
1066
+ } catch (error) {
1067
+ console.error("查询过程出错:", error);
1068
+ return error.message || "查询失败,请稍后重试";
1069
+ }
1070
+ });
1071
+ resolve();
1072
+ });
1073
+ });
1074
+ ctx.command("终端查询 <mac:string>", "查询终端基本信息").action(async ({ session }, mac) => {
1075
+ if (!mac) return "请输入要查询的MAC地址";
1076
+ return new Promise((resolve) => {
1077
+ addToMessageQueue(session, async () => {
1078
+ try {
1079
+ const formattedMac = formatMacAddress(mac);
1080
+ const onuList = await queryOnuList(formattedMac);
1081
+ if (!onuList) {
1082
+ return "未找到该MAC地址的设备信息";
1083
+ }
1084
+ const onuDetail = await queryOnuDetailInfo(onuList.id);
1085
+ const vlanInfo = await queryOnuDetailVlanInfo(onuList.id);
1086
+ const messages = [
1087
+ "🖥️ 终端基本信息",
1088
+ "--------------------------------",
1089
+ `MAC地址: ${formattedMac}`,
1090
+ `状态:${onuDetail.status === 1 ? "在线 ✅" : "不在线 ❌"}`,
1091
+ `设备名称: `,
1092
+ `${onuDetail.deviceName}`,
1093
+ `发射光功率: ${onuDetail.onuSendPower === "设备不在线" ? "设备不在线" : onuDetail.onuSendPower + "dBm"}`,
1094
+ `接收光功率: ${onuDetail.onuReceivePower === "设备不在线" ? "设备不在线" : onuDetail.onuReceivePower + "dBm"}${onuDetail.onuReceivePower !== "设备不在线" ? " " + evaluateOpticalPower(onuDetail.onuReceivePower) : ""}`,
1095
+ "",
1096
+ "⚙️ 业务配置信息",
1097
+ "--------------------------------"
1098
+ ];
1099
+ vlanInfo.forEach((info) => {
1100
+ messages.push(
1101
+ `端口 ${info.LAN}:`,
1102
+ ` 端口VLAN: ${info.VLAN || "未配置"}`,
1103
+ ` 工单VLAN: ${info.actualVlan || "未配置"}`
1104
+ );
1105
+ });
1106
+ messages.push("--------------------------------");
1107
+ return messages.join("\n");
1108
+ } catch (error) {
1109
+ console.error("查询过程出错:", error);
1110
+ return "查询失败,请稍后重试";
1111
+ }
1112
+ });
1113
+ resolve();
1114
+ });
1115
+ });
1116
+ ctx.command("终端详细查询 <mac:string>", "查询终端详细信息").action(async ({ session }, mac) => {
1117
+ if (!mac) return "请输入要查询的MAC地址";
1118
+ return new Promise((resolve) => {
1119
+ addToMessageQueue(session, async () => {
579
1120
  try {
580
- const onuList = await queryOnuList(cleanInput);
1121
+ const formattedMac = formatMacAddress(mac);
1122
+ const onuList = await queryOnuList(formattedMac);
581
1123
  if (!onuList) {
582
1124
  return "未找到该MAC地址的设备信息";
583
1125
  }
584
1126
  const onuDetail = await queryOnuDetailInfo(onuList.id);
585
- const ccname = await queryCCName(cleanInput);
1127
+ const ccname = await queryCCName(formattedMac);
586
1128
  const order = await queryOnuOrder(onuDetail);
587
1129
  const vlanInfo = await queryOnuDetailVlanInfo(onuList.id);
588
1130
  const messages = [
589
- "📊 终端基本信息",
1131
+ "🖥️ 终端基本信息",
590
1132
  "--------------------------------",
591
- `MAC地址: ${cleanInput}`,
592
- `状态:${onuDetail.status === 1 ? "在线" : "不在线"}`,
1133
+ `MAC地址: ${formattedMac}`,
1134
+ `状态:${onuDetail.status === 1 ? "在线" : "不在线"}`,
593
1135
  `机房: ${onuDetail.roomName}`,
594
- `设备名称: ${onuDetail.deviceName}`,
1136
+ `设备名称: `,
1137
+ `${onuDetail.deviceName}`,
595
1138
  `OLT IP: ${onuDetail.oltIp}`,
596
1139
  `PON端口: ${onuDetail.portName}`,
597
1140
  `端口逻辑号: ${onuDetail.logicId}`,
598
- `发射光功率: ${onuDetail.onuSendPower}dBm`,
599
- `接收光功率: ${onuDetail.onuReceivePower}dBm`,
1141
+ `发射光功率: ${onuDetail.onuSendPower === "设备不在线" ? "设备不在线" : onuDetail.onuSendPower + "dBm"}`,
1142
+ `接收光功率: ${onuDetail.onuReceivePower === "设备不在线" ? "设备不在线" : onuDetail.onuReceivePower + "dBm"}${onuDetail.onuReceivePower !== "设备不在线" ? " " + evaluateOpticalPower(onuDetail.onuReceivePower) : ""}`,
600
1143
  `CCName: ${ccname}`,
601
1144
  "",
602
- "📝 工单信息",
1145
+ "📃 工单信息",
603
1146
  "--------------------------------",
604
1147
  order ? [
605
1148
  `工单编号: ${order.orderId}`,
@@ -607,361 +1150,132 @@ function apply(ctx, config) {
607
1150
  `更新时间: ${order.updateDate}`
608
1151
  ].join("\n") : "无工单信息",
609
1152
  "",
610
- "🔧 业务配置信息",
1153
+ "⚙️ 业务配置信息",
611
1154
  "--------------------------------"
612
1155
  ];
613
1156
  vlanInfo.forEach((info) => {
614
1157
  messages.push(
615
1158
  `端口 ${info.LAN}:`,
616
- ` VLAN: ${info.actualVlan}`
1159
+ ` 端口VLAN: ${info.VLAN || "未配置"}`,
1160
+ ` 工单VLAN: ${info.actualVlan || "未配置"}`
617
1161
  );
618
1162
  });
1163
+ messages.push("--------------------------------");
619
1164
  return messages.join("\n");
620
1165
  } catch (error) {
621
- console.error("查询MAC地址过程出错:", error);
1166
+ console.error("查询过程出错:", error);
622
1167
  return "查询失败,请稍后重试";
623
1168
  }
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();
653
- }
654
- });
655
- ctx.command("账号查询 <account:string>", "查询宽带账号状态").action(async (_, account) => {
656
- if (!account) return "请输入要查询的账号";
657
- try {
658
- const accountInfo = await queryAccount(account);
659
- const message = [
660
- "📊 账号查询结果",
661
- "--------------------------------",
662
- `账号: ${accountInfo.accessUserName}`,
663
- `状态: ${accountInfo.onlineStatus}`,
664
- `认证: ${accountInfo.isPass}`,
665
- `IP地址: ${accountInfo.userIp}`,
666
- `MAC地址: ${accountInfo.mac}`,
667
- `最大上行: ${accountInfo.maxUpSpeed}Mbps`,
668
- `最大下行: ${accountInfo.maxDownSpeed}Mbps`,
669
- `接入域: ${accountInfo.accessDomain}`,
670
- `开始时间: ${accountInfo.startTime}`,
671
- `在线时长: ${accountInfo.startTimeSum}分钟`,
672
- `设备名称: ${accountInfo.nickName}`
673
- ].join("\n");
674
- return message;
675
- } catch (error) {
676
- console.error("查询过程出错:", error);
677
- return error.message || "查询失败,请检查账号是否正确";
678
- }
679
- });
680
- ctx.command("账号详情 <account:string>", "查询宽带账号详细记录").action(async (_, account) => {
681
- if (!account) return "请输入要查询的账号";
682
- try {
683
- const records = await queryAccountDetail(account);
684
- if (records.length === 0) {
685
- return "未找到该账号的详细记录";
686
- }
687
- const messages = records.map((record, index) => [
688
- `📝 记录 #${index + 1}`,
689
- "--------------------------------",
690
- `账号: ${record.accessUserName}`,
691
- `记录类型: ${record.recordType}`,
692
- `设备名称: ${record.nickName}`,
693
- `IP地址: ${record.ip}`,
694
- `MAC地址: ${record.mac}`,
695
- `登录时间: ${record.userLoginInTime}`,
696
- `登出时间: ${record.userLoginOutTime}`,
697
- `原因: ${record.reason || "无"}`
698
- ].join("\n"));
699
- return messages.join("\n\n");
700
- } catch (error) {
701
- console.error("查询过程出错:", error);
702
- return error.message || "查询失败,请稍后重试";
703
- }
704
- });
705
- ctx.command("终端查询 <mac:string>", "查询终端基本信息").action(async (_, mac) => {
706
- if (!mac) return "请输入要查询的MAC地址";
707
- try {
708
- const formattedMac = formatMacAddress(mac);
709
- const onuList = await queryOnuList(formattedMac);
710
- if (!onuList) {
711
- return "未找到该MAC地址的设备信息";
712
- }
713
- const onuDetail = await queryOnuDetailInfo(onuList.id);
714
- const vlanInfo = await queryOnuDetailVlanInfo(onuList.id);
715
- const messages = [
716
- "📊 终端基本信息",
717
- "--------------------------------",
718
- `MAC地址: ${formattedMac}`,
719
- `状态:${onuDetail.status === 1 ? "在线" : "不在线"}`,
720
- `发射光功率: ${onuDetail.onuSendPower}dBm`,
721
- `接收光功率: ${onuDetail.onuReceivePower}dBm`,
722
- "",
723
- "🔧 业务配置信息",
724
- "--------------------------------"
725
- ];
726
- vlanInfo.forEach((info) => {
727
- messages.push(
728
- `端口 ${info.LAN}:`,
729
- ` VLAN: ${info.actualVlan}`
730
- );
731
1169
  });
732
- return messages.join("\n");
733
- } catch (error) {
734
- console.error("查询过程出错:", error);
735
- return "查询失败,请稍后重试";
736
- }
1170
+ resolve();
1171
+ });
737
1172
  });
738
- ctx.command("终端详细查询 <mac:string>", "查询终端详细信息").action(async (_, mac) => {
1173
+ ctx.command("日志查询 <mac:string> [startTime:string] [endTime:string]", "查询终端工单日志").action(async ({ session }, mac, startTime, endTime) => {
739
1174
  if (!mac) return "请输入要查询的MAC地址";
740
1175
  try {
1176
+ await session?.send("正在查询日志,请稍候...");
741
1177
  const formattedMac = formatMacAddress(mac);
742
- const onuList = await queryOnuList(formattedMac);
743
- if (!onuList) {
744
- return "未找到该MAC地址的设备信息";
745
- }
746
- const onuDetail = await queryOnuDetailInfo(onuList.id);
747
- const ccname = await queryCCName(formattedMac);
748
- const order = await queryOnuOrder(onuDetail);
749
- const vlanInfo = await queryOnuDetailVlanInfo(onuList.id);
750
- const messages = [
751
- "📊 终端基本信息",
752
- "--------------------------------",
753
- `MAC地址: ${formattedMac}`,
754
- `状态:${onuDetail.status === 1 ? "在线" : "不在线"}`,
755
- `机房: ${onuDetail.roomName}`,
756
- `设备名称: ${onuDetail.deviceName}`,
757
- `OLT IP: ${onuDetail.oltIp}`,
758
- `PON端口: ${onuDetail.portName}`,
759
- `端口逻辑号: ${onuDetail.logicId}`,
760
- `发射光功率: ${onuDetail.onuSendPower}dBm`,
761
- `接收光功率: ${onuDetail.onuReceivePower}dBm`,
762
- `CCName: ${ccname}`,
763
- "",
764
- "📝 工单信息",
765
- "--------------------------------",
766
- order ? [
767
- `工单编号: ${order.orderId}`,
768
- `创建时间: ${order.createDate}`,
769
- `更新时间: ${order.updateDate}`
770
- ].join("\n") : "无工单信息",
771
- "",
772
- "🔧 业务配置信息",
773
- "--------------------------------"
774
- ];
775
- vlanInfo.forEach((info) => {
776
- messages.push(
777
- `端口 ${info.LAN}:`,
778
- ` VLAN: ${info.actualVlan}`
779
- );
1178
+ const { formattedStartTime, formattedEndTime } = processTimeRange(startTime, endTime);
1179
+ const token = await getToken();
1180
+ const fetchLogsPromise = queryOrderLog(formattedMac, formattedStartTime, formattedEndTime, token);
1181
+ const timeoutPromise = new Promise((_, reject) => {
1182
+ setTimeout(() => reject(new Error("查询超时,请稍后重试或缩短查询时间范围")), 3e4);
780
1183
  });
781
- return messages.join("\n");
782
- } catch (error) {
783
- console.error("查询过程出错:", error);
784
- return "查询失败,请稍后重试";
785
- }
786
- });
787
- ctx.command("日志查询 <mac:string> [startTime:string] [endTime:string]", "查询终端工单日志").action(async (_, mac, startTime, endTime) => {
788
- if (!mac) return "请输入要查询的MAC地址";
789
- try {
790
- const formatDate = /* @__PURE__ */ __name((date) => {
791
- const year = date.getFullYear();
792
- const month = String(date.getMonth() + 1).padStart(2, "0");
793
- const day = String(date.getDate()).padStart(2, "0");
794
- return `${year}-${month}-${day}`;
795
- }, "formatDate");
796
- const parseDate = /* @__PURE__ */ __name((dateStr) => {
797
- if (dateStr.includes(".") || dateStr.includes("/")) {
798
- const parts = dateStr.split(/[./]/);
799
- if (parts.length === 3) {
800
- const [year, month, day] = parts.map(Number);
801
- return new Date(year, month - 1, day);
802
- } else if (parts.length === 2) {
803
- const [month, day] = parts.map(Number);
804
- const year = (/* @__PURE__ */ new Date()).getFullYear();
805
- return new Date(year, month - 1, day);
806
- }
807
- }
808
- const chineseMonthMap = {
809
- "一": 1,
810
- "二": 2,
811
- "三": 3,
812
- "四": 4,
813
- "五": 5,
814
- "六": 6,
815
- "七": 7,
816
- "八": 8,
817
- "九": 9,
818
- "十": 10,
819
- "十一": 11,
820
- "十二": 12
821
- };
822
- const chineseDayMap = {
823
- "一": 1,
824
- "二": 2,
825
- "三": 3,
826
- "四": 4,
827
- "五": 5,
828
- "六": 6,
829
- "七": 7,
830
- "八": 8,
831
- "九": 9,
832
- "十": 10,
833
- "十一": 11,
834
- "十二": 12,
835
- "十三": 13,
836
- "十四": 14,
837
- "十五": 15,
838
- "十六": 16,
839
- "十七": 17,
840
- "十八": 18,
841
- "十九": 19,
842
- "二十": 20,
843
- "二十一": 21,
844
- "二十二": 22,
845
- "二十三": 23,
846
- "二十四": 24,
847
- "二十五": 25,
848
- "二十六": 26,
849
- "二十七": 27,
850
- "二十八": 28,
851
- "二十九": 29,
852
- "三十": 30,
853
- "三十一": 31
854
- };
855
- const monthMatch = dateStr.match(/[一二三四五六七八九十]+月/);
856
- const dayMatch = dateStr.match(/[一二三四五六七八九十]+[号日]/);
857
- if (monthMatch && dayMatch) {
858
- const monthStr = monthMatch[0].replace("月", "");
859
- const dayStr = dayMatch[0].replace(/[号日]/, "");
860
- const year = (/* @__PURE__ */ new Date()).getFullYear();
861
- const month = chineseMonthMap[monthStr];
862
- const day = chineseDayMap[dayStr];
863
- return new Date(year, month - 1, day);
864
- }
865
- throw new Error("不支持的日期格式");
866
- }, "parseDate");
867
- let queryStartTime;
868
- let queryEndTime;
869
- try {
870
- if (startTime && endTime) {
871
- queryStartTime = formatDate(parseDate(startTime));
872
- queryEndTime = formatDate(parseDate(endTime));
873
- } else if (startTime) {
874
- const endDate = parseDate(startTime);
875
- const startDate = new Date(endDate);
876
- startDate.setDate(startDate.getDate() - 1);
877
- queryStartTime = formatDate(startDate);
878
- queryEndTime = formatDate(endDate);
879
- } else {
880
- const today = /* @__PURE__ */ new Date();
881
- const yesterday = new Date(today);
882
- yesterday.setDate(yesterday.getDate() - 1);
883
- queryStartTime = formatDate(yesterday);
884
- queryEndTime = formatDate(today);
885
- }
886
- } catch (error) {
887
- return "日期格式错误,支持的格式:\n1. 2025.4.4 或 2025/4/4\n2. 4.7 或 4/7(自动补全当前年份)\n3. 四月五号\n4. 四月五日";
1184
+ const logs = await Promise.race([fetchLogsPromise, timeoutPromise]).catch((error) => {
1185
+ console.error("日志查询超时或出错:", error);
1186
+ session?.send("日志查询耗时较长,结果将稍后发送。如长时间未收到,请重试或缩短查询范围");
1187
+ return fetchLogsPromise.catch(() => []);
1188
+ });
1189
+ const filteredLogs = Array.isArray(logs) ? logs.filter((log) => log.title && log.title.includes("上线分析")) : [];
1190
+ if (!filteredLogs || filteredLogs.length === 0) {
1191
+ return "未找到该MAC地址的上线分析日志";
888
1192
  }
889
- const logs = await queryOrderLog(mac, queryStartTime, queryEndTime);
890
- if (logs.length === 0) {
891
- return `未找到${queryStartTime}到${queryEndTime}的上线分析日志`;
1193
+ const MAX_LOGS_PER_MESSAGE = 5;
1194
+ const totalBatches = Math.ceil(filteredLogs.length / MAX_LOGS_PER_MESSAGE);
1195
+ if (filteredLogs.length > MAX_LOGS_PER_MESSAGE) {
1196
+ await session?.send(formatOutputMessage(`共找到 ${filteredLogs.length} 条上线分析日志,将分${totalBatches}批发送`));
892
1197
  }
893
- const messages = [
894
- "📋 工单日志",
895
- "--------------------------------"
896
- ];
897
- logs.forEach((log) => {
898
- if (log.title.includes("上线分析")) {
1198
+ for (let i = 0; i < totalBatches; i++) {
1199
+ const startIdx = i * MAX_LOGS_PER_MESSAGE;
1200
+ const endIdx = Math.min(startIdx + MAX_LOGS_PER_MESSAGE, filteredLogs.length);
1201
+ const batchLogs = filteredLogs.slice(startIdx, endIdx);
1202
+ const messages = [
1203
+ `📝 上线分析日志 ( ${i + 1}/${totalBatches} 批)`,
1204
+ "--------------------------------"
1205
+ ];
1206
+ batchLogs.forEach((log, index) => {
899
1207
  messages.push(
900
- `时间: ${log.updateDate}`,
901
- `标题: ${log.title}`
1208
+ `📄 日志 #${startIdx + index + 1}`,
1209
+ `标题: ${log.title || "无标题"}`,
1210
+ `描述: ${log.description || "无描述"}`,
1211
+ `创建时间: ${log.createTime || "未知"}`,
1212
+ `更新时间: ${log.updateTime || "未知"}`,
1213
+ "--------------------------------"
902
1214
  );
903
- log.logs.forEach((logGroup) => {
904
- logGroup.forEach((logLine) => {
905
- if (logLine.startsWith("1.") && logLine.includes("Pon端TrunkAll检查结果是:") || logLine.startsWith("2.") && logLine.includes("查询ccname=")) {
906
- messages.push(` ${logLine}`);
907
- }
908
- });
909
- });
1215
+ });
1216
+ if (!messages[messages.length - 1].includes("----")) {
910
1217
  messages.push("--------------------------------");
911
1218
  }
912
- });
913
- if (messages.length === 2) {
914
- return `未找到${queryStartTime}到${queryEndTime}的上线分析日志`;
1219
+ await session?.send(formatOutputMessage(messages.join("\n")));
1220
+ if (i < totalBatches - 1) {
1221
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
1222
+ }
915
1223
  }
916
- return messages.join("\n");
1224
+ return;
917
1225
  } catch (error) {
918
1226
  console.error("查询过程出错:", error);
919
1227
  return "查询失败,请稍后重试";
920
1228
  }
921
1229
  });
922
- ctx.command("用户查询 <account:string>", "查询RADIUS用户信息").action(async (_, account) => {
1230
+ ctx.command("用户查询 <account:string>", "查询RADIUS用户信息").action(async ({ session }, account) => {
923
1231
  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
- }
1232
+ return new Promise((resolve) => {
1233
+ addToMessageQueue(session, async () => {
1234
+ try {
1235
+ const radiusUserInfo = await queryRadiusUser(account);
1236
+ if (radiusUserInfo.code !== "000000" || !radiusUserInfo.data) {
1237
+ return `查询失败: ${radiusUserInfo.message || "未知错误"}`;
1238
+ }
1239
+ const { user, orders } = radiusUserInfo.data;
1240
+ const messages = [
1241
+ "🔐 RADIUS用户信息",
1242
+ "--------------------------------",
1243
+ `账号: ${user.login_name}`,
1244
+ // `密码: ${user.password}`,
1245
+ `状态: ${translateUserStatus(user.user_status)} ${user.user_status === "active" ? "✅" : user.user_status === "suspend" ? "⚠️" : "❌"}`,
1246
+ `漫游状态: ${user.roam_status === "0" ? "允许漫游" : "禁止漫游"}`,
1247
+ `分公司标识: ${user.org_code}`,
1248
+ `BOSS分公司标识: ${user.boss_org_code}`,
1249
+ `用户VLAN: ${user.user_vlan}`,
1250
+ "",
1251
+ "🛒 订购信息",
1252
+ "--------------------------------"
1253
+ ];
1254
+ if (orders && orders.length > 0) {
1255
+ orders.forEach((order, index) => {
1256
+ messages.push(
1257
+ `订购 #${index + 1}:`,
1258
+ ` 订购状态: ${translateOrderStatus(order.order_status)}`,
1259
+ ` 服务名称: ${order.service_name}`,
1260
+ ` 生效时间: ${formatRadiusTime(order.valid_date)}`,
1261
+ ` 失效时间: ${formatRadiusTime(order.expire_date)}`
1262
+ );
1263
+ if (index < orders.length - 1) {
1264
+ messages.push("");
1265
+ }
1266
+ });
1267
+ } else {
1268
+ messages.push("无订购信息");
1269
+ }
1270
+ messages.push("--------------------------------");
1271
+ return messages.join("\n");
1272
+ } catch (error) {
1273
+ console.error("查询过程出错:", error);
1274
+ return error.message || "查询失败,请稍后重试";
1275
+ }
1276
+ });
1277
+ resolve();
1278
+ });
965
1279
  });
966
1280
  }
967
1281
  __name(apply, "apply");