h5相关
This commit is contained in:
parent
c7a9801549
commit
a95322b0d2
@ -7,3 +7,7 @@ H5 通用主题放在 common/theme.css,新页面默认引用该文件。
|
||||
页面样式不要硬编码主色,优先消费 common/theme.css 里的 CSS 变量;只有 Figma 强制要求 100% 还原时才允许局部覆盖。
|
||||
|
||||
H5 多语言能力放在 common/i18n.js 和 common/locales/\*.json,当前面向英语 en、阿拉伯语 ar、土耳其语 tr、西班牙语 es。页面文案使用 data-i18n / data-i18n-placeholder / data-i18n-aria 绑定语言包 key;新增页面必须优先复用 common 的语言包机制,不在页面脚本里硬编码多语言字典。
|
||||
|
||||
所有逻辑功能配置默认打开;只有密钥、地址、三方账号等必须由环境提供的敏感值使用占位符或环境配置,不在默认配置里伪造可用凭证。
|
||||
|
||||
所有业务逻辑、状态流转、权限判断、支付链路、异步流程都保持高密度逻辑注释,注释解释为什么这样处理和失败分支,不复述语法。
|
||||
|
||||
164
common/api.js
164
common/api.js
@ -6,6 +6,7 @@ var default_api = 'https://api.global-interaction.com/';
|
||||
var API_ENV_KEY = 'hyapp_h5_env';
|
||||
var ACCESS_TOKEN_KEY = 'hyapp_access_token';
|
||||
var APP_CODE_KEY = 'hyapp_app_code';
|
||||
var RENEWED_ACCESS_TOKEN_HEADER = 'X-Hyapp-Access-Token';
|
||||
var memoryEnv = '';
|
||||
var memoryAccessToken = '';
|
||||
var memoryAppCode = '';
|
||||
@ -14,6 +15,36 @@ var default_api = 'https://api.global-interaction.com/';
|
||||
return new URLSearchParams(window.location.search).get(name);
|
||||
}
|
||||
|
||||
function normalizeToken(value) {
|
||||
var token = String(value || '').trim();
|
||||
if (!token) return '';
|
||||
if (/^Bearer\s+/i.test(token)) token = token.replace(/^Bearer\s+/i, '');
|
||||
var match = token.match(
|
||||
/[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/
|
||||
);
|
||||
return match ? match[0] : token;
|
||||
}
|
||||
|
||||
function decodeBase64URLJSON(value) {
|
||||
try {
|
||||
var normalized = String(value || '').replace(/-/g, '+').replace(/_/g, '/');
|
||||
while (normalized.length % 4) normalized += '=';
|
||||
return JSON.parse(window.atob(normalized));
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function isExpiredToken(token) {
|
||||
var parts = String(token || '').split('.');
|
||||
if (parts.length < 2) return false;
|
||||
var payload = decodeBase64URLJSON(parts[1]);
|
||||
if (!payload || !payload.exp) return false;
|
||||
// JWT exp 是秒级时间戳;本地 H5 不能只凭 query 有 token 就进入 token 模式,过期 token 会被 gateway 当成未登录。
|
||||
// 这里预留 5 秒偏移,避免页面发请求时刚好跨过过期点,导致 H5 隐藏账号输入但服务端收到空 display_user_id。
|
||||
return Number(payload.exp) * 1000 <= Date.now() + 5000;
|
||||
}
|
||||
|
||||
function normalizeBaseURL(value) {
|
||||
return String(value || '').replace(/\/+$/, '') + '/';
|
||||
}
|
||||
@ -85,19 +116,36 @@ var default_api = 'https://api.global-interaction.com/';
|
||||
}
|
||||
|
||||
function getAccessToken() {
|
||||
if (memoryAccessToken && !isExpiredToken(memoryAccessToken))
|
||||
return memoryAccessToken;
|
||||
if (memoryAccessToken && isExpiredToken(memoryAccessToken)) {
|
||||
memoryAccessToken = '';
|
||||
if (shouldPersist()) window.localStorage.removeItem(ACCESS_TOKEN_KEY);
|
||||
}
|
||||
var queryToken =
|
||||
readQuery('token') ||
|
||||
readQuery('access_token') ||
|
||||
readQuery('accessToken');
|
||||
normalizeToken(readQuery('token')) ||
|
||||
normalizeToken(readQuery('access_token')) ||
|
||||
normalizeToken(readQuery('accessToken'));
|
||||
if (queryToken) {
|
||||
if (isExpiredToken(queryToken)) {
|
||||
if (shouldPersist())
|
||||
window.localStorage.removeItem(ACCESS_TOKEN_KEY);
|
||||
return '';
|
||||
}
|
||||
memoryAccessToken = queryToken;
|
||||
if (shouldPersist())
|
||||
window.localStorage.setItem(ACCESS_TOKEN_KEY, queryToken);
|
||||
return queryToken;
|
||||
}
|
||||
if (memoryAccessToken) return memoryAccessToken;
|
||||
if (!shouldPersist()) return '';
|
||||
return window.localStorage.getItem(ACCESS_TOKEN_KEY) || '';
|
||||
var storedToken = normalizeToken(
|
||||
window.localStorage.getItem(ACCESS_TOKEN_KEY) || ''
|
||||
);
|
||||
if (storedToken && isExpiredToken(storedToken)) {
|
||||
window.localStorage.removeItem(ACCESS_TOKEN_KEY);
|
||||
return '';
|
||||
}
|
||||
return storedToken;
|
||||
}
|
||||
|
||||
function getAppCode() {
|
||||
@ -114,6 +162,8 @@ var default_api = 'https://api.global-interaction.com/';
|
||||
}
|
||||
|
||||
function setAccessToken(token) {
|
||||
token = normalizeToken(token);
|
||||
if (token && isExpiredToken(token)) token = '';
|
||||
memoryAccessToken = token || '';
|
||||
if (token) {
|
||||
if (shouldPersist())
|
||||
@ -184,6 +234,14 @@ var default_api = 'https://api.global-interaction.com/';
|
||||
});
|
||||
}
|
||||
|
||||
function persistRenewedAccessToken(response) {
|
||||
var renewedToken =
|
||||
response && response.headers
|
||||
? response.headers.get(RENEWED_ACCESS_TOKEN_HEADER)
|
||||
: '';
|
||||
if (renewedToken) setAccessToken(renewedToken);
|
||||
}
|
||||
|
||||
function request(path, options) {
|
||||
var opts = options || {};
|
||||
var headers = Object.assign({}, opts.headers || {});
|
||||
@ -210,7 +268,10 @@ var default_api = 'https://api.global-interaction.com/';
|
||||
cache: shouldPersist() ? 'default' : 'no-store',
|
||||
credentials: opts.credentials || 'omit',
|
||||
})
|
||||
.then(parseResponse);
|
||||
.then(function (response) {
|
||||
persistRenewedAccessToken(response);
|
||||
return parseResponse(response);
|
||||
});
|
||||
}
|
||||
|
||||
var vipAPI = {
|
||||
@ -235,6 +296,9 @@ var default_api = 'https://api.global-interaction.com/';
|
||||
overview: function () {
|
||||
return request('/api/v1/users/me/overview', { method: 'GET' });
|
||||
},
|
||||
appearance: function () {
|
||||
return request('/api/v1/users/me/appearance', { method: 'GET' });
|
||||
},
|
||||
hostIdentity: function () {
|
||||
return request('/api/v1/users/me/host-identity', {
|
||||
method: 'GET',
|
||||
@ -280,6 +344,50 @@ var default_api = 'https://api.global-interaction.com/';
|
||||
},
|
||||
};
|
||||
|
||||
// H5 充值 API 只做路径和参数名封装;token、app_code、env、错误 envelope 仍由 request 统一处理。
|
||||
// 金额、金币数、普通/币商钱包、MiFaPay 参数和 USDT 链上校验都以后端订单快照为准。
|
||||
var rechargeAPI = {
|
||||
context: function (displayUserID) {
|
||||
return request('/api/v1/recharge/h5/context', {
|
||||
method: 'GET',
|
||||
query: { display_user_id: displayUserID || '' },
|
||||
});
|
||||
},
|
||||
options: function (displayUserID) {
|
||||
return request('/api/v1/recharge/h5/options', {
|
||||
method: 'GET',
|
||||
query: { display_user_id: displayUserID || '' },
|
||||
});
|
||||
},
|
||||
createOrder: function (payload) {
|
||||
return request('/api/v1/recharge/h5/orders', {
|
||||
method: 'POST',
|
||||
body: payload || {},
|
||||
});
|
||||
},
|
||||
submitTx: function (orderID, payload) {
|
||||
return request(
|
||||
'/api/v1/recharge/h5/orders/' +
|
||||
encodeURIComponent(orderID || '') +
|
||||
'/tx',
|
||||
{
|
||||
method: 'POST',
|
||||
body: payload || {},
|
||||
}
|
||||
);
|
||||
},
|
||||
getOrder: function (orderID, displayUserID) {
|
||||
return request(
|
||||
'/api/v1/recharge/h5/orders/' +
|
||||
encodeURIComponent(orderID || ''),
|
||||
{
|
||||
method: 'GET',
|
||||
query: { display_user_id: displayUserID || '' },
|
||||
}
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
var salaryWalletAPI = {
|
||||
overview: function (identity) {
|
||||
return request('/api/v1/salary-wallet/overview', {
|
||||
@ -548,6 +656,48 @@ var default_api = 'https://api.global-interaction.com/';
|
||||
},
|
||||
};
|
||||
|
||||
var diceGameAPI = {
|
||||
config: function (gameID) {
|
||||
return request('/api/v1/games/dice/config', {
|
||||
method: 'GET',
|
||||
query: { game_id: gameID || 'dice' },
|
||||
});
|
||||
},
|
||||
match: function (payload) {
|
||||
return request('/api/v1/games/dice/match', {
|
||||
method: 'POST',
|
||||
body: payload || {},
|
||||
});
|
||||
},
|
||||
getMatch: function (matchID) {
|
||||
return request(
|
||||
'/api/v1/games/dice/matches/' +
|
||||
encodeURIComponent(matchID || ''),
|
||||
{ method: 'GET' }
|
||||
);
|
||||
},
|
||||
roll: function (matchID) {
|
||||
return request(
|
||||
'/api/v1/games/dice/matches/' +
|
||||
encodeURIComponent(matchID || '') +
|
||||
'/roll',
|
||||
{ method: 'POST', body: {} }
|
||||
);
|
||||
},
|
||||
cancel: function (matchID) {
|
||||
return request(
|
||||
'/api/v1/games/dice/matches/' +
|
||||
encodeURIComponent(matchID || '') +
|
||||
'/cancel',
|
||||
{ method: 'POST', body: {} }
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
var gameAPI = {
|
||||
dice: diceGameAPI,
|
||||
};
|
||||
|
||||
window.HyAppAPI = {
|
||||
baseURL: resolveBaseURL,
|
||||
buildURL: buildURL,
|
||||
@ -574,6 +724,7 @@ var default_api = 'https://api.global-interaction.com/';
|
||||
vip: vipAPI,
|
||||
user: userAPI,
|
||||
wallet: walletAPI,
|
||||
recharge: rechargeAPI,
|
||||
salaryWallet: salaryWalletAPI,
|
||||
host: hostAPI,
|
||||
hostCenter: hostCenterAPI,
|
||||
@ -584,6 +735,7 @@ var default_api = 'https://api.global-interaction.com/';
|
||||
superadminCenter: superadminCenterAPI,
|
||||
level: levelAPI,
|
||||
weeklyStar: weeklyStarAPI,
|
||||
game: gameAPI,
|
||||
};
|
||||
clearLocalDevCache();
|
||||
})();
|
||||
|
||||
@ -10,6 +10,28 @@
|
||||
var messages = {};
|
||||
var currentLang = '';
|
||||
|
||||
function scopedSupported() {
|
||||
var scoped =
|
||||
window.HyAppI18nSupported || window.HyAppSupportedLanguages || null;
|
||||
if (!Array.isArray(scoped)) return SUPPORTED;
|
||||
var normalized = [];
|
||||
scoped.forEach(function (value) {
|
||||
var lang = String(value || '')
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace('_', '-');
|
||||
if (lang.indexOf('ar') === 0) lang = 'ar';
|
||||
else if (lang.indexOf('tr') === 0) lang = 'tr';
|
||||
else if (lang.indexOf('es') === 0) lang = 'es';
|
||||
else if (lang.indexOf('zh') === 0) lang = 'zh';
|
||||
else if (lang.indexOf('id') === 0) lang = 'id';
|
||||
if (SUPPORTED.indexOf(lang) >= 0 && normalized.indexOf(lang) < 0) {
|
||||
normalized.push(lang);
|
||||
}
|
||||
});
|
||||
return normalized.length ? normalized : SUPPORTED;
|
||||
}
|
||||
|
||||
function storageGet(key) {
|
||||
try {
|
||||
return window.localStorage ? window.localStorage.getItem(key) : '';
|
||||
@ -28,8 +50,34 @@
|
||||
}
|
||||
}
|
||||
|
||||
function currentParams() {
|
||||
var parsed =
|
||||
window.HyAppParams &&
|
||||
window.HyAppParams.current &&
|
||||
window.HyAppParams.current.raw;
|
||||
if (parsed && parsed.get) return parsed;
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
var hash = window.location.hash || '';
|
||||
if (hash.indexOf('?') >= 0) {
|
||||
new URLSearchParams(hash.split('?').slice(1).join('?')).forEach(
|
||||
function (value, key) {
|
||||
if (!params.has(key)) params.set(key, value);
|
||||
}
|
||||
);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
function queryLang() {
|
||||
return new URLSearchParams(window.location.search).get('lang') || '';
|
||||
var params = currentParams();
|
||||
return (
|
||||
params.get('lang') ||
|
||||
params.get('language') ||
|
||||
params.get('locale') ||
|
||||
params.get('app_lang') ||
|
||||
params.get('appLanguage') ||
|
||||
''
|
||||
);
|
||||
}
|
||||
|
||||
function normalizeLang(value) {
|
||||
@ -38,12 +86,12 @@
|
||||
.toLowerCase()
|
||||
.replace('_', '-');
|
||||
if (!lang) return '';
|
||||
if (lang.indexOf('ar') === 0) return 'ar';
|
||||
if (lang.indexOf('tr') === 0) return 'tr';
|
||||
if (lang.indexOf('es') === 0) return 'es';
|
||||
if (lang.indexOf('zh') === 0) return 'zh';
|
||||
if (lang.indexOf('id') === 0) return 'id';
|
||||
return SUPPORTED.indexOf(lang) >= 0 ? lang : '';
|
||||
if (lang.indexOf('ar') === 0) lang = 'ar';
|
||||
else if (lang.indexOf('tr') === 0) lang = 'tr';
|
||||
else if (lang.indexOf('es') === 0) lang = 'es';
|
||||
else if (lang.indexOf('zh') === 0) lang = 'zh';
|
||||
else if (lang.indexOf('id') === 0) lang = 'id';
|
||||
return scopedSupported().indexOf(lang) >= 0 ? lang : '';
|
||||
}
|
||||
|
||||
function resolveLang() {
|
||||
@ -182,7 +230,7 @@
|
||||
lang: function () {
|
||||
return currentLang || DEFAULT_LANG;
|
||||
},
|
||||
supported: SUPPORTED.slice(),
|
||||
supported: scopedSupported(),
|
||||
};
|
||||
|
||||
function init() {
|
||||
|
||||
@ -8,6 +8,17 @@
|
||||
"diceMatch.unknownOpponent": "?",
|
||||
"diceMatch.win": "فوز",
|
||||
"diceMatch.coins": "عملات",
|
||||
"diceMatch.changeLanguage": "تغيير اللغة",
|
||||
"diceMatch.loading": "جار التحميل",
|
||||
"diceMatch.roll": "ارمِ",
|
||||
"diceMatch.rolling": "جار الرمي...",
|
||||
"diceMatch.ready": "جاهز",
|
||||
"diceMatch.draw": "تعادل",
|
||||
"diceMatch.compare": "مقارنة",
|
||||
"diceMatch.apiUnavailable": "واجهة لعبة النرد غير متاحة",
|
||||
"diceMatch.selectStake": "اختر قيمة الرهان",
|
||||
"diceMatch.requestFailed": "فشل الطلب",
|
||||
"diceMatch.configFeeNote": "الرسوم {fee}% · المجمع {pool}%",
|
||||
"roomReward.pageTitle": "فعالية مكافآت الغرفة",
|
||||
"roomReward.pageLabel": "فعالية مكافآت الغرفة",
|
||||
"roomReward.currentTarget": "هدف المكافأة الحالي",
|
||||
@ -397,5 +408,55 @@
|
||||
"cp.rewardMarquis7": "ماركيز*7 أيام",
|
||||
"cp.rewardCoins10000": "عملات*10000",
|
||||
"cp.rewardCount7": "عدّاد*7 أيام",
|
||||
"cp.copyright": "حقوق هذا النشاط تعود إلى Shila"
|
||||
"cp.copyright": "حقوق هذا النشاط تعود إلى Shila",
|
||||
"recharge.pageTitle": "الشحن",
|
||||
"recharge.pageSubtitle": "اختر باقة عملات وادفع عبر USDT-TRC20 أو طريقة دفع محلية مدعومة.",
|
||||
"recharge.changeLanguage": "تغيير اللغة",
|
||||
"recharge.accountTitle": "الحساب",
|
||||
"recharge.accountHint": "أكد الحساب قبل اختيار الباقة.",
|
||||
"recharge.userIdPlaceholder": "أدخل معرف المستخدم",
|
||||
"recharge.searchAccount": "تأكيد",
|
||||
"recharge.loading": "جار التحميل...",
|
||||
"recharge.accountConfirmed": "تم تأكيد الحساب",
|
||||
"recharge.ordinaryUser": "مستخدم",
|
||||
"recharge.coinSeller": "بائع عملات",
|
||||
"recharge.productTitle": "الباقة",
|
||||
"recharge.productEmpty": "لا توجد باقة متاحة لهذا الحساب.",
|
||||
"recharge.paymentTitle": "الدفع",
|
||||
"recharge.backToPackages": "العودة إلى الباقات",
|
||||
"recharge.selectedPackage": "الباقة المحددة",
|
||||
"recharge.selectProductFirst": "اختر باقة أولا.",
|
||||
"recharge.noPaymentMethods": "لا توجد طريقة دفع متاحة.",
|
||||
"recharge.usdtTrc20": "USDT-TRC20",
|
||||
"recharge.usdtNetwork": "شبكة TRON",
|
||||
"recharge.thirdPartyPayment": "دفع محلي",
|
||||
"recharge.createOrder": "إنشاء الطلب",
|
||||
"recharge.creating": "جار الإنشاء...",
|
||||
"recharge.orderTitle": "الطلب",
|
||||
"recharge.paymentOperation": "عملية الدفع",
|
||||
"recharge.close": "إغلاق",
|
||||
"recharge.orderId": "رقم الطلب",
|
||||
"recharge.orderStatus": "الحالة",
|
||||
"recharge.payRedirecting": "جار فتح صفحة الدفع...",
|
||||
"recharge.payOpenHint": "افتح صفحة الدفع وأكمل الدفع.",
|
||||
"recharge.openPayment": "فتح الدفع",
|
||||
"recharge.usdtAddress": "عنوان USDT-TRC20",
|
||||
"recharge.usdtHint": "حوّل USDT ثم أرسل TXID.",
|
||||
"recharge.copy": "نسخ",
|
||||
"recharge.txHashPlaceholder": "أدخل TXID بعد الدفع",
|
||||
"recharge.submitTx": "إرسال TXID",
|
||||
"recharge.submitted": "جار الإرسال...",
|
||||
"recharge.txSubmitted": "تم إرسال TXID",
|
||||
"recharge.paidSuccess": "اكتمل الدفع",
|
||||
"recharge.orderFailed": "فشل الطلب",
|
||||
"recharge.accountRequired": "أدخل معرف المستخدم",
|
||||
"recharge.orderCreateFailed": "فشل إنشاء الطلب",
|
||||
"recharge.loadFailed": "فشل التحميل",
|
||||
"recharge.copied": "تم النسخ",
|
||||
"recharge.copyFailed": "فشل النسخ",
|
||||
"recharge.coins": "عملات",
|
||||
"recharge.status.pending": "قيد الانتظار",
|
||||
"recharge.status.redirected": "بانتظار الدفع",
|
||||
"recharge.status.credited": "تمت الإضافة",
|
||||
"recharge.status.failed": "فشل"
|
||||
}
|
||||
|
||||
@ -8,6 +8,17 @@
|
||||
"diceMatch.unknownOpponent": "?",
|
||||
"diceMatch.win": "Win",
|
||||
"diceMatch.coins": "Coins",
|
||||
"diceMatch.changeLanguage": "Change language",
|
||||
"diceMatch.loading": "Loading",
|
||||
"diceMatch.roll": "Roll",
|
||||
"diceMatch.rolling": "Rolling...",
|
||||
"diceMatch.ready": "Ready",
|
||||
"diceMatch.draw": "Draw",
|
||||
"diceMatch.compare": "Compare",
|
||||
"diceMatch.apiUnavailable": "Dice API unavailable",
|
||||
"diceMatch.selectStake": "Select a stake",
|
||||
"diceMatch.requestFailed": "Request failed",
|
||||
"diceMatch.configFeeNote": "Fee {fee}% · Pool {pool}%",
|
||||
"roomReward.pageTitle": "Room Reward Event",
|
||||
"roomReward.pageLabel": "Room Reward Event",
|
||||
"roomReward.currentTarget": "Current reward target",
|
||||
@ -403,5 +414,55 @@
|
||||
"cp.rewardMarquis7": "Marquis*7days",
|
||||
"cp.rewardCoins10000": "Coins*10000",
|
||||
"cp.rewardCount7": "Count*7days",
|
||||
"cp.copyright": "The copyright of this activity belongs to Shila"
|
||||
"cp.copyright": "The copyright of this activity belongs to Shila",
|
||||
"recharge.pageTitle": "Recharge",
|
||||
"recharge.pageSubtitle": "Choose a coin package and pay with USDT-TRC20 or a supported local payment method.",
|
||||
"recharge.changeLanguage": "Change language",
|
||||
"recharge.accountTitle": "Account",
|
||||
"recharge.accountHint": "Confirm the account before selecting a package.",
|
||||
"recharge.userIdPlaceholder": "Enter user ID",
|
||||
"recharge.searchAccount": "Confirm",
|
||||
"recharge.loading": "Loading...",
|
||||
"recharge.accountConfirmed": "Account confirmed",
|
||||
"recharge.ordinaryUser": "User",
|
||||
"recharge.coinSeller": "Coin seller",
|
||||
"recharge.productTitle": "Package",
|
||||
"recharge.productEmpty": "No package is available for this account.",
|
||||
"recharge.paymentTitle": "Payment",
|
||||
"recharge.backToPackages": "Back to packages",
|
||||
"recharge.selectedPackage": "Selected package",
|
||||
"recharge.selectProductFirst": "Select a package first.",
|
||||
"recharge.noPaymentMethods": "No payment method is available.",
|
||||
"recharge.usdtTrc20": "USDT-TRC20",
|
||||
"recharge.usdtNetwork": "TRON network",
|
||||
"recharge.thirdPartyPayment": "Local payment",
|
||||
"recharge.createOrder": "Create order",
|
||||
"recharge.creating": "Creating...",
|
||||
"recharge.orderTitle": "Order",
|
||||
"recharge.paymentOperation": "Payment operation",
|
||||
"recharge.close": "Close",
|
||||
"recharge.orderId": "Order ID",
|
||||
"recharge.orderStatus": "Status",
|
||||
"recharge.payRedirecting": "Opening payment page...",
|
||||
"recharge.payOpenHint": "Open the payment page and finish the payment.",
|
||||
"recharge.openPayment": "Open payment",
|
||||
"recharge.usdtAddress": "USDT-TRC20 address",
|
||||
"recharge.usdtHint": "Transfer USDT and submit the TXID.",
|
||||
"recharge.copy": "Copy",
|
||||
"recharge.txHashPlaceholder": "Enter TXID after payment",
|
||||
"recharge.submitTx": "Submit TXID",
|
||||
"recharge.submitted": "Submitting...",
|
||||
"recharge.txSubmitted": "TXID submitted",
|
||||
"recharge.paidSuccess": "Payment completed",
|
||||
"recharge.orderFailed": "Order failed",
|
||||
"recharge.accountRequired": "Enter user ID",
|
||||
"recharge.orderCreateFailed": "Create order failed",
|
||||
"recharge.loadFailed": "Load failed",
|
||||
"recharge.copied": "Copied",
|
||||
"recharge.copyFailed": "Copy failed",
|
||||
"recharge.coins": "coins",
|
||||
"recharge.status.pending": "Pending",
|
||||
"recharge.status.redirected": "Waiting for payment",
|
||||
"recharge.status.credited": "Credited",
|
||||
"recharge.status.failed": "Failed"
|
||||
}
|
||||
|
||||
@ -8,6 +8,17 @@
|
||||
"diceMatch.unknownOpponent": "?",
|
||||
"diceMatch.win": "Victoria",
|
||||
"diceMatch.coins": "Monedas",
|
||||
"diceMatch.changeLanguage": "Cambiar idioma",
|
||||
"diceMatch.loading": "Cargando",
|
||||
"diceMatch.roll": "Tirar",
|
||||
"diceMatch.rolling": "Tirando...",
|
||||
"diceMatch.ready": "Listo",
|
||||
"diceMatch.draw": "Empate",
|
||||
"diceMatch.compare": "Comparar",
|
||||
"diceMatch.apiUnavailable": "API del juego de dados no disponible",
|
||||
"diceMatch.selectStake": "Selecciona una apuesta",
|
||||
"diceMatch.requestFailed": "Error de solicitud",
|
||||
"diceMatch.configFeeNote": "Comisión {fee}% · Bolsa {pool}%",
|
||||
"roomReward.pageTitle": "Evento de recompensas de sala",
|
||||
"roomReward.pageLabel": "Evento de recompensas de sala",
|
||||
"roomReward.currentTarget": "Objetivo de recompensa actual",
|
||||
@ -397,5 +408,55 @@
|
||||
"cp.rewardMarquis7": "Marqués*7 días",
|
||||
"cp.rewardCoins10000": "Monedas*10000",
|
||||
"cp.rewardCount7": "Contador*7 días",
|
||||
"cp.copyright": "Los derechos de esta actividad pertenecen a Shila"
|
||||
"cp.copyright": "Los derechos de esta actividad pertenecen a Shila",
|
||||
"recharge.pageTitle": "Recarga",
|
||||
"recharge.pageSubtitle": "Elige un paquete de monedas y paga con USDT-TRC20 o un método local compatible.",
|
||||
"recharge.changeLanguage": "Cambiar idioma",
|
||||
"recharge.accountTitle": "Cuenta",
|
||||
"recharge.accountHint": "Confirma la cuenta antes de elegir un paquete.",
|
||||
"recharge.userIdPlaceholder": "Ingresa el ID de usuario",
|
||||
"recharge.searchAccount": "Confirmar",
|
||||
"recharge.loading": "Cargando...",
|
||||
"recharge.accountConfirmed": "Cuenta confirmada",
|
||||
"recharge.ordinaryUser": "Usuario",
|
||||
"recharge.coinSeller": "Vendedor de monedas",
|
||||
"recharge.productTitle": "Paquete",
|
||||
"recharge.productEmpty": "No hay paquetes disponibles para esta cuenta.",
|
||||
"recharge.paymentTitle": "Pago",
|
||||
"recharge.backToPackages": "Volver a paquetes",
|
||||
"recharge.selectedPackage": "Paquete seleccionado",
|
||||
"recharge.selectProductFirst": "Elige un paquete primero.",
|
||||
"recharge.noPaymentMethods": "No hay métodos de pago disponibles.",
|
||||
"recharge.usdtTrc20": "USDT-TRC20",
|
||||
"recharge.usdtNetwork": "Red TRON",
|
||||
"recharge.thirdPartyPayment": "Pago local",
|
||||
"recharge.createOrder": "Crear pedido",
|
||||
"recharge.creating": "Creando...",
|
||||
"recharge.orderTitle": "Pedido",
|
||||
"recharge.paymentOperation": "Operación de pago",
|
||||
"recharge.close": "Cerrar",
|
||||
"recharge.orderId": "ID de pedido",
|
||||
"recharge.orderStatus": "Estado",
|
||||
"recharge.payRedirecting": "Abriendo página de pago...",
|
||||
"recharge.payOpenHint": "Abre la página de pago y completa el pago.",
|
||||
"recharge.openPayment": "Abrir pago",
|
||||
"recharge.usdtAddress": "Dirección USDT-TRC20",
|
||||
"recharge.usdtHint": "Transfiere USDT y envía el TXID.",
|
||||
"recharge.copy": "Copiar",
|
||||
"recharge.txHashPlaceholder": "Ingresa el TXID después del pago",
|
||||
"recharge.submitTx": "Enviar TXID",
|
||||
"recharge.submitted": "Enviando...",
|
||||
"recharge.txSubmitted": "TXID enviado",
|
||||
"recharge.paidSuccess": "Pago completado",
|
||||
"recharge.orderFailed": "Pedido fallido",
|
||||
"recharge.accountRequired": "Ingresa el ID de usuario",
|
||||
"recharge.orderCreateFailed": "No se pudo crear el pedido",
|
||||
"recharge.loadFailed": "Error al cargar",
|
||||
"recharge.copied": "Copiado",
|
||||
"recharge.copyFailed": "Error al copiar",
|
||||
"recharge.coins": "monedas",
|
||||
"recharge.status.pending": "Pendiente",
|
||||
"recharge.status.redirected": "Esperando pago",
|
||||
"recharge.status.credited": "Acreditado",
|
||||
"recharge.status.failed": "Fallido"
|
||||
}
|
||||
|
||||
@ -397,5 +397,55 @@
|
||||
"cp.rewardMarquis7": "Marquis*7 hari",
|
||||
"cp.rewardCoins10000": "Koin*10000",
|
||||
"cp.rewardCount7": "Hitungan*7 hari",
|
||||
"cp.copyright": "Hak cipta aktivitas ini milik Shila"
|
||||
"cp.copyright": "Hak cipta aktivitas ini milik Shila",
|
||||
"recharge.pageTitle": "Top up",
|
||||
"recharge.pageSubtitle": "Pilih paket coin dan bayar dengan USDT-TRC20 atau metode lokal yang didukung.",
|
||||
"recharge.changeLanguage": "Ganti bahasa",
|
||||
"recharge.accountTitle": "Akun",
|
||||
"recharge.accountHint": "Konfirmasi akun sebelum memilih paket.",
|
||||
"recharge.userIdPlaceholder": "Masukkan ID pengguna",
|
||||
"recharge.searchAccount": "Konfirmasi",
|
||||
"recharge.loading": "Memuat...",
|
||||
"recharge.accountConfirmed": "Akun dikonfirmasi",
|
||||
"recharge.ordinaryUser": "Pengguna",
|
||||
"recharge.coinSeller": "Coin seller",
|
||||
"recharge.productTitle": "Paket",
|
||||
"recharge.productEmpty": "Tidak ada paket untuk akun ini.",
|
||||
"recharge.paymentTitle": "Pembayaran",
|
||||
"recharge.backToPackages": "Kembali ke paket",
|
||||
"recharge.selectedPackage": "Paket dipilih",
|
||||
"recharge.selectProductFirst": "Pilih paket terlebih dahulu.",
|
||||
"recharge.noPaymentMethods": "Tidak ada metode pembayaran.",
|
||||
"recharge.usdtTrc20": "USDT-TRC20",
|
||||
"recharge.usdtNetwork": "Jaringan TRON",
|
||||
"recharge.thirdPartyPayment": "Pembayaran lokal",
|
||||
"recharge.createOrder": "Buat pesanan",
|
||||
"recharge.creating": "Membuat...",
|
||||
"recharge.orderTitle": "Pesanan",
|
||||
"recharge.paymentOperation": "Operasi pembayaran",
|
||||
"recharge.close": "Tutup",
|
||||
"recharge.orderId": "ID pesanan",
|
||||
"recharge.orderStatus": "Status",
|
||||
"recharge.payRedirecting": "Membuka halaman pembayaran...",
|
||||
"recharge.payOpenHint": "Buka halaman pembayaran dan selesaikan pembayaran.",
|
||||
"recharge.openPayment": "Buka pembayaran",
|
||||
"recharge.usdtAddress": "Alamat USDT-TRC20",
|
||||
"recharge.usdtHint": "Transfer USDT lalu kirim TXID.",
|
||||
"recharge.copy": "Salin",
|
||||
"recharge.txHashPlaceholder": "Masukkan TXID setelah bayar",
|
||||
"recharge.submitTx": "Kirim TXID",
|
||||
"recharge.submitted": "Mengirim...",
|
||||
"recharge.txSubmitted": "TXID terkirim",
|
||||
"recharge.paidSuccess": "Pembayaran selesai",
|
||||
"recharge.orderFailed": "Pesanan gagal",
|
||||
"recharge.accountRequired": "Masukkan ID pengguna",
|
||||
"recharge.orderCreateFailed": "Gagal membuat pesanan",
|
||||
"recharge.loadFailed": "Gagal memuat",
|
||||
"recharge.copied": "Disalin",
|
||||
"recharge.copyFailed": "Gagal menyalin",
|
||||
"recharge.coins": "coin",
|
||||
"recharge.status.pending": "Menunggu",
|
||||
"recharge.status.redirected": "Menunggu pembayaran",
|
||||
"recharge.status.credited": "Masuk",
|
||||
"recharge.status.failed": "Gagal"
|
||||
}
|
||||
|
||||
@ -397,5 +397,55 @@
|
||||
"cp.rewardMarquis7": "Marki*7 gün",
|
||||
"cp.rewardCoins10000": "Coin*10000",
|
||||
"cp.rewardCount7": "Sayaç*7 gün",
|
||||
"cp.copyright": "Bu etkinliğin telif hakkı Shila'ya aittir"
|
||||
"cp.copyright": "Bu etkinliğin telif hakkı Shila'ya aittir",
|
||||
"recharge.pageTitle": "Yükleme",
|
||||
"recharge.pageSubtitle": "Coin paketi seçin ve USDT-TRC20 ya da desteklenen yerel ödeme yöntemiyle ödeyin.",
|
||||
"recharge.changeLanguage": "Dili değiştir",
|
||||
"recharge.accountTitle": "Hesap",
|
||||
"recharge.accountHint": "Paket seçmeden önce hesabı onaylayın.",
|
||||
"recharge.userIdPlaceholder": "Kullanıcı ID girin",
|
||||
"recharge.searchAccount": "Onayla",
|
||||
"recharge.loading": "Yükleniyor...",
|
||||
"recharge.accountConfirmed": "Hesap onaylandı",
|
||||
"recharge.ordinaryUser": "Kullanıcı",
|
||||
"recharge.coinSeller": "Coin seller",
|
||||
"recharge.productTitle": "Paket",
|
||||
"recharge.productEmpty": "Bu hesap için paket yok.",
|
||||
"recharge.paymentTitle": "Ödeme",
|
||||
"recharge.backToPackages": "Paketlere dön",
|
||||
"recharge.selectedPackage": "Seçilen paket",
|
||||
"recharge.selectProductFirst": "Önce paket seçin.",
|
||||
"recharge.noPaymentMethods": "Kullanılabilir ödeme yöntemi yok.",
|
||||
"recharge.usdtTrc20": "USDT-TRC20",
|
||||
"recharge.usdtNetwork": "TRON ağı",
|
||||
"recharge.thirdPartyPayment": "Yerel ödeme",
|
||||
"recharge.createOrder": "Sipariş oluştur",
|
||||
"recharge.creating": "Oluşturuluyor...",
|
||||
"recharge.orderTitle": "Sipariş",
|
||||
"recharge.paymentOperation": "Ödeme işlemi",
|
||||
"recharge.close": "Kapat",
|
||||
"recharge.orderId": "Sipariş ID",
|
||||
"recharge.orderStatus": "Durum",
|
||||
"recharge.payRedirecting": "Ödeme sayfası açılıyor...",
|
||||
"recharge.payOpenHint": "Ödeme sayfasını açın ve ödemeyi tamamlayın.",
|
||||
"recharge.openPayment": "Ödemeyi aç",
|
||||
"recharge.usdtAddress": "USDT-TRC20 adresi",
|
||||
"recharge.usdtHint": "USDT gönderin ve TXID girin.",
|
||||
"recharge.copy": "Kopyala",
|
||||
"recharge.txHashPlaceholder": "Ödemeden sonra TXID girin",
|
||||
"recharge.submitTx": "TXID gönder",
|
||||
"recharge.submitted": "Gönderiliyor...",
|
||||
"recharge.txSubmitted": "TXID gönderildi",
|
||||
"recharge.paidSuccess": "Ödeme tamamlandı",
|
||||
"recharge.orderFailed": "Sipariş başarısız",
|
||||
"recharge.accountRequired": "Kullanıcı ID girin",
|
||||
"recharge.orderCreateFailed": "Sipariş oluşturulamadı",
|
||||
"recharge.loadFailed": "Yükleme başarısız",
|
||||
"recharge.copied": "Kopyalandı",
|
||||
"recharge.copyFailed": "Kopyalama başarısız",
|
||||
"recharge.coins": "coin",
|
||||
"recharge.status.pending": "Bekliyor",
|
||||
"recharge.status.redirected": "Ödeme bekleniyor",
|
||||
"recharge.status.credited": "Yüklendi",
|
||||
"recharge.status.failed": "Başarısız"
|
||||
}
|
||||
|
||||
@ -403,5 +403,55 @@
|
||||
"cp.rewardMarquis7": "侯爵*7天",
|
||||
"cp.rewardCoins10000": "金币*10000",
|
||||
"cp.rewardCount7": "计数*7天",
|
||||
"cp.copyright": "本活动版权归 Shila 所有"
|
||||
"cp.copyright": "本活动版权归 Shila 所有",
|
||||
"recharge.pageTitle": "充值",
|
||||
"recharge.pageSubtitle": "选择金币档位,使用 USDT-TRC20 或支持的本地支付方式付款。",
|
||||
"recharge.changeLanguage": "切换语言",
|
||||
"recharge.accountTitle": "账号",
|
||||
"recharge.accountHint": "确认账号后再选择充值档位。",
|
||||
"recharge.userIdPlaceholder": "输入用户 ID",
|
||||
"recharge.searchAccount": "确认",
|
||||
"recharge.loading": "加载中...",
|
||||
"recharge.accountConfirmed": "账号已确认",
|
||||
"recharge.ordinaryUser": "普通用户",
|
||||
"recharge.coinSeller": "币商",
|
||||
"recharge.productTitle": "充值档位",
|
||||
"recharge.productEmpty": "当前账号暂无可用档位。",
|
||||
"recharge.paymentTitle": "支付方式",
|
||||
"recharge.backToPackages": "返回充值档位",
|
||||
"recharge.selectedPackage": "已选档位",
|
||||
"recharge.selectProductFirst": "请先选择充值档位。",
|
||||
"recharge.noPaymentMethods": "当前暂无可用支付方式。",
|
||||
"recharge.usdtTrc20": "USDT-TRC20",
|
||||
"recharge.usdtNetwork": "TRON 网络",
|
||||
"recharge.thirdPartyPayment": "本地支付",
|
||||
"recharge.createOrder": "创建订单",
|
||||
"recharge.creating": "创建中...",
|
||||
"recharge.orderTitle": "订单",
|
||||
"recharge.paymentOperation": "支付操作",
|
||||
"recharge.close": "关闭",
|
||||
"recharge.orderId": "订单号",
|
||||
"recharge.orderStatus": "状态",
|
||||
"recharge.payRedirecting": "正在打开支付页面...",
|
||||
"recharge.payOpenHint": "打开支付页面并完成付款。",
|
||||
"recharge.openPayment": "打开支付",
|
||||
"recharge.usdtAddress": "USDT-TRC20 收款地址",
|
||||
"recharge.usdtHint": "转账 USDT 后提交 TXID。",
|
||||
"recharge.copy": "复制",
|
||||
"recharge.txHashPlaceholder": "付款后输入 TXID",
|
||||
"recharge.submitTx": "提交 TXID",
|
||||
"recharge.submitted": "提交中...",
|
||||
"recharge.txSubmitted": "TXID 已提交",
|
||||
"recharge.paidSuccess": "支付已完成",
|
||||
"recharge.orderFailed": "订单失败",
|
||||
"recharge.accountRequired": "请输入用户 ID",
|
||||
"recharge.orderCreateFailed": "创建订单失败",
|
||||
"recharge.loadFailed": "加载失败",
|
||||
"recharge.copied": "已复制",
|
||||
"recharge.copyFailed": "复制失败",
|
||||
"recharge.coins": "金币",
|
||||
"recharge.status.pending": "待支付",
|
||||
"recharge.status.redirected": "等待支付",
|
||||
"recharge.status.credited": "已到账",
|
||||
"recharge.status.failed": "失败"
|
||||
}
|
||||
|
||||
@ -28,10 +28,31 @@
|
||||
function normalizeToken(value) {
|
||||
var token = String(value || '').trim();
|
||||
if (!token) return '';
|
||||
if (/^Bearer\s+/i.test(token)) token = token.replace(/^Bearer\s+/i, '');
|
||||
var match = token.match(
|
||||
/[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/
|
||||
);
|
||||
return match ? match[0] : token;
|
||||
token = match ? match[0] : token;
|
||||
return isExpiredToken(token) ? '' : token;
|
||||
}
|
||||
|
||||
function decodeBase64URLJSON(value) {
|
||||
try {
|
||||
var normalized = String(value || '').replace(/-/g, '+').replace(/_/g, '/');
|
||||
while (normalized.length % 4) normalized += '=';
|
||||
return JSON.parse(window.atob(normalized));
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function isExpiredToken(token) {
|
||||
var parts = String(token || '').split('.');
|
||||
if (parts.length < 2) return false;
|
||||
var payload = decodeBase64URLJSON(parts[1]);
|
||||
if (!payload || !payload.exp) return false;
|
||||
// params 是页面入口模式的判定来源;过期 JWT 必须当作无 token,否则充值页会隐藏用户 ID 输入并触发 INVALID_ARGUMENT。
|
||||
return Number(payload.exp) * 1000 <= Date.now() + 5000;
|
||||
}
|
||||
|
||||
function parse() {
|
||||
|
||||
1
common/vendor/svga.min.js
vendored
Normal file
1
common/vendor/svga.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
game/touzi/assets/figma/dice-roll.svga
Normal file
BIN
game/touzi/assets/figma/dice-roll.svga
Normal file
Binary file not shown.
35
game/touzi/assets/figma/matching-center-bg.svg
Normal file
35
game/touzi/assets/figma/matching-center-bg.svg
Normal file
@ -0,0 +1,35 @@
|
||||
<svg width="132" height="132" viewBox="0 0 132 132" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<radialGradient id="matchingCenterGlow" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(66 66) rotate(90) scale(66)">
|
||||
<stop offset="0" stop-color="#0AF4FF" stop-opacity="0.44"/>
|
||||
<stop offset="0.48" stop-color="#0087FF" stop-opacity="0.28"/>
|
||||
<stop offset="1" stop-color="#001C5B" stop-opacity="0"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="matchingCenterStroke" x1="25" y1="15" x2="104" y2="116" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#7FFFFF"/>
|
||||
<stop offset="0.47" stop-color="#00A8FF"/>
|
||||
<stop offset="1" stop-color="#B7FFFF"/>
|
||||
</linearGradient>
|
||||
<filter id="matchingCenterBlur" x="-20" y="-20" width="172" height="172" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur stdDeviation="2.2"/>
|
||||
</filter>
|
||||
<filter id="matchingCenterShadow" x="-16" y="-16" width="164" height="164" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feDropShadow dx="0" dy="0" stdDeviation="5" flood-color="#00B7FF" flood-opacity="0.82"/>
|
||||
</filter>
|
||||
</defs>
|
||||
<circle cx="66" cy="66" r="60" fill="url(#matchingCenterGlow)"/>
|
||||
<g filter="url(#matchingCenterBlur)" opacity="0.9">
|
||||
<path d="M18 64C18.8 38.4 39.5 18.2 65.2 17.6" stroke="#6FFFFF" stroke-width="2.2" stroke-linecap="round" stroke-dasharray="30 15"/>
|
||||
<path d="M112 69C110.8 94.8 89.7 114.4 64 114.3" stroke="#4CEBFF" stroke-width="2.2" stroke-linecap="round" stroke-dasharray="28 18"/>
|
||||
<path d="M35.5 25.2C52.2 13 75 11.8 93.2 22.6" stroke="#2EBBFF" stroke-width="1.8" stroke-linecap="round" stroke-dasharray="18 13"/>
|
||||
<path d="M28.2 97.5C17.2 82.4 14.6 62.5 21.5 45.2" stroke="#0087FF" stroke-width="1.8" stroke-linecap="round" stroke-dasharray="16 12"/>
|
||||
</g>
|
||||
<g filter="url(#matchingCenterShadow)">
|
||||
<circle cx="66" cy="66" r="49" stroke="url(#matchingCenterStroke)" stroke-width="2.8" stroke-linecap="round" stroke-dasharray="86 19 22 12"/>
|
||||
<circle cx="66" cy="66" r="41" stroke="#107BFF" stroke-width="2" stroke-linecap="round" stroke-dasharray="12 8"/>
|
||||
<circle cx="66" cy="66" r="34" stroke="#7DFBFF" stroke-width="2.6" stroke-linecap="round" stroke-dasharray="52 15 9 13"/>
|
||||
<circle cx="66" cy="66" r="27" stroke="#006EFF" stroke-width="1.8" stroke-linecap="round" stroke-dasharray="8 7"/>
|
||||
<circle cx="66" cy="66" r="19" fill="#0098FF" fill-opacity="0.28" stroke="#2AECFF" stroke-width="2"/>
|
||||
<path d="M66 8.5V14.5M66 117.5V123.5M8.5 66H14.5M117.5 66H123.5" stroke="#8CFFFF" stroke-width="1.8" stroke-linecap="round" opacity="0.82"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
37
game/touzi/assets/figma/matching-center.svg
Normal file
37
game/touzi/assets/figma/matching-center.svg
Normal file
@ -0,0 +1,37 @@
|
||||
<svg width="132" height="132" viewBox="0 0 132 132" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<radialGradient id="matchingCenterGlow" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(66 66) rotate(90) scale(66)">
|
||||
<stop offset="0" stop-color="#0AF4FF" stop-opacity="0.44"/>
|
||||
<stop offset="0.48" stop-color="#0087FF" stop-opacity="0.28"/>
|
||||
<stop offset="1" stop-color="#001C5B" stop-opacity="0"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="matchingCenterStroke" x1="25" y1="15" x2="104" y2="116" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#7FFFFF"/>
|
||||
<stop offset="0.47" stop-color="#00A8FF"/>
|
||||
<stop offset="1" stop-color="#B7FFFF"/>
|
||||
</linearGradient>
|
||||
<filter id="matchingCenterBlur" x="-20" y="-20" width="172" height="172" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur stdDeviation="2.2"/>
|
||||
</filter>
|
||||
<filter id="matchingCenterShadow" x="-16" y="-16" width="164" height="164" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feDropShadow dx="0" dy="0" stdDeviation="5" flood-color="#00B7FF" flood-opacity="0.82"/>
|
||||
</filter>
|
||||
</defs>
|
||||
<circle cx="66" cy="66" r="60" fill="url(#matchingCenterGlow)"/>
|
||||
<g filter="url(#matchingCenterBlur)" opacity="0.9">
|
||||
<path d="M18 64C18.8 38.4 39.5 18.2 65.2 17.6" stroke="#6FFFFF" stroke-width="2.2" stroke-linecap="round" stroke-dasharray="30 15"/>
|
||||
<path d="M112 69C110.8 94.8 89.7 114.4 64 114.3" stroke="#4CEBFF" stroke-width="2.2" stroke-linecap="round" stroke-dasharray="28 18"/>
|
||||
<path d="M35.5 25.2C52.2 13 75 11.8 93.2 22.6" stroke="#2EBBFF" stroke-width="1.8" stroke-linecap="round" stroke-dasharray="18 13"/>
|
||||
<path d="M28.2 97.5C17.2 82.4 14.6 62.5 21.5 45.2" stroke="#0087FF" stroke-width="1.8" stroke-linecap="round" stroke-dasharray="16 12"/>
|
||||
</g>
|
||||
<g filter="url(#matchingCenterShadow)">
|
||||
<circle cx="66" cy="66" r="49" stroke="url(#matchingCenterStroke)" stroke-width="2.8" stroke-linecap="round" stroke-dasharray="86 19 22 12"/>
|
||||
<circle cx="66" cy="66" r="41" stroke="#107BFF" stroke-width="2" stroke-linecap="round" stroke-dasharray="12 8"/>
|
||||
<circle cx="66" cy="66" r="34" stroke="#7DFBFF" stroke-width="2.6" stroke-linecap="round" stroke-dasharray="52 15 9 13"/>
|
||||
<circle cx="66" cy="66" r="27" stroke="#006EFF" stroke-width="1.8" stroke-linecap="round" stroke-dasharray="8 7"/>
|
||||
<circle cx="66" cy="66" r="19" fill="#0098FF" fill-opacity="0.28" stroke="#2AECFF" stroke-width="2"/>
|
||||
<path d="M74.2 74.1L80.5 80.4" stroke="white" stroke-width="3.1" stroke-linecap="round"/>
|
||||
<circle cx="64" cy="64" r="8.4" stroke="white" stroke-width="3.1"/>
|
||||
<path d="M66 8.5V14.5M66 117.5V123.5M8.5 66H14.5M117.5 66H123.5" stroke="#8CFFFF" stroke-width="1.8" stroke-linecap="round" opacity="0.82"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
File diff suppressed because it is too large
Load Diff
1555
recharge/index.html
1555
recharge/index.html
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user