@ohos-cpf/3rdloop 0.0.4 → 0.0.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/README.md +119 -128
- package/lib/cli.js +25 -0
- package/lib/serve.js +280 -0
- package/lib/update.js +46 -6
- package/lib/web-ext.js +454 -0
- package/lib/web.js +664 -0
- package/package.json +2 -1
- package/vendor/Server/CLI/opencode/index.js +2 -2
- package/vendor/Server/DbUse/StorageManager.js +7 -1
- package/vendor/Server/Routes/controllers/FlexRunnerController.js +92 -0
- package/vendor/Server/Routes/routes/flexrunner.js +2 -0
- package/vendor/Server/Skills/arkts-code-use/SKILL.md +270 -0
- package/vendor/Server/Skills/arkts-code-use/assets/TEMPLATES.md +367 -0
- package/vendor/Server/Skills/arkts-code-use/references/API_VERIFICATION.md +144 -0
- package/vendor/Server/Skills/arkts-code-use/references/ARKTS_RULES.md +240 -0
- package/vendor/Server/Skills/arkts-code-use/references/CODE_PATTERNS.md +431 -0
- package/vendor/Server/Skills/arkts-code-use/references/SYNTAX_CHECK_GUIDE.md +164 -0
- package/vendor/Server/Skills/arkts-code-use/scripts/verify-arkts.cjs +428 -0
- package/vendor/Server/Skills/gitcode-repo-fork/SKILL.md +310 -0
- package/vendor/Server/Skills/gitcode-repo-fork/assets/FORK_REPORT_TEMPLATE.md +113 -0
- package/vendor/Server/Skills/gitcode-repo-fork/references/FORK_DECISION_GUIDE.md +124 -0
- package/vendor/Server/Skills/gitcode-repo-fork/references/GITCODE_FORK_API.md +95 -0
- package/vendor/Server/Skills/gitcode-repo-fork/scripts/gitcode-fork.cjs +285 -0
- package/vendor/VERSION +3 -3
- package/web/css/arktslibrarycheck.css +322 -0
- package/web/css/codecheck.css +464 -0
- package/web/css/flutterlibrarycheck.css +322 -0
- package/web/css/knowledge.css +332 -0
- package/web/css/loop.css +578 -0
- package/web/css/md-reader.css +240 -0
- package/web/css/rnlibrarycheck.css +322 -0
- package/web/css/theme.css +702 -0
- package/web/index.html +713 -0
- package/web/js/arktslibrarycheck.js +1495 -0
- package/web/js/codecheck.js +1098 -0
- package/web/js/flutterlibrarycheck.js +1447 -0
- package/web/js/health.js +69 -0
- package/web/js/knowledge.js +358 -0
- package/web/js/loop.js +1102 -0
- package/web/js/md-reader.js +435 -0
- package/web/js/navigation.js +238 -0
- package/web/js/rnlibrarycheck.js +1462 -0
- package/web/js/stats.js +110 -0
- package/web/js/theme.js +46 -0
- package/web/js/utils.js +228 -0
- package/web/knowledge.html +146 -0
- package/web/loop.html +219 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @tool gitcode-fork
|
|
4
|
+
* @description gitcode-repo-fork SKILL 的 GitCode Fork 辅助脚本:Token 用户查询、仓库信息(含权限与 parent 源仓库)、Fork 存在性探测、创建 Fork(内置幂等回查与就绪轮询)、分支存在性探测。所有请求统一使用 Authorization: Bearer 头认证(POST 写操作必须,GET 一致处理),避免 form body 内 token 被拒(401)。
|
|
5
|
+
* @param token: string - GitCode API Token(也可用环境变量 GIT_TOKEN 或 Server/.env 的 GIT_TOKEN)
|
|
6
|
+
* @param owner: string - 仓库所属空间(owner/组织)
|
|
7
|
+
* @param repo: string - 仓库名
|
|
8
|
+
* 子命令:
|
|
9
|
+
* get-user 获取 Token 用户信息(fork 目标 namespace)
|
|
10
|
+
* get-repo --owner x --repo y [--allow-missing]
|
|
11
|
+
* 获取仓库信息(id/default_branch/parent/permissions);
|
|
12
|
+
* --allow-missing 时 404 返回 {exists:false} 而非报错
|
|
13
|
+
* get-branch --owner x --repo y --branch b 探测分支是否存在(200 存在 / 404 不存在)
|
|
14
|
+
* create-fork --owner x --repo y [--name n] [--fork-owner me] [--timeout s]
|
|
15
|
+
* 创建 Fork 到 Token 用户名下(POST /repos/{owner}/{repo}/forks,
|
|
16
|
+
* 仅 fork 源仓库本身);失败时自动回查已有 Fork(reused:true);
|
|
17
|
+
* 创建后自动轮询就绪(Fork 为异步操作)。
|
|
18
|
+
* --fork-owner:Token 无 read_user scope(GET /user 403)时
|
|
19
|
+
* 必传,用于指定 Fork 目标用户名(跳过 /user 查询)
|
|
20
|
+
* wait-fork --owner x --repo y [--timeout s] [--interval s]
|
|
21
|
+
* 轮询 Fork 仓库可访问(刚创建的 Fork 可能短暂 404)
|
|
22
|
+
* 用法示例:
|
|
23
|
+
* node gitcode-fork.cjs get-user --token "$GIT_TOKEN"
|
|
24
|
+
* node gitcode-fork.cjs create-fork --token "$GIT_TOKEN" --owner CPF-RN --repo rntpc_lib --timeout 60
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
'use strict';
|
|
28
|
+
const fs = require('fs');
|
|
29
|
+
const path = require('path');
|
|
30
|
+
const { URLSearchParams } = require('url');
|
|
31
|
+
|
|
32
|
+
const BASE = 'https://gitcode.com/api/v5';
|
|
33
|
+
|
|
34
|
+
// ---------- 参数解析 ----------
|
|
35
|
+
function parseArgs(argv) {
|
|
36
|
+
const args = { _: [] };
|
|
37
|
+
for (let i = 0; i < argv.length; i++) {
|
|
38
|
+
const a = argv[i];
|
|
39
|
+
if (a === '--help' || a === '-h') { args.help = true; continue; }
|
|
40
|
+
if (a.startsWith('--')) {
|
|
41
|
+
const key = a.slice(2).replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
42
|
+
args[key] = argv[i + 1] && !argv[i + 1].startsWith('--') ? argv[++i] : true;
|
|
43
|
+
} else {
|
|
44
|
+
args._.push(a);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return args;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function die(msg, code = 1) {
|
|
51
|
+
console.error(JSON.stringify({ ok: false, error: msg }, null, 2));
|
|
52
|
+
process.exit(code);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function requireParam(args, names) {
|
|
56
|
+
for (const n of names) {
|
|
57
|
+
if (!args[n] || args[n] === true) die(`缺少必填参数 --${n.replace(/([A-Z])/g, '-$1').toLowerCase()}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ---------- HTTP ----------
|
|
62
|
+
/**
|
|
63
|
+
* 统一 Bearer 头认证(POST 写操作必须:token 放 form body 会被拒 401 token not found,
|
|
64
|
+
* 见 references/GITCODE_FORK_API.md 踩坑记录)。
|
|
65
|
+
* @param opts.allow404 boolean - 404 时返回 null(不 die),用于探测类调用
|
|
66
|
+
*/
|
|
67
|
+
async function api(method, endpoint, params, token, opts = {}) {
|
|
68
|
+
const url = new URL(BASE + endpoint);
|
|
69
|
+
const headers = { Authorization: `Bearer ${token}` };
|
|
70
|
+
let body = null;
|
|
71
|
+
if (method === 'GET') {
|
|
72
|
+
const search = new URLSearchParams();
|
|
73
|
+
for (const [k, v] of Object.entries(params || {})) search.set(k, String(v));
|
|
74
|
+
url.search = search.toString();
|
|
75
|
+
} else {
|
|
76
|
+
headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
|
77
|
+
const form = new URLSearchParams();
|
|
78
|
+
for (const [k, v] of Object.entries(params || {})) form.set(k, String(v));
|
|
79
|
+
body = form.toString();
|
|
80
|
+
}
|
|
81
|
+
const res = await fetch(url, { method, headers, body });
|
|
82
|
+
const text = await res.text();
|
|
83
|
+
let json;
|
|
84
|
+
try { json = JSON.parse(text); } catch { json = { raw: text }; }
|
|
85
|
+
if (!res.ok) {
|
|
86
|
+
if (opts.allow404 && res.status === 404) return null;
|
|
87
|
+
const err = new Error(`GitCode API ${method} ${endpoint} -> HTTP ${res.status}: ${text.slice(0, 500)}`);
|
|
88
|
+
err.status = res.status;
|
|
89
|
+
throw err;
|
|
90
|
+
}
|
|
91
|
+
return json;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ---------- Token 加载 ----------
|
|
95
|
+
function resolveToken(args) {
|
|
96
|
+
if (args.token && args.token !== true) return args.token;
|
|
97
|
+
if (process.env.GIT_TOKEN) return process.env.GIT_TOKEN;
|
|
98
|
+
// 从 SKILL 目录向上回溯读取 Server/.env 的 GIT_TOKEN
|
|
99
|
+
// 本脚本位于 Server/Skills/gitcode-repo-fork/scripts/ → .env 在 ../../../.env
|
|
100
|
+
let dir = __dirname;
|
|
101
|
+
for (let i = 0; i < 4; i++) {
|
|
102
|
+
const envPath = path.join(dir, '.env');
|
|
103
|
+
if (fs.existsSync(envPath)) {
|
|
104
|
+
const m = fs.readFileSync(envPath, 'utf8').match(/^GIT_TOKEN=(.+)$/m);
|
|
105
|
+
if (m) return m[1].trim().replace(/^["']|["']$/g, '');
|
|
106
|
+
}
|
|
107
|
+
dir = path.dirname(dir);
|
|
108
|
+
}
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ---------- 结果提取 ----------
|
|
113
|
+
function pickRepo(r, owner, repo) {
|
|
114
|
+
const parent = (r.parent && (r.parent.path_with_namespace || r.parent.full_path)) || null;
|
|
115
|
+
const perms = r.permissions && typeof r.permissions === 'object'
|
|
116
|
+
? {
|
|
117
|
+
pull: !!r.permissions.pull,
|
|
118
|
+
push: !!r.permissions.push,
|
|
119
|
+
admin: !!r.permissions.admin,
|
|
120
|
+
}
|
|
121
|
+
: null;
|
|
122
|
+
return {
|
|
123
|
+
exists: true,
|
|
124
|
+
id: r.id,
|
|
125
|
+
owner: (r.namespace && (r.namespace.path || r.namespace.name)) || (r.owner && (r.owner.login || r.owner.name)) || owner,
|
|
126
|
+
repo: r.path || repo,
|
|
127
|
+
pathWithNamespace: r.full_path || r.path_with_namespace || `${owner}/${repo}`,
|
|
128
|
+
defaultBranch: r.default_branch || 'master',
|
|
129
|
+
fork: !!(r.fork || parent),
|
|
130
|
+
parent, // fork 仓库的直接源仓库(上游推断依据,ohos-lib-pr-push Phase 1.1 d 复用)
|
|
131
|
+
permissions: perms,
|
|
132
|
+
url: `https://gitcode.com/${(r.full_path || r.path_with_namespace || `${owner}/${repo}`).replace(/^\//, '')}`,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function sleep(ms) {
|
|
137
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ---------- 子命令 ----------
|
|
141
|
+
async function cmdGetUser(token) {
|
|
142
|
+
const u = await api('GET', '/user', {}, token);
|
|
143
|
+
console.log(JSON.stringify({
|
|
144
|
+
ok: true,
|
|
145
|
+
username: u.login || u.username, // 登录名 = fork 目标 namespace
|
|
146
|
+
name: u.name,
|
|
147
|
+
email: u.email,
|
|
148
|
+
id: u.id,
|
|
149
|
+
}, null, 2));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async function cmdGetRepo(args, token) {
|
|
153
|
+
requireParam(args, ['owner', 'repo']);
|
|
154
|
+
const allowMissing = args.allowMissing === true;
|
|
155
|
+
const r = await api('GET', `/repos/${args.owner}/${args.repo}`, {}, token, { allow404: allowMissing });
|
|
156
|
+
if (!r) {
|
|
157
|
+
console.log(JSON.stringify({ ok: true, exists: false, owner: args.owner, repo: args.repo }, null, 2));
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
console.log(JSON.stringify({ ok: true, ...pickRepo(r, args.owner, args.repo) }, null, 2));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
async function cmdGetBranch(args, token) {
|
|
164
|
+
requireParam(args, ['owner', 'repo', 'branch']);
|
|
165
|
+
const b = await api('GET', `/repos/${args.owner}/${args.repo}/branches/${encodeURIComponent(args.branch)}`, {}, token, { allow404: true });
|
|
166
|
+
console.log(JSON.stringify({ ok: true, exists: !!b, branch: (b && b.name) || args.branch }, null, 2));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async function waitForFork(token, owner, repo, timeoutSec, intervalSec) {
|
|
170
|
+
const start = Date.now();
|
|
171
|
+
const timeoutMs = timeoutSec * 1000;
|
|
172
|
+
const intervalMs = intervalSec * 1000;
|
|
173
|
+
// Fork 为异步操作:POST 成功后仓库可能短暂 404,轮询直到可访问
|
|
174
|
+
for (;;) {
|
|
175
|
+
const r = await api('GET', `/repos/${owner}/${repo}`, {}, token, { allow404: true });
|
|
176
|
+
if (r) {
|
|
177
|
+
return { waitedMs: Date.now() - start, repo: pickRepo(r, owner, repo) };
|
|
178
|
+
}
|
|
179
|
+
if (Date.now() - start >= timeoutMs) {
|
|
180
|
+
throw new Error(`等待 Fork 就绪超时(${timeoutSec}s):${owner}/${repo} 仍不可访问。Fork 可能仍在后台创建,请稍后用 wait-fork 重试`);
|
|
181
|
+
}
|
|
182
|
+
await sleep(intervalMs);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async function cmdCreateFork(args, token) {
|
|
187
|
+
requireParam(args, ['owner', 'repo']);
|
|
188
|
+
const timeoutSec = parseInt(args.timeout, 10) || 60;
|
|
189
|
+
const forkName = (typeof args.name === 'string' && args.name) || args.repo;
|
|
190
|
+
|
|
191
|
+
// Fork 目标 namespace = Token 用户名下。
|
|
192
|
+
// 实测:Token 可能无 read_user scope(GET /user -> 403 no scopes:read_user),
|
|
193
|
+
// 此时必须由 --fork-owner 显式指定,否则给出可操作的错误提示。
|
|
194
|
+
let forkOwner;
|
|
195
|
+
if (typeof args.forkOwner === 'string' && args.forkOwner) {
|
|
196
|
+
forkOwner = args.forkOwner;
|
|
197
|
+
} else {
|
|
198
|
+
let user;
|
|
199
|
+
try {
|
|
200
|
+
user = await api('GET', '/user', {}, token);
|
|
201
|
+
} catch (e) {
|
|
202
|
+
if (e.status === 403) {
|
|
203
|
+
die(`获取 Token 用户失败(${e.message.slice(0, 200)})。请传 --fork-owner 指定 Fork 目标用户名,或为 Token 增加 read_user scope 后重试`);
|
|
204
|
+
}
|
|
205
|
+
throw e;
|
|
206
|
+
}
|
|
207
|
+
forkOwner = user.login || user.username;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// 先探测幂等:已有 Fork 直接复用(避免依赖平台的"已存在"错误语义)
|
|
211
|
+
const existing = await api('GET', `/repos/${forkOwner}/${forkName}`, {}, token, { allow404: true });
|
|
212
|
+
if (existing) {
|
|
213
|
+
console.log(JSON.stringify({
|
|
214
|
+
ok: true, reused: true, note: 'Fork 已存在,直接复用(请校验 parent 是否指向目标源仓库)',
|
|
215
|
+
...pickRepo(existing, forkOwner, forkName),
|
|
216
|
+
}, null, 2));
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// 创建 Fork(POST 必须 Bearer 头认证,token 不进 form body)
|
|
221
|
+
const params = {};
|
|
222
|
+
if (typeof args.name === 'string' && args.name) params.name = args.name;
|
|
223
|
+
let created;
|
|
224
|
+
try {
|
|
225
|
+
created = await api('POST', `/repos/${args.owner}/${args.repo}/forks`, params, token);
|
|
226
|
+
} catch (e) {
|
|
227
|
+
// 幂等回查:创建失败但仓库已出现(并发/平台异步语义)→ 复用;否则透出原始错误
|
|
228
|
+
const retry = await api('GET', `/repos/${forkOwner}/${forkName}`, {}, token, { allow404: true });
|
|
229
|
+
if (retry) {
|
|
230
|
+
console.log(JSON.stringify({
|
|
231
|
+
ok: true, reused: true, note: `create-fork 报错但 Fork 已存在,自动复用(原始错误:${e.message.slice(0, 200)})`,
|
|
232
|
+
...pickRepo(retry, forkOwner, forkName),
|
|
233
|
+
}, null, 2));
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
die(e.message);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// 响应可能是 fork 仓库对象,也可能只是消息对象;统一以轮询结果为准
|
|
240
|
+
const wait = await waitForFork(token, forkOwner, forkName, timeoutSec, 3);
|
|
241
|
+
console.log(JSON.stringify({
|
|
242
|
+
ok: true,
|
|
243
|
+
reused: false,
|
|
244
|
+
forkOwner,
|
|
245
|
+
forkRepo: forkName,
|
|
246
|
+
forkUrl: `https://gitcode.com/${forkOwner}/${forkName}`,
|
|
247
|
+
ready: true,
|
|
248
|
+
waitedMs: wait.waitedMs,
|
|
249
|
+
...wait.repo,
|
|
250
|
+
}, null, 2));
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
async function cmdWaitFork(args, token) {
|
|
254
|
+
requireParam(args, ['owner', 'repo']);
|
|
255
|
+
const timeoutSec = parseInt(args.timeout, 10) || 60;
|
|
256
|
+
const intervalSec = parseInt(args.interval, 10) || 3;
|
|
257
|
+
const wait = await waitForFork(token, args.owner, args.repo, timeoutSec, intervalSec);
|
|
258
|
+
console.log(JSON.stringify({
|
|
259
|
+
ok: true, ready: true, waitedMs: wait.waitedMs, ...wait.repo,
|
|
260
|
+
}, null, 2));
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// ---------- 主流程 ----------
|
|
264
|
+
async function main() {
|
|
265
|
+
const args = parseArgs(process.argv.slice(2));
|
|
266
|
+
const cmd = args._[0];
|
|
267
|
+
if (args.help || !cmd) {
|
|
268
|
+
console.log(fs.readFileSync(__filename, 'utf8').split('*/')[0]);
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
const token = resolveToken(args);
|
|
272
|
+
if (!token) die('未找到 Token:请传 --token,或设置环境变量 GIT_TOKEN,或确保 Server/.env 中存在 GIT_TOKEN');
|
|
273
|
+
|
|
274
|
+
switch (cmd) {
|
|
275
|
+
case 'get-user': await cmdGetUser(token); break;
|
|
276
|
+
case 'get-repo': await cmdGetRepo(args, token); break;
|
|
277
|
+
case 'get-branch': await cmdGetBranch(args, token); break;
|
|
278
|
+
case 'create-fork': await cmdCreateFork(args, token); break;
|
|
279
|
+
case 'wait-fork': await cmdWaitFork(args, token); break;
|
|
280
|
+
default:
|
|
281
|
+
die(`未知子命令: ${cmd}(可用: get-user | get-repo | get-branch | create-fork | wait-fork)`);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
main().catch((e) => die(e.message));
|
package/vendor/VERSION
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
0.0.
|
|
2
|
-
built=2026-09-
|
|
3
|
-
sha=
|
|
1
|
+
0.0.6
|
|
2
|
+
built=2026-09-03T04:17:37.208Z
|
|
3
|
+
sha=3dae4a21a88fb4e7
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
/* ════════════════════════════════════════════════════════════════════
|
|
2
|
+
* arktslibrarycheck.css — ArkTS 仓库检视面板专用样式
|
|
3
|
+
*
|
|
4
|
+
* 依赖:theme.css(CSS 变量)、codecheck.css(cc-* 通用卡片/徽章/按钮样式)
|
|
5
|
+
* ════════════════════════════════════════════════════════════════════ */
|
|
6
|
+
|
|
7
|
+
/* ─── 入参说明 ─────────────────────────────────────────────────────── */
|
|
8
|
+
.akt-param-intro {
|
|
9
|
+
background: var(--card);
|
|
10
|
+
border: 1px solid var(--border);
|
|
11
|
+
border-radius: 8px;
|
|
12
|
+
padding: 12px 14px;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.akt-param-title {
|
|
16
|
+
font-size: 12px;
|
|
17
|
+
font-weight: 600;
|
|
18
|
+
color: var(--text2);
|
|
19
|
+
margin-bottom: 10px;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.akt-param-grid {
|
|
23
|
+
display: grid;
|
|
24
|
+
grid-template-columns: repeat(2, 1fr);
|
|
25
|
+
gap: 8px;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@media (max-width: 900px) {
|
|
29
|
+
.akt-param-grid { grid-template-columns: 1fr; }
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.akt-param-item {
|
|
33
|
+
display: flex;
|
|
34
|
+
flex-direction: column;
|
|
35
|
+
gap: 3px;
|
|
36
|
+
padding: 8px 10px;
|
|
37
|
+
background: var(--bg);
|
|
38
|
+
border: 1px solid var(--border-light);
|
|
39
|
+
border-radius: 6px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.akt-param-name {
|
|
43
|
+
font-size: 11px;
|
|
44
|
+
font-weight: 600;
|
|
45
|
+
color: var(--blue);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.akt-param-code {
|
|
49
|
+
font-family: var(--mono);
|
|
50
|
+
font-size: 11px;
|
|
51
|
+
color: var(--text2);
|
|
52
|
+
background: var(--code-bg);
|
|
53
|
+
padding: 2px 6px;
|
|
54
|
+
border-radius: 4px;
|
|
55
|
+
word-break: break-all;
|
|
56
|
+
line-height: 1.5;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.akt-param-note {
|
|
60
|
+
font-size: 10px;
|
|
61
|
+
color: var(--text3);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.akt-param-tip {
|
|
65
|
+
margin-top: 10px;
|
|
66
|
+
font-size: 11px;
|
|
67
|
+
color: var(--text3);
|
|
68
|
+
padding-top: 8px;
|
|
69
|
+
border-top: 1px dashed var(--border-light);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* ─── 评分概览面板 ─────────────────────────────────────────────────── */
|
|
73
|
+
.akt-score-panel {
|
|
74
|
+
background: var(--bg);
|
|
75
|
+
border: 1px solid var(--border);
|
|
76
|
+
border-radius: 8px;
|
|
77
|
+
padding: 14px 16px;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.akt-score-panel-title {
|
|
81
|
+
font-size: 13px;
|
|
82
|
+
font-weight: 600;
|
|
83
|
+
color: var(--text);
|
|
84
|
+
margin-bottom: 10px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.akt-score-overall-row {
|
|
88
|
+
display: flex;
|
|
89
|
+
align-items: center;
|
|
90
|
+
gap: 10px;
|
|
91
|
+
padding: 8px 12px;
|
|
92
|
+
background: var(--card);
|
|
93
|
+
border-radius: 6px;
|
|
94
|
+
margin-bottom: 10px;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.akt-score-label {
|
|
98
|
+
font-size: 12px;
|
|
99
|
+
font-weight: 700;
|
|
100
|
+
color: var(--text);
|
|
101
|
+
width: 64px;
|
|
102
|
+
flex-shrink: 0;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.akt-score-value {
|
|
106
|
+
font-size: 18px;
|
|
107
|
+
font-weight: 700;
|
|
108
|
+
font-family: var(--mono);
|
|
109
|
+
padding: 3px 12px;
|
|
110
|
+
border-radius: 6px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.akt-score-weights {
|
|
114
|
+
font-size: 10px;
|
|
115
|
+
color: var(--text3);
|
|
116
|
+
margin-left: auto;
|
|
117
|
+
text-align: right;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.akt-score-grid {
|
|
121
|
+
display: grid;
|
|
122
|
+
grid-template-columns: repeat(4, 1fr);
|
|
123
|
+
gap: 8px;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@media (max-width: 900px) {
|
|
127
|
+
.akt-score-grid { grid-template-columns: repeat(2, 1fr); }
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.akt-score-item {
|
|
131
|
+
display: flex;
|
|
132
|
+
align-items: center;
|
|
133
|
+
gap: 6px;
|
|
134
|
+
padding: 7px 10px;
|
|
135
|
+
background: var(--card);
|
|
136
|
+
border: 1px solid var(--border-light);
|
|
137
|
+
border-radius: 6px;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.akt-score-item-label {
|
|
141
|
+
font-size: 11px;
|
|
142
|
+
color: var(--text2);
|
|
143
|
+
flex-shrink: 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.akt-score-item-value {
|
|
147
|
+
font-size: 13px;
|
|
148
|
+
font-weight: 700;
|
|
149
|
+
font-family: var(--mono);
|
|
150
|
+
padding: 2px 8px;
|
|
151
|
+
border-radius: 4px;
|
|
152
|
+
color: var(--text3);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* ─── 步骤进度面板 ─────────────────────────────────────────────────── */
|
|
156
|
+
.akt-steps-panel {
|
|
157
|
+
background: var(--bg);
|
|
158
|
+
border: 1px solid var(--border);
|
|
159
|
+
border-radius: 8px;
|
|
160
|
+
padding: 14px 16px;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.akt-steps-title-row {
|
|
164
|
+
display: flex;
|
|
165
|
+
align-items: center;
|
|
166
|
+
justify-content: space-between;
|
|
167
|
+
gap: 10px;
|
|
168
|
+
margin-bottom: 10px;
|
|
169
|
+
flex-wrap: wrap;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.akt-steps-title {
|
|
173
|
+
font-size: 13px;
|
|
174
|
+
font-weight: 600;
|
|
175
|
+
color: var(--text);
|
|
176
|
+
margin-bottom: 0;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/* ─── 打包下载全部报告按钮 ─────────────────────────────────────────── */
|
|
180
|
+
.akt-archive-btn {
|
|
181
|
+
display: inline-flex;
|
|
182
|
+
align-items: center;
|
|
183
|
+
gap: 5px;
|
|
184
|
+
padding: 6px 14px;
|
|
185
|
+
border-radius: 6px;
|
|
186
|
+
font-size: 12px;
|
|
187
|
+
font-weight: 600;
|
|
188
|
+
background: rgba(52,199,89,0.12);
|
|
189
|
+
color: var(--green);
|
|
190
|
+
border: 1px solid rgba(52,199,89,0.3);
|
|
191
|
+
cursor: pointer;
|
|
192
|
+
white-space: nowrap;
|
|
193
|
+
flex-shrink: 0;
|
|
194
|
+
transition: all 0.15s;
|
|
195
|
+
}
|
|
196
|
+
.akt-archive-btn:hover:not(:disabled) {
|
|
197
|
+
background: rgba(52,199,89,0.2);
|
|
198
|
+
border-color: rgba(52,199,89,0.5);
|
|
199
|
+
}
|
|
200
|
+
.akt-archive-btn:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
201
|
+
|
|
202
|
+
.akt-steps-list {
|
|
203
|
+
display: flex;
|
|
204
|
+
flex-direction: column;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.akt-step-row {
|
|
208
|
+
display: flex;
|
|
209
|
+
align-items: center;
|
|
210
|
+
gap: 12px;
|
|
211
|
+
padding: 9px 0;
|
|
212
|
+
border-bottom: 1px dashed var(--border-light);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.akt-step-row:last-child { border-bottom: none; }
|
|
216
|
+
|
|
217
|
+
.akt-step-icon {
|
|
218
|
+
width: 32px;
|
|
219
|
+
height: 32px;
|
|
220
|
+
font-size: 13px;
|
|
221
|
+
font-weight: 700;
|
|
222
|
+
border: 2px solid var(--border);
|
|
223
|
+
border-radius: 50%;
|
|
224
|
+
display: flex;
|
|
225
|
+
align-items: center;
|
|
226
|
+
justify-content: center;
|
|
227
|
+
background: var(--card);
|
|
228
|
+
color: var(--text2);
|
|
229
|
+
flex-shrink: 0;
|
|
230
|
+
transition: border-color 0.2s, background 0.2s, color 0.2s;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.akt-step-icon.running {
|
|
234
|
+
border-color: var(--blue);
|
|
235
|
+
background: rgba(0,113,227,0.08);
|
|
236
|
+
}
|
|
237
|
+
.akt-step-icon.completed {
|
|
238
|
+
border-color: var(--green);
|
|
239
|
+
background: rgba(52,199,89,0.1);
|
|
240
|
+
color: var(--green);
|
|
241
|
+
}
|
|
242
|
+
.akt-step-icon.failed {
|
|
243
|
+
border-color: var(--red);
|
|
244
|
+
background: rgba(255,59,48,0.1);
|
|
245
|
+
color: var(--red);
|
|
246
|
+
}
|
|
247
|
+
.akt-step-icon.skipped {
|
|
248
|
+
border-color: var(--gray);
|
|
249
|
+
background: rgba(142,142,147,0.08);
|
|
250
|
+
color: var(--gray);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.akt-step-info { flex: 1; min-width: 0; }
|
|
254
|
+
|
|
255
|
+
.akt-step-name {
|
|
256
|
+
font-size: 13px;
|
|
257
|
+
font-weight: 600;
|
|
258
|
+
color: var(--text);
|
|
259
|
+
margin-bottom: 1px;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.akt-step-weight {
|
|
263
|
+
font-size: 10px;
|
|
264
|
+
font-weight: 400;
|
|
265
|
+
color: var(--text3);
|
|
266
|
+
font-family: var(--mono);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.akt-step-desc {
|
|
270
|
+
font-size: 11px;
|
|
271
|
+
color: var(--text3);
|
|
272
|
+
font-family: var(--mono);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.akt-step-actions {
|
|
276
|
+
display: flex;
|
|
277
|
+
align-items: center;
|
|
278
|
+
gap: 6px;
|
|
279
|
+
flex-shrink: 0;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.akt-step-score {
|
|
283
|
+
font-size: 12px;
|
|
284
|
+
font-weight: 700;
|
|
285
|
+
font-family: var(--mono);
|
|
286
|
+
padding: 3px 9px;
|
|
287
|
+
border-radius: 5px;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/* ─── 步骤对话按钮 ─────────────────────────────────────────────────── */
|
|
291
|
+
.akt-session-btn {
|
|
292
|
+
display: inline-flex;
|
|
293
|
+
align-items: center;
|
|
294
|
+
justify-content: center;
|
|
295
|
+
width: 30px;
|
|
296
|
+
height: 26px;
|
|
297
|
+
padding: 0;
|
|
298
|
+
border-radius: 6px;
|
|
299
|
+
font-size: 12px;
|
|
300
|
+
background: rgba(175,82,222,0.1);
|
|
301
|
+
color: var(--purple);
|
|
302
|
+
border: 1px solid rgba(175,82,222,0.3);
|
|
303
|
+
cursor: pointer;
|
|
304
|
+
white-space: nowrap;
|
|
305
|
+
transition: all 0.15s;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.akt-session-btn:hover:not(:disabled) {
|
|
309
|
+
background: rgba(175,82,222,0.2);
|
|
310
|
+
border-color: rgba(175,82,222,0.5);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.akt-session-btn:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
314
|
+
|
|
315
|
+
/* ─── 面板布局 ─────────────────────────────────────────────────────── */
|
|
316
|
+
#p-arktslibrarycheck .panel-pad {
|
|
317
|
+
padding: 20px 24px;
|
|
318
|
+
overflow-y: auto;
|
|
319
|
+
display: flex;
|
|
320
|
+
flex-direction: column;
|
|
321
|
+
gap: 16px;
|
|
322
|
+
}
|