Skip to content

Commit 015cfec

Browse files
authored
Sync switch execution mode display
Read current execution mode/dry_run_only for strategy switch UI and display paper mode as Dry run.
1 parent 983752d commit 015cfec

3 files changed

Lines changed: 91 additions & 13 deletions

File tree

web/strategy-switch-console/index.html

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,7 @@ <h2 data-i18n="summary">切换摘要</h2>
681681
strategy: "策略",
682682
mode: "模式",
683683
live: "实盘",
684-
paper: "模拟",
684+
paper: "Dry run",
685685
summary: "切换摘要",
686686
copySummary: "复制摘要",
687687
loginToRun: "登录后切换",
@@ -718,7 +718,7 @@ <h2 data-i18n="summary">切换摘要</h2>
718718
strategy: "Strategy",
719719
mode: "Mode",
720720
live: "Live",
721-
paper: "Paper",
721+
paper: "Dry run",
722722
summary: "Switch Summary",
723723
copySummary: "Copy summary",
724724
loginToRun: "Sign in to switch",
@@ -827,18 +827,57 @@ <h2 data-i18n="summary">切换摘要</h2>
827827
return strategyLabels[profile] || profile;
828828
}
829829

830-
function currentStrategyForAccount(platform, account) {
830+
function modeLabel(mode) {
831+
return mode === "paper" ? t("paper") : t("live");
832+
}
833+
834+
function currentEntryForAccount(platform, account) {
831835
const byPlatform = state.currentStrategies[platform] || {};
832836
const keys = [account?.key, account?.target_name, account?.label]
833837
.filter(Boolean)
834838
.map((value) => String(value));
835839
for (const key of keys) {
836-
const profile = cleanStrategyProfile(byPlatform[key]?.strategy_profile);
837-
if (profile) return profile;
840+
const entry = byPlatform[key];
841+
const profile = cleanStrategyProfile(entry?.strategy_profile);
842+
if (profile) return entry;
838843
}
844+
return null;
845+
}
846+
847+
function currentStrategyForAccount(platform, account) {
848+
const entry = currentEntryForAccount(platform, account);
849+
const profile = cleanStrategyProfile(entry?.strategy_profile);
850+
return profile || "";
851+
}
852+
853+
function normalizeExecutionMode(value, dryRunOnly) {
854+
const mode = String(value || "").trim().toLowerCase();
855+
if (mode === "live" || mode === "paper") return mode;
856+
if (dryRunOnly === true || dryRunOnly === "true" || dryRunOnly === "1" || dryRunOnly === 1) return "paper";
857+
if (dryRunOnly === false || dryRunOnly === "false" || dryRunOnly === "0" || dryRunOnly === 0) return "live";
839858
return "";
840859
}
841860

861+
function defaultExecutionModeForAccount(platform, account, fallback = "live") {
862+
const currentMode = normalizeExecutionMode(
863+
currentEntryForAccount(platform, account)?.execution_mode,
864+
currentEntryForAccount(platform, account)?.dry_run_only,
865+
);
866+
if (currentMode) return currentMode;
867+
const hint = [
868+
account?.key,
869+
account?.label,
870+
account?.target_name,
871+
account?.deployment_selector,
872+
account?.account_scope,
873+
account?.service_name,
874+
].join(" ").toLowerCase();
875+
if (hint.split(/\s+/).includes("paper") || hint.includes("-paper") || hint.includes("_paper")) {
876+
return "paper";
877+
}
878+
return fallback;
879+
}
880+
842881
function defaultStrategyForAccount(platform, account, fallback = "tqqq_growth_income") {
843882
const currentProfile = currentStrategyForAccount(platform, account);
844883
if (currentProfile) return currentProfile;
@@ -862,6 +901,10 @@ <h2 data-i18n="summary">切换摘要</h2>
862901
const account = selectedAccount(platform);
863902
if (!account) return;
864903
state.forms[platform].strategy = defaultStrategyForAccount(platform, account, state.forms[platform].strategy);
904+
state.forms[platform].executionMode = defaultExecutionModeForAccount(
905+
platform,
906+
account,
907+
);
865908
}
866909

867910
function ensureAccountSelection(platform) {
@@ -923,7 +966,7 @@ <h2 data-i18n="summary">切换摘要</h2>
923966
[t("repository"), repositories[state.selected]],
924967
[t("selectedAccount"), account.label],
925968
[t("selectedStrategy"), strategyLabel(inputs.strategy_profile)],
926-
[t("selectedMode"), inputs.execution_mode],
969+
[t("selectedMode"), modeLabel(inputs.execution_mode)],
927970
[t("target"), inputs.target_name],
928971
[t("accountSelector"), inputs.account_selector || "auto"],
929972
[t("service"), inputs.service_name || derivedService(state.selected, inputs.target_name)],
@@ -1001,7 +1044,7 @@ <h2 data-i18n="summary">切换摘要</h2>
10011044
</div>
10021045
`).join("");
10031046

1004-
el("mode-pill").textContent = inputs.execution_mode;
1047+
el("mode-pill").textContent = modeLabel(inputs.execution_mode);
10051048
}
10061049

10071050
function renderAuth() {
@@ -1125,6 +1168,8 @@ <h2 data-i18n="summary">切换摘要</h2>
11251168
if (!profile) continue;
11261169
normalized[platform][String(key)] = {
11271170
strategy_profile: profile,
1171+
execution_mode: normalizeExecutionMode(entry?.execution_mode, entry?.dry_run_only),
1172+
dry_run_only: entry?.dry_run_only === true || entry?.dry_run_only === "true" || entry?.dry_run_only === "1",
11281173
source: entry?.source ? String(entry.source) : "",
11291174
};
11301175
}

web/strategy-switch-console/page_asset.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web/strategy-switch-console/worker.js

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -480,10 +480,12 @@ async function loadCurrentStrategies(accountOptions, env) {
480480

481481
async function resolveCurrentStrategyForAccount({ platform, option, optionsCount, repository, readVariable }) {
482482
const serviceTargetsValue = await readVariable(repository, "repository", "", "CLOUD_RUN_SERVICE_TARGETS_JSON");
483-
const serviceTargetProfile = strategyFromServiceTargets(serviceTargetsValue, platform, option);
483+
const serviceTarget = runtimeTargetFromServiceTargets(serviceTargetsValue, platform, option);
484+
const serviceTargetProfile = cleanCurrentStrategy(serviceTarget?.strategy_profile);
484485
if (serviceTargetProfile) {
485486
return {
486487
strategy_profile: serviceTargetProfile,
488+
...runtimeModePayload(serviceTarget),
487489
source: "CLOUD_RUN_SERVICE_TARGETS_JSON",
488490
variable_scope: "repository",
489491
};
@@ -498,6 +500,7 @@ async function resolveCurrentStrategyForAccount({ platform, option, optionsCount
498500
if (runtimeTargetProfile) {
499501
return {
500502
strategy_profile: runtimeTargetProfile,
503+
...runtimeModePayload(runtimeTarget),
501504
source: "RUNTIME_TARGET_JSON",
502505
variable_scope: variableScope,
503506
github_environment: githubEnvironment || "",
@@ -508,12 +511,16 @@ async function resolveCurrentStrategyForAccount({ platform, option, optionsCount
508511
const profileValue = await readVariable(repository, variableScope, githubEnvironment, "STRATEGY_PROFILE");
509512
const profile = cleanCurrentStrategy(profileValue);
510513
if (profile) {
511-
return {
514+
const current = {
512515
strategy_profile: profile,
513516
source: "STRATEGY_PROFILE",
514517
variable_scope: variableScope,
515518
github_environment: githubEnvironment || "",
516519
};
520+
if (variableScope === "environment" && normalizeMatchValue(option?.target_name) === "paper") {
521+
current.execution_mode = "paper";
522+
}
523+
return current;
517524
}
518525
}
519526

@@ -834,7 +841,7 @@ function resolveGithubEnvironment(platform, option, variableScope) {
834841
return targetName;
835842
}
836843

837-
function strategyFromServiceTargets(rawValue, platform, option) {
844+
function runtimeTargetFromServiceTargets(rawValue, platform, option) {
838845
const payload = parseJsonObject(rawValue);
839846
const targets = Array.isArray(payload?.targets) ? payload.targets : [];
840847
for (const entry of targets) {
@@ -843,12 +850,38 @@ function strategyFromServiceTargets(rawValue, platform, option) {
843850
? entry.runtime_target
844851
: {};
845852
if (!runtimeTargetMatchesAccount(runtimeTarget, platform, option, entry)) continue;
846-
const profile = cleanCurrentStrategy(runtimeTarget.strategy_profile || entry.strategy_profile);
847-
if (profile) return profile;
853+
return {
854+
...runtimeTarget,
855+
strategy_profile: runtimeTarget.strategy_profile || entry.strategy_profile,
856+
};
848857
}
858+
return null;
859+
}
860+
861+
function runtimeModePayload(runtimeTarget) {
862+
const executionMode = normalizeRuntimeExecutionMode(runtimeTarget?.execution_mode, runtimeTarget?.dry_run_only);
863+
const payload = {};
864+
if (executionMode) payload.execution_mode = executionMode;
865+
const dryRunOnly = cleanOptionalBoolean(runtimeTarget?.dry_run_only);
866+
if (dryRunOnly !== null) payload.dry_run_only = dryRunOnly;
867+
return payload;
868+
}
869+
870+
function normalizeRuntimeExecutionMode(value, dryRunOnly) {
871+
const mode = String(value || "").trim().toLowerCase();
872+
if (mode === "live" || mode === "paper") return mode;
873+
const dryRun = cleanOptionalBoolean(dryRunOnly);
874+
if (dryRun === true) return "paper";
875+
if (dryRun === false) return "live";
849876
return "";
850877
}
851878

879+
function cleanOptionalBoolean(value) {
880+
if (value === true || value === "true" || value === "1" || value === 1) return true;
881+
if (value === false || value === "false" || value === "0" || value === 0) return false;
882+
return null;
883+
}
884+
852885
function runtimeTargetMatchesAccount(runtimeTarget, platform, option, entry = {}) {
853886
const runtimePlatform = String(runtimeTarget?.platform_id || "").trim().toLowerCase();
854887
if (runtimePlatform && runtimePlatform !== platform) return false;

0 commit comments

Comments
 (0)