feat: new xboard

This commit is contained in:
xboard
2025-01-21 14:57:54 +08:00
parent de18cfe596
commit 0f43fff242
373 changed files with 17923 additions and 20264 deletions

View File

@@ -95,5 +95,23 @@
"Sending frequently, please try again later": "Sending frequently, please try again later",
"Current product is sold out": "Current product is sold out",
"There are too many password errors, please try again after :minute minutes.": "There are too many password errors, please try again after :minute minutes.",
"Reset failed, Please try again later": "Reset failed, Please try again later"
"Reset failed, Please try again later": "Reset failed, Please try again later",
"Subscribe": "Subscribe",
"User Information": "User Information",
"Username": "Username",
"Status": "Status",
"Active": "Active",
"Inactive": "Inactive",
"Data Used": "Data Used",
"Data Limit": "Data Limit",
"Expiration Date": "Expiration Date",
"Reset In": "Reset In",
"Days": "Days",
"Subscription Link": "Subscription Link",
"Copy": "Copy",
"Copied": "Copied",
"QR Code": "QR Code",
"Unlimited": "Unlimited",
"Device Limit": "Device Limit",
"Devices": "Devices"
}

View File

@@ -95,5 +95,23 @@
"Sending frequently, please try again later": "发送频繁,请稍后再试",
"Current product is sold out": "当前商品已售罄",
"There are too many password errors, please try again after :minute minutes.": "密码错误次数过多,请 :minute 分钟后再试",
"Reset failed, Please try again later": "重置失败,请稍后再试"
"Reset failed, Please try again later": "重置失败,请稍后再试",
"Subscribe": "订阅信息",
"User Information": "用户信息",
"Username": "用户名",
"Status": "状态",
"Active": "正常",
"Inactive": "未激活",
"Data Used": "已用流量",
"Data Limit": "流量限制",
"Expiration Date": "到期时间",
"Reset In": "距离重置",
"Days": "天",
"Subscription Link": "订阅链接",
"Copy": "复制",
"Copied": "已复制",
"QR Code": "二维码",
"Unlimited": "长期有效",
"Device Limit": "设备限制",
"Devices": "台设备"
}

117
resources/lang/zh-TW.json Normal file
View File

@@ -0,0 +1,117 @@
{
"The user does not exist": "該用戶不存在",
"The old password is wrong": "舊密碼有誤",
"Save failed": "保存失敗",
"Subscription plan does not exist": "訂閱計劃不存在",
"Reset failed": "重置失敗",
"Invalid parameter": "參數錯誤",
"Insufficient commission balance": "推廣佣金餘額不足",
"Transfer failed": "劃轉失敗",
"Ticket does not exist": "工單不存在",
"There are other unresolved tickets": "存在其他工單尚未處理",
"Failed to open ticket": "工單創建失敗",
"Message cannot be empty": "消息不能為空",
"The ticket is closed and cannot be replied": "工單已關閉,無法回復",
"Please wait for the technical enginneer to reply": "請等待技術支持回復",
"Ticket reply failed": "工單回復失敗",
"Close failed": "關閉失敗",
"Unsupported withdrawal method": "不支持的提現方式",
"The current required minimum withdrawal commission is :limit": "當前系統要求的最少提現佣金為:¥:limitCNY",
"[Commission Withdrawal Request] This ticket is opened by the system": "[提現申請] 本工單由系統發出",
"Withdrawal method": "提現方式",
"Withdrawal account": "提現賬號",
"Unsupported withdrawal": "不支持提現",
"Order does not exist": "訂單不存在",
"You have an unpaid or pending order, please try again later or cancel it": "您有未付款或開通中的訂單,請稍後再試或將其取消",
"This subscription has been sold out, please choose another subscription": "該訂閱已售罄,請更換其它訂閱",
"This subscription cannot be renewed, please change to another subscription": "該訂閱無法續費,請更換其它訂閱",
"This payment period cannot be purchased, please choose another period": "該訂閱週期無法進行購買,請選擇其它週期",
"Subscription has expired or no active subscription, unable to purchase Data Reset Package": "訂閱已過期或無有效訂閱,無法購買重置包",
"This subscription has expired, please change to another subscription": "訂閱已過期,請更換其它訂閱",
"Coupon failed": "優惠券使用失敗",
"Insufficient balance": "餘額不足",
"Failed to create order": "訂單創建失敗",
"Order does not exist or has been paid": "訂單不存在或已支付",
"Payment method is not available": "支付方式不可用",
"You can only cancel pending orders": "只可以取消待支付訂單",
"Cancel failed": "取消失敗",
"Currency conversion has timed out, please try again later": "貨幣轉換超時,請稍後再試",
"Payment gateway request failed": "支付網關請求失敗",
"Oops, there's a problem... Please refresh the page and try again later": "出現了點問題,請刷新頁面稍後再試",
"Payment failed. Please check your credit card information": "扣款失敗,請檢查信用卡信息",
"Article does not exist": "文章不存在",
"No active subscription. Unable to use our provided Apple ID": "無有效訂閱,無法使用本站提供的 Apple ID",
"You must have a valid subscription to view content in this area": "您必須擁有有效的訂閱才可以查看該區域的內容",
"The maximum number of creations has been reached": "已達到創建數量上限",
"Coupon cannot be empty": "優惠券不能為空",
"This coupon is no longer available": "優惠券已無可用次數",
"This coupon has not yet started": "優惠券還未到可用時間",
"This coupon has expired": "優惠券已過期",
"The coupon code cannot be used for this subscription": "該訂閱無法使用此優惠碼",
"Invalid coupon": "優惠券無效",
"Invalid code is incorrect": "驗證碼有誤",
"Email suffix is not in the Whitelist": "郵箱後綴不處於白名單中",
"Gmail alias is not supported": "不支持 Gmail 別名郵箱",
"Registration has closed": "本站已關閉註冊",
"You must use the invitation code to register": "必須使用邀請碼才可以註冊",
"Email verification code cannot be empty": "郵箱驗證碼不能為空",
"Incorrect email verification code": "郵箱驗證碼有誤",
"Email already exists": "郵箱已在系統中存在",
"Invalid invitation code": "邀請碼無效",
"Register failed": "註冊失敗",
"Incorrect email or password": "郵箱或密碼錯誤",
"Your account has been suspended": "該賬戶已被停止使用",
"Token error": "令牌有誤",
"This email is not registered in the system": "該郵箱不存在系統中",
"Email verification code has been sent, please request again later": "驗證碼已發送,請過一會兒再請求",
"Email verification code": "郵箱驗證碼",
"Plan ID cannot be empty": "套餐 ID 不能為空",
"Plan period cannot be empty": "套餐週期不能為空",
"Wrong plan period": "套餐週期參數有誤",
"Ticket subject cannot be empty": "工單主題不能為空",
"Ticket level cannot be empty": "工單等級不能為空",
"Incorrect ticket level format": "工單等級參數有誤",
"The withdrawal method cannot be empty": "提現方式不能為空",
"The withdrawal account cannot be empty": "提現賬號不能為空",
"Old password cannot be empty": "舊密碼不能為空",
"New password cannot be empty": "新密碼不能為空",
"Password must be greater than 8 digits": "密碼必須大於 8 個字符",
"The transfer amount cannot be empty": "劃轉金額不能為空",
"The transfer amount parameter is wrong": "劃轉金額參數有誤",
"Incorrect format of expiration reminder": "過期提醒參數有誤",
"Incorrect traffic alert format": "流量提醒參數有誤",
"Email can not be empty": "郵箱不能為空",
"Email format is incorrect": "郵箱格式不正確",
"Password can not be empty": "密碼不能為空",
"The traffic usage in :app_name has reached 80%": "在 :app_name 的已用流量已達到 80%",
"The service in :app_name is about to expire": "在 :app_name 的服務即將到期",
"The coupon can only be used :limit_use_with_user per person": "該優惠券每人只能用 :limit_use_with_user 次",
"The coupon code cannot be used for this period": "此優惠券無法用於該付款週期",
"Request failed, please try again later": "請求失敗,請稍後再試",
"Register frequently, please try again after :minute minute": "註冊頻繁,請等待 :minute 分鐘後再次嘗試",
"Uh-oh, we've had some problems, we're working on it.": "遇到了些問題,我們正在進行處理",
"This subscription reset package does not apply to your subscription": "該訂閱重置包不適用於你的訂閱",
"Login to :name": "登入到 :name",
"Sending frequently, please try again later": "發送頻繁,請稍後再試",
"Current product is sold out": "當前商品已售罄",
"There are too many password errors, please try again after :minute minutes.": "密碼錯誤次數過多,請 :minute 分鐘後再試",
"Reset failed, Please try again later": "重置失敗,請稍後再試",
"Subscribe": "訂閱資訊",
"User Information": "用戶資訊",
"Username": "用戶名",
"Status": "狀態",
"Active": "正常",
"Inactive": "未啟用",
"Data Used": "已用流量",
"Data Limit": "流量限制",
"Expiration Date": "到期時間",
"Reset In": "距離重置",
"Days": "天",
"Subscription Link": "訂閱連結",
"Copy": "複製",
"Copied": "已複製",
"QR Code": "二維碼",
"Unlimited": "長期有效",
"Device Limit": "設備限制",
"Devices": "台設備"
}

View File

@@ -49,8 +49,7 @@
"auto_route": true,
"domain_strategy": "prefer_ipv4",
"endpoint_independent_nat": true,
"inet4_address": "172.19.0.1/30",
"inet6_address": "2001:0470:f9da:fdfa::1/64",
"address": ["172.19.0.1/30", "2001:0470:f9da:fdfa::1/64"],
"mtu": 9000,
"sniff": true,
"sniff_override_destination": true,

View File

@@ -1,36 +1,29 @@
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<link rel="stylesheet" href="/assets/admin/components.chunk.css?v={{$version}}">
<link rel="stylesheet" href="/assets/admin/umi.css?v={{$version}}">
<link rel="stylesheet" href="/assets/admin/custom.css?v={{$version}}">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">
<title>{{$title}}</title>
<!-- <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito+Sans:300,400,400i,600,700"> -->
<script>window.routerBase = "/";</script>
<script>
window.settings = {
title: '{{$title}}',
theme: {
sidebar: '{{$theme_sidebar}}',
header: '{{$theme_header}}',
color: '{{$theme_color}}',
},
version: '{{$version}}',
background_url: '{{$background_url}}',
logo: '{{$logo}}',
secure_path: '{{$secure_path}}'
}
</script>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{ $title }}</title>
<script>
window.settings = {
base_url: "/",
title: "{{ $title }}",
version: "{{ $version }}",
logo: "{{ $logo }}",
secure_path: "{{ $secure_path }}",
};
</script>
<script type="module" crossorigin src="/assets/admin/assets/index.js"></script>
<link rel="stylesheet" crossorigin href="/assets/admin/assets/index.css" />
<link rel="stylesheet" crossorigin href="/assets/admin/assets/vendor.css">
<script src="/assets/admin/locales/en-US.js"></script>
<script src="/assets/admin/locales/zh-CN.js"></script>
<script src="/assets/admin/locales/ko-KR.js"></script>
</head>
<body>
<div id="root"></div>
<script src="/assets/admin/vendors.async.js?v={{$version}}"></script>
<script src="/assets/admin/components.async.js?v={{$version}}"></script>
<script src="/assets/admin/umi.js?v={{$version}}"></script>
<div id="root"></div>
</body>
</html>

View File

@@ -0,0 +1,296 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ __('Subscribe') }}</title>
<style>
:root {
--bg: #ffffff;
--text: #000000;
--text-secondary: #666666;
--primary: #2196f3;
--success: #4caf50;
--danger: #f44336;
--border: #eee;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
line-height: 1.6;
background: var(--bg);
color: var(--text);
-webkit-font-smoothing: antialiased;
padding: 2rem 1rem;
}
.container {
max-width: 600px;
margin: 0 auto;
}
.title {
font-size: 1.75rem;
font-weight: bold;
margin-bottom: 2rem;
}
.info-list {
display: flex;
flex-direction: column;
gap: 1.25rem;
margin-bottom: 3rem;
}
.info-item {
display: flex;
align-items: center;
font-size: 1rem;
}
.info-label {
min-width: 100px;
color: var(--text-secondary);
}
.info-value {
color: var(--text);
flex: 1;
font-weight: 500;
margin-left: 1rem;
}
.status {
display: inline-block;
padding: 0.25rem 0.75rem;
border-radius: 4px;
font-size: 0.875rem;
font-weight: 500;
}
.status.active {
background: var(--success);
color: white;
}
.status.inactive {
background: var(--danger);
color: white;
}
.links-section {
margin-top: 2rem;
}
.links-title {
font-size: 1.25rem;
font-weight: bold;
margin-bottom: 1rem;
color: var(--text-secondary);
}
.link-item {
position: relative;
display: flex;
gap: 0.5rem;
margin-bottom: 1.5rem;
}
.link-input {
flex: 1;
width: 100%;
padding: 0.75rem;
padding-right: 4rem;
border: 1px solid var(--border);
border-radius: 4px;
font-size: 0.875rem;
color: var(--text);
background: #f5f5f5;
}
.link-input:focus {
outline: none;
border-color: var(--primary);
}
.copy-btn {
position: absolute;
right: 0.5rem;
top: 50%;
transform: translateY(-50%);
padding: 0.5rem;
border: none;
background: none;
color: var(--text-secondary);
cursor: pointer;
font-size: 0.875rem;
display: flex;
align-items: center;
gap: 0.25rem;
transition: color 0.2s;
}
.copy-btn:hover {
color: var(--primary);
}
.copy-btn svg {
width: 1rem;
height: 1rem;
}
.copy-btn.copied {
color: var(--success);
}
.qr-section {
display: flex;
justify-content: center;
margin-top: 2rem;
}
.qr-section img {
width: 180px;
height: 180px;
padding: 0.75rem;
background: white;
border-radius: 4px;
}
@media (max-width: 640px) {
body {
padding: 1.5rem 1rem;
}
.title {
font-size: 1.5rem;
margin-bottom: 1.5rem;
}
.info-item {
font-size: 0.875rem;
}
.info-label {
min-width: 80px;
}
.qr-section img {
width: 160px;
height: 160px;
}
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #000000;
--text: #ffffff;
--text-secondary: #999999;
--border: #222;
}
.link-input {
background: #111;
border-color: var(--border);
color: var(--text);
}
}
</style>
</head>
<body>
<div class="container">
<h1 class="title">{{ __('User Information') }}</h1>
<div class="info-list">
<div class="info-item">
<div class="info-label">{{ __('Username') }}</div>
<div class="info-value">{{ $username }}</div>
</div>
<div class="info-item">
<div class="info-label">{{ __('Status') }}</div>
<div class="info-value">
<span class="status {{ $status }}">
{{ $status === 'active' ? __('Active') : __('Inactive') }}
</span>
</div>
</div>
<div class="info-item">
<div class="info-label">{{ __('Data Used') }}</div>
<div class="info-value">{{ $data_used }}</div>
</div>
<div class="info-item">
<div class="info-label">{{ __('Data Limit') }}</div>
<div class="info-value">{{ $data_limit }}</div>
</div>
<div class="info-item">
<div class="info-label">{{ __('Expiration Date') }}</div>
<div class="info-value">{{ $expired_date }}</div>
</div>
@if (isset($device_limit))
<div class="info-item">
<div class="info-label">{{ __('Device Limit') }}</div>
<div class="info-value">{{ $device_limit }} {{ __('Devices') }}</div>
</div>
@endif
@if ($reset_day)
<div class="info-item">
<div class="info-label">{{ __('Reset In') }}</div>
<div class="info-value">{{ $reset_day }} {{ __('Days') }}</div>
</div>
@endif
</div>
<div class="links-section">
<h2 class="links-title">{{ __('Subscription Link') }}</h2>
<div class="link-item">
<input type="text" value="{{ $subscription_url }}" readonly id="sub_url" class="link-input" onclick="this.select()">
<button class="copy-btn" onclick="copyToClipboard('sub_url')" title="{{ __('Copy') }}">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" />
</svg>
<span>{{ __('Copy') }}</span>
</button>
</div>
<div class="qr-section">
<img src="data:image/svg+xml;base64,{{ $qr_code }}" alt="{{ __('QR Code') }}">
</div>
</div>
</div>
<script>
function copyToClipboard(elementId) {
const element = document.getElementById(elementId);
element.select();
document.execCommand('copy');
element.blur();
const btn = element.nextElementSibling;
const span = btn.querySelector('span');
const originalText = span.textContent;
btn.classList.add('copied');
span.textContent = '{{ __('Copied') }}';
setTimeout(() => {
btn.classList.remove('copied');
span.textContent = originalText;
}, 1000);
}
</script>
</body>
</html>

View File

@@ -184,4 +184,4 @@
</table>
</body>
</html>
</html>