@jamiexiongr/panda-hub 0.1.25 → 0.1.27
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/dist/{chunk-KWFBUSH3.mjs → chunk-EUY5V2XS.mjs} +113 -35
- package/dist/{chunk-QSMTYAZX.mjs → chunk-KMQMS3IT.mjs} +2 -2
- package/dist/cli.mjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{src-ILWWSZFE.mjs → src-SMFYPE6P.mjs} +1 -1
- package/dist/web/assets/{diagnostics-page-CUUs5mBW.js → diagnostics-page-CoIdkIQI.js} +1 -1
- package/dist/web/assets/index-OTfJjsxL.js +148 -0
- package/dist/web/assets/{session-diff-preview-BXSETWfx.js → session-diff-preview-CCCZmf4G.js} +1 -1
- package/dist/web/assets/{session-file-markdown-preview-CNB0_vuB.js → session-file-markdown-preview-Dv-eVJZC.js} +1 -1
- package/dist/web/assets/{session-file-preview-page-DZKIRsxQ.js → session-file-preview-page-DK4GwzJS.js} +3 -3
- package/dist/web/assets/{web-BiRQ43B_.js → web-CwfmVur7.js} +1 -1
- package/dist/web/assets/{web-BufOpPB2.js → web-D1pcnorX.js} +1 -1
- package/dist/web/assets/{web-CVdkFm8V.js → web-DeqRViq6.js} +1 -1
- package/dist/web/assets/{web-D7DF4ZhP.js → web-Dy_S-Kpy.js} +1 -1
- package/dist/web/assets/{web-c9a9eQ4-.js → web-vTFNt5EQ.js} +1 -1
- package/dist/web/assets/{xml-C8Jwua6u.js → xml-CQYUv0yT.js} +1 -1
- package/dist/web/index.html +1 -1
- package/dist/web/sw.js +1 -1
- package/package.json +1 -1
- package/dist/web/assets/index-BV97xtnA.js +0 -148
|
@@ -2538,6 +2538,8 @@ var devManagerJobKindSchema = external_exports.enum([
|
|
|
2538
2538
|
"npm-publish",
|
|
2539
2539
|
"release-service-install",
|
|
2540
2540
|
"release-service-uninstall",
|
|
2541
|
+
"release-install-package",
|
|
2542
|
+
"release-restart",
|
|
2541
2543
|
"release-install-run",
|
|
2542
2544
|
"apk-build"
|
|
2543
2545
|
]);
|
|
@@ -2654,6 +2656,8 @@ var devManagerActionRequestSchema = external_exports.object({
|
|
|
2654
2656
|
"publish-npm",
|
|
2655
2657
|
"install-release-services",
|
|
2656
2658
|
"uninstall-release-services",
|
|
2659
|
+
"install-latest-release-package",
|
|
2660
|
+
"restart-release-services",
|
|
2657
2661
|
"install-latest-release",
|
|
2658
2662
|
"build-apk"
|
|
2659
2663
|
])
|
|
@@ -9193,11 +9197,16 @@ const main = async () => {
|
|
|
9193
9197
|
const payloadPath = process.argv[2]
|
|
9194
9198
|
const payload = await readJson(payloadPath)
|
|
9195
9199
|
const jobPath = payload.jobPath
|
|
9200
|
+
const workflowLabel = String(payload.workflowLabel || '正式版恢复')
|
|
9201
|
+
const stopServices = Array.isArray(payload.stopServices) ? payload.stopServices : []
|
|
9202
|
+
const startServices = Array.isArray(payload.startServices) ? payload.startServices : []
|
|
9196
9203
|
try {
|
|
9197
9204
|
await appendLog(jobPath, 'info', '后台升级助手已接管当前任务。')
|
|
9205
|
+
await appendLog(jobPath, 'info', workflowLabel + ':准备停止当前正式版进程。')
|
|
9198
9206
|
await wait(payload.stopDelayMs || 1500)
|
|
9199
9207
|
|
|
9200
|
-
for (const service of
|
|
9208
|
+
for (const service of stopServices) {
|
|
9209
|
+
await appendLog(jobPath, 'info', '正在停止 ' + service.label + '。')
|
|
9201
9210
|
if (service.serviceName) {
|
|
9202
9211
|
const status = await stopWindowsService(service.serviceName)
|
|
9203
9212
|
await appendLog(
|
|
@@ -9226,16 +9235,23 @@ const main = async () => {
|
|
|
9226
9235
|
}
|
|
9227
9236
|
|
|
9228
9237
|
let installError = null
|
|
9229
|
-
|
|
9230
|
-
await
|
|
9231
|
-
|
|
9232
|
-
|
|
9233
|
-
|
|
9234
|
-
|
|
9238
|
+
if (payload.installCommand) {
|
|
9239
|
+
await appendLog(jobPath, 'info', workflowLabel + ':开始执行 npm 安装阶段。')
|
|
9240
|
+
try {
|
|
9241
|
+
await runCommandWithLogs(jobPath, payload.installCommand, '安装最新正式版')
|
|
9242
|
+
await appendLog(jobPath, 'success', '最新正式版安装完成。')
|
|
9243
|
+
} catch (error) {
|
|
9244
|
+
installError = error instanceof Error ? error.message : String(error)
|
|
9245
|
+
await appendLog(jobPath, 'error', '安装最新正式版失败:' + installError)
|
|
9246
|
+
}
|
|
9247
|
+
} else {
|
|
9248
|
+
await appendLog(jobPath, 'info', workflowLabel + ':跳过 npm 安装阶段。')
|
|
9235
9249
|
}
|
|
9236
9250
|
|
|
9237
9251
|
const probeResults = []
|
|
9238
|
-
|
|
9252
|
+
await appendLog(jobPath, 'info', workflowLabel + ':开始恢复正式版服务。')
|
|
9253
|
+
for (const service of startServices) {
|
|
9254
|
+
await appendLog(jobPath, 'info', '正在启动 ' + service.label + '。')
|
|
9239
9255
|
if (service.serviceName) {
|
|
9240
9256
|
try {
|
|
9241
9257
|
await startWindowsService(service.serviceName)
|
|
@@ -9280,7 +9296,7 @@ const main = async () => {
|
|
|
9280
9296
|
jobPath,
|
|
9281
9297
|
'succeeded',
|
|
9282
9298
|
installError
|
|
9283
|
-
? '
|
|
9299
|
+
? workflowLabel + '已完成,但安装阶段曾报错,请核对日志。'
|
|
9284
9300
|
: '正式版 Hub + Agent 已恢复可用。',
|
|
9285
9301
|
installError,
|
|
9286
9302
|
)
|
|
@@ -9298,8 +9314,8 @@ const main = async () => {
|
|
|
9298
9314
|
)
|
|
9299
9315
|
} catch (error) {
|
|
9300
9316
|
const message = error instanceof Error ? error.message : String(error)
|
|
9301
|
-
await appendLog(jobPath, 'error', '
|
|
9302
|
-
await finishJob(jobPath, 'failed', '
|
|
9317
|
+
await appendLog(jobPath, 'error', workflowLabel + '失败:' + message)
|
|
9318
|
+
await finishJob(jobPath, 'failed', workflowLabel + '失败。', message)
|
|
9303
9319
|
}
|
|
9304
9320
|
}
|
|
9305
9321
|
|
|
@@ -9967,21 +9983,47 @@ var createDevManager = ({
|
|
|
9967
9983
|
await job.succeed("\u6B63\u5F0F\u7248 Hub \u4E0E Agent \u670D\u52A1\u5DF2\u79FB\u9664\u3002");
|
|
9968
9984
|
});
|
|
9969
9985
|
};
|
|
9970
|
-
const
|
|
9986
|
+
const launchDetachedHelper = (helperSourcePath, helperPayloadPath) => {
|
|
9987
|
+
if (process.platform === "win32") {
|
|
9988
|
+
const escapePowerShellLiteral = (value) => value.replaceAll("'", "''");
|
|
9989
|
+
const command = [
|
|
9990
|
+
`$nodePath = '${escapePowerShellLiteral(process.execPath)}'`,
|
|
9991
|
+
`$argumentList = @('${escapePowerShellLiteral(helperSourcePath)}', '${escapePowerShellLiteral(helperPayloadPath)}')`,
|
|
9992
|
+
"Start-Process -FilePath $nodePath -ArgumentList $argumentList -WindowStyle Hidden"
|
|
9993
|
+
].join("; ");
|
|
9994
|
+
const launcher = spawn3(
|
|
9995
|
+
"powershell.exe",
|
|
9996
|
+
["-NoProfile", "-Command", command],
|
|
9997
|
+
{
|
|
9998
|
+
detached: true,
|
|
9999
|
+
stdio: "ignore",
|
|
10000
|
+
windowsHide: true
|
|
10001
|
+
}
|
|
10002
|
+
);
|
|
10003
|
+
launcher.unref();
|
|
10004
|
+
return "powershell-start-process";
|
|
10005
|
+
}
|
|
10006
|
+
const helper = spawn3(
|
|
10007
|
+
process.execPath,
|
|
10008
|
+
[helperSourcePath, helperPayloadPath],
|
|
10009
|
+
{
|
|
10010
|
+
detached: true,
|
|
10011
|
+
stdio: "ignore",
|
|
10012
|
+
windowsHide: true
|
|
10013
|
+
}
|
|
10014
|
+
);
|
|
10015
|
+
helper.unref();
|
|
10016
|
+
return "direct-spawn";
|
|
10017
|
+
};
|
|
10018
|
+
const spawnReleaseRecoveryHelper = async (input) => {
|
|
9971
10019
|
const { config } = await readStoredConfig(codexHome);
|
|
9972
|
-
const executionRoot = getExecutionRoot(config);
|
|
9973
10020
|
const releaseHubServiceStatus = queryWindowsServiceStatus(config.release_hub_service_name);
|
|
9974
10021
|
const releaseAgentServiceStatus = queryWindowsServiceStatus(config.release_agent_service_name);
|
|
9975
|
-
const installCommand = await resolveManagedCommand({
|
|
9976
|
-
projectPath: executionRoot,
|
|
9977
|
-
command: `npm install -g ${RELEASE_PACKAGE_NAME}@latest --registry=${NPM_REGISTRY_URL}`,
|
|
9978
|
-
nodeVersion: config.nvm_version
|
|
9979
|
-
});
|
|
9980
10022
|
const releaseHubCommand = await resolveServiceCommand(config, "release-hub");
|
|
9981
10023
|
const releaseAgentCommand = await resolveServiceCommand(config, "release-agent");
|
|
9982
10024
|
const helperDirectory = resolveHelperDirectory(codexHome);
|
|
9983
10025
|
await ensureDirectory(helperDirectory);
|
|
9984
|
-
const job = createManagedJob(
|
|
10026
|
+
const job = createManagedJob(input.kind, input.title, {
|
|
9985
10027
|
disconnectExpected: true
|
|
9986
10028
|
});
|
|
9987
10029
|
const jobPath = buildJobFilePath(codexHome, job.id);
|
|
@@ -9990,7 +10032,7 @@ var createDevManager = ({
|
|
|
9990
10032
|
logs: [
|
|
9991
10033
|
createJobLogEntry(
|
|
9992
10034
|
"info",
|
|
9993
|
-
|
|
10035
|
+
`${input.workflowLabel}\u5373\u5C06\u7531\u540E\u53F0\u5347\u7EA7\u52A9\u624B\u63A5\u7BA1\u3002\u5F53\u524D Hub \u4F1A\u77ED\u65F6\u4E2D\u65AD\uFF0C\u8BF7\u7B49\u5F85\u81EA\u52A8\u6062\u590D\u3002`
|
|
9994
10036
|
)
|
|
9995
10037
|
]
|
|
9996
10038
|
});
|
|
@@ -9999,6 +10041,7 @@ var createDevManager = ({
|
|
|
9999
10041
|
await fs7.writeFile(helperSourcePath, createUpgradeHelperSource(), "utf8");
|
|
10000
10042
|
await writeJsonFile(helperPayloadPath, {
|
|
10001
10043
|
jobPath,
|
|
10044
|
+
workflowLabel: input.workflowLabel,
|
|
10002
10045
|
stopDelayMs: RELEASE_RESTART_DELAY_MS,
|
|
10003
10046
|
stopServices: [
|
|
10004
10047
|
{
|
|
@@ -10012,7 +10055,7 @@ var createDevManager = ({
|
|
|
10012
10055
|
serviceName: releaseHubServiceStatus?.installed ? config.release_hub_service_name : null
|
|
10013
10056
|
}
|
|
10014
10057
|
],
|
|
10015
|
-
installCommand,
|
|
10058
|
+
installCommand: input.installCommand ?? null,
|
|
10016
10059
|
startServices: [
|
|
10017
10060
|
{
|
|
10018
10061
|
label: "\u6B63\u5F0F\u7248 Hub",
|
|
@@ -10032,23 +10075,58 @@ var createDevManager = ({
|
|
|
10032
10075
|
}
|
|
10033
10076
|
]
|
|
10034
10077
|
});
|
|
10035
|
-
const
|
|
10036
|
-
process.execPath,
|
|
10037
|
-
[helperSourcePath, helperPayloadPath],
|
|
10038
|
-
{
|
|
10039
|
-
detached: true,
|
|
10040
|
-
stdio: "ignore",
|
|
10041
|
-
windowsHide: true
|
|
10042
|
-
}
|
|
10043
|
-
);
|
|
10044
|
-
helper.unref();
|
|
10078
|
+
const helperLaunchMode = launchDetachedHelper(helperSourcePath, helperPayloadPath);
|
|
10045
10079
|
logger.info({
|
|
10046
10080
|
jobId: job.id,
|
|
10047
10081
|
helperSourcePath,
|
|
10048
|
-
helperPayloadPath
|
|
10082
|
+
helperPayloadPath,
|
|
10083
|
+
helperLaunchMode
|
|
10049
10084
|
}, "Spawned detached release install helper.");
|
|
10050
10085
|
return job;
|
|
10051
10086
|
};
|
|
10087
|
+
const installLatestReleasePackage = async () => {
|
|
10088
|
+
const { config } = await readStoredConfig(codexHome);
|
|
10089
|
+
const executionRoot = getExecutionRoot(config);
|
|
10090
|
+
return runManagedJob("release-install-package", "\u5B89\u88C5\u6700\u65B0\u6B63\u5F0F\u7248 npm \u5305", async (job) => {
|
|
10091
|
+
await job.append("info", "\u51C6\u5907\u5B89\u88C5\u6700\u65B0\u6B63\u5F0F\u7248 npm \u5305\u3002");
|
|
10092
|
+
const command = await resolveManagedCommand({
|
|
10093
|
+
projectPath: executionRoot,
|
|
10094
|
+
command: `npm install -g ${RELEASE_PACKAGE_NAME}@latest --registry=${NPM_REGISTRY_URL}`,
|
|
10095
|
+
nodeVersion: config.nvm_version
|
|
10096
|
+
});
|
|
10097
|
+
await runCommandWithLogs(command, job, "\u5B89\u88C5\u6700\u65B0\u6B63\u5F0F\u7248 npm \u5305");
|
|
10098
|
+
let installedVersion = null;
|
|
10099
|
+
try {
|
|
10100
|
+
installedVersion = await refreshInstalledPackageVersion();
|
|
10101
|
+
} catch (error) {
|
|
10102
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
10103
|
+
await job.append("warn", `\u5B89\u88C5\u5B8C\u6210\uFF0C\u4F46\u5237\u65B0\u672C\u5730\u7248\u672C\u7F13\u5B58\u5931\u8D25\uFF1A${message}`);
|
|
10104
|
+
}
|
|
10105
|
+
await job.succeed(
|
|
10106
|
+
installedVersion ? `\u6700\u65B0\u6B63\u5F0F\u7248 npm \u5305\u5B89\u88C5\u5B8C\u6210\uFF0C\u5F53\u524D\u7248\u672C ${installedVersion}\u3002` : "\u6700\u65B0\u6B63\u5F0F\u7248 npm \u5305\u5B89\u88C5\u5B8C\u6210\u3002"
|
|
10107
|
+
);
|
|
10108
|
+
});
|
|
10109
|
+
};
|
|
10110
|
+
const restartReleaseServices = async () => await spawnReleaseRecoveryHelper({
|
|
10111
|
+
kind: "release-restart",
|
|
10112
|
+
title: "\u91CD\u542F\u6B63\u5F0F\u7248 Hub + Agent",
|
|
10113
|
+
workflowLabel: "\u6B63\u5F0F\u7248\u91CD\u542F"
|
|
10114
|
+
});
|
|
10115
|
+
const installLatestRelease = async () => {
|
|
10116
|
+
const { config } = await readStoredConfig(codexHome);
|
|
10117
|
+
const executionRoot = getExecutionRoot(config);
|
|
10118
|
+
const installCommand = await resolveManagedCommand({
|
|
10119
|
+
projectPath: executionRoot,
|
|
10120
|
+
command: `npm install -g ${RELEASE_PACKAGE_NAME}@latest --registry=${NPM_REGISTRY_URL}`,
|
|
10121
|
+
nodeVersion: config.nvm_version
|
|
10122
|
+
});
|
|
10123
|
+
return await spawnReleaseRecoveryHelper({
|
|
10124
|
+
kind: "release-install-run",
|
|
10125
|
+
title: "\u5B89\u88C5\u5E76\u8FD0\u884C\u6700\u65B0\u6B63\u5F0F\u7248",
|
|
10126
|
+
workflowLabel: "\u6B63\u5F0F\u7248\u5347\u7EA7",
|
|
10127
|
+
installCommand
|
|
10128
|
+
});
|
|
10129
|
+
};
|
|
10052
10130
|
const readApkDownload = async (expectedArtifactId) => {
|
|
10053
10131
|
const { config } = await readStoredConfig(codexHome);
|
|
10054
10132
|
const artifact = await readApkArtifact(config);
|
|
@@ -10064,7 +10142,7 @@ var createDevManager = ({
|
|
|
10064
10142
|
};
|
|
10065
10143
|
};
|
|
10066
10144
|
const executeAction = async (action) => {
|
|
10067
|
-
const job = action === "start-development" ? await runDevelopmentLifecycle("start") : action === "restart-development" ? await runDevelopmentLifecycle("restart") : action === "stop-development" ? await runDevelopmentLifecycle("stop") : action === "probe-development" ? await runDevelopmentLifecycle("probe") : action === "publish-npm" ? await runNpmPublish() : action === "install-release-services" ? await installReleaseServices() : action === "uninstall-release-services" ? await uninstallReleaseServices() : action === "build-apk" ? await runApkBuild() : await installLatestRelease();
|
|
10145
|
+
const job = action === "start-development" ? await runDevelopmentLifecycle("start") : action === "restart-development" ? await runDevelopmentLifecycle("restart") : action === "stop-development" ? await runDevelopmentLifecycle("stop") : action === "probe-development" ? await runDevelopmentLifecycle("probe") : action === "publish-npm" ? await runNpmPublish() : action === "install-release-services" ? await installReleaseServices() : action === "uninstall-release-services" ? await uninstallReleaseServices() : action === "install-latest-release-package" ? await installLatestReleasePackage() : action === "restart-release-services" ? await restartReleaseServices() : action === "build-apk" ? await runApkBuild() : await installLatestRelease();
|
|
10068
10146
|
return {
|
|
10069
10147
|
ok: true,
|
|
10070
10148
|
job,
|
|
@@ -11887,7 +11965,7 @@ ${attachmentNames.map((name) => `- ${name}`).join("\n")}` : null
|
|
|
11887
11965
|
return nextOverlayEntries;
|
|
11888
11966
|
};
|
|
11889
11967
|
const readTimelineFromRollout = async (sessionId) => {
|
|
11890
|
-
const { readCodexTimeline } = await import("./src-
|
|
11968
|
+
const { readCodexTimeline } = await import("./src-SMFYPE6P.mjs");
|
|
11891
11969
|
return readCodexTimeline(sessionId, {
|
|
11892
11970
|
codexHome,
|
|
11893
11971
|
sessionFiles: discoveredSessionFiles
|
|
@@ -13393,7 +13471,7 @@ ${attachmentNames.map((name) => `- ${name}`).join("\n")}` : null
|
|
|
13393
13471
|
lastSnapshotRefreshAt = Date.now();
|
|
13394
13472
|
return snapshot;
|
|
13395
13473
|
}
|
|
13396
|
-
const { discoverLocalCodexData } = await import("./src-
|
|
13474
|
+
const { discoverLocalCodexData } = await import("./src-SMFYPE6P.mjs");
|
|
13397
13475
|
const discovery = await discoverLocalCodexData({
|
|
13398
13476
|
agentId: localAgentId,
|
|
13399
13477
|
agentName: localAgentName,
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
resolveTailscalePublicationMode,
|
|
6
6
|
resolveTailscaleServePort,
|
|
7
7
|
startPandaSessionService
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-EUY5V2XS.mjs";
|
|
9
9
|
|
|
10
10
|
// release/panda-hub/src/index.ts
|
|
11
11
|
import fs from "fs";
|
|
@@ -15,7 +15,7 @@ import { fileURLToPath as fileURLToPath2 } from "url";
|
|
|
15
15
|
// release/panda-hub/package.json
|
|
16
16
|
var package_default = {
|
|
17
17
|
name: "@jamiexiongr/panda-hub",
|
|
18
|
-
version: "0.1.
|
|
18
|
+
version: "0.1.27",
|
|
19
19
|
type: "module",
|
|
20
20
|
private: false,
|
|
21
21
|
description: "Panda hub runtime",
|
package/dist/cli.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
manageJamiexiongrHubService,
|
|
3
3
|
startJamiexiongrHub
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KMQMS3IT.mjs";
|
|
5
5
|
import {
|
|
6
6
|
resolveTailscalePublicationMode
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-EUY5V2XS.mjs";
|
|
8
8
|
import "./chunk-AEQMWH7D.mjs";
|
|
9
9
|
|
|
10
10
|
// release/panda-hub/src/cli.ts
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
manageJamiexiongrHubService,
|
|
3
3
|
startJamiexiongrHub
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-KMQMS3IT.mjs";
|
|
5
|
+
import "./chunk-EUY5V2XS.mjs";
|
|
6
6
|
import "./chunk-AEQMWH7D.mjs";
|
|
7
7
|
export {
|
|
8
8
|
manageJamiexiongrHubService,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{u as j,r as d,j as e}from"./index-BV97xtnA.js";const v=[{key:"color-mix-oklab",property:"background",value:"color-mix(in oklab, white 50%, black)"},{key:"color-mix-srgb",property:"background",value:"color-mix(in srgb, white 50%, black)"},{key:"backdrop-filter",property:"backdrop-filter",value:"blur(12px)"},{key:"webkit-backdrop-filter",property:"-webkit-backdrop-filter",value:"blur(12px)"},{key:"viewport-dvh",property:"height",value:"100dvh"}],y=["--color-surface-base","--color-surface-panel","--color-surface-floating","--color-surface-border","--color-surface-border-soft","--color-text-primary","--color-text-secondary","--color-accent-primary","--color-accent-primary-soft"],w=[".conversation-topbar",".topbar-menu",".conversation-run-popover",".chat-composer",".chat-composer__input",".composer-utility-menu__popover",".session-run-panel__command-card",".session-run-panel__input",".session-git-panel__summary"],b=["background-color","background-image","backdrop-filter","-webkit-backdrop-filter","border-color","box-shadow","color","display","opacity","position"],x=(t,r=180)=>{const n=(t??"").replace(/\s+/g," ").trim();return n?n.length<=r?n:`${n.slice(0,r-1).trimEnd()}…`:null},h=t=>Number(t.toFixed(2)),k=(t,r)=>{var n;if(typeof window>"u"||typeof((n=window.CSS)==null?void 0:n.supports)!="function")return!1;try{return window.CSS.supports(t,r)}catch{return!1}},_=()=>Object.fromEntries(v.map(t=>[t.key,k(t.property,t.value)])),S=()=>typeof document>"u"?[]:Array.from(document.styleSheets).map(t=>{var n,i;let r=null;try{r=t.cssRules.length}catch{r=null}return{href:t.href??null,owner_node:t.ownerNode instanceof Element?t.ownerNode.tagName.toLowerCase():null,media:((i=(n=t.media)==null?void 0:n.mediaText)==null?void 0:i.trim())||null,disabled:t.disabled,css_rule_count:r}}),N=()=>{if(typeof document>"u"||typeof window>"u")return[];const t=new Map,r=(n,i)=>{const o=n==null?void 0:n.trim();if(o)try{const l=new URL(o,window.location.href);if(!/^https?:$/i.test(l.protocol))return;t.set(l.toString(),i)}catch{return}};for(const n of document.styleSheets)r(n.href,"stylesheet");for(const n of Array.from(document.scripts))r(n.src,"script");for(const n of Array.from(document.querySelectorAll('link[rel~="manifest"]')))r(n.href,"manifest");for(const n of Array.from(document.querySelectorAll('link[rel~="icon"], link[rel="apple-touch-icon"]')))r(n.href,"icon");return Array.from(t.entries()).slice(0,20).map(([n,i])=>({url:n,kind:i}))},E=async t=>{const r=async n=>fetch(t.url,{method:n,cache:"no-store",redirect:"follow"});try{let n=await r("HEAD");return(n.status===405||n.status===501)&&(n=await r("GET")),{url:t.url,kind:t.kind,ok:n.ok,status:n.status,content_type:n.headers.get("content-type"),cache_control:n.headers.get("cache-control"),error:null}}catch(n){return{url:t.url,kind:t.kind,ok:!1,status:null,content_type:null,cache_control:null,error:n instanceof Error?n.message:"Unknown fetch failure"}}},C=()=>typeof performance>"u"||typeof performance.getEntriesByType!="function"?[]:performance.getEntriesByType("resource").map(t=>t).filter(t=>{const r=t.name.toLowerCase();return r.includes(".css")||r.includes(".js")||r.includes("manifest")||t.initiatorType==="link"||t.initiatorType==="script"}).slice(-40).map(t=>({name:t.name,initiator_type:t.initiatorType||null,duration_ms:h(t.duration),transfer_size:typeof t.transferSize=="number"?t.transferSize:null,decoded_body_size:typeof t.decodedBodySize=="number"?t.decodedBodySize:null})),T=()=>{if(typeof document>"u"||typeof window>"u")return{};const t=window.getComputedStyle(document.documentElement);return Object.fromEntries(y.map(r=>[r,t.getPropertyValue(r).trim()||"(empty)"]))},R=t=>{if(typeof document>"u"||typeof window>"u")return{selector:t,found:!1,text_preview:null,rect:null,computed:{}};const r=document.querySelector(t);if(!r)return{selector:t,found:!1,text_preview:null,rect:null,computed:{}};const n=r.getBoundingClientRect(),i=window.getComputedStyle(r);return{selector:t,found:!0,text_preview:x(r.textContent),rect:{x:h(n.x),y:h(n.y),width:h(n.width),height:h(n.height)},computed:Object.fromEntries(b.map(o=>[o,i.getPropertyValue(o).trim()||"(empty)"]))}},A=async()=>{if(typeof navigator>"u"||!("serviceWorker"in navigator))return{supported:!1,controller:!1,registrations:[]};try{const t=await navigator.serviceWorker.getRegistrations();return{supported:!0,controller:!!navigator.serviceWorker.controller,registrations:t.map(r=>{var n,i,o;return{scope:r.scope,active_script_url:((n=r.active)==null?void 0:n.scriptURL)??null,waiting_script_url:((i=r.waiting)==null?void 0:i.scriptURL)??null,installing_script_url:((o=r.installing)==null?void 0:o.scriptURL)??null}})}}catch{return{supported:!0,controller:!!navigator.serviceWorker.controller,registrations:[]}}},O=async()=>{if(typeof window>"u"||!("caches"in window))return{supported:!1,keys:[]};try{return{supported:!0,keys:await window.caches.keys()}}catch{return{supported:!0,keys:[]}}},L=t=>{const r=[];return t.feature_support["color-mix-oklab"]||r.push("当前浏览器不支持 color-mix(in oklab, ...),混色背景会直接失效,常见现象就是输入区或面板背景透明。"),!t.feature_support["backdrop-filter"]&&!t.feature_support["webkit-backdrop-filter"]&&r.push("当前浏览器不支持 backdrop-filter,磨砂浮层会退化成纯色面板。"),t.service_worker.controller&&t.cache.keys.length>0&&r.push(`检测到 ${t.cache.keys.length} 个 Cache Storage 项,若真机页面和桌面不一致,可以先清理缓存再重试。`),t.stylesheets.length===0&&r.push("当前页面没有读取到任何样式表对象,需要重点检查 CSS 是否被正确加载。"),t.resource_probes.some(n=>!n.ok)&&r.push("至少有一个静态资源探测失败,需要继续检查网络、缓存或 Service Worker 拦截。"),r},P=async()=>{var u,p,m,s,a,g;const t=N(),[r,n,i]=await Promise.all([A(),O(),Promise.all(t.map(f=>E(f)))]),o=navigator,l={width:window.innerWidth,height:window.innerHeight,device_pixel_ratio:window.devicePixelRatio||1,visual_width:((u=window.visualViewport)==null?void 0:u.width)??null,visual_height:((p=window.visualViewport)==null?void 0:p.height)??null,screen_width:((m=window.screen)==null?void 0:m.width)??null,screen_height:((s=window.screen)==null?void 0:s.height)??null},c={captured_at:new Date().toISOString(),page:{href:window.location.href,pathname:window.location.pathname,referrer:x(document.referrer),visibility_state:document.visibilityState??null},environment:{user_agent:navigator.userAgent,language:navigator.language??null,languages:Array.isArray(navigator.languages)?navigator.languages:[],platform:navigator.platform??null,vendor:navigator.vendor??null,online:typeof navigator.onLine=="boolean"?navigator.onLine:null,cookie_enabled:typeof navigator.cookieEnabled=="boolean"?navigator.cookieEnabled:null,secure_context:window.isSecureContext,standalone_display_mode:window.matchMedia("(display-mode: standalone)").matches,hardware_concurrency:typeof navigator.hardwareConcurrency=="number"?navigator.hardwareConcurrency:null,device_memory_gb:typeof o.deviceMemory=="number"?o.deviceMemory:null,max_touch_points:typeof navigator.maxTouchPoints=="number"?navigator.maxTouchPoints:null},viewport:l,feature_support:_(),service_worker:r,cache:n,manifest:{href:((a=document.querySelector('link[rel~="manifest"]'))==null?void 0:a.href)??null,rel:((g=document.querySelector('link[rel~="manifest"]'))==null?void 0:g.rel)??null},stylesheets:S(),resource_probes:i,performance_entries:C(),theme_variables:T(),element_snapshots:w.map(f=>R(f)),notes:[]};return c.notes=L(c),c},W=t=>t?"支持":"不支持",$=t=>t?t.feature_support["color-mix-oklab"]?t.resource_probes.some(r=>!r.ok)?"至少有一个静态资源探测失败,更像是 CSS 或脚本资源没有正确加载,或者被缓存 / Service Worker 干扰。":t.service_worker.controller&&t.cache.keys.length>0?"样式能力本身看起来正常,但页面被 Service Worker 控制且存在缓存,下一步要重点排查缓存是否陈旧。":"浏览器能力和基础资源看起来正常,下一步需要对比具体元素快照与安卓真机截图。":"高概率是安卓浏览器不支持 color-mix(in oklab, ...),导致输入框和面板的混色背景规则整体失效。":"正在采集浏览器能力、样式表、缓存和关键元素快照。",U=t=>{if(!t.found)return"未找到对应元素";const r=t.computed["background-color"]??"(empty)",n=t.computed["background-image"]??"(empty)";return r==="rgba(0, 0, 0, 0)"&&n==="none"?"背景完全透明":`${r} / ${n}`},M=()=>{const t=j(),[r,n]=d.useState(null),[i,o]=d.useState(!0),[l,c]=d.useState(null),u=async()=>{o(!0),c(null);try{const s=await P();d.startTransition(()=>{n(s)})}catch(s){c(s instanceof Error?`采集失败:${s.message}`:"采集失败,请稍后重试。")}finally{o(!1)}};d.useEffect(()=>{u()},[]);const p=async()=>{var s;if(r){if(typeof navigator>"u"||typeof((s=navigator.clipboard)==null?void 0:s.writeText)!="function"){c("当前浏览器不支持直接复制,请手动截图或长按选择。");return}try{await navigator.clipboard.writeText(JSON.stringify(r,null,2)),c("诊断 JSON 已复制,可以直接发给我继续分析。")}catch(a){c(a instanceof Error?`复制失败:${a.message}`:"复制失败,请手动截图或长按选择。")}}},m=d.useMemo(()=>$(r),[r]);return e.jsx("main",{className:"diagnostics-page",children:e.jsxs("div",{className:"diagnostics-shell",children:[e.jsxs("header",{className:"diagnostics-header",children:[e.jsxs("div",{className:"diagnostics-header__copy",children:[e.jsx("button",{type:"button",className:"diagnostics-back",onClick:()=>void t({to:"/settings"}),children:"返回设置"}),e.jsx("h1",{children:"安卓样式诊断"}),e.jsx("p",{children:"在手机上打开本页,可以直接检查浏览器能力、样式加载、缓存和关键面板快照。"})]}),e.jsxs("div",{className:"diagnostics-toolbar",children:[e.jsx("button",{type:"button",className:"diagnostics-button",onClick:()=>void u(),disabled:i,children:i?"采集中…":"刷新诊断"}),e.jsx("button",{type:"button",className:"diagnostics-button diagnostics-button--ghost",onClick:()=>void p(),disabled:!r,children:"复制 JSON"})]})]}),l?e.jsx("p",{className:"diagnostics-status",children:l}):null,e.jsxs("section",{className:"diagnostics-card diagnostics-card--hero",children:[e.jsx("span",{className:"diagnostics-eyebrow",children:"初步判断"}),e.jsx("h2",{children:m}),e.jsx("p",{children:"真机异常而桌面浏览器和 F12 模拟正常,最常见就是浏览器 CSS 能力和缓存状态与桌面环境不同。"}),r!=null&&r.notes.length?e.jsx("ul",{className:"diagnostics-list",children:r.notes.map(s=>e.jsx("li",{children:s},s))}):null]}),r?e.jsxs(e.Fragment,{children:[e.jsxs("section",{className:"diagnostics-grid",children:[e.jsxs("article",{className:"diagnostics-card",children:[e.jsx("h2",{children:"环境"}),e.jsxs("dl",{className:"diagnostics-kv",children:[e.jsxs("div",{children:[e.jsx("dt",{children:"页面"}),e.jsx("dd",{children:r.page.pathname})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"安全上下文"}),e.jsx("dd",{children:r.environment.secure_context?"是":"否"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"独立窗口"}),e.jsx("dd",{children:r.environment.standalone_display_mode?"是":"否"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"在线状态"}),e.jsx("dd",{children:r.environment.online==null?"未知":r.environment.online?"在线":"离线"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"视口"}),e.jsxs("dd",{children:[r.viewport.width," x ",r.viewport.height," @ ",r.viewport.device_pixel_ratio]})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"UA"}),e.jsx("dd",{className:"diagnostics-break",children:r.environment.user_agent})]})]})]}),e.jsxs("article",{className:"diagnostics-card",children:[e.jsx("h2",{children:"浏览器能力"}),e.jsx("dl",{className:"diagnostics-kv",children:Object.entries(r.feature_support).map(([s,a])=>e.jsxs("div",{children:[e.jsx("dt",{children:s}),e.jsx("dd",{children:W(a)})]},s))})]}),e.jsxs("article",{className:"diagnostics-card",children:[e.jsx("h2",{children:"缓存与 SW"}),e.jsxs("dl",{className:"diagnostics-kv",children:[e.jsxs("div",{children:[e.jsx("dt",{children:"Service Worker"}),e.jsx("dd",{children:r.service_worker.supported?"支持":"不支持"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"当前受控"}),e.jsx("dd",{children:r.service_worker.controller?"是":"否"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"注册数量"}),e.jsx("dd",{children:r.service_worker.registrations.length})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"Cache Storage"}),e.jsx("dd",{children:r.cache.supported?r.cache.keys.join(", ")||"空":"不支持"})]})]})]}),e.jsxs("article",{className:"diagnostics-card",children:[e.jsx("h2",{children:"主题变量"}),e.jsx("dl",{className:"diagnostics-kv",children:Object.entries(r.theme_variables).map(([s,a])=>e.jsxs("div",{children:[e.jsx("dt",{children:s}),e.jsx("dd",{children:a})]},s))})]})]}),e.jsxs("section",{className:"diagnostics-card",children:[e.jsx("h2",{children:"资源探测"}),e.jsx("div",{className:"diagnostics-table-wrap",children:e.jsxs("table",{className:"diagnostics-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"类型"}),e.jsx("th",{children:"URL"}),e.jsx("th",{children:"状态"}),e.jsx("th",{children:"内容类型"}),e.jsx("th",{children:"Cache-Control"})]})}),e.jsx("tbody",{children:r.resource_probes.map(s=>e.jsxs("tr",{children:[e.jsx("td",{children:s.kind}),e.jsx("td",{className:"diagnostics-break",children:s.url}),e.jsx("td",{children:s.ok?`OK (${s.status??"-"})`:`失败 (${s.status??"-"})`}),e.jsx("td",{children:s.content_type??"-"}),e.jsx("td",{children:s.cache_control??s.error??"-"})]},`${s.kind}:${s.url}`))})]})})]}),e.jsxs("section",{className:"diagnostics-card",children:[e.jsx("h2",{children:"关键元素快照"}),e.jsx("div",{className:"diagnostics-element-grid",children:r.element_snapshots.map(s=>e.jsxs("article",{className:"diagnostics-element-card",children:[e.jsx("h3",{children:s.selector}),e.jsx("p",{children:U(s)}),e.jsxs("dl",{className:"diagnostics-kv diagnostics-kv--compact",children:[e.jsxs("div",{children:[e.jsx("dt",{children:"找到元素"}),e.jsx("dd",{children:s.found?"是":"否"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"尺寸"}),e.jsx("dd",{children:s.rect?`${s.rect.width} x ${s.rect.height}`:"-"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"背景色"}),e.jsx("dd",{children:s.computed["background-color"]??"-"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"背景图"}),e.jsx("dd",{className:"diagnostics-break",children:s.computed["background-image"]??"-"})]})]})]},s.selector))})]}),e.jsxs("section",{className:"diagnostics-card",children:[e.jsx("h2",{children:"原始 JSON"}),e.jsx("pre",{className:"diagnostics-json",children:JSON.stringify(r,null,2)})]})]}):e.jsx("section",{className:"diagnostics-card",children:e.jsx("p",{children:"正在等待诊断结果…"})})]})})};export{M as DiagnosticsPage};
|
|
1
|
+
import{u as j,r as d,j as e}from"./index-OTfJjsxL.js";const v=[{key:"color-mix-oklab",property:"background",value:"color-mix(in oklab, white 50%, black)"},{key:"color-mix-srgb",property:"background",value:"color-mix(in srgb, white 50%, black)"},{key:"backdrop-filter",property:"backdrop-filter",value:"blur(12px)"},{key:"webkit-backdrop-filter",property:"-webkit-backdrop-filter",value:"blur(12px)"},{key:"viewport-dvh",property:"height",value:"100dvh"}],y=["--color-surface-base","--color-surface-panel","--color-surface-floating","--color-surface-border","--color-surface-border-soft","--color-text-primary","--color-text-secondary","--color-accent-primary","--color-accent-primary-soft"],w=[".conversation-topbar",".topbar-menu",".conversation-run-popover",".chat-composer",".chat-composer__input",".composer-utility-menu__popover",".session-run-panel__command-card",".session-run-panel__input",".session-git-panel__summary"],b=["background-color","background-image","backdrop-filter","-webkit-backdrop-filter","border-color","box-shadow","color","display","opacity","position"],x=(t,r=180)=>{const n=(t??"").replace(/\s+/g," ").trim();return n?n.length<=r?n:`${n.slice(0,r-1).trimEnd()}…`:null},h=t=>Number(t.toFixed(2)),k=(t,r)=>{var n;if(typeof window>"u"||typeof((n=window.CSS)==null?void 0:n.supports)!="function")return!1;try{return window.CSS.supports(t,r)}catch{return!1}},_=()=>Object.fromEntries(v.map(t=>[t.key,k(t.property,t.value)])),S=()=>typeof document>"u"?[]:Array.from(document.styleSheets).map(t=>{var n,i;let r=null;try{r=t.cssRules.length}catch{r=null}return{href:t.href??null,owner_node:t.ownerNode instanceof Element?t.ownerNode.tagName.toLowerCase():null,media:((i=(n=t.media)==null?void 0:n.mediaText)==null?void 0:i.trim())||null,disabled:t.disabled,css_rule_count:r}}),N=()=>{if(typeof document>"u"||typeof window>"u")return[];const t=new Map,r=(n,i)=>{const o=n==null?void 0:n.trim();if(o)try{const l=new URL(o,window.location.href);if(!/^https?:$/i.test(l.protocol))return;t.set(l.toString(),i)}catch{return}};for(const n of document.styleSheets)r(n.href,"stylesheet");for(const n of Array.from(document.scripts))r(n.src,"script");for(const n of Array.from(document.querySelectorAll('link[rel~="manifest"]')))r(n.href,"manifest");for(const n of Array.from(document.querySelectorAll('link[rel~="icon"], link[rel="apple-touch-icon"]')))r(n.href,"icon");return Array.from(t.entries()).slice(0,20).map(([n,i])=>({url:n,kind:i}))},E=async t=>{const r=async n=>fetch(t.url,{method:n,cache:"no-store",redirect:"follow"});try{let n=await r("HEAD");return(n.status===405||n.status===501)&&(n=await r("GET")),{url:t.url,kind:t.kind,ok:n.ok,status:n.status,content_type:n.headers.get("content-type"),cache_control:n.headers.get("cache-control"),error:null}}catch(n){return{url:t.url,kind:t.kind,ok:!1,status:null,content_type:null,cache_control:null,error:n instanceof Error?n.message:"Unknown fetch failure"}}},C=()=>typeof performance>"u"||typeof performance.getEntriesByType!="function"?[]:performance.getEntriesByType("resource").map(t=>t).filter(t=>{const r=t.name.toLowerCase();return r.includes(".css")||r.includes(".js")||r.includes("manifest")||t.initiatorType==="link"||t.initiatorType==="script"}).slice(-40).map(t=>({name:t.name,initiator_type:t.initiatorType||null,duration_ms:h(t.duration),transfer_size:typeof t.transferSize=="number"?t.transferSize:null,decoded_body_size:typeof t.decodedBodySize=="number"?t.decodedBodySize:null})),T=()=>{if(typeof document>"u"||typeof window>"u")return{};const t=window.getComputedStyle(document.documentElement);return Object.fromEntries(y.map(r=>[r,t.getPropertyValue(r).trim()||"(empty)"]))},R=t=>{if(typeof document>"u"||typeof window>"u")return{selector:t,found:!1,text_preview:null,rect:null,computed:{}};const r=document.querySelector(t);if(!r)return{selector:t,found:!1,text_preview:null,rect:null,computed:{}};const n=r.getBoundingClientRect(),i=window.getComputedStyle(r);return{selector:t,found:!0,text_preview:x(r.textContent),rect:{x:h(n.x),y:h(n.y),width:h(n.width),height:h(n.height)},computed:Object.fromEntries(b.map(o=>[o,i.getPropertyValue(o).trim()||"(empty)"]))}},A=async()=>{if(typeof navigator>"u"||!("serviceWorker"in navigator))return{supported:!1,controller:!1,registrations:[]};try{const t=await navigator.serviceWorker.getRegistrations();return{supported:!0,controller:!!navigator.serviceWorker.controller,registrations:t.map(r=>{var n,i,o;return{scope:r.scope,active_script_url:((n=r.active)==null?void 0:n.scriptURL)??null,waiting_script_url:((i=r.waiting)==null?void 0:i.scriptURL)??null,installing_script_url:((o=r.installing)==null?void 0:o.scriptURL)??null}})}}catch{return{supported:!0,controller:!!navigator.serviceWorker.controller,registrations:[]}}},O=async()=>{if(typeof window>"u"||!("caches"in window))return{supported:!1,keys:[]};try{return{supported:!0,keys:await window.caches.keys()}}catch{return{supported:!0,keys:[]}}},L=t=>{const r=[];return t.feature_support["color-mix-oklab"]||r.push("当前浏览器不支持 color-mix(in oklab, ...),混色背景会直接失效,常见现象就是输入区或面板背景透明。"),!t.feature_support["backdrop-filter"]&&!t.feature_support["webkit-backdrop-filter"]&&r.push("当前浏览器不支持 backdrop-filter,磨砂浮层会退化成纯色面板。"),t.service_worker.controller&&t.cache.keys.length>0&&r.push(`检测到 ${t.cache.keys.length} 个 Cache Storage 项,若真机页面和桌面不一致,可以先清理缓存再重试。`),t.stylesheets.length===0&&r.push("当前页面没有读取到任何样式表对象,需要重点检查 CSS 是否被正确加载。"),t.resource_probes.some(n=>!n.ok)&&r.push("至少有一个静态资源探测失败,需要继续检查网络、缓存或 Service Worker 拦截。"),r},P=async()=>{var u,p,m,s,a,g;const t=N(),[r,n,i]=await Promise.all([A(),O(),Promise.all(t.map(f=>E(f)))]),o=navigator,l={width:window.innerWidth,height:window.innerHeight,device_pixel_ratio:window.devicePixelRatio||1,visual_width:((u=window.visualViewport)==null?void 0:u.width)??null,visual_height:((p=window.visualViewport)==null?void 0:p.height)??null,screen_width:((m=window.screen)==null?void 0:m.width)??null,screen_height:((s=window.screen)==null?void 0:s.height)??null},c={captured_at:new Date().toISOString(),page:{href:window.location.href,pathname:window.location.pathname,referrer:x(document.referrer),visibility_state:document.visibilityState??null},environment:{user_agent:navigator.userAgent,language:navigator.language??null,languages:Array.isArray(navigator.languages)?navigator.languages:[],platform:navigator.platform??null,vendor:navigator.vendor??null,online:typeof navigator.onLine=="boolean"?navigator.onLine:null,cookie_enabled:typeof navigator.cookieEnabled=="boolean"?navigator.cookieEnabled:null,secure_context:window.isSecureContext,standalone_display_mode:window.matchMedia("(display-mode: standalone)").matches,hardware_concurrency:typeof navigator.hardwareConcurrency=="number"?navigator.hardwareConcurrency:null,device_memory_gb:typeof o.deviceMemory=="number"?o.deviceMemory:null,max_touch_points:typeof navigator.maxTouchPoints=="number"?navigator.maxTouchPoints:null},viewport:l,feature_support:_(),service_worker:r,cache:n,manifest:{href:((a=document.querySelector('link[rel~="manifest"]'))==null?void 0:a.href)??null,rel:((g=document.querySelector('link[rel~="manifest"]'))==null?void 0:g.rel)??null},stylesheets:S(),resource_probes:i,performance_entries:C(),theme_variables:T(),element_snapshots:w.map(f=>R(f)),notes:[]};return c.notes=L(c),c},W=t=>t?"支持":"不支持",$=t=>t?t.feature_support["color-mix-oklab"]?t.resource_probes.some(r=>!r.ok)?"至少有一个静态资源探测失败,更像是 CSS 或脚本资源没有正确加载,或者被缓存 / Service Worker 干扰。":t.service_worker.controller&&t.cache.keys.length>0?"样式能力本身看起来正常,但页面被 Service Worker 控制且存在缓存,下一步要重点排查缓存是否陈旧。":"浏览器能力和基础资源看起来正常,下一步需要对比具体元素快照与安卓真机截图。":"高概率是安卓浏览器不支持 color-mix(in oklab, ...),导致输入框和面板的混色背景规则整体失效。":"正在采集浏览器能力、样式表、缓存和关键元素快照。",U=t=>{if(!t.found)return"未找到对应元素";const r=t.computed["background-color"]??"(empty)",n=t.computed["background-image"]??"(empty)";return r==="rgba(0, 0, 0, 0)"&&n==="none"?"背景完全透明":`${r} / ${n}`},M=()=>{const t=j(),[r,n]=d.useState(null),[i,o]=d.useState(!0),[l,c]=d.useState(null),u=async()=>{o(!0),c(null);try{const s=await P();d.startTransition(()=>{n(s)})}catch(s){c(s instanceof Error?`采集失败:${s.message}`:"采集失败,请稍后重试。")}finally{o(!1)}};d.useEffect(()=>{u()},[]);const p=async()=>{var s;if(r){if(typeof navigator>"u"||typeof((s=navigator.clipboard)==null?void 0:s.writeText)!="function"){c("当前浏览器不支持直接复制,请手动截图或长按选择。");return}try{await navigator.clipboard.writeText(JSON.stringify(r,null,2)),c("诊断 JSON 已复制,可以直接发给我继续分析。")}catch(a){c(a instanceof Error?`复制失败:${a.message}`:"复制失败,请手动截图或长按选择。")}}},m=d.useMemo(()=>$(r),[r]);return e.jsx("main",{className:"diagnostics-page",children:e.jsxs("div",{className:"diagnostics-shell",children:[e.jsxs("header",{className:"diagnostics-header",children:[e.jsxs("div",{className:"diagnostics-header__copy",children:[e.jsx("button",{type:"button",className:"diagnostics-back",onClick:()=>void t({to:"/settings"}),children:"返回设置"}),e.jsx("h1",{children:"安卓样式诊断"}),e.jsx("p",{children:"在手机上打开本页,可以直接检查浏览器能力、样式加载、缓存和关键面板快照。"})]}),e.jsxs("div",{className:"diagnostics-toolbar",children:[e.jsx("button",{type:"button",className:"diagnostics-button",onClick:()=>void u(),disabled:i,children:i?"采集中…":"刷新诊断"}),e.jsx("button",{type:"button",className:"diagnostics-button diagnostics-button--ghost",onClick:()=>void p(),disabled:!r,children:"复制 JSON"})]})]}),l?e.jsx("p",{className:"diagnostics-status",children:l}):null,e.jsxs("section",{className:"diagnostics-card diagnostics-card--hero",children:[e.jsx("span",{className:"diagnostics-eyebrow",children:"初步判断"}),e.jsx("h2",{children:m}),e.jsx("p",{children:"真机异常而桌面浏览器和 F12 模拟正常,最常见就是浏览器 CSS 能力和缓存状态与桌面环境不同。"}),r!=null&&r.notes.length?e.jsx("ul",{className:"diagnostics-list",children:r.notes.map(s=>e.jsx("li",{children:s},s))}):null]}),r?e.jsxs(e.Fragment,{children:[e.jsxs("section",{className:"diagnostics-grid",children:[e.jsxs("article",{className:"diagnostics-card",children:[e.jsx("h2",{children:"环境"}),e.jsxs("dl",{className:"diagnostics-kv",children:[e.jsxs("div",{children:[e.jsx("dt",{children:"页面"}),e.jsx("dd",{children:r.page.pathname})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"安全上下文"}),e.jsx("dd",{children:r.environment.secure_context?"是":"否"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"独立窗口"}),e.jsx("dd",{children:r.environment.standalone_display_mode?"是":"否"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"在线状态"}),e.jsx("dd",{children:r.environment.online==null?"未知":r.environment.online?"在线":"离线"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"视口"}),e.jsxs("dd",{children:[r.viewport.width," x ",r.viewport.height," @ ",r.viewport.device_pixel_ratio]})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"UA"}),e.jsx("dd",{className:"diagnostics-break",children:r.environment.user_agent})]})]})]}),e.jsxs("article",{className:"diagnostics-card",children:[e.jsx("h2",{children:"浏览器能力"}),e.jsx("dl",{className:"diagnostics-kv",children:Object.entries(r.feature_support).map(([s,a])=>e.jsxs("div",{children:[e.jsx("dt",{children:s}),e.jsx("dd",{children:W(a)})]},s))})]}),e.jsxs("article",{className:"diagnostics-card",children:[e.jsx("h2",{children:"缓存与 SW"}),e.jsxs("dl",{className:"diagnostics-kv",children:[e.jsxs("div",{children:[e.jsx("dt",{children:"Service Worker"}),e.jsx("dd",{children:r.service_worker.supported?"支持":"不支持"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"当前受控"}),e.jsx("dd",{children:r.service_worker.controller?"是":"否"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"注册数量"}),e.jsx("dd",{children:r.service_worker.registrations.length})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"Cache Storage"}),e.jsx("dd",{children:r.cache.supported?r.cache.keys.join(", ")||"空":"不支持"})]})]})]}),e.jsxs("article",{className:"diagnostics-card",children:[e.jsx("h2",{children:"主题变量"}),e.jsx("dl",{className:"diagnostics-kv",children:Object.entries(r.theme_variables).map(([s,a])=>e.jsxs("div",{children:[e.jsx("dt",{children:s}),e.jsx("dd",{children:a})]},s))})]})]}),e.jsxs("section",{className:"diagnostics-card",children:[e.jsx("h2",{children:"资源探测"}),e.jsx("div",{className:"diagnostics-table-wrap",children:e.jsxs("table",{className:"diagnostics-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"类型"}),e.jsx("th",{children:"URL"}),e.jsx("th",{children:"状态"}),e.jsx("th",{children:"内容类型"}),e.jsx("th",{children:"Cache-Control"})]})}),e.jsx("tbody",{children:r.resource_probes.map(s=>e.jsxs("tr",{children:[e.jsx("td",{children:s.kind}),e.jsx("td",{className:"diagnostics-break",children:s.url}),e.jsx("td",{children:s.ok?`OK (${s.status??"-"})`:`失败 (${s.status??"-"})`}),e.jsx("td",{children:s.content_type??"-"}),e.jsx("td",{children:s.cache_control??s.error??"-"})]},`${s.kind}:${s.url}`))})]})})]}),e.jsxs("section",{className:"diagnostics-card",children:[e.jsx("h2",{children:"关键元素快照"}),e.jsx("div",{className:"diagnostics-element-grid",children:r.element_snapshots.map(s=>e.jsxs("article",{className:"diagnostics-element-card",children:[e.jsx("h3",{children:s.selector}),e.jsx("p",{children:U(s)}),e.jsxs("dl",{className:"diagnostics-kv diagnostics-kv--compact",children:[e.jsxs("div",{children:[e.jsx("dt",{children:"找到元素"}),e.jsx("dd",{children:s.found?"是":"否"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"尺寸"}),e.jsx("dd",{children:s.rect?`${s.rect.width} x ${s.rect.height}`:"-"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"背景色"}),e.jsx("dd",{children:s.computed["background-color"]??"-"})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"背景图"}),e.jsx("dd",{className:"diagnostics-break",children:s.computed["background-image"]??"-"})]})]})]},s.selector))})]}),e.jsxs("section",{className:"diagnostics-card",children:[e.jsx("h2",{children:"原始 JSON"}),e.jsx("pre",{className:"diagnostics-json",children:JSON.stringify(r,null,2)})]})]}):e.jsx("section",{className:"diagnostics-card",children:e.jsx("p",{children:"正在等待诊断结果…"})})]})})};export{M as DiagnosticsPage};
|