This commit is contained in:
zhx 2026-06-12 19:35:46 +08:00
parent cd9dfb4bfb
commit 54deddd72d
8 changed files with 175 additions and 19 deletions

View File

@ -34,6 +34,9 @@
--countdown-card-bg: url("./assets/djs.png");
--button-active-bg: url("./assets/btnselect.png");
--button-inactive-bg: url("./assets/btnunselect.png");
--gift-cta-side: 12px;
--gift-cta-height: min(68px, 18.235vw);
--gift-cta-bottom: calc(env(safe-area-inset-bottom) + 10px);
}
* {
@ -763,7 +766,10 @@
.gift-overlay {
position: relative;
z-index: 1;
padding: calc(env(safe-area-inset-top) + 18px) 14px calc(env(safe-area-inset-bottom) + 26px);
padding:
calc(env(safe-area-inset-top) + 18px)
14px
calc(var(--gift-cta-height) + var(--gift-cta-bottom) + 22px);
background: linear-gradient(180deg, rgba(11, 48, 8, 0.08), rgba(11, 48, 8, 0.2));
}
@ -835,12 +841,20 @@
}
.cta-button {
width: 100%;
position: fixed;
left: 50%;
bottom: var(--gift-cta-bottom);
z-index: 30;
width: min(
calc(100vw - var(--gift-cta-side) - var(--gift-cta-side)),
calc(var(--page-width) - var(--gift-cta-side) - var(--gift-cta-side))
);
height: auto;
margin-top: 18px;
margin: 0;
padding: 0;
border: 0;
background: transparent;
transform: translateX(-50%);
}
.toast {

View File

@ -15,6 +15,9 @@
--panel-top: url("./assets/panel-top.png");
--panel-middle: url("./assets/panel-middle.png");
--panel-bottom: url("./assets/panel-bottom.png");
--fixed-cta-side: 14px;
--fixed-cta-height: min(64px, 15.238vw);
--fixed-cta-bottom: calc(env(safe-area-inset-bottom) + 10px);
}
* {
@ -76,7 +79,10 @@
position: relative;
z-index: 1;
min-height: max(100vh, min(990px, 235.714vw));
padding: calc(env(safe-area-inset-top) + 45px) 14px calc(env(safe-area-inset-bottom) + 16px);
padding:
calc(env(safe-area-inset-top) + 45px)
14px
calc(var(--fixed-cta-height) + var(--fixed-cta-bottom) + 18px);
background:
linear-gradient(180deg, rgba(1, 12, 8, 0.02) 0%, rgba(1, 16, 9, 0.12) 38%, rgba(1, 18, 9, 0.34) 100%);
}
@ -265,18 +271,21 @@
.download-button {
position: fixed;
/* top: min(865px, 205.952vw); */
left: 14px;
right: 14px;
left: 50%;
right: auto;
z-index: 4;
display: flex;
align-items: center;
justify-content: center;
height: min(64px, 15.238vw);
width: auto;
width: min(
calc(100vw - var(--fixed-cta-side) - var(--fixed-cta-side)),
calc(var(--page-width) - var(--fixed-cta-side) - var(--fixed-cta-side))
);
height: var(--fixed-cta-height);
margin: 0;
background: center / 100% 100% no-repeat url("./assets/btn-bg.png");
bottom: 40px;
bottom: var(--fixed-cta-bottom);
transform: translateX(-50%);
}
.download-button span {

View File

@ -17,9 +17,11 @@
"refreshing": "جار التحديث...",
"no_bd_leaders": "لا يوجد قادة BD بعد",
"add_bd_leader": "إضافة قائد BD",
"add_bd_leader_disabled": "إضافة قائد BD معطلة",
"adding_bd_leader": "جار الإضافة...",
"add_bd_leader_success": "تمت إضافة قائد BD",
"gift_props": "إرسال العناصر",
"gift_props_disabled": "إرسال العناصر معطل",
"gift_type": "نوع الهدية",
"prop_type_ride": "مركبة",
"prop_type_noble_vip": "VIP نبيل",
@ -32,11 +34,13 @@
"sending": "جار الإرسال...",
"send_success": "تم الإرسال بنجاح",
"ban_user": "حظر المستخدم",
"ban_user_disabled": "حظر المستخدم معطل",
"ban_reason": "سبب الحظر",
"ban": "حظر",
"submitting": "جار الإرسال...",
"ban_success": "تم حظر المستخدم",
"unban_user": "إلغاء حظر المستخدم",
"unban_user_disabled": "إلغاء حظر المستخدم معطل",
"unban_reason": "سبب إلغاء الحظر",
"unban": "إلغاء الحظر",
"unban_success": "تم إلغاء حظر المستخدم",
@ -63,6 +67,7 @@
"user_already_bound_bd_leader": "هذا المستخدم مرتبط بالفعل بقائد BD",
"prop_not_giftable": "هذا العنصر غير متاح كهديّة من المدير",
"vip_not_giftable": "لا يمكن إهداء عنصر VIP هذا",
"manager_feature_disabled": "تم تعطيل هذه الميزة من الإدارة",
"request_failed": "فشل الطلب",
"enter_user": "أدخل معرّف المستخدم أو الحساب"
}

View File

@ -17,9 +17,11 @@
"refreshing": "Refreshing...",
"no_bd_leaders": "No BD Leaders yet",
"add_bd_leader": "Add BD Leader",
"add_bd_leader_disabled": "Add BD Leader disabled",
"adding_bd_leader": "Adding...",
"add_bd_leader_success": "BD Leader added",
"gift_props": "Gift Props",
"gift_props_disabled": "Gift Props disabled",
"gift_type": "Gift Type",
"prop_type_ride": "Ride",
"prop_type_noble_vip": "Noble VIP",
@ -32,11 +34,13 @@
"sending": "Sending...",
"send_success": "Sent successfully",
"ban_user": "Ban User",
"ban_user_disabled": "Ban User disabled",
"ban_reason": "Ban reason",
"ban": "Ban",
"submitting": "Submitting...",
"ban_success": "User banned",
"unban_user": "Unban User",
"unban_user_disabled": "Unban User disabled",
"unban_reason": "Unban reason",
"unban": "Unban",
"unban_success": "User unbanned",
@ -63,6 +67,7 @@
"user_already_bound_bd_leader": "This user is already bound to a BD Leader",
"prop_not_giftable": "This prop is not available for manager gifting",
"vip_not_giftable": "This noble prop cannot be gifted",
"manager_feature_disabled": "This feature is disabled by admin",
"request_failed": "Request failed",
"enter_user": "Enter user ID or account"
}

View File

@ -17,9 +17,11 @@
"refreshing": "Menyegarkan...",
"no_bd_leaders": "Belum ada BD Leader",
"add_bd_leader": "Tambah BD Leader",
"add_bd_leader_disabled": "Tambah BD Leader dinonaktifkan",
"adding_bd_leader": "Menambahkan...",
"add_bd_leader_success": "BD Leader ditambahkan",
"gift_props": "Kirim Properti",
"gift_props_disabled": "Kirim properti dinonaktifkan",
"gift_type": "Jenis Hadiah",
"prop_type_ride": "Kendaraan",
"prop_type_noble_vip": "Noble VIP",
@ -32,11 +34,13 @@
"sending": "Mengirim...",
"send_success": "Berhasil dikirim",
"ban_user": "Blokir Pengguna",
"ban_user_disabled": "Blokir pengguna dinonaktifkan",
"ban_reason": "Alasan blokir",
"ban": "Blokir",
"submitting": "Mengirim...",
"ban_success": "Pengguna diblokir",
"unban_user": "Buka Blokir Pengguna",
"unban_user_disabled": "Buka blokir pengguna dinonaktifkan",
"unban_reason": "Alasan buka blokir",
"unban": "Buka blokir",
"unban_success": "Blokir pengguna dibuka",
@ -63,6 +67,7 @@
"user_already_bound_bd_leader": "Pengguna ini sudah terhubung ke BD Leader",
"prop_not_giftable": "Properti ini tidak tersedia untuk hadiah manajer",
"vip_not_giftable": "Properti noble ini tidak dapat dikirim",
"manager_feature_disabled": "Fitur ini dinonaktifkan oleh admin",
"request_failed": "Permintaan gagal",
"enter_user": "Masukkan ID pengguna atau akun"
}

View File

@ -17,9 +17,11 @@
"refreshing": "Yenileniyor...",
"no_bd_leaders": "Henüz BD lideri yok",
"add_bd_leader": "BD Lideri Ekle",
"add_bd_leader_disabled": "BD lideri ekleme kapalı",
"adding_bd_leader": "Ekleniyor...",
"add_bd_leader_success": "BD lideri eklendi",
"gift_props": "Eşya Gönder",
"gift_props_disabled": "Eşya gönderme kapalı",
"gift_type": "Hediye Türü",
"prop_type_ride": "Araç",
"prop_type_noble_vip": "Noble VIP",
@ -32,11 +34,13 @@
"sending": "Gönderiliyor...",
"send_success": "Başarıyla gönderildi",
"ban_user": "Kullanıcıyı Yasakla",
"ban_user_disabled": "Kullanıcı yasaklama kapalı",
"ban_reason": "Yasaklama nedeni",
"ban": "Yasakla",
"submitting": "Gönderiliyor...",
"ban_success": "Kullanıcı yasaklandı",
"unban_user": "Yasağı Kaldır",
"unban_user_disabled": "Yasak kaldırma kapalı",
"unban_reason": "Yasağı kaldırma nedeni",
"unban": "Yasağı kaldır",
"unban_success": "Kullanıcının yasağı kaldırıldı",
@ -63,6 +67,7 @@
"user_already_bound_bd_leader": "Bu kullanıcı zaten bir BD liderine bağlı",
"prop_not_giftable": "Bu eşya yönetici hediyesi için açık değil",
"vip_not_giftable": "Bu noble eşyası gönderilemez",
"manager_feature_disabled": "Bu özellik admin tarafından kapatıldı",
"request_failed": "İstek başarısız",
"enter_user": "Kullanıcı ID veya hesap gir"
}

View File

@ -31,9 +31,11 @@
refreshing: "Refreshing...",
no_bd_leaders: "No BD Leaders yet",
add_bd_leader: "Add BD Leader",
add_bd_leader_disabled: "Add BD Leader disabled",
adding_bd_leader: "Adding...",
add_bd_leader_success: "BD Leader added",
gift_props: "Gift Props",
gift_props_disabled: "Gift Props disabled",
gift_type: "Gift Type",
prop_type_ride: "Ride",
prop_type_noble_vip: "Noble VIP",
@ -46,11 +48,13 @@
sending: "Sending...",
send_success: "Sent successfully",
ban_user: "Ban User",
ban_user_disabled: "Ban User disabled",
ban_reason: "Ban reason",
ban: "Ban",
submitting: "Submitting...",
ban_success: "User banned",
unban_user: "Unban User",
unban_user_disabled: "Unban User disabled",
unban_reason: "Unban reason",
unban: "Unban",
unban_success: "User unbanned",
@ -77,6 +81,7 @@
user_already_bound_bd_leader: "This user is already bound to a BD Leader",
prop_not_giftable: "This prop is not available for manager gifting",
vip_not_giftable: "This noble prop cannot be gifted",
manager_feature_disabled: "This feature is disabled by admin",
request_failed: "Request failed",
enter_user: "Enter user ID or account"
},
@ -99,9 +104,11 @@
refreshing: "جار التحديث...",
no_bd_leaders: "لا يوجد قادة BD بعد",
add_bd_leader: "إضافة قائد BD",
add_bd_leader_disabled: "إضافة قائد BD معطلة",
adding_bd_leader: "جار الإضافة...",
add_bd_leader_success: "تمت إضافة قائد BD",
gift_props: "إرسال العناصر",
gift_props_disabled: "إرسال العناصر معطل",
gift_type: "نوع الهدية",
prop_type_ride: "مركبة",
prop_type_noble_vip: "VIP نبيل",
@ -114,11 +121,13 @@
sending: "جار الإرسال...",
send_success: "تم الإرسال بنجاح",
ban_user: "حظر المستخدم",
ban_user_disabled: "حظر المستخدم معطل",
ban_reason: "سبب الحظر",
ban: "حظر",
submitting: "جار الإرسال...",
ban_success: "تم حظر المستخدم",
unban_user: "إلغاء حظر المستخدم",
unban_user_disabled: "إلغاء حظر المستخدم معطل",
unban_reason: "سبب إلغاء الحظر",
unban: "إلغاء الحظر",
unban_success: "تم إلغاء حظر المستخدم",
@ -145,6 +154,7 @@
user_already_bound_bd_leader: "هذا المستخدم مرتبط بالفعل بقائد BD",
prop_not_giftable: "هذا العنصر غير متاح كهديّة من المدير",
vip_not_giftable: "لا يمكن إهداء عنصر VIP هذا",
manager_feature_disabled: "تم تعطيل هذه الميزة من الإدارة",
request_failed: "فشل الطلب",
enter_user: "أدخل معرّف المستخدم أو الحساب"
},
@ -167,9 +177,11 @@
refreshing: "Yenileniyor...",
no_bd_leaders: "Henüz BD lideri yok",
add_bd_leader: "BD Lideri Ekle",
add_bd_leader_disabled: "BD lideri ekleme kapalı",
adding_bd_leader: "Ekleniyor...",
add_bd_leader_success: "BD lideri eklendi",
gift_props: "Eşya Gönder",
gift_props_disabled: "Eşya gönderme kapalı",
gift_type: "Hediye Türü",
prop_type_ride: "Araç",
prop_type_noble_vip: "Noble VIP",
@ -182,11 +194,13 @@
sending: "Gönderiliyor...",
send_success: "Başarıyla gönderildi",
ban_user: "Kullanıcıyı Yasakla",
ban_user_disabled: "Kullanıcı yasaklama kapalı",
ban_reason: "Yasaklama nedeni",
ban: "Yasakla",
submitting: "Gönderiliyor...",
ban_success: "Kullanıcı yasaklandı",
unban_user: "Yasağı Kaldır",
unban_user_disabled: "Yasak kaldırma kapalı",
unban_reason: "Yasağı kaldırma nedeni",
unban: "Yasağı kaldır",
unban_success: "Kullanıcının yasağı kaldırıldı",
@ -213,6 +227,7 @@
user_already_bound_bd_leader: "Bu kullanıcı zaten bir BD liderine bağlı",
prop_not_giftable: "Bu eşya yönetici hediyesi için açık değil",
vip_not_giftable: "Bu noble eşyası gönderilemez",
manager_feature_disabled: "Bu özellik admin tarafından kapatıldı",
request_failed: "İstek başarısız",
enter_user: "Kullanıcı ID veya hesap gir"
},
@ -235,9 +250,11 @@
refreshing: "Menyegarkan...",
no_bd_leaders: "Belum ada BD Leader",
add_bd_leader: "Tambah BD Leader",
add_bd_leader_disabled: "Tambah BD Leader dinonaktifkan",
adding_bd_leader: "Menambahkan...",
add_bd_leader_success: "BD Leader ditambahkan",
gift_props: "Kirim Properti",
gift_props_disabled: "Kirim properti dinonaktifkan",
gift_type: "Jenis Hadiah",
prop_type_ride: "Kendaraan",
prop_type_noble_vip: "Noble VIP",
@ -250,11 +267,13 @@
sending: "Mengirim...",
send_success: "Berhasil dikirim",
ban_user: "Blokir Pengguna",
ban_user_disabled: "Blokir pengguna dinonaktifkan",
ban_reason: "Alasan blokir",
ban: "Blokir",
submitting: "Mengirim...",
ban_success: "Pengguna diblokir",
unban_user: "Buka Blokir Pengguna",
unban_user_disabled: "Buka blokir pengguna dinonaktifkan",
unban_reason: "Alasan buka blokir",
unban: "Buka blokir",
unban_success: "Blokir pengguna dibuka",
@ -281,6 +300,7 @@
user_already_bound_bd_leader: "Pengguna ini sudah terhubung ke BD Leader",
prop_not_giftable: "Properti ini tidak tersedia untuk hadiah manajer",
vip_not_giftable: "Properti noble ini tidak dapat dikirim",
manager_feature_disabled: "Fitur ini dinonaktifkan oleh admin",
request_failed: "Permintaan gagal",
enter_user: "Masukkan ID pengguna atau akun"
}
@ -289,6 +309,7 @@
const state = {
manager: null,
target: null,
features: defaultFeatures(),
propsType: defaultPropsType,
props: [],
selectedPropsId: "",
@ -461,6 +482,7 @@
renderTarget();
renderProps();
renderBDLeaders();
updateActionState();
}
function $(selector) {
@ -623,6 +645,10 @@
}
function openGiftModal() {
if (!featureEnabled("giftProps")) {
showToast(message("gift_props_disabled"));
return;
}
if (!state.target) {
showToast(message("enter_user"));
return;
@ -632,6 +658,10 @@
}
function openBanModal() {
if (!featureEnabled("banUser")) {
showToast(message("ban_user_disabled"));
return;
}
if (!state.target) {
showToast(message("enter_user"));
return;
@ -642,6 +672,10 @@
}
function openUnbanModal() {
if (!featureEnabled("unbanUser")) {
showToast(message("unban_user_disabled"));
return;
}
if (!state.target) {
showToast(message("enter_user"));
return;
@ -710,6 +744,28 @@
return Boolean(target) && target.canBan !== false && !target.hasRecharge && !canUnbanTarget(target);
}
function defaultFeatures() {
return {
addBdLeader: true,
giftProps: true,
banUser: true,
unbanUser: true
};
}
function normalizeFeatures(features) {
return {
addBdLeader: features?.addBdLeader !== false,
giftProps: features?.giftProps !== false,
banUser: features?.banUser !== false,
unbanUser: features?.unbanUser !== false
};
}
function featureEnabled(key) {
return state.features?.[key] !== false;
}
function canUnbanTarget(target) {
const status = String(target?.accountStatus || "").trim().toUpperCase();
return Boolean(target) && (status === "FREEZE" || status === "ARCHIVE" || status === "ARCHIVE_DEVICE");
@ -930,29 +986,59 @@
const banButton = $("#banButton");
const unbanButton = $("#unbanButton");
if (addBDLeaderButton) {
addBDLeaderButton.disabled = !state.target || state.addingBDLeader || isTargetBDLeader();
const disabledByFeature = !featureEnabled("addBdLeader");
addBDLeaderButton.disabled = disabledByFeature || !state.target || state.addingBDLeader || isTargetBDLeader();
addBDLeaderButton.classList.toggle("is-feature-disabled", disabledByFeature);
const title = addBDLeaderButton.querySelector(".action-item-title");
if (title) title.textContent = state.addingBDLeader ? message("adding_bd_leader") : message("add_bd_leader");
if (title) {
title.textContent = disabledByFeature
? message("add_bd_leader_disabled")
: state.addingBDLeader ? message("adding_bd_leader") : message("add_bd_leader");
}
}
if (giftEntryButton) {
const disabledByFeature = !featureEnabled("giftProps");
giftEntryButton.disabled = disabledByFeature || !state.target;
giftEntryButton.classList.toggle("is-feature-disabled", disabledByFeature);
const title = giftEntryButton.querySelector(".action-item-title");
if (title) title.textContent = disabledByFeature ? message("gift_props_disabled") : message("gift_props");
}
if (banEntryButton) {
const disabledByFeature = !featureEnabled("banUser");
banEntryButton.disabled = disabledByFeature || !state.target;
banEntryButton.classList.toggle("is-feature-disabled", disabledByFeature);
const title = banEntryButton.querySelector(".action-item-title");
if (title) title.textContent = disabledByFeature ? message("ban_user_disabled") : message("ban_user");
}
if (unbanEntryButton) {
const disabledByFeature = !featureEnabled("unbanUser");
unbanEntryButton.disabled = disabledByFeature || !state.target;
unbanEntryButton.classList.toggle("is-feature-disabled", disabledByFeature);
const title = unbanEntryButton.querySelector(".action-item-title");
if (title) title.textContent = disabledByFeature ? message("unban_user_disabled") : message("unban_user");
}
if (giftEntryButton) giftEntryButton.disabled = !state.target;
if (banEntryButton) banEntryButton.disabled = !state.target;
if (unbanEntryButton) unbanEntryButton.disabled = !state.target;
if (refreshBDLeaderButton) refreshBDLeaderButton.disabled = state.bdLeadersLoading;
if (sendButton) sendButton.disabled = !state.target || !state.selectedPropsId;
if (banButton) banButton.disabled = !canBanTarget(state.target);
if (unbanButton) unbanButton.disabled = !canUnbanTarget(state.target);
if (sendButton) sendButton.disabled = !featureEnabled("giftProps") || !state.target || !state.selectedPropsId;
if (banButton) banButton.disabled = !featureEnabled("banUser") || !canBanTarget(state.target);
if (unbanButton) unbanButton.disabled = !featureEnabled("unbanUser") || !canUnbanTarget(state.target);
}
async function loadProfile() {
const body = await requestGoJSON(endpointProfile());
state.manager = body?.manager || body || {};
state.features = normalizeFeatures(body?.features);
renderManager(state.manager);
updateActionState();
}
async function loadProps() {
state.props = [];
state.selectedPropsId = "";
renderProps();
if (!featureEnabled("giftProps")) {
setStatus($("#propsStatus"), message("gift_props_disabled"));
return;
}
setStatus($("#propsStatus"), message("loading"));
const body = await requestGoJSON(endpointProps(state.propsType));
@ -1004,6 +1090,10 @@
}
async function addBDLeader() {
if (!featureEnabled("addBdLeader")) {
showToast(message("add_bd_leader_disabled"));
return;
}
if (!state.target || state.addingBDLeader) return;
if (isTargetBDLeader()) {
showToast(message("user_already_bd_leader"));
@ -1030,6 +1120,10 @@
}
async function sendProps() {
if (!featureEnabled("giftProps")) {
showToast(message("gift_props_disabled"));
return;
}
if (!state.target || !state.selectedPropsId) return;
const button = $("#sendPropsButton");
@ -1052,6 +1146,10 @@
}
async function banUser() {
if (!featureEnabled("banUser")) {
setStatus($("#banStatus"), message("ban_user_disabled"), "error");
return;
}
if (!canBanTarget(state.target)) return;
const button = $("#banButton");
@ -1078,6 +1176,10 @@
}
async function unbanUser() {
if (!featureEnabled("unbanUser")) {
setStatus($("#unbanStatus"), message("unban_user_disabled"), "error");
return;
}
if (!canUnbanTarget(state.target)) return;
const button = $("#unbanButton");
@ -1118,6 +1220,7 @@
if (code === "user_already_bound_bd_leader") return message("user_already_bound_bd_leader");
if (code === "prop_not_giftable") return message("prop_not_giftable");
if (code === "vip_not_giftable") return message("vip_not_giftable");
if (code === "manager_feature_disabled") return message("manager_feature_disabled");
return error?.message || message("request_failed");
}
@ -1189,7 +1292,8 @@
}
try {
await Promise.all([loadProfile(), loadProps(), loadBDLeaders()]);
await loadProfile();
await Promise.all([loadProps(), loadBDLeaders()]);
} catch (error) {
showToast(friendlyError(error));
} finally {

View File

@ -300,6 +300,15 @@ button:disabled {
background: #f4f7f8;
}
.action-item:disabled {
color: #9aa4af;
cursor: not-allowed;
}
.action-item.is-feature-disabled {
background: #f7f8fa;
}
.action-item-icon {
display: inline-flex;
align-items: center;