fogact 1.2.5 → 1.2.6
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/bin/web-server.js +481 -22
- package/frontend/admin/admin-panel-v2.js +115 -7
- package/frontend/admin/index.html +3 -1
- package/frontend/user/assets/CardBind-CsCxihhP-fogact-live.js +1 -1
- package/frontend/user/assets/CardBind-CsCxihhP.js +1 -1
- package/lib/commands/test.js +23 -14
- package/lib/services/database.js +58 -0
- package/lib/services/node-service.js +6 -17
- package/package.json +1 -1
package/lib/services/database.js
CHANGED
|
@@ -7,6 +7,7 @@ const DATA_DIR = path.join(__dirname, "..", "..", "data");
|
|
|
7
7
|
const USERS_FILE = path.join(DATA_DIR, "users.json");
|
|
8
8
|
const CODES_FILE = path.join(DATA_DIR, "codes.json");
|
|
9
9
|
const USAGE_FILE = path.join(DATA_DIR, "usage.json");
|
|
10
|
+
const CARD_MERGES_FILE = path.join(DATA_DIR, "card-merges.json");
|
|
10
11
|
|
|
11
12
|
// 确保数据目录存在
|
|
12
13
|
function ensureDataDir() {
|
|
@@ -136,6 +137,11 @@ const codeDb = {
|
|
|
136
137
|
name: codeData.name || `Code-${Date.now()}`,
|
|
137
138
|
service: codeData.service || "Claude Code",
|
|
138
139
|
category: codeData.category || "标准运营",
|
|
140
|
+
subServiceType: codeData.subServiceType || codeData.category || "标准运营",
|
|
141
|
+
billingType: codeData.billingType || codeData.quota?.billingType || codeData.quota?.type || "quota",
|
|
142
|
+
cycleType: codeData.cycleType || codeData.quota?.cycleType || codeData.quota?.type || "fixed",
|
|
143
|
+
quotaUnit: codeData.quotaUnit || codeData.quota?.unit || "tokens",
|
|
144
|
+
resetTimezone: codeData.resetTimezone || codeData.quota?.resetTimezone || "Asia/Shanghai",
|
|
139
145
|
status: codeData.status || "未使用",
|
|
140
146
|
enabled: codeData.enabled !== undefined ? codeData.enabled : true,
|
|
141
147
|
usedBy: codeData.usedBy || null,
|
|
@@ -148,9 +154,14 @@ const codeDb = {
|
|
|
148
154
|
total: codeData.quota?.total || 100000,
|
|
149
155
|
used: codeData.quota?.used || 0,
|
|
150
156
|
dailyLimit: codeData.quota?.dailyLimit || 5000,
|
|
157
|
+
dailyQuota: codeData.quota?.dailyQuota || codeData.quota?.dailyLimit || 5000,
|
|
151
158
|
dailyUsed: codeData.quota?.dailyUsed || 0,
|
|
152
159
|
periodDays: codeData.quota?.periodDays || 30,
|
|
153
160
|
periodLimit: codeData.quota?.periodLimit || 50000,
|
|
161
|
+
billingType: codeData.billingType || codeData.quota?.billingType || codeData.quota?.type || "quota",
|
|
162
|
+
cycleType: codeData.cycleType || codeData.quota?.cycleType || codeData.quota?.type || "fixed",
|
|
163
|
+
unit: codeData.quotaUnit || codeData.quota?.unit || "tokens",
|
|
164
|
+
resetTimezone: codeData.resetTimezone || codeData.quota?.resetTimezone || "Asia/Shanghai",
|
|
154
165
|
},
|
|
155
166
|
// 计费设置
|
|
156
167
|
billing: {
|
|
@@ -303,6 +314,52 @@ const usageDb = {
|
|
|
303
314
|
},
|
|
304
315
|
};
|
|
305
316
|
|
|
317
|
+
// 叠卡合并记录数据库操作
|
|
318
|
+
const cardMergeDb = {
|
|
319
|
+
getAll() {
|
|
320
|
+
return readJsonFile(CARD_MERGES_FILE, []);
|
|
321
|
+
},
|
|
322
|
+
|
|
323
|
+
create(mergeData) {
|
|
324
|
+
const items = this.getAll();
|
|
325
|
+
const now = new Date().toISOString();
|
|
326
|
+
const newItem = {
|
|
327
|
+
id: mergeData.id || `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
328
|
+
parentCodeId: mergeData.parentCodeId,
|
|
329
|
+
parentCode: mergeData.parentCode,
|
|
330
|
+
childCodeId: mergeData.childCodeId,
|
|
331
|
+
childCode: mergeData.childCode,
|
|
332
|
+
serviceType: mergeData.serviceType,
|
|
333
|
+
subServiceType: mergeData.subServiceType || "",
|
|
334
|
+
billingType: mergeData.billingType,
|
|
335
|
+
cycleType: mergeData.cycleType,
|
|
336
|
+
quotaUnit: mergeData.quotaUnit,
|
|
337
|
+
timezone: mergeData.timezone || "Asia/Shanghai",
|
|
338
|
+
mergeMode: mergeData.mergeMode,
|
|
339
|
+
parentDailyQuota: Number(mergeData.parentDailyQuota || 0),
|
|
340
|
+
childDailyQuota: Number(mergeData.childDailyQuota || 0),
|
|
341
|
+
childDays: Number(mergeData.childDays || 0),
|
|
342
|
+
childTotalValue: Number(mergeData.childTotalValue || 0),
|
|
343
|
+
addedDays: Number(mergeData.addedDays || 0),
|
|
344
|
+
addedQuota: Number(mergeData.addedQuota || 0),
|
|
345
|
+
oldExpiresAt: mergeData.oldExpiresAt || null,
|
|
346
|
+
newExpiresAt: mergeData.newExpiresAt || null,
|
|
347
|
+
createdAt: mergeData.createdAt || now,
|
|
348
|
+
};
|
|
349
|
+
items.push(newItem);
|
|
350
|
+
writeJsonFile(CARD_MERGES_FILE, items);
|
|
351
|
+
return newItem;
|
|
352
|
+
},
|
|
353
|
+
|
|
354
|
+
getByParent(parentCodeId) {
|
|
355
|
+
return this.getAll().filter((item) => item.parentCodeId === parentCodeId);
|
|
356
|
+
},
|
|
357
|
+
|
|
358
|
+
getByChild(childCodeId) {
|
|
359
|
+
return this.getAll().filter((item) => item.childCodeId === childCodeId);
|
|
360
|
+
},
|
|
361
|
+
};
|
|
362
|
+
|
|
306
363
|
// 初始化示例数据
|
|
307
364
|
function initializeSampleData() {
|
|
308
365
|
ensureDataDir();
|
|
@@ -504,5 +561,6 @@ module.exports = {
|
|
|
504
561
|
userDb,
|
|
505
562
|
codeDb,
|
|
506
563
|
usageDb,
|
|
564
|
+
cardMergeDb,
|
|
507
565
|
initializeSampleData,
|
|
508
566
|
};
|
|
@@ -100,19 +100,13 @@ function padCell(value, width) {
|
|
|
100
100
|
function formatNodeLine(result, best) {
|
|
101
101
|
const mark = result.available ? "✓" : "✗";
|
|
102
102
|
const name = padCell(result.name || result.url || "FogAct", 12);
|
|
103
|
-
const service = padCell(result.serviceLabel || result.region || "Global", 9);
|
|
104
103
|
|
|
105
104
|
if (!result.available) {
|
|
106
|
-
return ` ${mark} ${name}
|
|
105
|
+
return ` ${mark} ${name} 不可达`;
|
|
107
106
|
}
|
|
108
107
|
|
|
109
|
-
const latency = padCell(`${result.avgLatency}ms`, 8);
|
|
110
|
-
const jitter = padCell(`±${result.latencyStdDev}ms`, 7);
|
|
111
|
-
const stability = padCell(stabilityLabel(result.latencyStdDev), 6);
|
|
112
|
-
const score = padCell(`${getResultScore(result)}分`, 5);
|
|
113
|
-
const level = padCell(latencyLevel(result.avgLatency), 4);
|
|
114
108
|
const bestMark = best && best === result ? " ★ 最优" : "";
|
|
115
|
-
return ` ${mark} ${name} ${
|
|
109
|
+
return ` ${mark} ${name} ${result.avgLatency}ms (±${result.latencyStdDev}ms) ${stabilityLabel(result.latencyStdDev)} ${getResultScore(result)}分${bestMark}`;
|
|
116
110
|
}
|
|
117
111
|
|
|
118
112
|
function formatNodeResults(results, options = {}) {
|
|
@@ -123,21 +117,16 @@ function formatNodeResults(results, options = {}) {
|
|
|
123
117
|
const title = options.title || "节点测试结果";
|
|
124
118
|
|
|
125
119
|
lines.push(` ${title}`);
|
|
126
|
-
lines.push("
|
|
127
|
-
lines.push("
|
|
128
|
-
lines.push(" ────────────────────────────────────────────────────────────");
|
|
120
|
+
lines.push(" ───────────────────────────────────────────────────");
|
|
121
|
+
lines.push("");
|
|
129
122
|
|
|
130
123
|
for (const result of sorted) {
|
|
131
124
|
lines.push(formatNodeLine(result, best));
|
|
132
125
|
}
|
|
133
126
|
|
|
134
|
-
lines.push("
|
|
127
|
+
lines.push("");
|
|
128
|
+
lines.push(" ───────────────────────────────────────────────────");
|
|
135
129
|
lines.push(` 测试完成,共 ${results.length} 个节点,${availableCount} 个可用`);
|
|
136
|
-
if (best) {
|
|
137
|
-
lines.push(` 推荐节点: ${best.name || best.url} · ${best.avgLatency}ms · ${getResultScore(best)}分`);
|
|
138
|
-
} else {
|
|
139
|
-
lines.push(" 暂无可用节点,请稍后重试或联系管理员");
|
|
140
|
-
}
|
|
141
130
|
return lines.join("\n");
|
|
142
131
|
}
|
|
143
132
|
|