fogact 1.1.7 → 1.1.9
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/README.md +5 -5
- package/README.zh-CN.md +5 -5
- package/bin/web-server.js +83 -19
- package/frontend/activate.html +1 -1
- package/frontend/admin/admin-panel-v2.js +2 -2
- package/frontend/admin/index.html +1 -1
- package/frontend/assets/market-ui.css +0 -257
- package/frontend/color-test.html +1 -1
- package/frontend/index.html +1 -32
- package/frontend/user/assets/DashboardLayout-DDkxHYFj.js +1 -1
- package/frontend/user/assets/Welcome-Dtfp6oER.js +1 -1
- package/frontend/user/assets/announcement-35mOnjRL.js +1 -1
- package/frontend/user/assets/index-Da98HOxL.js +2 -2
- package/frontend/user/index.html +1 -1
- package/install.sh +25 -25
- package/lib/commands/activate.js +2 -2
- package/lib/commands/test.js +1 -1
- package/lib/config/codex.js +28 -22
- package/lib/config/upstream.js +1 -1
- package/lib/index.js +2 -2
- package/lib/platforms/editor-codex.js +2 -2
- package/lib/services/activation-orchestrator.js +73 -55
- package/lib/services/backup-service.js +1 -2
- package/lib/services/{cliproxy-api.js → fogact-api.js} +7 -5
- package/lib/services/newapi.js +2 -1
- package/lib/services/node-service.js +1 -1
- package/package.json +2 -9
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[简体中文](./README.zh-CN.md) | English
|
|
4
4
|
|
|
5
|
-
FogAct is a simple activation helper for Claude Code and Codex. It is designed to be used like `npx
|
|
5
|
+
FogAct is a simple activation helper for Claude Code and Codex. It is designed to be used like `npx fogact`: run one command, choose from the menu, paste your activation code, and let FogAct auto-detect the Codex / Claude entitlement before writing local config.
|
|
6
6
|
|
|
7
7
|
## Start
|
|
8
8
|
|
|
@@ -27,7 +27,7 @@ That is the user-facing command. Running it opens the interactive menu:
|
|
|
27
27
|
|
|
28
28
|
Do not run `npm fogact`; npm treats that as an npm subcommand. Use `npx fogact`.
|
|
29
29
|
|
|
30
|
-
FogAct checks npm for the latest version before opening the menu. If an older installed version is detected, it updates first and then continues. Set `FOGACT_SKIP_UPDATE=1` to skip
|
|
30
|
+
FogAct checks npm for the latest version before opening the menu. If an older installed version is detected, it updates first and then continues. Activation codes use the public panel `https://cliproxy.fogidc.com` by default; set `FOGACT_API_BASE` to use another backend. Set `FOGACT_SKIP_UPDATE=1` to skip the update check.
|
|
31
31
|
|
|
32
32
|
## Clean VPS
|
|
33
33
|
|
|
@@ -49,8 +49,8 @@ Minimum bootstrap requirement: the machine needs `curl` or `wget`. The installer
|
|
|
49
49
|
|
|
50
50
|
1. Run `npx fogact`.
|
|
51
51
|
2. Choose `1. Activate service`.
|
|
52
|
-
3.
|
|
53
|
-
4.
|
|
52
|
+
3. Enter the activation / redeem code.
|
|
53
|
+
4. FogAct auto-detects the Codex / Claude entitlement and shows only supported targets.
|
|
54
54
|
5. Confirm the plan and restart the target tool.
|
|
55
55
|
|
|
56
56
|
FogAct backs up existing configuration before writing new files.
|
|
@@ -73,7 +73,7 @@ Most users only need `npx fogact`. Advanced operators can still use:
|
|
|
73
73
|
fogact web
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
The Web UI defaults to `http://localhost:34020/`. You can set `PORT`, `ADMIN_PASSWORD`, `NEWAPI_BASE_URL`, `NEWAPI_API_KEY`, `
|
|
76
|
+
The Web UI defaults to `http://localhost:34020/`. You can set `PORT`, `ADMIN_PASSWORD`, `NEWAPI_BASE_URL`, `NEWAPI_API_KEY`, `FOGACT_API_BASE`, or `FOGACT_UPSTREAM_CONFIG` when needed.
|
|
77
77
|
|
|
78
78
|
## Repository
|
|
79
79
|
|
package/README.zh-CN.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# FogAct
|
|
2
2
|
|
|
3
|
-
FogAct 是一个简单的 Claude Code / Codex 激活工具。它的使用方式要和 `npx
|
|
3
|
+
FogAct 是一个简单的 Claude Code / Codex 激活工具。它的使用方式要和 `npx fogact` 一样:用户只运行一个命令,进入菜单,输入激活码,FogAct 自动识别 Codex / Claude 能力并写入本地配置。
|
|
4
4
|
|
|
5
5
|
[English](./README.md) | 简体中文
|
|
6
6
|
|
|
@@ -27,7 +27,7 @@ npx fogact
|
|
|
27
27
|
|
|
28
28
|
不要运行 `npm fogact`;npm 会把它当成 npm 子命令。正确方式是 `npx fogact`。
|
|
29
29
|
|
|
30
|
-
FogAct 启动时会自动检查 npm
|
|
30
|
+
FogAct 启动时会自动检查 npm 最新版本;检测到旧版本会先更新,再进入菜单。激活码默认连接公网面板 `https://cliproxy.fogidc.com`,需要切换测试后端时可设置 `FOGACT_API_BASE`。需要跳过更新检查时可设置 `FOGACT_SKIP_UPDATE=1`。
|
|
31
31
|
|
|
32
32
|
## 干净 VPS
|
|
33
33
|
|
|
@@ -49,8 +49,8 @@ fogact
|
|
|
49
49
|
|
|
50
50
|
1. 运行 `npx fogact`。
|
|
51
51
|
2. 选择 `1. 激活服务`。
|
|
52
|
-
3.
|
|
53
|
-
4.
|
|
52
|
+
3. 输入激活码 / 兑换码。
|
|
53
|
+
4. FogAct 自动识别 Codex / Claude 能力,并只展示可激活的平台。
|
|
54
54
|
5. 确认激活计划,然后重启对应工具。
|
|
55
55
|
|
|
56
56
|
FogAct 写入新配置前会自动备份旧配置。
|
|
@@ -73,7 +73,7 @@ FogAct 写入新配置前会自动备份旧配置。
|
|
|
73
73
|
fogact web
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
Web UI 默认地址是 `http://localhost:34020/`。需要时可以设置 `PORT`、`ADMIN_PASSWORD`、`NEWAPI_BASE_URL`、`NEWAPI_API_KEY`、`
|
|
76
|
+
Web UI 默认地址是 `http://localhost:34020/`。需要时可以设置 `PORT`、`ADMIN_PASSWORD`、`NEWAPI_BASE_URL`、`NEWAPI_API_KEY`、`FOGACT_API_BASE` 或 `FOGACT_UPSTREAM_CONFIG`。
|
|
77
77
|
|
|
78
78
|
## 项目链接
|
|
79
79
|
|
package/bin/web-server.js
CHANGED
|
@@ -6,7 +6,7 @@ const fs = require("fs");
|
|
|
6
6
|
const path = require("path");
|
|
7
7
|
const os = require("os");
|
|
8
8
|
const { userDb, codeDb, initializeSampleData } = require("../lib/services/database");
|
|
9
|
-
const { DEFAULT_CONFIG_PATH, loadUpstreamConfig } = require("../lib/config/upstream");
|
|
9
|
+
const { DEFAULT_CONFIG_PATH, getServiceBaseUrl, loadUpstreamConfig } = require("../lib/config/upstream");
|
|
10
10
|
const { readJsonFile, writeJsonFile } = require("../lib/utils/json-file");
|
|
11
11
|
const { maskKey, verifyNewApiKey } = require("../lib/services/newapi");
|
|
12
12
|
|
|
@@ -213,12 +213,71 @@ function serializeCode(code) {
|
|
|
213
213
|
};
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
+
function getActivationPlatforms(serviceKey) {
|
|
217
|
+
if (serviceKey === "codex") return ["codex-cli"];
|
|
218
|
+
if (serviceKey === "claude") return ["claude-code"];
|
|
219
|
+
return [];
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function buildActivationData(serializedCode) {
|
|
223
|
+
const serviceKey = serializedCode.serviceKey;
|
|
224
|
+
const upstream = loadUpstreamConfig({ configPath: getUpstreamConfigPath() });
|
|
225
|
+
const serviceConfig = serializedCode.serviceConfig || {};
|
|
226
|
+
const baseUrl = trimTrailingSlash(
|
|
227
|
+
serializedCode.baseUrl ||
|
|
228
|
+
serializedCode.baseURL ||
|
|
229
|
+
serializedCode.url ||
|
|
230
|
+
serviceConfig.baseUrl ||
|
|
231
|
+
serviceConfig.baseURL ||
|
|
232
|
+
serviceConfig.url ||
|
|
233
|
+
getServiceBaseUrl(upstream, serviceKey) ||
|
|
234
|
+
upstream.baseUrl
|
|
235
|
+
);
|
|
236
|
+
const apiKey = String(
|
|
237
|
+
serializedCode.apiKey ||
|
|
238
|
+
serializedCode.key ||
|
|
239
|
+
serializedCode.token ||
|
|
240
|
+
serviceConfig.apiKey ||
|
|
241
|
+
serviceConfig.key ||
|
|
242
|
+
serviceConfig.token ||
|
|
243
|
+
upstream.apiKey ||
|
|
244
|
+
""
|
|
245
|
+
).trim();
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
code: serializedCode.code,
|
|
249
|
+
service: serializedCode.service,
|
|
250
|
+
serviceKey,
|
|
251
|
+
services: [serviceKey],
|
|
252
|
+
platforms: getActivationPlatforms(serviceKey),
|
|
253
|
+
allowedModels: serializedCode.allowedModels,
|
|
254
|
+
quota: serializedCode.quota,
|
|
255
|
+
expiresAt: serializedCode.expiresAt,
|
|
256
|
+
baseUrl,
|
|
257
|
+
apiKey,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function ensureActivationDataReady(res, activationData) {
|
|
262
|
+
if (activationData.baseUrl && activationData.apiKey) {
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
267
|
+
res.end(JSON.stringify({
|
|
268
|
+
success: false,
|
|
269
|
+
valid: false,
|
|
270
|
+
message: '上游服务未配置完整,请先在管理面板设置 NewAPI Base URL 和 API Key'
|
|
271
|
+
}));
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
|
|
216
275
|
function trimTrailingSlash(value) {
|
|
217
276
|
return String(value || "").trim().replace(/\/+$/, "");
|
|
218
277
|
}
|
|
219
278
|
|
|
220
279
|
function getUpstreamConfigPath() {
|
|
221
|
-
return process.env.
|
|
280
|
+
return process.env.FOGACT_UPSTREAM_CONFIG || DEFAULT_CONFIG_PATH;
|
|
222
281
|
}
|
|
223
282
|
|
|
224
283
|
function readRawUpstreamConfig() {
|
|
@@ -865,6 +924,11 @@ const server = http.createServer((req, res) => {
|
|
|
865
924
|
return;
|
|
866
925
|
}
|
|
867
926
|
|
|
927
|
+
const activationData = buildActivationData(serializedCode);
|
|
928
|
+
if (!ensureActivationDataReady(res, activationData)) {
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
|
|
868
932
|
// 更新激活码状态
|
|
869
933
|
const updatedCode = codeDb.update(code.id, {
|
|
870
934
|
status: 'used',
|
|
@@ -886,12 +950,7 @@ const server = http.createServer((req, res) => {
|
|
|
886
950
|
success: true,
|
|
887
951
|
message: '激活成功',
|
|
888
952
|
data: {
|
|
889
|
-
|
|
890
|
-
service: serializeCode(updatedCode).service,
|
|
891
|
-
serviceKey: serializeCode(updatedCode).serviceKey,
|
|
892
|
-
allowedModels: serializeCode(updatedCode).allowedModels,
|
|
893
|
-
quota: updatedCode.quota,
|
|
894
|
-
expiresAt: updatedCode.expiresAt,
|
|
953
|
+
...buildActivationData(serializeCode(updatedCode)),
|
|
895
954
|
activatedAt: updatedCode.lastUsedAt
|
|
896
955
|
}
|
|
897
956
|
}));
|
|
@@ -1095,20 +1154,17 @@ const server = http.createServer((req, res) => {
|
|
|
1095
1154
|
return;
|
|
1096
1155
|
}
|
|
1097
1156
|
|
|
1157
|
+
const activationData = buildActivationData(serializedCode);
|
|
1158
|
+
if (!ensureActivationDataReady(res, activationData)) {
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1098
1162
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1099
1163
|
res.end(JSON.stringify({
|
|
1100
1164
|
success: true,
|
|
1101
1165
|
valid: true,
|
|
1102
1166
|
message: '验证成功',
|
|
1103
|
-
data:
|
|
1104
|
-
code: serializedCode.code,
|
|
1105
|
-
service: serializedCode.service,
|
|
1106
|
-
services: [serializedCode.serviceKey],
|
|
1107
|
-
platforms: serializedCode.serviceKey === 'codex' ? ['codex-cli'] : ['claude-code'],
|
|
1108
|
-
allowedModels: serializedCode.allowedModels,
|
|
1109
|
-
quota: serializedCode.quota,
|
|
1110
|
-
expiresAt: serializedCode.expiresAt
|
|
1111
|
-
}
|
|
1167
|
+
data: activationData
|
|
1112
1168
|
}));
|
|
1113
1169
|
return;
|
|
1114
1170
|
}
|
|
@@ -1277,10 +1333,18 @@ const server = http.createServer((req, res) => {
|
|
|
1277
1333
|
return;
|
|
1278
1334
|
}
|
|
1279
1335
|
|
|
1280
|
-
// Proxy requests to
|
|
1336
|
+
// Proxy requests to configured upstream API for user frontend
|
|
1281
1337
|
if (urlPath.startsWith("/proxy/")) {
|
|
1282
1338
|
const targetPath = urlPath.replace("/proxy", "");
|
|
1283
|
-
const
|
|
1339
|
+
const proxyBaseUrl = trimTrailingSlash(process.env.FOGACT_PROXY_TARGET || readRawUpstreamConfig().baseUrl || "");
|
|
1340
|
+
|
|
1341
|
+
if (!proxyBaseUrl) {
|
|
1342
|
+
res.writeHead(502, { "Content-Type": "application/json" });
|
|
1343
|
+
res.end(JSON.stringify({ success: false, message: "Proxy target is not configured" }));
|
|
1344
|
+
return;
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
const targetUrl = `${proxyBaseUrl}${targetPath}`;
|
|
1284
1348
|
|
|
1285
1349
|
const options = {
|
|
1286
1350
|
method: req.method,
|
package/frontend/activate.html
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<meta name="description" content="输入 FogAct 激活码,完成服务绑定并查看额度与有效期。" />
|
|
8
8
|
<script>
|
|
9
9
|
;(function () {
|
|
10
|
-
var theme = localStorage.getItem('fogact_theme') || localStorage.getItem('admin_theme') ||
|
|
10
|
+
var theme = localStorage.getItem('fogact_theme') || localStorage.getItem('admin_theme') || 'system';
|
|
11
11
|
var prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
12
12
|
var isDark = theme === 'dark' || (theme === 'system' && prefersDark);
|
|
13
13
|
document.documentElement.classList.toggle('dark', isDark);
|
|
@@ -270,7 +270,7 @@ const DEFAULT_SETTINGS = {
|
|
|
270
270
|
notifyLowQuota: true
|
|
271
271
|
},
|
|
272
272
|
app: {
|
|
273
|
-
appName: '
|
|
273
|
+
appName: 'FogAct Client',
|
|
274
274
|
appDownloadUrl: '',
|
|
275
275
|
iosUrl: '',
|
|
276
276
|
androidUrl: '',
|
|
@@ -1277,7 +1277,7 @@ const LogsManagement = {
|
|
|
1277
1277
|
};
|
|
1278
1278
|
|
|
1279
1279
|
const SettingsManagement = {
|
|
1280
|
-
storageKey: '
|
|
1280
|
+
storageKey: 'fogact_admin_settings_v1',
|
|
1281
1281
|
|
|
1282
1282
|
sections: [
|
|
1283
1283
|
{
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
<script>
|
|
9
9
|
;(function () {
|
|
10
|
-
var theme = localStorage.getItem('fogact_theme') || localStorage.getItem('admin_theme') ||
|
|
10
|
+
var theme = localStorage.getItem('fogact_theme') || localStorage.getItem('admin_theme') || 'system';
|
|
11
11
|
var prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
12
12
|
var isDark = theme === 'dark' || (theme === 'system' && prefersDark);
|
|
13
13
|
document.documentElement.classList.toggle('dark', isDark);
|
|
@@ -731,35 +731,6 @@ body.market-dark .market-auth-card::before {
|
|
|
731
731
|
color: var(--market-primary);
|
|
732
732
|
}
|
|
733
733
|
|
|
734
|
-
.market-quick-links {
|
|
735
|
-
display: grid;
|
|
736
|
-
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
737
|
-
gap: 8px;
|
|
738
|
-
margin-top: 16px;
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
.market-quick-links a {
|
|
742
|
-
display: inline-flex;
|
|
743
|
-
align-items: center;
|
|
744
|
-
justify-content: center;
|
|
745
|
-
min-height: 36px;
|
|
746
|
-
border: 1px solid var(--market-line);
|
|
747
|
-
border-radius: 14px;
|
|
748
|
-
color: var(--market-ink);
|
|
749
|
-
background: var(--market-panel-muted);
|
|
750
|
-
text-decoration: none;
|
|
751
|
-
font-size: 13px;
|
|
752
|
-
font-weight: 800;
|
|
753
|
-
transition: transform 0.18s ease, border-color 0.18s ease, background 0.18s ease, color 0.18s ease;
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
.market-quick-links a:hover {
|
|
757
|
-
transform: translateY(-1px);
|
|
758
|
-
border-color: color-mix(in srgb, var(--market-primary) 42%, var(--market-line));
|
|
759
|
-
color: var(--market-primary);
|
|
760
|
-
background: color-mix(in srgb, var(--market-primary) 10%, var(--market-panel-muted));
|
|
761
|
-
}
|
|
762
|
-
|
|
763
734
|
.market-result-list {
|
|
764
735
|
display: grid;
|
|
765
736
|
gap: 10px;
|
|
@@ -1212,190 +1183,6 @@ body.market-user {
|
|
|
1212
1183
|
transform: translateY(-1px);
|
|
1213
1184
|
}
|
|
1214
1185
|
|
|
1215
|
-
/* Distinct motion layer */
|
|
1216
|
-
.market-orbit-stage {
|
|
1217
|
-
position: absolute;
|
|
1218
|
-
inset: auto 28px 28px auto;
|
|
1219
|
-
width: min(48vw, 440px);
|
|
1220
|
-
height: min(48vw, 440px);
|
|
1221
|
-
pointer-events: none;
|
|
1222
|
-
opacity: 0.98;
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
|
-
.market-orbit-stage::before,
|
|
1226
|
-
.market-orbit-stage::after {
|
|
1227
|
-
content: "";
|
|
1228
|
-
position: absolute;
|
|
1229
|
-
inset: 12%;
|
|
1230
|
-
border: 1px solid color-mix(in srgb, var(--market-ink) 12%, transparent);
|
|
1231
|
-
border-radius: 999px;
|
|
1232
|
-
background:
|
|
1233
|
-
radial-gradient(circle at center, color-mix(in srgb, var(--market-primary) 7%, transparent), transparent 62%);
|
|
1234
|
-
animation: orbitSpin 22s linear infinite;
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
.market-orbit-stage::after {
|
|
1238
|
-
inset: 25%;
|
|
1239
|
-
border-style: dashed;
|
|
1240
|
-
animation-duration: 16s;
|
|
1241
|
-
animation-direction: reverse;
|
|
1242
|
-
opacity: 0.72;
|
|
1243
|
-
}
|
|
1244
|
-
|
|
1245
|
-
.market-orbit-core {
|
|
1246
|
-
position: absolute;
|
|
1247
|
-
left: 50%;
|
|
1248
|
-
top: 50%;
|
|
1249
|
-
z-index: 2;
|
|
1250
|
-
display: grid;
|
|
1251
|
-
place-items: center;
|
|
1252
|
-
width: 132px;
|
|
1253
|
-
height: 132px;
|
|
1254
|
-
padding: 18px;
|
|
1255
|
-
border: 1px solid color-mix(in srgb, var(--market-primary) 30%, var(--market-line));
|
|
1256
|
-
border-radius: 36px;
|
|
1257
|
-
color: var(--market-ink);
|
|
1258
|
-
background:
|
|
1259
|
-
linear-gradient(145deg, color-mix(in srgb, var(--market-panel-strong) 92%, transparent), var(--market-panel-muted)),
|
|
1260
|
-
radial-gradient(circle at 30% 20%, color-mix(in srgb, var(--market-primary) 24%, transparent), transparent 58%);
|
|
1261
|
-
box-shadow: 0 24px 60px color-mix(in srgb, var(--market-primary) 20%, transparent);
|
|
1262
|
-
transform: translate(-50%, -50%) rotate(-2deg);
|
|
1263
|
-
}
|
|
1264
|
-
|
|
1265
|
-
.market-orbit-core .material-symbols-outlined {
|
|
1266
|
-
display: inline-flex;
|
|
1267
|
-
align-items: center;
|
|
1268
|
-
justify-content: center;
|
|
1269
|
-
width: 42px;
|
|
1270
|
-
height: 42px;
|
|
1271
|
-
border-radius: 16px;
|
|
1272
|
-
color: #fff;
|
|
1273
|
-
background: linear-gradient(135deg, var(--market-primary), var(--market-primary-2));
|
|
1274
|
-
box-shadow: 0 14px 32px color-mix(in srgb, var(--market-primary) 28%, transparent);
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
.market-orbit-core strong {
|
|
1278
|
-
margin-top: 8px;
|
|
1279
|
-
font-family: var(--market-headline);
|
|
1280
|
-
font-size: 18px;
|
|
1281
|
-
letter-spacing: -0.04em;
|
|
1282
|
-
}
|
|
1283
|
-
|
|
1284
|
-
.market-orbit-core small {
|
|
1285
|
-
color: var(--market-muted);
|
|
1286
|
-
font-size: 12px;
|
|
1287
|
-
font-weight: 800;
|
|
1288
|
-
}
|
|
1289
|
-
|
|
1290
|
-
.market-orbit-node {
|
|
1291
|
-
position: absolute;
|
|
1292
|
-
z-index: 3;
|
|
1293
|
-
display: inline-flex;
|
|
1294
|
-
align-items: center;
|
|
1295
|
-
gap: 8px;
|
|
1296
|
-
min-width: 118px;
|
|
1297
|
-
min-height: 54px;
|
|
1298
|
-
padding: 10px 12px;
|
|
1299
|
-
border: 1px solid color-mix(in srgb, var(--node-a, var(--market-primary)) 30%, var(--market-line));
|
|
1300
|
-
border-radius: 20px;
|
|
1301
|
-
color: var(--market-ink);
|
|
1302
|
-
background:
|
|
1303
|
-
linear-gradient(145deg, color-mix(in srgb, var(--market-panel-strong) 94%, transparent), var(--market-panel-muted)),
|
|
1304
|
-
radial-gradient(circle at 15% 0%, color-mix(in srgb, var(--node-a, var(--market-primary)) 24%, transparent), transparent 64%);
|
|
1305
|
-
box-shadow: 0 18px 44px color-mix(in srgb, var(--node-a, var(--market-primary)) 18%, transparent);
|
|
1306
|
-
transform: translate3d(0, 0, 0) rotate(var(--tilt, 0deg));
|
|
1307
|
-
animation: nodeFloat var(--speed, 6s) ease-in-out infinite;
|
|
1308
|
-
}
|
|
1309
|
-
|
|
1310
|
-
.market-orbit-node .material-symbols-outlined {
|
|
1311
|
-
display: inline-flex;
|
|
1312
|
-
align-items: center;
|
|
1313
|
-
justify-content: center;
|
|
1314
|
-
flex: 0 0 auto;
|
|
1315
|
-
width: 32px;
|
|
1316
|
-
height: 32px;
|
|
1317
|
-
border-radius: 13px;
|
|
1318
|
-
color: #fff;
|
|
1319
|
-
background: linear-gradient(135deg, var(--node-a, var(--market-primary)), var(--node-b, var(--market-primary-2)));
|
|
1320
|
-
font-size: 18px;
|
|
1321
|
-
}
|
|
1322
|
-
|
|
1323
|
-
.market-orbit-node span:last-child {
|
|
1324
|
-
color: var(--market-ink);
|
|
1325
|
-
font-size: 13px;
|
|
1326
|
-
font-weight: 900;
|
|
1327
|
-
white-space: nowrap;
|
|
1328
|
-
}
|
|
1329
|
-
|
|
1330
|
-
.market-orbit-node-cli {
|
|
1331
|
-
--node-a: #6d5dfc;
|
|
1332
|
-
--node-b: #b86bff;
|
|
1333
|
-
--tilt: -8deg;
|
|
1334
|
-
--speed: 6.5s;
|
|
1335
|
-
left: 1%;
|
|
1336
|
-
top: 18%;
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
.market-orbit-node-cdk {
|
|
1340
|
-
--node-a: #ff7a59;
|
|
1341
|
-
--node-b: #ffd166;
|
|
1342
|
-
--tilt: 7deg;
|
|
1343
|
-
--speed: 7.5s;
|
|
1344
|
-
right: 2%;
|
|
1345
|
-
top: 9%;
|
|
1346
|
-
animation-delay: -1.8s;
|
|
1347
|
-
}
|
|
1348
|
-
|
|
1349
|
-
.market-orbit-node-quota {
|
|
1350
|
-
--node-a: #17c3b2;
|
|
1351
|
-
--node-b: #5eead4;
|
|
1352
|
-
--tilt: 8deg;
|
|
1353
|
-
--speed: 8s;
|
|
1354
|
-
right: 0;
|
|
1355
|
-
bottom: 20%;
|
|
1356
|
-
animation-delay: -3s;
|
|
1357
|
-
}
|
|
1358
|
-
|
|
1359
|
-
.market-orbit-node-sync {
|
|
1360
|
-
--node-a: #111827;
|
|
1361
|
-
--node-b: #6d5dfc;
|
|
1362
|
-
--tilt: -7deg;
|
|
1363
|
-
--speed: 7s;
|
|
1364
|
-
left: 7%;
|
|
1365
|
-
bottom: 8%;
|
|
1366
|
-
animation-delay: -4.3s;
|
|
1367
|
-
}
|
|
1368
|
-
|
|
1369
|
-
.market-signal-line {
|
|
1370
|
-
position: absolute;
|
|
1371
|
-
left: 8%;
|
|
1372
|
-
right: 8%;
|
|
1373
|
-
top: 50%;
|
|
1374
|
-
height: 1px;
|
|
1375
|
-
background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--market-primary) 55%, transparent), transparent);
|
|
1376
|
-
transform: rotate(-18deg);
|
|
1377
|
-
opacity: 0.72;
|
|
1378
|
-
overflow: hidden;
|
|
1379
|
-
}
|
|
1380
|
-
|
|
1381
|
-
.market-signal-line-alt {
|
|
1382
|
-
transform: rotate(36deg);
|
|
1383
|
-
opacity: 0.42;
|
|
1384
|
-
}
|
|
1385
|
-
|
|
1386
|
-
.market-signal-line::after {
|
|
1387
|
-
content: "";
|
|
1388
|
-
position: absolute;
|
|
1389
|
-
inset: 0 auto 0 0;
|
|
1390
|
-
width: 38%;
|
|
1391
|
-
background: linear-gradient(90deg, transparent, #fff, transparent);
|
|
1392
|
-
animation: signalSweep 2.6s cubic-bezier(0.16, 1, 0.3, 1) infinite;
|
|
1393
|
-
}
|
|
1394
|
-
|
|
1395
|
-
.market-signal-line-alt::after {
|
|
1396
|
-
animation-delay: -1.1s;
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
1186
|
.market-card-lab {
|
|
1400
1187
|
min-height: 318px;
|
|
1401
1188
|
padding: 0;
|
|
@@ -1837,16 +1624,6 @@ body.is-pointer-active .market-mouse-light {
|
|
|
1837
1624
|
to { transform: rotate(360deg); }
|
|
1838
1625
|
}
|
|
1839
1626
|
|
|
1840
|
-
@keyframes nodeFloat {
|
|
1841
|
-
0%, 100% { transform: translate3d(0, 0, 0) rotate(var(--tilt)); }
|
|
1842
|
-
50% { transform: translate3d(0, -3px, 0) rotate(var(--tilt)); }
|
|
1843
|
-
}
|
|
1844
|
-
|
|
1845
|
-
@keyframes signalSweep {
|
|
1846
|
-
0% { transform: translateX(-120%); }
|
|
1847
|
-
100% { transform: translateX(360%); }
|
|
1848
|
-
}
|
|
1849
|
-
|
|
1850
1627
|
@keyframes cardShine {
|
|
1851
1628
|
from { transform: translateX(-120%); }
|
|
1852
1629
|
to { transform: translateX(120%); }
|
|
@@ -1909,14 +1686,6 @@ body.is-pointer-active .market-mouse-light {
|
|
|
1909
1686
|
}
|
|
1910
1687
|
|
|
1911
1688
|
@media (max-width: 980px) {
|
|
1912
|
-
.market-orbit-stage {
|
|
1913
|
-
position: relative;
|
|
1914
|
-
inset: auto;
|
|
1915
|
-
width: min(100%, 420px);
|
|
1916
|
-
height: 300px;
|
|
1917
|
-
margin: 28px auto 0;
|
|
1918
|
-
}
|
|
1919
|
-
|
|
1920
1689
|
.market-hero,
|
|
1921
1690
|
.market-activation {
|
|
1922
1691
|
grid-template-columns: 1fr;
|
|
@@ -1984,32 +1753,6 @@ body.is-pointer-active .market-mouse-light {
|
|
|
1984
1753
|
min-height: 150px;
|
|
1985
1754
|
}
|
|
1986
1755
|
|
|
1987
|
-
.market-orbit-stage {
|
|
1988
|
-
height: 240px;
|
|
1989
|
-
}
|
|
1990
|
-
|
|
1991
|
-
.market-orbit-core {
|
|
1992
|
-
width: 104px;
|
|
1993
|
-
height: 104px;
|
|
1994
|
-
border-radius: 28px;
|
|
1995
|
-
}
|
|
1996
|
-
|
|
1997
|
-
.market-orbit-core strong {
|
|
1998
|
-
font-size: 16px;
|
|
1999
|
-
}
|
|
2000
|
-
|
|
2001
|
-
.market-orbit-node {
|
|
2002
|
-
min-width: 58px;
|
|
2003
|
-
min-height: 58px;
|
|
2004
|
-
padding: 8px;
|
|
2005
|
-
border-radius: 20px;
|
|
2006
|
-
justify-content: center;
|
|
2007
|
-
}
|
|
2008
|
-
|
|
2009
|
-
.market-orbit-node span:last-child {
|
|
2010
|
-
display: none;
|
|
2011
|
-
}
|
|
2012
|
-
|
|
2013
1756
|
.market-mouse-light {
|
|
2014
1757
|
display: none;
|
|
2015
1758
|
}
|
package/frontend/color-test.html
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>配色方案测试 |
|
|
6
|
+
<title>配色方案测试 | FogAct</title>
|
|
7
7
|
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@600;700;800&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
|
|
8
8
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
9
9
|
<script>
|
package/frontend/index.html
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<meta name="description" content="FogAct 提供用户中心、激活码管理、配额查看和多平台 CLI 接入入口。" />
|
|
8
8
|
<script>
|
|
9
9
|
;(function () {
|
|
10
|
-
var theme = localStorage.getItem('fogact_theme') || localStorage.getItem('admin_theme') ||
|
|
10
|
+
var theme = localStorage.getItem('fogact_theme') || localStorage.getItem('admin_theme') || 'system';
|
|
11
11
|
var prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
12
12
|
var isDark = theme === 'dark' || (theme === 'system' && prefersDark);
|
|
13
13
|
document.documentElement.classList.toggle('dark', isDark);
|
|
@@ -73,31 +73,6 @@
|
|
|
73
73
|
<span class="market-ambient-item"><span class="material-symbols-outlined">query_stats</span></span>
|
|
74
74
|
</div>
|
|
75
75
|
|
|
76
|
-
<div class="market-orbit-stage" aria-label="FogAct 服务流程拓扑">
|
|
77
|
-
<div class="market-orbit-core">
|
|
78
|
-
<span class="material-symbols-outlined">hub</span>
|
|
79
|
-
<strong>FogAct</strong>
|
|
80
|
-
<small>统一入口</small>
|
|
81
|
-
</div>
|
|
82
|
-
<span class="market-orbit-node market-orbit-node-cli">
|
|
83
|
-
<span class="material-symbols-outlined">terminal</span>
|
|
84
|
-
<span>CLI 接入</span>
|
|
85
|
-
</span>
|
|
86
|
-
<span class="market-orbit-node market-orbit-node-cdk">
|
|
87
|
-
<span class="material-symbols-outlined">vpn_key</span>
|
|
88
|
-
<span>CDK 校验</span>
|
|
89
|
-
</span>
|
|
90
|
-
<span class="market-orbit-node market-orbit-node-quota">
|
|
91
|
-
<span class="material-symbols-outlined">monitoring</span>
|
|
92
|
-
<span>配额监控</span>
|
|
93
|
-
</span>
|
|
94
|
-
<span class="market-orbit-node market-orbit-node-sync">
|
|
95
|
-
<span class="material-symbols-outlined">cloud_sync</span>
|
|
96
|
-
<span>上游同步</span>
|
|
97
|
-
</span>
|
|
98
|
-
<span class="market-signal-line market-signal-line-main"></span>
|
|
99
|
-
<span class="market-signal-line market-signal-line-alt"></span>
|
|
100
|
-
</div>
|
|
101
76
|
</div>
|
|
102
77
|
|
|
103
78
|
<aside class="market-hero-side" aria-label="服务状态概览">
|
|
@@ -136,12 +111,6 @@
|
|
|
136
111
|
<p class="market-mini-copy" style="margin-top: 14px; font-size: 14px; line-height: 1.7;">
|
|
137
112
|
本地 Web 服务默认运行在 34020 端口,提供首页、用户中心、管理中心和激活入口。
|
|
138
113
|
</p>
|
|
139
|
-
<div class="market-quick-links" aria-label="本地服务快捷入口">
|
|
140
|
-
<a href="/">首页</a>
|
|
141
|
-
<a href="/user/">用户中心</a>
|
|
142
|
-
<a href="/admin/">管理中心</a>
|
|
143
|
-
<a href="/activate.html">激活入口</a>
|
|
144
|
-
</div>
|
|
145
114
|
</div>
|
|
146
115
|
</aside>
|
|
147
116
|
</section>
|