kdczyz-dsh-model 1.2.2-beta → 1.2.4-beta
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.
|
@@ -273,21 +273,12 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
273
273
|
.wotr-credit-region-title{font-size:11px;font-weight:600;color:var(--dsw-alias-label-primary)}
|
|
274
274
|
.wotr-credit-region-sub{font-size:11px;color:var(--dsw-alias-label-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
275
275
|
.wotr-credit-row{margin-top:6px;padding:8px;border:.5px solid var(--dsw-alias-border-l2);border-radius:8px;display:flex;flex-direction:column;gap:6px}
|
|
276
|
-
.wotr-credit-row[data-off="1"]{opacity:.55}
|
|
277
276
|
.wotr-credit-row[data-serving="1"]{border-color:var(--dsw-alias-label-primary)}
|
|
278
277
|
.wotr-credit-row-top{display:flex;align-items:baseline;gap:8px;justify-content:space-between}
|
|
279
278
|
.wotr-credit-row-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-primary);font-weight:600}
|
|
280
279
|
.wotr-credit-row-credits{flex:none;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary)}
|
|
281
280
|
.wotr-credit-row-foot{display:flex;align-items:center;justify-content:space-between;gap:8px}
|
|
282
281
|
.wotr-credit-tags{display:flex;align-items:center;gap:4px;flex-wrap:wrap;min-width:0}
|
|
283
|
-
/* 启停开关:本页自绘(不引 primitives 的 Switch),配色沿用本文件
|
|
284
|
-
既有的 token 组合 —— 开 = label-primary 底 + bg-layer-1 滑块,
|
|
285
|
-
与 .wbc-btn-primary 同一套对比关系,深浅色主题下都不会糊。 */
|
|
286
|
-
.wotr-credit-switch{position:relative;flex:none;width:30px;height:16px;padding:0;border:none;border-radius:8px;background:var(--dsw-alias-bg-layer-3,rgba(127,127,127,.35));cursor:pointer;transition:background .12s ease-out}
|
|
287
|
-
.wotr-credit-switch::after{content:'';position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:50%;background:var(--dsw-alias-label-secondary,#888);transition:transform .12s ease-out,background .12s ease-out}
|
|
288
|
-
.wotr-credit-switch[data-on="1"]{background:var(--dsw-alias-label-primary,#4c8dff)}
|
|
289
|
-
.wotr-credit-switch[data-on="1"]::after{transform:translateX(14px);background:var(--dsw-alias-bg-layer-1,#fff)}
|
|
290
|
-
.wotr-credit-switch:disabled{opacity:.5;cursor:default}
|
|
291
282
|
.wotr-credit-foot{margin-top:10px;padding-top:8px;border-top:.5px solid var(--dsw-alias-border-l2);font-size:11px;line-height:16px}
|
|
292
283
|
.wotr-credit-note{margin-top:6px;font-size:11px;line-height:16px;color:var(--dsw-alias-label-primary)}
|
|
293
284
|
.wotr-credit-err{margin-top:6px;font-size:11px;line-height:16px;color:var(--dsw-alias-label-error,#e5484d)}
|
|
@@ -645,7 +636,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
645
636
|
const ignored = asArray(status?.ignored);
|
|
646
637
|
const selection = status?.selection ?? {};
|
|
647
638
|
const automation = status?.automation;
|
|
648
|
-
const usable = accounts.filter((a) => a.disabled !== true).length;
|
|
649
639
|
const automationOn = automation?.enabled === true;
|
|
650
640
|
|
|
651
641
|
const draft = draftByRegion[region];
|
|
@@ -696,17 +686,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
696
686
|
}
|
|
697
687
|
};
|
|
698
688
|
|
|
699
|
-
// —— 账号启停 ——
|
|
700
|
-
const onToggleDisabled = (accountId, disabled) => {
|
|
701
|
-
if (!writable) return;
|
|
702
|
-
return run(accountId, () =>
|
|
703
|
-
fetchJson(`${POOL_API}/accounts/disabled`, {
|
|
704
|
-
method: 'POST',
|
|
705
|
-
headers: { 'Content-Type': 'application/json' },
|
|
706
|
-
body: JSON.stringify({ accountId, disabled }),
|
|
707
|
-
}), disabled ? '已停用该账号' : '已重新启用该账号');
|
|
708
|
-
};
|
|
709
|
-
|
|
710
689
|
// —— 移出池子 / 恢复 ——
|
|
711
690
|
const onIgnore = (accountId, ignoredNext) => {
|
|
712
691
|
return run(`ignore-${accountId}`, () =>
|
|
@@ -1042,7 +1021,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
1042
1021
|
: jsx(StatsRow, {
|
|
1043
1022
|
items: [
|
|
1044
1023
|
{ label: '账号', value: fmtNum(accounts.length), sub: '个已登录' },
|
|
1045
|
-
{ label: '可用', value: fmtNum(usable), sub: '未被停用' },
|
|
1046
1024
|
{
|
|
1047
1025
|
label: '当前使用',
|
|
1048
1026
|
value: currentName,
|
|
@@ -1082,12 +1060,11 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
1082
1060
|
AccountCard,
|
|
1083
1061
|
{
|
|
1084
1062
|
name: a.nickname || a.label || a.id,
|
|
1085
|
-
dim:
|
|
1063
|
+
dim: (currentId !== '' && isCurrent !== true),
|
|
1086
1064
|
tags: [
|
|
1087
1065
|
isCurrent
|
|
1088
1066
|
? { text: '当前使用', cls: 'wbc-tag wbc-tag-on' }
|
|
1089
1067
|
: { text: '备用', cls: 'wbc-tag' },
|
|
1090
|
-
a.disabled === true ? { text: '已停用', cls: 'wbc-tag' } : null,
|
|
1091
1068
|
],
|
|
1092
1069
|
rows: [
|
|
1093
1070
|
/**
|
|
@@ -1116,9 +1093,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
1116
1093
|
CardActions,
|
|
1117
1094
|
{
|
|
1118
1095
|
locked: !writable,
|
|
1119
|
-
disabled: a.disabled === true,
|
|
1120
|
-
saving: busy === a.id,
|
|
1121
|
-
onToggleDisabled: (next) => onToggleDisabled(a.id, next),
|
|
1122
1096
|
onRemove: () => onIgnore(a.id, true),
|
|
1123
1097
|
removeBusy: busy === `ignore-${a.id}`,
|
|
1124
1098
|
},
|
|
@@ -1713,19 +1687,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
1713
1687
|
}
|
|
1714
1688
|
};
|
|
1715
1689
|
|
|
1716
|
-
const [savingPool, setSavingPool] = useState(null);
|
|
1717
|
-
|
|
1718
|
-
const onToggleDisabled = (accountId, disabled) => {
|
|
1719
|
-
setSavingPool(accountId);
|
|
1720
|
-
const currentIds = asArray(traeRegionSlotOf(scopeObj?.getSnapshot?.().value, region).disabledAccountIds);
|
|
1721
|
-
const next = disabled
|
|
1722
|
-
? [...new Set([...currentIds, accountId])]
|
|
1723
|
-
: currentIds.filter((id) => id !== accountId);
|
|
1724
|
-
writePoolField({ disabledAccountIds: next }, (readBack) =>
|
|
1725
|
-
JSON.stringify(traeRegionSlotOf(readBack, region).disabledAccountIds ?? []) === JSON.stringify(next),
|
|
1726
|
-
disabled ? '已停用该账号' : '已重新启用该账号')
|
|
1727
|
-
.finally(() => setSavingPool(null));
|
|
1728
|
-
};
|
|
1729
1690
|
|
|
1730
1691
|
/** 供应商开关:只改 enabled,其余字段原样保留(关掉不丢勾选) */
|
|
1731
1692
|
const [togglingRegion, setTogglingRegion] = useState(null);
|
|
@@ -1830,10 +1791,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
1830
1791
|
.filter((pool) => !accounts.some((account) => String(account.id) === String(pool.id)))
|
|
1831
1792
|
.map((pool) => ({ account: null, pool })),
|
|
1832
1793
|
];
|
|
1833
|
-
const traeUsable =
|
|
1834
|
-
poolAccounts.length === 0
|
|
1835
|
-
? accounts.length
|
|
1836
|
-
: poolAccounts.filter((a) => a.disabled !== true).length;
|
|
1837
1794
|
const checkinText =
|
|
1838
1795
|
usage?.checkin?.checkedIn === true
|
|
1839
1796
|
? '今日已签到'
|
|
@@ -1958,7 +1915,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
1958
1915
|
? jsx(StatsRow, {
|
|
1959
1916
|
items: [
|
|
1960
1917
|
{ label: '账号', value: fmtNum(accounts.length), sub: '个已登录' },
|
|
1961
|
-
{ label: '可用', value: fmtNum(traeUsable), sub: '未被停用' },
|
|
1962
1918
|
{
|
|
1963
1919
|
label: '当前使用',
|
|
1964
1920
|
value: usage.accountName ?? current?.accountName ?? '–',
|
|
@@ -2003,7 +1959,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
2003
1959
|
isCurrent
|
|
2004
1960
|
? { text: '当前使用', cls: 'wbc-tag wbc-tag-on' }
|
|
2005
1961
|
: { text: '备用', cls: 'wbc-tag' },
|
|
2006
|
-
pool?.disabled === true ? { text: '已停用', cls: 'wbc-tag' } : null,
|
|
2007
1962
|
],
|
|
2008
1963
|
// 余额来自 /usage 的逐账号 credits,号池状态来自 pool 段,
|
|
2009
1964
|
// 两张表按 id 对齐后拼成同一张卡。
|
|
@@ -2018,16 +1973,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
2018
1973
|
: null,
|
|
2019
1974
|
],
|
|
2020
1975
|
extra: [
|
|
2021
|
-
jsx(
|
|
2022
|
-
CardActions,
|
|
2023
|
-
{
|
|
2024
|
-
locked: !writable || pool === null || pool === undefined,
|
|
2025
|
-
disabled: pool?.disabled === true,
|
|
2026
|
-
saving: savingPool === id,
|
|
2027
|
-
onToggleDisabled: (next) => onToggleDisabled(id, next),
|
|
2028
|
-
},
|
|
2029
|
-
'actions',
|
|
2030
|
-
),
|
|
2031
1976
|
/* 卡片最后一行:与 XD Pool 页同款的两按钮排 —— 左边「切换
|
|
2032
1977
|
* 到此账号」(**当前那张不给**:它已经是当前了),右边
|
|
2033
1978
|
* 「签到」。签到这个按钮是**每张卡都有**的:它签的是卡片
|
|
@@ -2475,26 +2420,18 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
2475
2420
|
* 账号卡里的控件行:三个配置页同一套。
|
|
2476
2421
|
*
|
|
2477
2422
|
* 完全手动语义(本 fork):账号之间没有分配策略 / 轮换 / 冷却,卡上的操作
|
|
2478
|
-
*
|
|
2423
|
+
* 只剩一件**手动管理**的事 ——
|
|
2479
2424
|
*
|
|
2480
|
-
* 「停用 / 启用」:写 `disabledAccountIds`,停用的账号不会被取号;
|
|
2481
2425
|
* 「移出池子」:只在传了 `onRemove` 时渲染(Trae 半边没有「移出」概念,
|
|
2482
2426
|
* 不给它硬塞一个按不动的按钮)。
|
|
2483
2427
|
*
|
|
2484
|
-
*
|
|
2428
|
+
* 早先这里的「参与轮换」勾选 / 「保留额度」输入 / 「停用」按钮都已按完全手动
|
|
2429
|
+
* 语义删除 —— 停用不影响任何请求(取号只认手动选中的那一个)。
|
|
2485
2430
|
*/
|
|
2486
|
-
function CardActions({ locked,
|
|
2431
|
+
function CardActions({ locked, onRemove, removeBusy }) {
|
|
2487
2432
|
return jsxs('div', {
|
|
2488
2433
|
className: 'wbc-bar',
|
|
2489
2434
|
children: [
|
|
2490
|
-
jsx('button', {
|
|
2491
|
-
type: 'button',
|
|
2492
|
-
className: 'wbc-btn',
|
|
2493
|
-
title: disabled === true ? '恢复这个账号参与取号' : '停用后取号不再选中它(请求失败时请手动切换)',
|
|
2494
|
-
disabled: locked === true || saving === true,
|
|
2495
|
-
onClick: () => onToggleDisabled(disabled !== true),
|
|
2496
|
-
children: disabled === true ? '启用' : '停用',
|
|
2497
|
-
}),
|
|
2498
2435
|
jsx('div', { className: 'wbc-spacer' }),
|
|
2499
2436
|
typeof onRemove !== 'function'
|
|
2500
2437
|
? null
|
|
@@ -2969,7 +2906,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
2969
2906
|
creditsAtMs,
|
|
2970
2907
|
onRefresh,
|
|
2971
2908
|
onAddAccount,
|
|
2972
|
-
onToggle,
|
|
2973
2909
|
onRemove,
|
|
2974
2910
|
onSelect,
|
|
2975
2911
|
/**
|
|
@@ -2985,7 +2921,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
2985
2921
|
checkinNote,
|
|
2986
2922
|
}) {
|
|
2987
2923
|
const accounts = asArray(status?.accounts);
|
|
2988
|
-
const usable = accounts.filter((a) => a.disabled !== true).length;
|
|
2989
2924
|
/**
|
|
2990
2925
|
* 「当前使用」的那一个 —— 请求就固定用它。
|
|
2991
2926
|
*
|
|
@@ -3168,7 +3103,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
3168
3103
|
? jsx(StatsRow, {
|
|
3169
3104
|
items: [
|
|
3170
3105
|
{ label: '账号', value: fmtNum(accounts.length), sub: '个已入池' },
|
|
3171
|
-
{ label: '可用', value: fmtNum(usable), sub: '未被停用' },
|
|
3172
3106
|
{
|
|
3173
3107
|
// 「当前使用」是谁:这是本页最该一眼看到的一件事 —— 请求就打在
|
|
3174
3108
|
// 它身上。它这一轮的余额(真正在扣的那份)与全池合计退到 sub,
|
|
@@ -3208,13 +3142,12 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
3208
3142
|
name: a.label ?? a.id,
|
|
3209
3143
|
// 完全手动:只有「当前使用」那张是亮的,其余卡片压暗。
|
|
3210
3144
|
// 不可用(停用)也压暗 —— 具体原因由标签说明。
|
|
3211
|
-
dim:
|
|
3145
|
+
dim: isSelected !== true,
|
|
3212
3146
|
tags: [
|
|
3213
3147
|
isServing ? { text: '本次调用', cls: 'wbc-tag wbc-tag-on' } : null,
|
|
3214
3148
|
isSelected
|
|
3215
3149
|
? { text: '当前使用', cls: isServing ? 'wbc-tag' : 'wbc-tag wbc-tag-on' }
|
|
3216
3150
|
: { text: '备用', cls: 'wbc-tag' },
|
|
3217
|
-
a.disabled === true ? { text: '已停用', cls: 'wbc-tag' } : null,
|
|
3218
3151
|
expired ? { text: '令牌已过期', cls: 'wbc-tag wbc-tag-warn' } : null,
|
|
3219
3152
|
],
|
|
3220
3153
|
rows: [
|
|
@@ -3245,9 +3178,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
3245
3178
|
CardActions,
|
|
3246
3179
|
{
|
|
3247
3180
|
locked,
|
|
3248
|
-
disabled: a.disabled === true,
|
|
3249
|
-
onToggleDisabled: (next) => onToggle(a.id, next),
|
|
3250
|
-
saving: busy === true,
|
|
3251
3181
|
onRemove: () => onRemove(a.id),
|
|
3252
3182
|
removeBusy: busy === true,
|
|
3253
3183
|
},
|
|
@@ -3867,7 +3797,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
3867
3797
|
fullName: name || id,
|
|
3868
3798
|
credits:
|
|
3869
3799
|
typeof raw?.credits === 'number' && Number.isFinite(raw.credits) ? raw.credits : undefined,
|
|
3870
|
-
disabled: raw?.disabled === true,
|
|
3871
3800
|
expired: raw?.expired === true,
|
|
3872
3801
|
pinned: raw?.pinned === true,
|
|
3873
3802
|
serving: raw?.serving === true,
|
|
@@ -3886,7 +3815,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
3886
3815
|
id: a.id,
|
|
3887
3816
|
name: a.nickname ?? a.label ?? '',
|
|
3888
3817
|
credits: accountCreditsOf(a),
|
|
3889
|
-
disabled: a.disabled,
|
|
3890
3818
|
pinned: pinned !== '' && a.id === pinned,
|
|
3891
3819
|
serving: serving !== '' && a.id === serving,
|
|
3892
3820
|
error: a.creditsError,
|
|
@@ -3960,7 +3888,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
3960
3888
|
credits: isServing
|
|
3961
3889
|
? (accountCreditsOf(serving, 'qoder') ?? accountCreditsOf(a, 'qoder'))
|
|
3962
3890
|
: accountCreditsOf(a, 'qoder'),
|
|
3963
|
-
disabled: a.disabled,
|
|
3964
3891
|
expired: a.expired,
|
|
3965
3892
|
pinned: typeof a.id === 'string' && a.id !== '' && a.id === pinned,
|
|
3966
3893
|
serving: isServing,
|
|
@@ -4045,8 +3972,8 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
4045
3972
|
* 就地改缓存里的行(写完之后的即时反馈)。
|
|
4046
3973
|
*
|
|
4047
3974
|
* 刻意**不**为了这一次改动再打一遍状态接口 —— 那个接口每个账号都会触发一次
|
|
4048
|
-
* 计费调用。写路径本身已经做过读回确认(见
|
|
4049
|
-
*
|
|
3975
|
+
* 计费调用。写路径本身已经做过读回确认(见 selectAccountRemote),
|
|
3976
|
+
* 所以就地改动是有依据的;下一次打开卡片或点「刷新」
|
|
4050
3977
|
* 会用真实快照把它对齐。
|
|
4051
3978
|
*/
|
|
4052
3979
|
function patchCreditRows(family, match, patch) {
|
|
@@ -4059,81 +3986,11 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
4059
3986
|
});
|
|
4060
3987
|
}
|
|
4061
3988
|
|
|
4062
|
-
/** 停用名单的加减:**只动这一个 id**,其余原样带过 */
|
|
4063
|
-
function mergeDisabledIds(ids, accountId, disabled) {
|
|
4064
|
-
const current = asArray(ids).filter((id) => typeof id === 'string' && id !== '');
|
|
4065
|
-
return disabled
|
|
4066
|
-
? [...new Set([...current, accountId])]
|
|
4067
|
-
: current.filter((id) => id !== accountId);
|
|
4068
|
-
}
|
|
4069
|
-
|
|
4070
|
-
/** 两份停用名单是否等价(读回确认用;顺序无关) */
|
|
4071
|
-
function sameIdSet(a, b) {
|
|
4072
|
-
const left = asArray(a).filter((id) => typeof id === 'string' && id !== '');
|
|
4073
|
-
const right = asArray(b).filter((id) => typeof id === 'string' && id !== '');
|
|
4074
|
-
if (left.length !== right.length) return false;
|
|
4075
|
-
const set = new Set(left);
|
|
4076
|
-
return right.every((id) => set.has(id));
|
|
4077
|
-
}
|
|
4078
|
-
|
|
4079
3989
|
/** 该平台设置作用域(拿不到就是 null,调用方按只读处理) */
|
|
4080
3990
|
function creditScopeOf(family) {
|
|
4081
3991
|
return poolScopeOf(family === 'qoder' ? qoderSettings : traeSettings);
|
|
4082
3992
|
}
|
|
4083
3993
|
|
|
4084
|
-
/**
|
|
4085
|
-
* 停用 / 启用一个账号 —— 三家写法不同,语义是同一条。
|
|
4086
|
-
*
|
|
4087
|
-
* WorkBuddy:走路由 `POST /accounts/disabled`。**不要**在这里自己拼
|
|
4088
|
-
* `disabledAccountIds` 写设置:国内版与国际版共用**同一份**设置文档
|
|
4089
|
-
* (两个 provider 用同一个 settingsNs、`settingsPath: []`),只按当前区域的
|
|
4090
|
-
* 行拼出来的列表会把另一个区域的停用项整段抹掉。路由在服务端按整份设置合并
|
|
4091
|
-
* (`setAccountDisabled` 读 `current().disabledAccountIds` 再加减一个 id)。
|
|
4092
|
-
*
|
|
4093
|
-
* Trae / Qoder:没有可用的写路由(Trae 的 `/pool/account` 只改进程内的池,
|
|
4094
|
-
* 下一次设置同步就被覆盖回去),所以写设置字段 —— 但**从当前设置文档里读旧值
|
|
4095
|
-
* 再合并**,而不是从行里拼。
|
|
4096
|
-
*/
|
|
4097
|
-
async function setAccountDisabledRemote(family, region, accountId, disabled) {
|
|
4098
|
-
if (typeof accountId !== 'string' || accountId === '') throw new Error('缺少账号 id');
|
|
4099
|
-
const want = disabled === true;
|
|
4100
|
-
if (family === 'wb') {
|
|
4101
|
-
await fetchJson(`${POOL_API}/accounts/disabled`, {
|
|
4102
|
-
method: 'POST',
|
|
4103
|
-
headers: { 'Content-Type': 'application/json' },
|
|
4104
|
-
body: JSON.stringify({ accountId, disabled: want }),
|
|
4105
|
-
});
|
|
4106
|
-
return;
|
|
4107
|
-
}
|
|
4108
|
-
const scope = creditScopeOf(family);
|
|
4109
|
-
const who = family === 'qoder' ? 'qoder' : 'trae';
|
|
4110
|
-
if (scope === undefined || scope === null) {
|
|
4111
|
-
throw new Error(`${who}: 拿不到设置作用域,无法保存(配置页同一处也只读)`);
|
|
4112
|
-
}
|
|
4113
|
-
if (!poolWritable(scope)) throw new Error(`${who}: 设置当前不可写`);
|
|
4114
|
-
if (family === 'qoder') {
|
|
4115
|
-
const currentIds = asArray(unwrapVolatileDeep(scope.getSnapshot?.().value)?.disabledAccountIds);
|
|
4116
|
-
const next = mergeDisabledIds(currentIds, accountId, want);
|
|
4117
|
-
await writeSettingsField(
|
|
4118
|
-
scope,
|
|
4119
|
-
'disabledAccountIds',
|
|
4120
|
-
next,
|
|
4121
|
-
(doc) => sameIdSet(doc?.disabledAccountIds, next),
|
|
4122
|
-
'qoder',
|
|
4123
|
-
);
|
|
4124
|
-
return;
|
|
4125
|
-
}
|
|
4126
|
-
const value = scope.getSnapshot?.().value;
|
|
4127
|
-
const next = mergeDisabledIds(traeRegionSlotOf(value, region).disabledAccountIds, accountId, want);
|
|
4128
|
-
const slot = { ...traeRegionSlotOf(value, region), disabledAccountIds: next };
|
|
4129
|
-
await writeTraeField(
|
|
4130
|
-
scope,
|
|
4131
|
-
'regions',
|
|
4132
|
-
nextRegionSlots(regionsMapOf(value), region, slot),
|
|
4133
|
-
(readBack) => sameIdSet(traeRegionSlotOf(readBack, region).disabledAccountIds, next),
|
|
4134
|
-
);
|
|
4135
|
-
}
|
|
4136
|
-
|
|
4137
3994
|
/**
|
|
4138
3995
|
* 把某个账号设成「当前账号」。
|
|
4139
3996
|
*
|
|
@@ -4273,8 +4130,7 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
4273
4130
|
*
|
|
4274
4131
|
* 展开的卡片里是**当前这个平台的全部账号**(不是「所有平台的账号」):
|
|
4275
4132
|
* WorkBuddy 与 Trae 各自的国内版 + 国际版都列出来,Qoder 只有一个池。
|
|
4276
|
-
*
|
|
4277
|
-
* setAccountDisabledRemote / selectAccountRemote 的语义说明。
|
|
4133
|
+
* 每行带一个控件 —— 「切换到此账号」,见 selectAccountRemote 的语义说明。
|
|
4278
4134
|
*
|
|
4279
4135
|
* 刷新策略分两档,因为两档的成本差一个量级:
|
|
4280
4136
|
* - 胶囊那颗数字:**每 30 秒自动刷一次**(见 CREDIT_REFRESH_MS 的成本说明),
|
|
@@ -4550,28 +4406,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
4550
4406
|
refreshHeadline();
|
|
4551
4407
|
};
|
|
4552
4408
|
|
|
4553
|
-
/** 停用 / 启用某一行 */
|
|
4554
|
-
const onToggleRow = async (row) => {
|
|
4555
|
-
const next = row.disabled !== true;
|
|
4556
|
-
setBusyRow(row.key);
|
|
4557
|
-
setWriteError('');
|
|
4558
|
-
setNote('');
|
|
4559
|
-
try {
|
|
4560
|
-
await setAccountDisabledRemote(row.family, row.region, row.id, next);
|
|
4561
|
-
patchCreditRows(row.family, (r) => r.key === row.key, { disabled: next });
|
|
4562
|
-
// 停掉的正好是「这一轮在用的那个」→ 胶囊上的主语马上就会变,补一发
|
|
4563
|
-
if (next === true && row.serving === true && row.region === source.region) {
|
|
4564
|
-
refreshHeadline();
|
|
4565
|
-
}
|
|
4566
|
-
setNote(next ? `已停用 ${row.name},请求失败时请手动切换` : `已重新启用 ${row.name}`);
|
|
4567
|
-
} catch (e) {
|
|
4568
|
-
setWriteError(e?.message ?? String(e));
|
|
4569
|
-
} finally {
|
|
4570
|
-
setBusyRow('');
|
|
4571
|
-
setTick((n) => n + 1);
|
|
4572
|
-
}
|
|
4573
|
-
};
|
|
4574
|
-
|
|
4575
4409
|
/** 切换到此账号 / 取消固定 */
|
|
4576
4410
|
const onSelectRow = async (row) => {
|
|
4577
4411
|
// WorkBuddy 独有的「取消固定」:完全手动语义下它的池把「没有当前账号」
|
|
@@ -4607,7 +4441,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
4607
4441
|
// 但选中账号不可用时上一轮可能根本没扣到它。
|
|
4608
4442
|
if (row.pinned === true) push('on', row.family === 'wb' ? '已固定' : '当前使用');
|
|
4609
4443
|
if (row.serving === true) push(row.pinned === true ? 'muted' : 'on', '本次调用');
|
|
4610
|
-
if (row.disabled === true) push('warn', '已停用');
|
|
4611
4444
|
if (row.expired === true) push('warn', '凭据已过期');
|
|
4612
4445
|
if (row.error !== '') push('warn', `额度读不到:${row.error}`);
|
|
4613
4446
|
return tags.map((tag, i) =>
|
|
@@ -4641,14 +4474,11 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
4641
4474
|
const hideSelect = unpin === false && row.pinned === true;
|
|
4642
4475
|
const selectTitle = unpin
|
|
4643
4476
|
? '取消固定后请求会失败,请手动切换'
|
|
4644
|
-
: row.disabled === true
|
|
4645
|
-
? '这个账号已停用:选中它请求会失败,请先启用或换一个'
|
|
4646
4477
|
: `让 ${row.fullName} 成为「当前账号」,请求只用它`;
|
|
4647
4478
|
return jsxs(
|
|
4648
4479
|
'div',
|
|
4649
4480
|
{
|
|
4650
4481
|
className: 'wotr-credit-row',
|
|
4651
|
-
'data-off': row.disabled === true ? '1' : '0',
|
|
4652
4482
|
'data-serving': row.serving === true ? '1' : '0',
|
|
4653
4483
|
children: [
|
|
4654
4484
|
jsxs('div', {
|
|
@@ -4678,22 +4508,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
4678
4508
|
},
|
|
4679
4509
|
children: label,
|
|
4680
4510
|
}),
|
|
4681
|
-
jsx('button', {
|
|
4682
|
-
type: 'button',
|
|
4683
|
-
role: 'switch',
|
|
4684
|
-
className: 'wotr-credit-switch',
|
|
4685
|
-
'aria-checked': row.disabled === true ? 'false' : 'true',
|
|
4686
|
-
'aria-label': `${row.name} 停用/启用`,
|
|
4687
|
-
'data-on': row.disabled === true ? '0' : '1',
|
|
4688
|
-
disabled: busy,
|
|
4689
|
-
title:
|
|
4690
|
-
row.disabled === true
|
|
4691
|
-
? `启用 ${row.fullName}(恢复参与取号)`
|
|
4692
|
-
: `停用 ${row.fullName}(选中它时请求会失败)`,
|
|
4693
|
-
onClick: () => {
|
|
4694
|
-
void onToggleRow(row);
|
|
4695
|
-
},
|
|
4696
|
-
}),
|
|
4697
4511
|
],
|
|
4698
4512
|
}),
|
|
4699
4513
|
],
|
|
@@ -5253,29 +5067,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
5253
5067
|
[loadQoder],
|
|
5254
5068
|
);
|
|
5255
5069
|
|
|
5256
|
-
/**
|
|
5257
|
-
* 停用 / 启用:往 `disabledAccountIds` 里加减这个账号。
|
|
5258
|
-
*
|
|
5259
|
-
* 必须**读出当前列表再合并** —— 整段覆盖写会把别的账号的停用状态清掉,
|
|
5260
|
-
* 表现为「停用了 A,B 自己被启用了」。
|
|
5261
|
-
*/
|
|
5262
|
-
const onQoderToggle = useCallback(
|
|
5263
|
-
(accountId, disabled) => {
|
|
5264
|
-
const current = asArray(qoderConfigSnapshot().disabledAccountIds).filter(
|
|
5265
|
-
(id) => typeof id === 'string',
|
|
5266
|
-
);
|
|
5267
|
-
const next = disabled === true
|
|
5268
|
-
? [...new Set([...current, accountId])]
|
|
5269
|
-
: current.filter((id) => id !== accountId);
|
|
5270
|
-
const want = disabled === true;
|
|
5271
|
-
return writeQoderPoolField(
|
|
5272
|
-
'disabledAccountIds',
|
|
5273
|
-
next,
|
|
5274
|
-
(doc) => asArray(doc?.disabledAccountIds).includes(accountId) === want,
|
|
5275
|
-
);
|
|
5276
|
-
},
|
|
5277
|
-
[qoderConfigSnapshot, writeQoderPoolField],
|
|
5278
|
-
);
|
|
5279
5070
|
|
|
5280
5071
|
const onQoderRemove = useCallback(
|
|
5281
5072
|
(accountId) => qoderAction(`${SELF_API}/qoder/pool/remove`, { accountId }),
|
|
@@ -5530,7 +5321,6 @@ export function createConsoleSection({ react, jsxRuntime, embedded }) {
|
|
|
5530
5321
|
creditsAtMs: qoderCreditsAtMs,
|
|
5531
5322
|
onRefresh: loadQoder,
|
|
5532
5323
|
onAddAccount: onQoderAddAccount,
|
|
5533
|
-
onToggle: onQoderToggle,
|
|
5534
5324
|
onRemove: onQoderRemove,
|
|
5535
5325
|
onSelect: onQoderSelect,
|
|
5536
5326
|
// 每日签到(按账号,不切号):正在签的 id / 本页各账号的答复 / 顶部结论。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-kdczyz-mode",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.4-beta",
|
|
4
4
|
"description": "WorkBuddy + Trae + Qoder merged into one DSH plugin: the WorkBuddy desktop account/model pool, the Trae connector and the Qoder account pool as three independent providers, plus one settings page with six tabs — two configuration tabs (XD Pool / Trae config: provider switch, account binding, model selection and its own multi-account pool) and four management/read-only tabs (accounts [WorkBuddy + Trae + Qoder, three columns] / Qoder pool / credits / usage history).",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|