a642bf16a2
design/ 同步自最新设计导出,新增 ui_kits/tablet/ 平板分栏布局;todo/ 录入 18 个并行实施任务。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
97 lines
9.4 KiB
React
97 lines
9.4 KiB
React
/* ucparts.jsx — 穿山甲 Web 用户中心 · atoms + i18n */
|
|
const UCLUCIDE = {
|
|
'layout-dashboard':'<rect width="7" height="9" x="3" y="3" rx="1"/><rect width="7" height="5" x="14" y="3" rx="1"/><rect width="7" height="9" x="14" y="12" rx="1"/><rect width="7" height="5" x="3" y="16" rx="1"/>',
|
|
link:'<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>',
|
|
ticket:'<path d="M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"/><path d="M13 5v2"/><path d="M13 17v2"/><path d="M13 11v2"/>',
|
|
users:'<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>',
|
|
copy:'<rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>',
|
|
'refresh-cw':'<path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/><path d="M3 21v-5h5"/>',
|
|
'qr-code':'<rect width="5" height="5" x="3" y="3" rx="1"/><rect width="5" height="5" x="16" y="3" rx="1"/><rect width="5" height="5" x="3" y="16" rx="1"/><path d="M21 16h-3a2 2 0 0 0-2 2v3"/><path d="M21 21v.01"/><path d="M12 7v3a2 2 0 0 1-2 2H7"/><path d="M3 12h.01"/><path d="M12 3h.01"/><path d="M12 16v.01"/><path d="M16 12h1"/><path d="M21 12v.01"/><path d="M12 21v-1"/>',
|
|
download:'<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" x2="12" y1="15" y2="3"/>',
|
|
check:'<path d="M20 6 9 17l-5-5"/>',
|
|
'check-circle':'<path d="M21.801 10A10 10 0 1 1 17 3.335"/><path d="m9 11 3 3L22 4"/>',
|
|
zap:'<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/>',
|
|
clock:'<circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/>',
|
|
'shield-check':'<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/><path d="m9 12 2 2 4-4"/>',
|
|
crown:'<path d="M11.562 3.266a.5.5 0 0 1 .876 0L15.39 8.87a1 1 0 0 0 1.516.294L21.183 5.5a.5.5 0 0 1 .798.519l-2.834 10.246a1 1 0 0 1-.956.734H5.81a1 1 0 0 1-.957-.734L2.02 6.02a.5.5 0 0 1 .798-.519l4.276 3.664a1 1 0 0 0 1.516-.294z"/><path d="M5 21h14"/>',
|
|
'credit-card':'<rect width="20" height="14" x="2" y="5" rx="2"/><line x1="2" x2="22" y1="10" y2="10"/>',
|
|
send:'<path d="M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"/><path d="m21.854 2.147-10.94 10.939"/>',
|
|
'message-circle':'<path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/>',
|
|
mail:'<rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/>',
|
|
'shopping-bag':'<path d="M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z"/><path d="M3 6h18"/><path d="M16 10a4 4 0 0 1-8 0"/>',
|
|
'log-out':'<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" x2="9" y1="12" y2="12"/>',
|
|
'external-link':'<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>',
|
|
gift:'<rect x="3" y="8" width="18" height="4" rx="1"/><path d="M12 8v13"/><path d="M19 12v7a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-7"/><path d="M7.5 8a2.5 2.5 0 0 1 0-5A4.8 8 0 0 1 12 8a4.8 8 0 0 1 4.5-5 2.5 2.5 0 0 1 0 5"/>',
|
|
smartphone:'<rect width="14" height="20" x="5" y="2" rx="2" ry="2"/><path d="M12 18h.01"/>',
|
|
lock:'<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>',
|
|
'chevron-right':'<path d="m9 18 6-6-6-6"/>',
|
|
'arrow-down':'<path d="M12 5v14"/><path d="m19 12-7 7-7-7"/>',
|
|
};
|
|
function UCIcon({ name, size=18, stroke=2, color='currentColor', style={} }) {
|
|
return <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" style={{ display:'block', flexShrink:0, ...style }} dangerouslySetInnerHTML={{ __html: UCLUCIDE[name]||'' }} />;
|
|
}
|
|
function UCMark({ size=30, color='var(--accent)' }) {
|
|
return (
|
|
<svg width={size} height={size} viewBox="0 0 96 96" fill="none" style={{ display:'block' }}>
|
|
<g transform="translate(96,0) scale(-1,1)">
|
|
<path d="M16 59 Q17 51 26 50 Q34 31 45 30 Q55 30 62 37 Q69 41 75 45 Q85 49 89 44 Q92 50 84 52 Q75 53 67 53 Q66 62 60 62 L56 62 Q54 55 49 55 Q47 62 37 62 L33 62 Q31 56 26 56 Q20 59 16 59 Z" fill={color}/>
|
|
<g stroke="#fff" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" fill="none" opacity="0.5"><path d="M27 50 Q35 43 43 50"/><path d="M37 48 Q45 41 53 48"/><path d="M47 48 Q55 41 63 49"/></g>
|
|
<circle cx="19" cy="56" r="2.2" fill="#fff" opacity="0.85"/>
|
|
</g>
|
|
</svg>
|
|
);
|
|
}
|
|
|
|
const UCSTRINGS = {
|
|
navOverview:{zh:'概览',en:'Overview'}, navSub:{zh:'订阅',en:'Subscription'}, navRedeem:{zh:'兑换 & 购买',en:'Redeem & buy'}, navInvite:{zh:'邀请返利',en:'Referral'},
|
|
signOut:{zh:'退出',en:'Sign out'},
|
|
/* login */
|
|
loginTitle:{zh:'登录用户中心',en:'Log in to your account'}, loginSub:{zh:'管理订阅、兑换激活码、查看用量',en:'Manage subscription, redeem codes, track usage'},
|
|
emailLabel:{zh:'邮箱',en:'Email'}, emailPh:{zh:'你的邮箱地址',en:'your@email.com'},
|
|
pwLabel:{zh:'密码',en:'Password'}, pwPh:{zh:'输入密码',en:'Enter password'},
|
|
doLogin:{zh:'登录',en:'Log in'}, forgotPw:{zh:'忘记密码?',en:'Forgot password?'},
|
|
noAccount:{zh:'没有账户?在 App 内注册',en:'No account? Sign up in the app'},
|
|
/* overview */
|
|
greeting:{zh:'欢迎回来',en:'Welcome back'},
|
|
curPlan:{zh:'当前套餐',en:'Current plan'}, freePlan:{zh:'免费版',en:'Free'}, proMember:{zh:'PRO 会员',en:'PRO member'},
|
|
expires:{zh:'有效期至',en:'Expires'}, renew:{zh:'续费 / 升级',en:'Renew / Upgrade'},
|
|
quotaToday:{zh:'今日剩余时长',en:'Time left today'}, dataToday:{zh:'今日已用流量',en:'Data used today'}, devices:{zh:'在线设备',en:'Devices online'},
|
|
quotaFree:{zh:'免费版 · 每日 10 分钟',en:'Free · 10 min/day'},
|
|
usageTitle:{zh:'近 7 日流量 (GB)',en:'Last 7 days (GB)'},
|
|
quickSub:{zh:'快速操作',en:'Quick actions'},
|
|
qaSub:{zh:'获取订阅链接',en:'Get subscription'}, qaRedeem:{zh:'兑换激活码',en:'Redeem a code'}, qaApp:{zh:'下载 App',en:'Download apps'},
|
|
/* subscription */
|
|
subTitle:{zh:'我的订阅',en:'My subscription'},
|
|
subDesc:{zh:'订阅链接是你的专属凭证,泄露后他人可使用你的额度。请勿分享。',en:'Your subscription link is a private credential. Never share it.'},
|
|
subCopy:{zh:'复制链接',en:'Copy link'}, subCopied:{zh:'已复制',en:'Copied'},
|
|
subReset:{zh:'重置链接',en:'Reset link'}, subResetSub:{zh:'旧链接立即失效,所有设备需重新导入',en:'Old link stops working; re-import on all devices'},
|
|
subResetOk:{zh:'已重置,请重新导入',en:'Reset — re-import on your devices'},
|
|
scanTitle:{zh:'扫码导入',en:'Scan to import'}, scanSub:{zh:'用穿山甲 App 或三方客户端扫码',en:'Scan with the Pangolin app or a 3rd-party client'},
|
|
importTitle:{zh:'一键导入三方客户端',en:'One-tap import'},
|
|
importSub:{zh:'已安装对应客户端时,点击即自动导入订阅。',en:'If the client is installed, tapping imports the subscription automatically.'},
|
|
fmtNote:{zh:'同一链接同时兼容 sing-box / Clash.Meta / v2ray 格式。',en:'One link serves sing-box / Clash.Meta / v2ray formats.'},
|
|
/* redeem */
|
|
redeemTitle:{zh:'兑换激活码',en:'Redeem a code'}, redeemPh:{zh:'输入激活码',en:'Enter activation code'}, redeemBtn:{zh:'激活',en:'Redeem'},
|
|
redeemOk:{zh:'激活成功 · 套餐已到账',en:'Activated — plan applied'},
|
|
buyTitle:{zh:'购买渠道',en:'Where to buy'},
|
|
buySub:{zh:'本站不直接收款。通过以下渠道购买激活码,回到本页兑换即可:',en:'We never take payment on this site. Buy a code via a channel below, then redeem here:'},
|
|
chStore:{zh:'自助发卡商店',en:'Self-serve store'}, chStoreSub:{zh:'支付宝 / 微信 · 自动发码',en:'Alipay / WeChat · instant code'},
|
|
chUsdtSub:{zh:'链上转账 · 最隐私 · 自动发码',en:'On-chain · most private · instant code'},
|
|
chEmail:{zh:'邮箱客服',en:'Email support'},
|
|
/* invite */
|
|
inviteTitle:{zh:'邀请返利',en:'Referral'},
|
|
inviteSub:{zh:'好友通过你的链接注册并付费,你获得其首单 20% 余额返利,可抵扣续费。',en:'When a friend signs up and pays via your link, you earn 20% of their first order as credit.'},
|
|
inviteLink:{zh:'我的邀请链接',en:'My invite link'},
|
|
invited:{zh:'已邀请',en:'Invited'}, paidUsers:{zh:'已付费',en:'Converted'}, earned:{zh:'累计返利',en:'Credit earned'},
|
|
inviteRecord:{zh:'邀请记录',en:'History'}, recEmpty:{zh:'暂无邀请记录',en:'No referrals yet'},
|
|
recRegistered:{zh:'已注册',en:'Registered'}, recPaid:{zh:'已付费',en:'Paid'},
|
|
/* 2FA */
|
|
twoFATitle:{zh:'双重认证',en:'Two-factor auth'},
|
|
twoFAHint:{zh:'你的账户已开启双重认证。请输入身份验证器 App 中的 6 位动态码。',en:'Two-factor auth is on for this account. Enter the 6-digit code from your authenticator app.'},
|
|
twoFAConfirm:{zh:'验证并登录',en:'Verify & log in'},
|
|
twoFABack:{zh:'返回上一步',en:'Back'},
|
|
};
|
|
function ucT(lang){ return k => { const v=UCSTRINGS[k]; return v?(v[lang]||k):k; }; }
|
|
|
|
Object.assign(window, { UCIcon, UCMark, UCSTRINGS, ucT });
|