Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/upstreams/AccountPanel.i18n.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const accountPanelText = messages(
noticeTheirPage: "授权页由对方提供,页面上显示的是他们自己的客户端名称。",
noticeKey:
"登录会在账号中创建一把名为 thinkwatch 的 API 密钥(已存在则直接使用),额度按该密钥计入套餐。",
noticeKeyStorage: (where: string) => `得到的密钥保存在${where}的配置文件中,与其他上游一同管理。`,
here: "本机",
server: (name: string) => ` ${name} `,
understood: "已阅读上述说明",
Expand Down Expand Up @@ -45,7 +46,7 @@ export const accountPanelText = messages(
open: "打开",
deviceWaiting: (min: number) => `等待输入 · ${min} 分钟内有效`,
newCode: "重新获取",
deviceWarning: "只输入这里显示的设备码",
deviceWarning: "只输入这里显示的设备码;他人提供的设备码请勿输入。",
doneTitle: "已登录",
reloginDone: (name: ReactNode) => <>已重新登录,上游 {name} 的凭据已更新。</>,
signedIn: "已登录",
Expand Down Expand Up @@ -75,6 +76,8 @@ export const accountPanelText = messages(
noticeTheirPage: "The authorization page is theirs, and it names their own client.",
noticeKey:
"Signing in creates an API key named thinkwatch on the account, or uses the existing one. Quota is counted against that key.",
noticeKeyStorage: (where: string) =>
`The key obtained by signing in is stored in the config file ${where} and managed together with the other upstreams.`,
here: "on this computer",
server: (name: string) => `on ${name}`,
understood: "Acknowledge the notes above",
Expand Down Expand Up @@ -103,7 +106,7 @@ export const accountPanelText = messages(
open: "Open",
deviceWaiting: (min: number) => `Waiting for the code · valid for ${min} min`,
newCode: "Get a new code",
deviceWarning: "Enter only the device code shown here",
deviceWarning: "Enter only the device code shown here; never enter a device code provided by someone else.",
doneTitle: "Signed in",
reloginDone: (name: ReactNode) => <>Signed in again. The credential of the upstream {name} has been replaced.</>,
signedIn: "Signed in",
Expand Down
9 changes: 5 additions & 4 deletions src/upstreams/AccountPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ function Methods({
<>
<li>{t.noticeTheirPage}</li>
<li>{t.noticeKey}</li>
<li>{t.noticeKeyStorage(where)}</li>
</>
)}
</ul>
Expand Down Expand Up @@ -273,8 +274,8 @@ function Way({
}

/**
* 设备码登录:验证网址和设备码并排(网址能复制、能打开,码大字、能复制),下面是有效期、
* 重新获取和那一句提醒。在这台电脑上时还能改回浏览器登录
* 设备码登录:验证网址和设备码并排(网址能复制、能打开,码大字、能复制),下面是有效期和
* 重新获取(在这台电脑上时还能改回浏览器登录),最后一句提醒
*/
function DeviceCode({ login, params }: { login: AccountLogin; params: LoginParams }) {
const t = useText(accountPanelText);
Expand Down Expand Up @@ -317,9 +318,9 @@ function DeviceCode({ login, params }: { login: AccountLogin; params: LoginParam
</LinkButton>
</>
)}
{/* 拿着别人给的码去输,等于把自己的账号授权给对方 */}
<span className="ml-auto tw-label">{t.deviceWarning}</span>
</div>
{/* 拿着别人给的码去输,等于把自己的账号授权给对方 */}
<p className="tw-label text-muted-foreground">{t.deviceWarning}</p>
</>
);
}
Expand Down
20 changes: 11 additions & 9 deletions src/upstreams/BillingSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export function BillingSection({
]
: [];

// 一屏放下:价格表在自己的框里滚,框按剩下的高度收
// 价格表在自己的框里滚,框按剩下的高度收;再矮就让对话框中间那一块去滚
return (
<div className="flex min-h-0 flex-1 flex-col gap-4">
<div className="grid shrink-0 grid-cols-2 gap-4">
Expand Down Expand Up @@ -110,21 +110,23 @@ export function BillingSection({
</div>

{perToken && linkSheet && (
<div className="flex shrink-0 items-center gap-2.5 rounded-lg border border-border px-3 py-2">
<span className="min-w-0 truncate tw-label text-muted-foreground">
{t.linkSheetDetail(linkSheet.multiplier, Object.keys(linkSheet.models).length)}
</span>
{sheetProblem && <span className="min-w-0 truncate tw-label text-destructive">{sheetProblem}</span>}
<div className="flex-1" />
<Button variant="outline" size="sm" onClick={onEditNewSheet}>
<div className="flex shrink-0 items-center gap-2.5 rounded-lg border border-border px-3 py-2.5">
{/* 两句都整句写出来:名称被占用的那一句要照着去改 */}
<div className="flex min-w-0 flex-1 flex-col gap-0.5 tw-label">
<span className="text-muted-foreground">
{t.linkSheetDetail(linkSheet.multiplier, Object.keys(linkSheet.models).length)}
</span>
{sheetProblem && <span className="text-destructive">{sheetProblem}</span>}
</div>
<Button variant="outline" size="sm" className="shrink-0" onClick={onEditNewSheet}>
<PencilIcon />
{t.editSheet}
</Button>
</div>
)}

{perToken && sheet && (
<div className="flex shrink-0 items-center gap-2.5 rounded-lg border border-border px-3 py-2">
<div className="flex shrink-0 items-center gap-2.5 rounded-lg border border-border px-3 py-2.5">
<span className="shrink-0 tw-label text-muted-foreground">{t.usedBy}</span>
<UpstreamChips names={users} providers={ov.providers} empty="" />
<div className="flex-1" />
Expand Down
2 changes: 2 additions & 0 deletions src/upstreams/ChatgptAccountSection.i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const chatgptAccountText = messages(
},
name: "名称",
egress: "出站方式",
egressDesc: "登录与后续请求都经此发出",
direct: "直连",
systemProxy: "系统代理",
quota: "订阅额度",
Expand Down Expand Up @@ -56,6 +57,7 @@ export const chatgptAccountText = messages(
},
name: "Name",
egress: "Outbound connection",
egressDesc: "Used for sign-in and all later requests",
direct: "Direct",
systemProxy: "System proxy",
quota: "Usage limits",
Expand Down
21 changes: 10 additions & 11 deletions src/upstreams/ChatgptAccountSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,9 @@ export function ChatgptAccountSection({
const list = credits?.credits ?? [];
const available = list.filter((c) => c.status === AVAILABLE);

// 一屏放下:名称、出站方式、并发上限一行,额度和重置卡左右两栏
return (
<div className="flex flex-col gap-4">
<div className="grid grid-cols-3 gap-4">
<div className="flex flex-col gap-5">
<div className="grid grid-cols-2 gap-4">
<FormItem label={t.name} htmlFor="cg-name">
<Input
id="cg-name"
Expand All @@ -128,7 +127,7 @@ export function ChatgptAccountSection({
onChange={(e) => set({ name: e.target.value })}
/>
</FormItem>
<FormItem label={t.egress} htmlFor="cg-proxy">
<FormItem label={t.egress} htmlFor="cg-proxy" desc={t.egressDesc}>
<NativeSelect
id="cg-proxy"
className="w-full"
Expand All @@ -145,15 +144,15 @@ export function ChatgptAccountSection({
</NativeSelect>
</FormItem>
{/* 账号一样限制同时进行的请求 */}
<ConcurrencyField form={form} set={set} bare />
<ConcurrencyField form={form} set={set} />
</div>

<LoginBox editing={editing} onRelogin={onRelogin} />

{!broken && (
<div className="grid grid-cols-2 items-start gap-6">
<section className="flex min-w-0 flex-col gap-2">
<div className="flex h-7 items-center justify-between gap-3">
<>
<section className="flex flex-col gap-2">
<div className="flex items-baseline justify-between gap-3">
<h3 className="tw-head font-medium">{t.quota}</h3>
<Button variant="ghost" size="sm" onClick={() => void load()} pending={loading}>
{!loading && <RefreshCwIcon />}
Expand Down Expand Up @@ -195,8 +194,8 @@ export function ChatgptAccountSection({
) : null}
</section>

<section className="flex min-w-0 flex-col gap-2">
<div className="flex h-7 items-center justify-between gap-3">
<section className="flex flex-col gap-2">
<div className="flex items-baseline justify-between gap-3">
<h3 className="tw-head font-medium">
{t.credits}
{credits && ` · ${t.available(available.length)}`}
Expand Down Expand Up @@ -233,7 +232,7 @@ export function ChatgptAccountSection({
</ul>
)}
</section>
</div>
</>
)}

<DialogError error={error} />
Expand Down
8 changes: 8 additions & 0 deletions src/upstreams/ConnectionSection.i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const connectionSectionText = messages(
namePlaceholder: "例如 relay-hk",
namePlaceholderGateway: "例如 corp-gateway",
baseUrl: "接口地址",
baseUrlDesc: "服务商提供的 Base URL,不含 /chat/completions、/messages 等接口路径。",
auth: "认证方式",
site: "站点",
siteZai: "Z.ai(国际)",
Expand All @@ -22,6 +23,7 @@ export const connectionSectionText = messages(
/** 收起时那一行列出的几项之间 */
listSep: "、",
headers: "请求头",
headersHint: "随每个请求发送。值中的 ${变量名} 读取系统环境变量。",
authUnknown: "鉴权头(按接口协议)",
renewedToken: "‹自动换发的 Access Token›",
signedPerRequest: "‹每个请求单独签名›",
Expand All @@ -31,6 +33,7 @@ export const connectionSectionText = messages(
accessKeyId: "访问密钥 ID",
secretAccessKey: "私有访问密钥",
sessionToken: "会话令牌(可选)",
sessionTokenDesc: "临时凭证才有。",
/** 术语表:两种语言都写 AWS profile(「配置文件」是 config.yaml) */
awsProfile: "AWS profile",
profileDesc: "读取本机 AWS 凭证文件(~/.aws/credentials、~/.aws/config)中的这个 profile,只支持写有访问密钥的 profile。",
Expand All @@ -56,6 +59,7 @@ export const connectionSectionText = messages(
clientId: "Client ID(可选)",
clientSecret: "Client Secret(可选)",
accessToken: "Access Token(检测用,可选)",
accessTokenDesc: "仅用于保存前检测连接。",
failed: "连接失败",
authenticated: "认证通过",
responded: (ms: string) => `响应 ${ms}`,
Expand All @@ -74,13 +78,15 @@ export const connectionSectionText = messages(
namePlaceholder: "e.g. relay-hk",
namePlaceholderGateway: "e.g. corp-gateway",
baseUrl: "Base URL",
baseUrlDesc: "The provider's base URL, without an endpoint path such as /chat/completions or /messages.",
auth: "Authentication",
site: "Site",
siteZai: "Z.ai (international)",
siteBigmodel: "BigModel (mainland China)",
advanced: "Advanced settings",
listSep: ", ",
headers: "Headers",
headersHint: "Sent with every request. ${NAME} in a value reads a system environment variable.",
authUnknown: "Auth header (per protocol)",
renewedToken: "‹renewed access token›",
signedPerRequest: "‹signed per request›",
Expand All @@ -90,6 +96,7 @@ export const connectionSectionText = messages(
accessKeyId: "Access key ID",
secretAccessKey: "Secret access key",
sessionToken: "Session token (optional)",
sessionTokenDesc: "Only temporary credentials have one.",
awsProfile: "AWS profile",
profileDesc:
"Reads this profile from the AWS credential files on this computer (~/.aws/credentials, ~/.aws/config). Only profiles that hold access keys are supported.",
Expand All @@ -115,6 +122,7 @@ export const connectionSectionText = messages(
clientId: "Client ID (optional)",
clientSecret: "Client secret (optional)",
accessToken: "Access token (for checking, optional)",
accessTokenDesc: "Only used to check the connection before saving.",
failed: "Connection failed",
authenticated: "Authenticated",
responded: (ms: string) => `responded in ${ms}`,
Expand Down
Loading
Loading