Compare commits

...
9 Commits
Author SHA1 Message Date
fengshao1227 cc3ea27b1d feat(gameRecords): 会员游戏记录增加洗码量显示 2026-05-29 11:58:31 +08:00
黎小北 b36f75599e 手机端项目整体UI调整修改 2026-05-14 16:45:12 +08:00
testadmin 31996b716f fix: 退出登录清空浏览器历史栈,防止返回键回到游戏页面 2026-05-13 13:49:47 +08:00
testadmin e8f0e2efbe feat: AlinPay 充值改为 iframe 内嵌弹窗,不再跳转外链 2026-04-26 20:37:50 +08:00
testadmin fcda0e1f0d feat: 充值页新增 CCpay 银行QR 第三通道
- recharge.vue: 新增 Ngân hàng QR tab + 银行QR弹窗 + 轮询到账
- api.js: 新增 ccpayDeposit / ccpayOrderStatus 接口
2026-04-20 11:15:47 +08:00
testadmin a81b39aef0 feat(recharge): USDT 提示语明确输入货币为 VND + 新汇率 27100 2026-04-16 23:33:46 +08:00
testadmin 301af6d91c feat(recharge): USDT 通道改为内嵌二维码弹窗,替代跳转 pay.g7g7.top
- 复用 qr-image 库生成 TRC20 地址二维码(YBF 分支已在用,无需新依赖)
- u-popup 内嵌展示:地址/精确金额/QR/倒计时,可一键复制
- 每 3s 轮询 /epay_order_status,成功后刷新用户信息并自动关闭
- 新增 api.epayOrderStatus
- 后端未返回 qrcode 时回退跳转式(向后兼容)
2026-04-16 23:31:52 +08:00
li 99e4265e01 fix(portal): 越南双 tab 按 area_id=3 判断,与 PC 统一
之前只认 pay_channel=='ALIN_VN'(只有 2 个账号),
现在所有 area_id=3 的越南用户都能看到 银行卡/USDT 双 tab。
BC/YBF 分支加 area_id != 3 条件避免重复。
2026-04-15 23:52:37 +08:00
li 91fa85f4ef feat: 越南充值页加 USDT (TRC20) 通道切换
- recharge.vue: 银行卡 / USDT 两个 tab,共用 amount 输入
- api.js: 新增 epayDeposit 调 /epay_online_order

USDT 请求体多传 pay_type='usdt',下单响应同 AlinPay 走 Data.url 跳转
2026-04-15 23:19:16 +08:00
33 changed files with 2786 additions and 746 deletions
+100 -9
View File
@@ -5,6 +5,7 @@
['Recharge', 'Withdraw', 'Index', 'User', 'Transfer'].includes(routeName) ['Recharge', 'Withdraw', 'Index', 'User', 'Transfer'].includes(routeName)
" "
> >
<view class="tab-bar__shell">
<view <view
class="item" class="item"
:class="{ active: routeName == item.name }" :class="{ active: routeName == item.name }"
@@ -12,14 +13,20 @@
:key="index" :key="index"
@click="goTab(item)" @click="goTab(item)"
> >
<view class="item-inner">
<view class="item-indicator"></view>
<view class="icon-box">
<image <image
class="icon" class="icon"
:src="routeName == item.name ? item.selectedIconPath : item.iconPath" :src="routeName == item.name ? item.selectedIconPath : item.iconPath"
alt="" alt=""
></image> ></image>
</view>
<view class="text">{{ item.text }}</view> <view class="text">{{ item.text }}</view>
</view> </view>
</view> </view>
</view>
</view>
</template> </template>
<script> <script>
@@ -122,27 +129,111 @@ export default {
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
z-index: 99;
padding: 0 8px 4px;
background: linear-gradient(
180deg,
rgba(0, 0, 0, 0) 0%,
rgba(0, 0, 0, 0.12) 26%,
rgba(0, 0, 0, 0.32) 100%
);
.tab-bar__shell {
display: flex; display: flex;
background: #000;
justify-content: space-between; justify-content: space-between;
height: 50px; align-items: stretch;
min-height: 56px;
padding: 4px 5px calc(4px + env(safe-area-inset-bottom));
background: linear-gradient(
180deg,
rgba(9, 8, 7, 0.98) 0%,
rgba(2, 2, 2, 0.99) 100%
);
border: 1px solid rgba(226, 193, 117, 0.22);
border-bottom: none;
border-radius: 16px 16px 0 0;
box-shadow: 0 -8px 22px rgba(0, 0, 0, 0.18),
inset 0 1px 0 rgba(255, 243, 212, 0.04);
}
.item { .item {
flex: 1; flex: 1;
min-width: 0;
color: rgba(255, 255, 255, 0.84);
.item-inner {
position: relative;
display: flex; display: flex;
align-items: center; align-items: center;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
color: #fff; min-height: 46px;
&.active { margin: 0 1px;
color: #deb366; padding: 5px 5px 2px;
border-radius: 14px;
transition: all 0.2s ease;
} }
.item-indicator {
position: absolute;
top: -1px;
left: 50%;
width: 20px;
height: 2px;
border-radius: 999px;
background: transparent;
transform: translateX(-50%);
}
.icon-box {
width: 28px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
transition: all 0.2s ease;
}
.icon { .icon {
width: 25px; width: 22px;
height: 25px; height: 22px;
} }
.text { .text {
font-size: 12px; margin-top: 2px;
padding-top: 2px; font-size: 11px;
line-height: 1.2;
letter-spacing: 0.2px;
white-space: nowrap;
transition: all 0.2s ease;
}
&.active {
color: #e8c26f;
.item-inner {
background: linear-gradient(
180deg,
rgba(63, 46, 20, 0.24) 0%,
rgba(30, 22, 13, 0.08) 100%
);
box-shadow: inset 0 1px 0 rgba(255, 236, 192, 0.08);
}
.item-indicator {
background: linear-gradient(90deg, #f4ddb0 0%, #d9ae55 100%);
}
.icon-box {
background: rgba(225, 191, 116, 0.08);
box-shadow: inset 0 1px 0 rgba(255, 244, 219, 0.06);
}
.text {
font-weight: 600;
text-shadow: 0 0 10px rgba(217, 174, 85, 0.1);
}
} }
} }
} }
+7
View File
@@ -72,6 +72,12 @@ var cn = {
commission: "手续费", commission: "手续费",
amountCannotBe0: "金额不能为0", amountCannotBe0: "金额不能为0",
submittingApplication: "提交申请中...", submittingApplication: "提交申请中...",
bankName: "银行名称",
accountName: "账户姓名",
accountNumber: "银行卡号",
enterAccountName: "请输入账户姓名",
enterAccountNumber: "请输入银行卡号",
insufficientBalance: "余额不足",
transfer: "划转", transfer: "划转",
accountBalance: "账户余额", accountBalance: "账户余额",
@@ -151,6 +157,7 @@ var cn = {
tableNumber: "桌台号", tableNumber: "桌台号",
playingMethod: "玩法", playingMethod: "玩法",
maliang: "码粮", maliang: "码粮",
ximaliang: "洗码量",
result: "结果", result: "结果",
totalBetting: "总投注", totalBetting: "总投注",
totalWin: "总输赢", totalWin: "总输赢",
+7
View File
@@ -72,6 +72,12 @@ var en = {
commission: "Commission", commission: "Commission",
amountCannotBe0: "Amount cannot be 0", amountCannotBe0: "Amount cannot be 0",
submittingApplication: "Submitting Application...", submittingApplication: "Submitting Application...",
bankName: "Bank Name",
accountName: "Account Name",
accountNumber: "Bank Account Number",
enterAccountName: "Please enter account name",
enterAccountNumber: "Please enter bank account number",
insufficientBalance: "Insufficient balance",
transfer: "Transfer", transfer: "Transfer",
accountBalance: "Account Balance", accountBalance: "Account Balance",
@@ -155,6 +161,7 @@ var en = {
tableNumber: "Table Number", tableNumber: "Table Number",
playingMethod: "Playing Method", playingMethod: "Playing Method",
maliang: "Rebate", maliang: "Rebate",
ximaliang: "Turnover",
result: "Result", result: "Result",
totalBetting: "Total Betting", totalBetting: "Total Betting",
totalWin: "Total Win or Lose", totalWin: "Total Win or Lose",
+7
View File
@@ -72,6 +72,12 @@ var In = {
commission: "Biaya Administrasi", commission: "Biaya Administrasi",
amountCannotBe0: "Jumlah tidak boleh 0", amountCannotBe0: "Jumlah tidak boleh 0",
submittingApplication: "Mengirimkan permintaan...", submittingApplication: "Mengirimkan permintaan...",
bankName: "Nama Bank",
accountName: "Nama Rekening",
accountNumber: "Nomor Rekening Bank",
enterAccountName: "Masukkan nama rekening",
enterAccountNumber: "Masukkan nomor rekening bank",
insufficientBalance: "Saldo tidak cukup",
transfer: "Transfer", transfer: "Transfer",
accountBalance: "Saldo", accountBalance: "Saldo",
@@ -151,6 +157,7 @@ var In = {
tableNumber: "Nomor Meja", tableNumber: "Nomor Meja",
playingMethod: "Gameplay", playingMethod: "Gameplay",
maliang: "Rabat Komisi", maliang: "Rabat Komisi",
ximaliang: "Turnover",
result: "Hasil", result: "Hasil",
totalBetting: "Total Taruhan", totalBetting: "Total Taruhan",
totalWin: "Total Menang/Kalah", totalWin: "Total Menang/Kalah",
+7
View File
@@ -72,6 +72,12 @@ var kr = {
commission: "수수료", commission: "수수료",
amountCannotBe0: "금액은 0일 수 없습니다.", amountCannotBe0: "금액은 0일 수 없습니다.",
submittingApplication: "신청 제출 중...", submittingApplication: "신청 제출 중...",
bankName: "은행명",
accountName: "예금주명",
accountNumber: "은행 계좌번호",
enterAccountName: "예금주명을 입력해 주세요",
enterAccountNumber: "은행 계좌번호를 입력해 주세요",
insufficientBalance: "잔액이 부족합니다",
transfer: "전송", transfer: "전송",
accountBalance: "계정 잔액", accountBalance: "계정 잔액",
@@ -151,6 +157,7 @@ var kr = {
tableNumber: "테이블 번호", tableNumber: "테이블 번호",
playingMethod: "플레이 방법", playingMethod: "플레이 방법",
maliang: "커미션 반환", maliang: "커미션 반환",
ximaliang: "롤링",
result: "결과", result: "결과",
totalBetting: "총 베팅", totalBetting: "총 베팅",
totalWin: "총 승패", totalWin: "총 승패",
+7
View File
@@ -71,6 +71,12 @@ var tl = {
commission: "คอมมิชชัน", commission: "คอมมิชชัน",
amountCannotBe0: "ยอดไม่สามารถเป็น 0", amountCannotBe0: "ยอดไม่สามารถเป็น 0",
submittingApplication: "ยื่นถอนเงิน", submittingApplication: "ยื่นถอนเงิน",
bankName: "ชื่อธนาคาร",
accountName: "ชื่อบัญชี",
accountNumber: "เลขที่บัญชีธนาคาร",
enterAccountName: "กรุณากรอกชื่อบัญชี",
enterAccountNumber: "กรุณากรอกเลขที่บัญชีธนาคาร",
insufficientBalance: "ยอดเงินคงเหลือไม่เพียงพอ",
transfer: "โอน", transfer: "โอน",
accountBalance: "ยอดเงินในบัญชี", accountBalance: "ยอดเงินในบัญชี",
@@ -150,6 +156,7 @@ var tl = {
tableNumber: "หมายเลขโต๊ะ", tableNumber: "หมายเลขโต๊ะ",
playingMethod: "วิธีเล่น", playingMethod: "วิธีเล่น",
maliang: "รับเงินคืน", maliang: "รับเงินคืน",
ximaliang: "ยอดเทิร์นโอเวอร์",
result: "ผล", result: "ผล",
totalBetting: "ยอดเดิมพัน", totalBetting: "ยอดเดิมพัน",
totalWin: "ยอดชนะหรือแพ้", totalWin: "ยอดชนะหรือแพ้",
+7
View File
@@ -72,6 +72,12 @@ var tw = {
commission: "手續費", commission: "手續費",
amountCannotBe0: "金額不能為0", amountCannotBe0: "金額不能為0",
submittingApplication: "提交申請中...", submittingApplication: "提交申請中...",
bankName: "銀行名稱",
accountName: "賬戶姓名",
accountNumber: "銀行卡號",
enterAccountName: "請輸入賬戶姓名",
enterAccountNumber: "請輸入銀行卡號",
insufficientBalance: "餘額不足",
transfer: "劃轉", transfer: "劃轉",
accountBalance: "賬戶餘額", accountBalance: "賬戶餘額",
@@ -151,6 +157,7 @@ var tw = {
tableNumber: "桌台號", tableNumber: "桌台號",
playingMethod: "玩法", playingMethod: "玩法",
maliang: "碼糧", maliang: "碼糧",
ximaliang: "洗碼量",
result: "結果", result: "結果",
totalBetting: "總投注", totalBetting: "總投注",
totalWin: "總輸贏", totalWin: "總輸贏",
+7
View File
@@ -72,6 +72,12 @@ var yn = {
commission: "Phí thủ tục", commission: "Phí thủ tục",
amountCannotBe0: "Số tiền không thể bằng 0", amountCannotBe0: "Số tiền không thể bằng 0",
submittingApplication: "Đang gửi yêu cầu...", submittingApplication: "Đang gửi yêu cầu...",
bankName: "Tên ngân hàng",
accountName: "Tên tài khoản",
accountNumber: "Số tài khoản ngân hàng",
enterAccountName: "Vui lòng nhập tên tài khoản",
enterAccountNumber: "Vui lòng nhập số tài khoản ngân hàng",
insufficientBalance: "Số dư không đủ",
transfer: "Chuyển khoản", transfer: "Chuyển khoản",
accountBalance: "Số dư tài khoản", accountBalance: "Số dư tài khoản",
@@ -155,6 +161,7 @@ var yn = {
tableNumber: "ID bàn", tableNumber: "ID bàn",
playingMethod: "Lối chơi", playingMethod: "Lối chơi",
maliang: "Phỉnh boa", maliang: "Phỉnh boa",
ximaliang: "Doanh số cược",
result: "Kết quả", result: "Kết quả",
totalBetting: "Tổng cược", totalBetting: "Tổng cược",
totalWin: "Tổng thắng thua", totalWin: "Tổng thắng thua",
+403 -127
View File
@@ -2,30 +2,59 @@
<view class="page-container"> <view class="page-container">
<!-- Top Header Area --> <!-- Top Header Area -->
<view class="top-header"> <view class="top-header">
<image class="header-bg" src="/static/images/login_bg.png" mode="aspectFill"></image> <image
class="header-bg"
src="/static/images/login_bg.png"
mode="aspectFill"
></image>
<view class="header-overlay"></view>
<view class="status-bar"></view> <view class="status-bar"></view>
<view class="header-content">
<!-- User Info Row --> <!-- User Info Row -->
<view class="user-bar"> <view class="user-bar">
<view class="left-info" @click="goPage('/pages/user/index')"> <view class="brand-side">
<u-icon name="arrow-left" color="#f4c46f" size="20" v-if="false"></u-icon> <view class="brand-logo-shell">
<view class="user-avatar"> <image
<u-icon name="account-fill" color="#fff" size="24"></u-icon> class="brand-logo"
src="/static/logo.png"
mode="aspectFit"
></image>
</view> </view>
</view>
<view class="header-right">
<view class="user-summary" @click="goPage('/pages/user/index')">
<text class="username">{{ userInfo.username || $lang.guest }}</text> <text class="username">{{ userInfo.username || $lang.guest }}</text>
<view class="balance-pill"> <view class="balance-pill">
<text class="currency-symbol"></text> <text class="currency-symbol"></text>
<text class="balance-text">{{ $fk(userInfo.money) || '0.00' }}</text> <text class="balance-text">{{
$fk(userInfo.money) || "0.00"
}}</text>
</view> </view>
</view> </view>
<view class="right-actions"> <view class="right-actions">
<u-icon name="server-fill" color="#fff" size="24" @click="goService" style="margin-right: 15px;"></u-icon> <view class="action-btn" @click="goService">
<u-icon name="grid-fill" color="#fff" size="24" @click="goPage('/pages/user/index')"></u-icon> <u-icon name="server-fill" color="#f6e7bf" size="20"></u-icon>
</view>
<view class="action-btn" @click="goPage('/pages/user/index')">
<u-icon name="grid-fill" color="#f6e7bf" size="20"></u-icon>
</view>
</view>
</view> </view>
</view> </view>
<!-- Banner Area --> <!-- Banner Area -->
<view class="banner-area"> <view class="banner-area">
<u-swiper :list="bannerList" height="140" radius="8" indicator indicatorMode="line" circular></u-swiper> <u-swiper
:list="bannerList"
height="150"
radius="14"
indicator
indicatorMode="line"
circular
></u-swiper>
</view>
</view> </view>
</view> </view>
@@ -40,13 +69,20 @@
:class="{ active: currentCategory === cat.id }" :class="{ active: currentCategory === cat.id }"
@click="switchCategory(cat.id)" @click="switchCategory(cat.id)"
> >
<view class="item-marker"></view>
<view class="icon-box"> <view class="icon-box">
<!-- Use local images or u-icons based on category --> <image :src="cat.icon" mode="widthFix" style="width: 22px; height: 22px;" v-if="cat.icon" />
<image :src="cat.icon" mode="widthFix" style="width: 24px; height: 24px;" v-if="cat.icon" /> <u-icon
<u-icon :name="cat.uIcon" color="#ccc" size="28" v-else></u-icon> :name="cat.uIcon"
:color="currentCategory === cat.id ? '#f1d392' : '#d1c6aa'"
size="24"
v-else
></u-icon>
</view> </view>
<view class="cat-texts">
<text class="cat-name">{{ $lang[cat.nameKey] }}</text> <text class="cat-name">{{ $lang[cat.nameKey] }}</text>
<text class="cat-count">({{ getCategoryCount(cat.id) }})</text> <text class="cat-count">{{ getCategoryCount(cat.id) }}</text>
</view>
</view> </view>
<!-- Online Count Bottom --> <!-- Online Count Bottom -->
@@ -76,12 +112,15 @@
</view> </view>
<view class="header-right"> <view class="header-right">
<text class="limit-info">{{ $lang.maxLimit }}:{{ $fk((item.game_id == 4 || item.game_id == 5) && userInfo.limit_high_nn > 0 ? userInfo.limit_high_nn : (userInfo.limit_high || 0)) }} {{ $lang.minLimit }}:{{ (item.game_id == 4 || item.game_id == 5) && userInfo.limit_low_nn > 0 ? userInfo.limit_low_nn : (userInfo.limit_low || 0) }}</text> <text class="limit-info">{{ $lang.maxLimit }}:{{ $fk((item.game_id == 4 || item.game_id == 5) && userInfo.limit_high_nn > 0 ? userInfo.limit_high_nn : (userInfo.limit_high || 0)) }} {{ $lang.minLimit }}:{{ (item.game_id == 4 || item.game_id == 5) && userInfo.limit_low_nn > 0 ? userInfo.limit_low_nn : (userInfo.limit_low || 0) }}</text>
<view class="status-live">
<view class="status-dot" :class="{ 'is-live': item.status===1 }"></view> <view class="status-dot" :class="{ 'is-live': item.status===1 }"></view>
</view> </view>
</view> </view>
</view>
<!-- Roadmap Visualization (Body) --> <!-- Roadmap Visualization (Body) -->
<view class="card-body"> <view class="card-body">
<view class="card-body-overlay"></view>
<!-- 百家乐/龙虎: 珠盘路圆圈 --> <!-- 百家乐/龙虎: 珠盘路圆圈 -->
<view class="roadmap-grid" v-if="item.game_id !== 4 && item.game_id !== 5"> <view class="roadmap-grid" v-if="item.game_id !== 4 && item.game_id !== 5">
<view <view
@@ -121,7 +160,6 @@
<!-- Center Overlay Status --> <!-- Center Overlay Status -->
<view class="center-overlay" v-if="true"> <view class="center-overlay" v-if="true">
<view class="status-badge-lg" :class="getStatusClass(item.bet_status)"> <view class="status-badge-lg" :class="getStatusClass(item.bet_status)">
<u-icon name="hourglass" size="20" color="#fff" v-if="item.bet_status == 1"></u-icon> <u-icon name="hourglass" size="20" color="#fff" v-if="item.bet_status == 1"></u-icon>
<u-icon name="lock" size="20" color="#fff" v-else-if="item.bet_status == 2"></u-icon> <u-icon name="lock" size="20" color="#fff" v-else-if="item.bet_status == 2"></u-icon>
@@ -330,8 +368,8 @@ export default {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100vh; height: 100vh;
background-color: #0c0c0d; background: linear-gradient(180deg, #060505 0%, #0d0b09 100%);
color: #fff; color: #fff6e1;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
} }
@@ -339,8 +377,7 @@ export default {
.top-header { .top-header {
flex-shrink: 0; flex-shrink: 0;
position: relative; position: relative;
/* background-image removed, using image tag instead */ padding-bottom: 14px;
padding-bottom: 5px;
overflow: hidden; overflow: hidden;
.header-bg { .header-bg {
@@ -350,6 +387,19 @@ export default {
width: 100%; width: 100%;
height: 100%; height: 100%;
z-index: 0; z-index: 0;
opacity: 0.42;
}
.header-overlay {
position: absolute;
inset: 0;
z-index: 0;
background: linear-gradient(
180deg,
rgba(5, 4, 4, 0.86) 0%,
rgba(11, 9, 8, 0.66) 54%,
rgba(13, 11, 9, 0.96) 100%
);
} }
.status-bar { .status-bar {
@@ -359,52 +409,135 @@ export default {
z-index: 1; z-index: 1;
} }
.user-bar { .header-content {
position: relative; position: relative;
z-index: 1; z-index: 1;
display: flex; padding: 8px 12px 0;
justify-content: space-between; }
align-items: center;
padding: 10px 15px;
.left-info { .user-bar {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px; gap: 14px;
padding: 6px 4px 14px;
.brand-side {
flex-shrink: 0;
}
.brand-logo-shell {
width: 58px;
height: 58px;
display: flex;
align-items: center;
justify-content: center;
}
.brand-logo {
width: 44px;
height: 44px;
display: block;
}
.header-right {
min-width: 0;
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.user-summary {
min-width: 0;
flex: 1;
display: flex;
flex-direction: column;
gap: 7px;
}
.username { .username {
font-size: 14px; max-width: 100%;
font-weight: bold; font-size: 16px;
color: #fff; font-weight: 700;
color: #fbf3e0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} }
.balance-pill { .balance-pill {
background: rgba(0,0,0,0.5); width: fit-content;
border: 1px solid #f4c46f; max-width: 100%;
border-radius: 12px; min-height: 30px;
padding: 2px 8px; padding: 0 12px;
display: flex; display: inline-flex;
align-items: center; align-items: center;
gap: 5px; gap: 6px;
border-radius: 999px;
background: rgba(10, 9, 8, 0.72);
border: 1px solid rgba(223, 189, 120, 0.24);
box-shadow: inset 0 1px 0 rgba(255, 243, 219, 0.04);
.currency-symbol { .currency-symbol {
color: #f4c46f; color: #f1cc84;
font-size: 14px; font-size: 13px;
font-weight: bold; font-weight: 700;
} }
.balance-text { .balance-text {
color: #f4c46f; color: #f6e1b2;
font-size: 12px; font-size: 12px;
font-weight: bold; font-weight: 700;
} }
} }
.right-actions {
display: flex;
align-items: center;
gap: 8px;
flex-shrink: 0;
.action-btn {
width: 42px;
height: 42px;
border-radius: 15px;
display: flex;
align-items: center;
justify-content: center;
background: rgba(12, 11, 10, 0.72);
border: 1px solid rgba(223, 189, 120, 0.16);
box-shadow: inset 0 1px 0 rgba(255, 244, 220, 0.04);
}
} }
} }
.banner-area { .banner-area {
position: relative; position: relative;
z-index: 1; z-index: 1;
padding: 5px 10px; padding: 0 2px;
::v-deep .u-swiper {
border-radius: 18px !important;
overflow: hidden;
border: 1px solid rgba(223, 189, 120, 0.14);
box-shadow: 0 16px 34px rgba(0, 0, 0, 0.24);
}
::v-deep .u-swiper__wrapper__item__wrapper {
border-radius: 18px !important;
}
::v-deep .u-swiper-indicator {
bottom: 10px !important;
}
::v-deep .u-swiper-indicator__wrapper__item {
background-color: rgba(255, 244, 220, 0.28) !important;
}
::v-deep .u-swiper-indicator__wrapper__item--active {
background-color: #dfbd78 !important;
}
} }
} }
@@ -413,126 +546,254 @@ export default {
flex: 1; flex: 1;
display: flex; display: flex;
overflow: hidden; overflow: hidden;
gap: 10px;
padding: 0 12px 12px;
/* Sidebar styles */ /* Sidebar styles */
.sidebar { .sidebar {
width: 80px; width: 86px;
background-color: #161618; background: linear-gradient(
border-right: 1px solid #1f1f1f; 180deg,
rgba(18, 15, 13, 0.98) 0%,
rgba(10, 9, 8, 0.98) 100%
);
border: 1px solid rgba(223, 189, 120, 0.14);
border-radius: 22px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden;
box-shadow: 0 14px 28px rgba(0, 0, 0, 0.18);
.sidebar-item { .sidebar-item {
padding: 15px 5px; position: relative;
margin: 6px;
padding: 14px 6px 12px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
border-bottom: 1px solid #222; border-radius: 18px;
transition: all 0.3s; transition: all 0.25s ease;
&.active { .item-marker {
background-color: #f4c46f; position: absolute;
left: 50%;
.cat-name, .cat-count { top: 0;
color: #000; width: 20px;
font-weight: bold; height: 3px;
border-radius: 999px;
transform: translateX(-50%);
background: transparent;
} }
// Could change icon color via filter if using svg &.active {
background: linear-gradient(
180deg,
rgba(59, 43, 19, 0.24) 0%,
rgba(27, 20, 12, 0.08) 100%
);
box-shadow: inset 0 1px 0 rgba(255, 239, 203, 0.06);
.item-marker {
background: linear-gradient(90deg, #f2ddb3 0%, #dbaf57 100%);
} }
.icon-box { .icon-box {
margin-bottom: 5px; background: rgba(223, 189, 120, 0.08);
border-color: rgba(223, 189, 120, 0.18);
}
.cat-name,
.cat-count {
color: #f1d392;
}
}
.icon-box {
width: 40px;
height: 40px;
margin-bottom: 8px;
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
background: rgba(14, 13, 12, 0.8);
border: 1px solid rgba(255, 255, 255, 0.03);
}
.cat-texts {
display: flex;
flex-direction: column;
align-items: center;
gap: 5px;
} }
.cat-name { .cat-name {
font-size: 11px; font-size: 11px;
color: #999; color: #cdc2a3;
margin-bottom: 2px;
text-align: center; text-align: center;
word-break: break-word; word-break: break-word;
line-height: 1.2; line-height: 1.25;
max-width: 70px; max-width: 70px;
} }
.cat-count { .cat-count {
font-size: 10px; min-width: 32px;
color: #666; height: 22px;
padding: 0 9px;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 11px;
font-weight: 700;
line-height: 1;
color: #e3c27a;
font-variant-numeric: tabular-nums;
letter-spacing: 0.2px;
background: linear-gradient(
180deg,
rgba(29, 24, 19, 0.96) 0%,
rgba(16, 13, 11, 0.96) 100%
);
border: 1px solid rgba(223, 189, 120, 0.12);
box-shadow: inset 0 1px 0 rgba(255, 245, 223, 0.04);
border-radius: 999px;
} }
} }
.online-count-box { .online-count-box {
margin-top: auto; margin: auto 6px 6px;
padding: 20px 5px; padding: 14px 6px calc(14px + env(safe-area-inset-bottom));
border-top: 1px solid rgba(223, 189, 120, 0.1);
text-align: center; text-align: center;
.label { font-size: 10px; color: #666; display: block; } .label {
.count { font-size: 14px; color: #f4c46f; font-weight: bold; } font-size: 10px;
color: #8d7a55;
display: block;
margin-bottom: 4px;
}
.count {
margin-top: 6px;
font-size: 15px;
color: #f1cc84;
font-weight: 700;
font-variant-numeric: tabular-nums;
letter-spacing: 0.3px;
}
} }
} }
/* Content styles */ /* Content styles */
.content-area { .content-area {
flex: 1; flex: 1;
background-color: #0c0c0d; background: rgba(8, 7, 6, 0.52);
padding: 10px; border: 1px solid rgba(223, 189, 120, 0.1);
border-radius: 22px;
padding: 12px;
box-shadow: inset 0 1px 0 rgba(255, 244, 220, 0.03);
.table-list {
min-height: 100%;
}
.loading-state {
min-height: 180px;
display: flex;
align-items: center;
justify-content: center;
}
.game-card { .game-card {
background-color: #1e1e1e; margin-bottom: 14px;
border-radius: 6px; background: linear-gradient(
margin-bottom: 12px; 180deg,
border: 1px solid #333; rgba(21, 18, 15, 0.98) 0%,
rgba(14, 12, 10, 0.98) 100%
);
border: 1px solid rgba(223, 189, 120, 0.14);
border-radius: 18px;
overflow: hidden; overflow: hidden;
box-shadow: 0 14px 28px rgba(0, 0, 0, 0.16);
.card-header { .card-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
background: #252627; padding: 10px 12px;
padding: 5px 10px; min-height: 44px;
border-bottom: 1px solid #333; background: linear-gradient(
height: 30px; 180deg,
rgba(30, 25, 20, 0.88) 0%,
rgba(19, 17, 14, 0.88) 100%
);
border-bottom: 1px solid rgba(223, 189, 120, 0.1);
.table-name { .table-name {
font-size: 13px; font-size: 14px;
color: #fff; color: #f9f1de;
font-weight: bold; font-weight: 700;
} }
.header-right { .header-right {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
}
.limit-info { .limit-info {
font-size: 10px; font-size: 10px;
color: #999; color: #bca987;
text-align: right;
line-height: 1.35;
}
.status-live {
width: 18px;
height: 18px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 999px;
background: rgba(255, 255, 255, 0.03);
} }
.status-dot { .status-dot {
width: 6px; width: 7px;
height: 6px; height: 7px;
border-radius: 50%; border-radius: 50%;
background-color: #666; background-color: #6f6658;
&.is-live { background-color: #0f0; }
&.is-live {
background-color: #53c57b;
box-shadow: 0 0 10px rgba(83, 197, 123, 0.28);
} }
} }
} }
.card-body { .card-body {
position: relative; position: relative;
height: 110px; // Fixed height for roadmap height: 114px;
background: #fff; // White background for roadmap grid background: linear-gradient(180deg, #fbf9f3 0%, #f0ece3 100%);
}
.card-body-overlay {
position: absolute;
inset: 0;
pointer-events: none;
background: linear-gradient(
180deg,
rgba(255, 255, 255, 0.02) 0%,
rgba(0, 0, 0, 0.02) 100%
);
}
.roadmap-grid { .roadmap-grid {
width: 100%; width: 100%;
height: 100%; height: 100%;
position: relative; position: relative;
// Grid background lines
background-size: 16.5px 17px; background-size: 16.5px 17px;
background-image: background-image: linear-gradient(to right, #dad3c7 1px, transparent 1px),
linear-gradient(to right, #ccc 1px, transparent 1px), linear-gradient(to bottom, #dad3c7 1px, transparent 1px);
linear-gradient(to bottom, #ccc 1px, transparent 1px);
.road-cell { .road-cell {
position: absolute; position: absolute;
@@ -542,27 +803,25 @@ export default {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
border: 1px solid rgba(0,0,0,0.1); border: 1px solid rgba(0, 0, 0, 0.08);
background-color: #fff;
&.cell-red { &.cell-red {
background-color: #fff; border: 2px solid #cf4444;
border: 2px solid #d0021b; color: #cf4444;
color: #d0021b;
} }
&.cell-blue { &.cell-blue {
background-color: #fff; border: 2px solid #467ed7;
border: 2px solid #4a90e2; color: #467ed7;
color: #4a90e2;
} }
&.cell-green { &.cell-green {
background-color: #fff; border: 2px solid #4ba96f;
border: 2px solid #7ed321; color: #4ba96f;
color: #7ed321;
} }
.cell-text { .cell-text {
font-size: 9px; font-size: 9px;
font-weight: bold; font-weight: 700;
} }
} }
} }
@@ -572,14 +831,16 @@ export default {
height: 100%; height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
background: #fff; background: linear-gradient(180deg, #fbf9f3 0%, #f0ece3 100%);
.nn-row { .nn-row {
display: flex; display: flex;
flex: 1; flex: 1;
border-bottom: 1px solid #e0e0e0; border-bottom: 1px solid #ddd4c8;
&:last-child { border-bottom: none; } &:last-child {
border-bottom: none;
}
} }
.nn-label { .nn-label {
@@ -588,12 +849,16 @@ export default {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
font-size: 10px; font-size: 10px;
font-weight: bold; font-weight: 700;
color: #fff; color: #fff;
flex-shrink: 0; flex-shrink: 0;
&.nn-label-banker { background: #c0392b; } &.nn-label-banker {
&.nn-label-player { background: #2c5fa1; } background: #a84237;
}
&.nn-label-player {
background: #3c6399;
}
} }
.nn-cells { .nn-cells {
@@ -611,21 +876,26 @@ export default {
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
border-right: 1px solid #e0e0e0; border-right: 1px solid #ddd4c8;
padding: 1px 0; padding: 1px 0;
} }
.nn-text { .nn-text {
font-size: 10px; font-size: 10px;
font-weight: bold; font-weight: 700;
&.nn-text-red { color: #c0392b; }
&.nn-text-blue { color: #2c5fa1; } &.nn-text-red {
color: #a84237;
}
&.nn-text-blue {
color: #3c6399;
}
} }
.nn-win-tag { .nn-win-tag {
font-size: 7px; font-size: 7px;
color: #fff; color: #fff;
background: #2c5fa1; background: #3c6399;
padding: 0 3px; padding: 0 3px;
border-radius: 2px; border-radius: 2px;
line-height: 1.4; line-height: 1.4;
@@ -633,7 +903,7 @@ export default {
} }
.nn-cell.nn-win-banker .nn-win-tag { .nn-cell.nn-win-banker .nn-win-tag {
background: #c0392b; background: #a84237;
} }
} }
@@ -648,32 +918,38 @@ export default {
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 10px 20px; min-width: 110px;
background: rgba(0,0,0,0.7); padding: 10px 18px;
border-radius: 8px; border-radius: 16px;
// Backdrop gradient
background: radial-gradient(circle, rgba(169,134,60,0.95) 0%, rgba(0,0,0,0.8) 100%);
color: #fff; color: #fff;
box-shadow: 0 4px 10px rgba(0,0,0,0.5); background: linear-gradient(
width: 100px; 180deg,
rgba(47, 39, 28, 0.92) 0%,
rgba(17, 14, 11, 0.92) 100%
);
border: 1px solid rgba(223, 189, 120, 0.18);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.18);
&.status-dealing { &.status-betting {
// background: radial-gradient(circle, rgba(200,50,50,0.9) 0%, rgba(0,0,0,0.8) 100%); background: linear-gradient(
180deg,
rgba(88, 67, 33, 0.92) 0%,
rgba(24, 18, 11, 0.94) 100%
);
} }
.status-text-lg { .status-text-lg {
font-size: 14px; font-size: 13px;
font-weight: bold; font-weight: 700;
margin-top: 5px; margin-top: 4px;
text-shadow: 1px 1px 2px #000;
} }
.countdown-text { .countdown-text {
font-size: 16px; font-size: 15px;
color: #fff; color: #fff5dc;
margin-top: 2px; margin-top: 2px;
font-family: monospace; font-family: monospace;
font-weight: bold; font-weight: 700;
}
} }
} }
} }
+143 -48
View File
@@ -1,11 +1,11 @@
<template> <template>
<view class="login"> <view class="login">
<div class="langview"> <view class="langview">
<div class="select" @click="showLangselect(true)"> <view class="select" @click="showLangselect(true)">
{{ langList[language] }} {{ langList[language] }}
</div> </view>
<div class="select-box" v-show="langselect"> <view class="select-box" v-show="langselect">
<div <view
class="option" class="option"
v-for="item in Object.keys(langList)" v-for="item in Object.keys(langList)"
:key="item" :key="item"
@@ -13,10 +13,11 @@
@click="choseLang(item)" @click="choseLang(item)"
> >
{{ langList[item] }} {{ langList[item] }}
</div> </view>
</div> </view>
</div> </view>
<view class="content"> <view class="content">
<view class="logo-shell">
<view class="logo"> <view class="logo">
<u--image <u--image
:showLoading="false" :showLoading="false"
@@ -26,12 +27,17 @@
mode="scaleToFill" mode="scaleToFill"
></u--image> ></u--image>
</view> </view>
</view>
<view class="panel">
<u-input <u-input
class="input" class="input"
v-model="phone" v-model="phone"
type="text" type="text"
clearable clearable
border="none"
color="#f7ecd2"
:placeholder="$lang.enterAccount" :placeholder="$lang.enterAccount"
placeholderStyle="color: rgba(245, 228, 184, 0.38); font-size: 14px;"
><!-- ><!--
<view class="phone-code" slot="prefix" @click="countryShow = true">{{ <view class="phone-code" slot="prefix" @click="countryShow = true">{{
countryData.country_code countryData.country_code
@@ -41,15 +47,23 @@
class="input" class="input"
v-model="password" v-model="password"
:password="true" :password="true"
border="none"
color="#f7ecd2"
:placeholder="$lang.enterPassword" :placeholder="$lang.enterPassword"
placeholderStyle="color: rgba(245, 228, 184, 0.38); font-size: 14px;"
> >
</u-input> </u-input>
<view class="btn-box"> <view class="btn-box">
<view class="btn" @tap="login('login')">{{ $lang.login }}</view> <view class="btn btn-primary" @tap="login('login')">{{
<view class="btn" @tap="login('dome')">{{ $lang.dome }}</view> $lang.login
}}</view>
<view class="btn btn-secondary" @tap="login('dome')">{{
$lang.dome
}}</view>
</view> </view>
<view class="tip" @tap="goRegister">{{ $lang.goRegister }}</view> <view class="tip" @tap="goRegister">{{ $lang.goRegister }}</view>
</view> </view>
</view>
<!-- 提示 --> <!-- 提示 -->
<u-toast ref="uToast" /> <u-toast ref="uToast" />
<!-- 区号 --> <!-- 区号 -->
@@ -202,65 +216,126 @@ export default {
overflow-y: auto; overflow-y: auto;
.langview { .langview {
position: absolute; position: absolute;
top: 15px; top: 16px;
right: 15px; right: 16px;
z-index: 20;
.select { .select {
border-radius: 4px; min-width: 96px;
width: 90px; padding: 0 14px;
display: inline-block; font-size: 13px;
font-size: 14px; color: #e8d39b;
color: #cfc189; line-height: 34px;
line-height: 35px; background: rgba(15, 12, 10, 0.74);
background: #212121; border: 1px solid rgba(213, 181, 103, 0.18);
border-radius: 10px;
text-align: center; text-align: center;
&:active { &:active {
opacity: 0.6; opacity: 0.82;
} }
} }
.select-box { .select-box {
position: absolute; position: absolute;
right: 0; right: 0;
top: 45px; top: 40px;
width: 90px; width: 108px;
line-height: 30px; padding: 4px 0;
background: #212121; line-height: 32px;
border-radius: 4px; background: rgba(15, 12, 10, 0.92);
border: 1px solid rgba(213, 181, 103, 0.18);
border-radius: 10px;
text-align: center; text-align: center;
color: #fff; color: rgba(255, 246, 226, 0.88);
font-size: 14px; font-size: 13px;
z-index: 9; z-index: 9;
.option {
padding: 0 8px;
}
.option:active { .option:active {
opacity: 0.6; opacity: 0.6;
} }
.active { .active {
color: #cfc189; color: #e8d39b;
font-weight: bold; font-weight: bold;
} }
} }
} }
.content { .content {
width: 280px; width: 86%;
padding-bottom: 50px; max-width: 326px;
margin: 0 auto; margin: 0 auto;
padding: 94px 0 48px;
.logo-shell {
margin-bottom: 20px;
}
.logo { .logo {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
margin-bottom: 20px; width: 125px;
margin-top: 20%; height: 119px;
margin: 0 auto;
}
.panel {
position: relative;
padding: 20px 18px 22px;
border-radius: 24px;
background: linear-gradient(
180deg,
rgba(14, 11, 9, 0.9) 0%,
rgba(10, 8, 7, 0.8) 100%
);
border: 1px solid rgba(213, 181, 103, 0.22);
box-shadow: 0 18px 40px rgba(0, 0, 0, 0.24),
inset 0 1px 0 rgba(255, 255, 255, 0.03);
overflow: hidden;
&::before {
content: "";
position: absolute;
top: 0;
left: 18px;
right: 18px;
height: 1px;
background: linear-gradient(
90deg,
rgba(213, 181, 103, 0),
rgba(244, 221, 169, 0.82),
rgba(213, 181, 103, 0)
);
}
} }
.input { .input {
height: 30px; height: 50px;
line-height: 30px; line-height: 50px;
margin-bottom: 15px; margin-bottom: 14px;
background: #fff; background: rgba(24, 20, 17, 0.96);
border-radius: 8px; border: 1px solid rgba(213, 181, 103, 0.14);
border-radius: 15px;
overflow: hidden; overflow: hidden;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03),
inset 0 -1px 0 rgba(0, 0, 0, 0.16);
&:last-of-type {
margin-bottom: 0;
}
::v-deep .u-input__content {
min-height: 100%;
padding: 0 15px;
}
::v-deep .u-input__content__field-wrapper {
width: 100%;
}
::v-deep input {
color: #f7ecd2 !important;
font-size: 15px !important;
letter-spacing: 0.2px;
}
::v-deep input::placeholder {
color: rgba(245, 228, 184, 0.42) !important;
}
} }
.phone-code { .phone-code {
min-width: 50px; min-width: 50px;
text-align: center; text-align: center;
border-right: 1px solid #ddd; border-right: 1px solid rgba(213, 181, 103, 0.18);
} }
.btn-box { .btn-box {
margin-top: 20px; margin-top: 20px;
@@ -269,15 +344,33 @@ export default {
height: 48px; height: 48px;
line-height: 48px; line-height: 48px;
text-align: center; text-align: center;
font-size: 16px; font-size: 14px;
background: url("~@/static/images/btn_bg.png") no-repeat; font-weight: 700;
background-size: 100% 100%; letter-spacing: 0.5px;
font-weight: 600; border-radius: 15px;
margin-top: 15px; margin-top: 12px;
&:active { &:active {
opacity: 0.8; opacity: 0.86;
} }
} }
.btn-primary {
margin-top: 0;
color: #241804;
background: linear-gradient(
180deg,
#f2dfb6 0%,
#dfbd78 52%,
#bd8d39 100%
);
box-shadow: 0 12px 24px rgba(125, 84, 22, 0.24),
inset 0 1px 0 rgba(255, 255, 255, 0.42);
}
.btn-secondary {
color: #ead6a0;
background: rgba(18, 15, 12, 0.92);
border: 1px solid rgba(213, 181, 103, 0.2);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03);
}
} }
} }
.country { .country {
@@ -287,12 +380,14 @@ export default {
} }
.tip { .tip {
font-size: 12px; font-size: 12px;
color: #b38f3c; color: rgba(234, 214, 160, 0.92);
margin-top: 20px; margin-top: 16px;
padding-top: 14px;
border-top: 1px solid rgba(213, 181, 103, 0.1);
text-align: center; text-align: center;
margin-bottom: 20px; letter-spacing: 0.2px;
&:active { &:active {
opacity: 0.6; opacity: 0.7;
} }
} }
} }
+780 -60
View File
@@ -2,7 +2,7 @@
<view class="recharge"> <view class="recharge">
<u-navbar <u-navbar
title="" title=""
bgColor="#000" bgColor="transparent"
:placeholder="true" :placeholder="true"
:fixed="true" :fixed="true"
leftIcon="" leftIcon=""
@@ -13,12 +13,12 @@
</view> </view>
</u-navbar> </u-navbar>
<view class="content"> <view class="content">
<template v-if="userInfo.pay_channel == 'BC'"> <template v-if="userInfo.pay_channel == 'BC' && userInfo.area_id != 3">
<view class="picker-view" @click="show = true"> <view class="picker-view" @click="show = true">
<u-input <u-input
readonly readonly
:placeholder="$lang.pleaseChoose" :placeholder="$lang.pleaseChoose"
color="#93979b" color="#f7ecd0"
v-model="type" v-model="type"
border="none" border="none"
> >
@@ -31,7 +31,7 @@
<u-icon <u-icon
slot="suffix" slot="suffix"
name="arrow-down-fill" name="arrow-down-fill"
color="#757272" color="#b9aa84"
size="16" size="16"
></u-icon> ></u-icon>
</u-input> </u-input>
@@ -59,14 +59,13 @@
readonly readonly
:placeholder="$lang.walletAddress" :placeholder="$lang.walletAddress"
fontSize="12px" fontSize="12px"
color="#93979b" color="#f7ecd0"
:value="address" :value="address"
> >
<template slot="suffix"> <template slot="suffix">
<u-button <u-button
class="btn" class="btn"
:text="$lang.copy" :text="$lang.copy"
type="success"
@click="copyCode" @click="copyCode"
color="#e5b932" color="#e5b932"
></u-button> ></u-button>
@@ -90,7 +89,7 @@
</view> </view>
</view> </view>
</template> </template>
<template v-if="userInfo.pay_channel == 'YBF'"> <template v-if="userInfo.pay_channel == 'YBF' && userInfo.area_id != 3">
<view <view
class="picker-view" class="picker-view"
@click="fnPicker('currency')" @click="fnPicker('currency')"
@@ -99,7 +98,7 @@
<u-input <u-input
readonly readonly
:placeholder="$lang.chooseCoin" :placeholder="$lang.chooseCoin"
color="#93979b" color="#f7ecd0"
v-model="currency.name" v-model="currency.name"
border="none" border="none"
> >
@@ -112,7 +111,7 @@
<u-icon <u-icon
slot="suffix" slot="suffix"
name="arrow-down-fill" name="arrow-down-fill"
color="#757272" color="#b9aa84"
size="16" size="16"
></u-icon> ></u-icon>
</u-input> </u-input>
@@ -125,7 +124,7 @@
<u-input <u-input
readonly readonly
:placeholder="$lang.chooseLine" :placeholder="$lang.chooseLine"
color="#93979b" color="#f7ecd0"
v-model="coin_type.name" v-model="coin_type.name"
border="none" border="none"
> >
@@ -138,7 +137,7 @@
<u-icon <u-icon
slot="suffix" slot="suffix"
name="arrow-down-fill" name="arrow-down-fill"
color="#757272" color="#b9aa84"
size="16" size="16"
></u-icon> ></u-icon>
</u-input> </u-input>
@@ -146,7 +145,7 @@
<view class="picker-view"> <view class="picker-view">
<u-input <u-input
:placeholder="$lang.enterMoney" :placeholder="$lang.enterMoney"
color="#93979b" color="#f7ecd0"
v-model="amount" v-model="amount"
border="none" border="none"
> >
@@ -184,18 +183,35 @@
@confirm="confirmPicker" @confirm="confirmPicker"
></u-picker> ></u-picker>
</template> </template>
<!-- 越南 AlinPay 在线充值 --> <!-- 越南地区银行卡 (AlinPay) / USDT (Epay) 双通道 PC 同步按 area_id 判断 -->
<template v-if="userInfo.pay_channel == 'ALIN_VN'"> <template v-if="userInfo.area_id == 3">
<view class="pay-tabs">
<view
class="pay-tab"
:class="{ active: payChannel === 'alin' }"
@click="payChannel = 'alin'"
>Thẻ ngân hàng</view>
<view
class="pay-tab"
:class="{ active: payChannel === 'epay' }"
@click="payChannel = 'epay'"
>USDT (TRC20)</view>
<view
class="pay-tab"
:class="{ active: payChannel === 'ccpay' }"
@click="payChannel = 'ccpay'"
>Ngân hàng QR</view>
</view>
<view class="picker-view"> <view class="picker-view">
<u-input <u-input
placeholder="Tối thiểu 1,000,000" :placeholder="payChannel === 'epay' ? 'Nhập số tiền VND (vd: 1,000,000)' : 'Tối thiểu 1,000,000'"
color="#93979b" color="#f7ecd0"
v-model="amount" v-model="amount"
type="number" type="number"
border="none" border="none"
> >
<u--text <u--text
:text="$lang.rechargeAmount || '充值金额'" :text="payChannel === 'epay' ? ($lang.rechargeAmount || '充值金额') + ' (VND)' : ($lang.rechargeAmount || '充值金额')"
slot="prefix" slot="prefix"
margin="0 3px 0 0" margin="0 3px 0 0"
type="tips" type="tips"
@@ -207,17 +223,109 @@
class="button" class="button"
color="#e5b932" color="#e5b932"
:text="$lang.submit" :text="$lang.submit"
@click="submitAlin" @click="payChannel === 'ccpay' ? submitCcpay() : (payChannel === 'epay' ? submitEpay() : submitAlin())"
></u-button> ></u-button>
</view> </view>
<view class="list"> <view class="list">
<view class="tip"> <view class="tip">
{{ $lang.rechargeTip }} {{ payChannel === 'epay' ? 'Nhập số tiền theo VND — hệ thống tự động quy đổi sang USDT theo tỷ giá 1 USDT ≈ 27,100 VND. Thanh toán qua mạng TRC20.' : (payChannel === 'ccpay' ? 'Nhập số tiền VND — hệ thống tạo mã QR ngân hàng. Quét mã thanh toán qua ứng dụng ngân hàng.' : $lang.rechargeTip) }}
</view> </view>
</view> </view>
</template> </template>
</view> </view>
<view class="mb60"></view> <view class="mb60"></view>
<!-- AlinPay 内嵌支付弹窗 -->
<view class="alin-overlay" v-if="alinPay.visible" @click.self="closeAlinPay">
<view class="alin-pay-box">
<view class="alin-pay-header">
<text class="alin-pay-title">Thanh toán ngân hàng</text>
<view class="epay-qr-close" @click="closeAlinPay">×</view>
</view>
<iframe v-if="alinPay.url" :src="alinPay.url" class="alin-iframe" frameborder="0" allow="payment"></iframe>
</view>
</view>
<!-- USDT 内嵌二维码弹窗 -->
<u-popup :show="epayQr.visible" mode="center" round="10" :closeOnClickOverlay="false" @close="closeEpayQr">
<view class="epay-qr-box">
<view class="epay-qr-close" @click="closeEpayQr">×</view>
<view class="epay-qr-title">USDT (TRC20)</view>
<view class="epay-qr-status" :class="epayQr.statusClass">{{ epayQr.statusText }}</view>
<view class="epay-qr-img-wrap">
<u--image v-if="epayQr.qrDataUrl" :src="epayQr.qrDataUrl" width="340rpx" height="340rpx" mode="scaleToFill"></u--image>
</view>
<view class="epay-qr-field">
<view class="epay-qr-label">Số tiền USDT (chính xác)</view>
<view class="epay-qr-value amount">
<text>{{ epayQr.data.usdt_amount }} USDT</text>
<view class="epay-qr-btn" @click="copyEpayText(epayQr.data.usdt_amount, 'amount')">
{{ epayQr.copied === 'amount' ? '' : 'Copy' }}
</view>
</view>
</view>
<view class="epay-qr-field">
<view class="epay-qr-label">Địa chỉ (TRC20)</view>
<view class="epay-qr-value addr">
<text>{{ epayQr.data.usdt_address }}</text>
<view class="epay-qr-btn" @click="copyEpayText(epayQr.data.usdt_address, 'addr')">
{{ epayQr.copied === 'addr' ? '' : 'Copy' }}
</view>
</view>
</view>
<view class="epay-qr-meta">
<text> {{ epayQr.data.vnd_amount }} VND</text>
<text class="epay-qr-countdown"> {{ epayQr.countdownText }}</text>
</view>
<view class="epay-qr-tip">
Vui lòng chuyển chính xác số tiền. Sai số sẽ không thể xác định đơn hàng!
</view>
</view>
</u-popup>
<!-- CCpay 银行QR弹窗 -->
<u-popup :show="bankQr.visible" mode="center" round="10" :closeOnClickOverlay="false" @close="closeBankQr">
<view class="epay-qr-box">
<view class="epay-qr-close" @click="closeBankQr">×</view>
<view class="epay-qr-title">Ngân hàng QR</view>
<view class="epay-qr-status" :class="bankQr.statusClass">{{ bankQr.statusText }}</view>
<view class="epay-qr-img-wrap" v-if="bankQr.qrDataUrl">
<u--image :src="bankQr.qrDataUrl" width="340rpx" height="340rpx" mode="scaleToFill"></u--image>
</view>
<view class="epay-qr-field">
<view class="epay-qr-label">Số tài khoản</view>
<view class="epay-qr-value amount">
<text>{{ bankQr.data.bank_account }}</text>
<view class="epay-qr-btn" @click="copyEpayText(bankQr.data.bank_account, 'bank_acc')">
{{ epayQr.copied === 'bank_acc' ? '' : 'Copy' }}
</view>
</view>
</view>
<view class="epay-qr-field">
<view class="epay-qr-label">Tên tài khoản Ngân hàng</view>
<view class="epay-qr-value addr">
<text>{{ bankQr.data.bank_name }} {{ bankQr.data.bank_short }}</text>
</view>
</view>
<view class="epay-qr-meta">
<text>{{ Number(bankQr.data.amount).toLocaleString() }} VND</text>
<text class="epay-qr-countdown"> {{ bankQr.countdownText }}</text>
</view>
<view class="epay-qr-tip">
Vui lòng chuyển khoản chính xác số tiền. Sai thông tin sẽ không thể xác nhận đơn hàng!
</view>
</view>
</u-popup>
</view> </view>
</template> </template>
@@ -240,6 +348,34 @@ export default {
amount: "", amount: "",
currency: { name: "", key: "" }, currency: { name: "", key: "" },
coin_type: { name: "", key: "" }, coin_type: { name: "", key: "" },
// 越南地区在线支付通道:'alin'(银行卡) | 'epay'(USDT)
payChannel: "alin",
// 内嵌 USDT 二维码弹窗状态
epayQr: {
visible: false,
data: { usdt_address: "", usdt_amount: "", vnd_amount: "", expires_at: 0, order_sn: "" },
qrDataUrl: "",
countdownText: "",
statusText: "",
statusClass: "waiting",
copied: "",
},
_epayPollTimer: null,
_epayCountdownTimer: null,
bankQr: {
visible: false,
data: { bank_account: "", bank_name: "", bank_short: "", qr_data: "", amount: 0, order_sn: "", expires_at: 0, timeout_sec: 600 },
qrDataUrl: "",
countdownText: "",
statusText: "",
statusClass: "waiting",
},
_bankPollTimer: null,
_bankCountdownTimer: null,
alinPay: {
visible: false,
url: "",
},
}; };
}, },
computed: { computed: {
@@ -388,13 +524,8 @@ export default {
.then((res) => { .then((res) => {
const d = res.Data || {}; const d = res.Data || {};
if (d.status == 1 && d.url) { if (d.status == 1 && d.url) {
const o = navigator.userAgent; this.alinPay.url = d.url;
const isiOS = !!o.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); this.alinPay.visible = true;
if (isiOS) {
window.location.href = d.url;
} else {
window.open(d.url, "_blank");
}
} else { } else {
this.$toast({ this.$toast({
message: d.message || '充值失败', message: d.message || '充值失败',
@@ -409,78 +540,667 @@ export default {
this.$toastHide(); this.$toastHide();
}); });
}, },
submitEpay() {
if (!this.amount || this.amount <= 0) {
this.$toast({ message: 'Vui lòng nhập số tiền', duration: 2000 });
return;
}
if (this.amount < 1000000) {
this.$toast({ message: 'Số tiền tối thiểu là 1,000,000', duration: 2000 });
return;
}
const params = {
user_id: this.userInfo.id,
price: this.amount,
client: 3,
username: this.userInfo.username,
pay_type: 'usdt',
};
this.$toast({
type: "loading",
message: `${this.$lang.submit}...`,
duration: 200000,
});
this.$api
.epayDeposit(params)
.then((res) => {
const d = res.Data || {};
if (d.status == 1 && d.qrcode) {
this.openEpayQr(d.qrcode);
} else if (d.status == 1 && d.url) {
// 后端未升级时兼容跳转
const isiOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
if (isiOS) window.location.href = d.url; else window.open(d.url, "_blank");
} else {
this.$toast({ message: d.message || 'Nạp thất bại', duration: 2000 });
}
})
.catch((err) => {
console.log(err);
})
.finally(() => {
this.$toastHide();
});
},
openEpayQr(qrcode) {
this.epayQr.data = qrcode;
this.epayQr.statusText = "Đang chờ thanh toán...";
this.epayQr.statusClass = "waiting";
this.epayQr.copied = "";
// 生成二维码图片(复用现有 qr-image 库)
try {
this.epayQr.qrDataUrl =
"data:image/png;base64," +
uni.arrayBufferToBase64(qr.imageSync(qrcode.usdt_address, { margin: 2 }));
} catch (e) {
this.epayQr.qrDataUrl = "";
}
this.epayQr.visible = true;
this.startEpayCountdown();
this.startEpayPolling();
},
startEpayCountdown() {
const tick = () => {
const left = Math.max(0, this.epayQr.data.expires_at - Math.floor(Date.now() / 1000));
const m = Math.floor(left / 60);
const s = left % 60;
this.epayQr.countdownText = (m < 10 ? "0" : "") + m + ":" + (s < 10 ? "0" : "") + s;
if (left <= 0) {
this.epayQr.statusText = "Đơn hàng đã hết hạn";
this.epayQr.statusClass = "expired";
this.stopEpayTimers();
}
};
tick();
this._epayCountdownTimer = setInterval(tick, 1000);
},
startEpayPolling() {
const poll = () => {
if (!this.epayQr.visible || !this.epayQr.data.order_sn) return;
this.$api
.epayOrderStatus({
user_id: this.userInfo.id,
order_sn: this.epayQr.data.order_sn,
})
.then((res) => {
const d = res.Data || {};
if (d.status == 1) {
this.epayQr.statusText = "Thanh toán thành công!";
this.epayQr.statusClass = "success";
this.stopEpayTimers();
this.$store.dispatch("app/getUserInfo");
setTimeout(() => this.closeEpayQr(), 2500);
} else if (d.status == 2) {
this.epayQr.statusText = "Đơn hàng đã hết hạn";
this.epayQr.statusClass = "expired";
this.stopEpayTimers();
}
})
.catch(() => {});
};
this._epayPollTimer = setInterval(poll, 3000);
setTimeout(poll, 1000);
},
copyEpayText(text, tag) {
uni.setClipboardData({
data: String(text),
success: () => {
this.epayQr.copied = tag;
setTimeout(() => {
if (this.epayQr.copied === tag) this.epayQr.copied = "";
}, 1500);
},
});
},
closeAlinPay() {
this.alinPay.visible = false;
this.alinPay.url = "";
},
closeEpayQr() {
this.epayQr.visible = false;
this.stopEpayTimers();
},
stopEpayTimers() {
if (this._epayPollTimer) {
clearInterval(this._epayPollTimer);
this._epayPollTimer = null;
}
if (this._epayCountdownTimer) {
clearInterval(this._epayCountdownTimer);
this._epayCountdownTimer = null;
}
},
submitCcpay() {
if (!this.amount || this.amount <= 0) {
this.$toast({ message: 'Vui lòng nhập số tiền', duration: 2000 });
return;
}
if (this.amount < 1000000) {
this.$toast({ message: 'Số tiền tối thiểu là 1,000,000', duration: 2000 });
return;
}
const params = {
user_id: this.userInfo.id,
price: this.amount,
client: 3,
username: this.userInfo.username,
};
this.$toast({ type: "loading", message: `${this.$lang.submit}...`, duration: 200000 });
this.$api
.ccpayDeposit(params)
.then((res) => {
const d = res.Data || {};
if (d.status == 1 && d.qrcode) {
this.openBankQr(d.qrcode);
} else if (d.status == 1 && d.url) {
const isiOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
if (isiOS) window.location.href = d.url; else window.open(d.url, "_blank");
} else {
this.$toast({ message: d.message || 'Nạp thất bại', duration: 2000 });
}
})
.catch((err) => { console.log(err); })
.finally(() => { this.$toastHide(); });
},
openBankQr(qrcode) {
this.bankQr.data = qrcode;
this.bankQr.statusText = "Đang chờ thanh toán...";
this.bankQr.statusClass = "waiting";
try {
this.bankQr.qrDataUrl = qrcode.qr_data
? "data:image/png;base64," + uni.arrayBufferToBase64(qr.imageSync(qrcode.qr_data, { margin: 2 }))
: "";
} catch (e) { this.bankQr.qrDataUrl = ""; }
this.bankQr.visible = true;
this.startBankCountdown();
this.startBankPolling();
},
startBankCountdown() {
const tick = () => {
const left = Math.max(0, this.bankQr.data.expires_at - Math.floor(Date.now() / 1000));
const m = Math.floor(left / 60);
const s = left % 60;
this.bankQr.countdownText = (m < 10 ? "0" : "") + m + ":" + (s < 10 ? "0" : "") + s;
if (left <= 0) {
this.bankQr.statusText = "Đơn hàng đã hết hạn";
this.bankQr.statusClass = "expired";
this.stopBankTimers();
}
};
tick();
this._bankCountdownTimer = setInterval(tick, 1000);
},
startBankPolling() {
const poll = () => {
if (!this.bankQr.visible || !this.bankQr.data.order_sn) return;
this.$api
.ccpayOrderStatus({ user_id: this.userInfo.id, order_sn: this.bankQr.data.order_sn })
.then((res) => {
const d = res.Data || {};
if (d.status == 1) {
this.bankQr.statusText = "Thanh toán thành công!";
this.bankQr.statusClass = "success";
this.stopBankTimers();
this.$store.dispatch("app/getUserInfo");
setTimeout(() => this.closeBankQr(), 2500);
} else if (d.status == 2) {
this.bankQr.statusText = "Đơn hàng đã hết hạn";
this.bankQr.statusClass = "expired";
this.stopBankTimers();
}
})
.catch(() => {});
};
this._bankPollTimer = setInterval(poll, 3000);
setTimeout(poll, 1000);
},
closeBankQr() {
this.bankQr.visible = false;
this.stopBankTimers();
},
stopBankTimers() {
if (this._bankPollTimer) { clearInterval(this._bankPollTimer); this._bankPollTimer = null; }
if (this._bankCountdownTimer) { clearInterval(this._bankCountdownTimer); this._bankCountdownTimer = null; }
},
},
beforeDestroy() {
this.stopEpayTimers();
this.stopBankTimers();
}, },
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.pay-tabs {
display: flex;
gap: 12rpx;
margin-bottom: 16px;
}
.pay-tab {
flex: 1;
min-height: 44px;
padding: 0 10rpx;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
color: #b9aa84;
background: linear-gradient(
180deg,
rgba(21, 18, 15, 0.96) 0%,
rgba(13, 11, 9, 0.96) 100%
);
border: 1rpx solid rgba(223, 189, 120, 0.14);
border-radius: 16px;
font-size: 24rpx;
line-height: 1.3;
transition: all 0.2s;
&.active {
color: #231705;
font-weight: 700;
background: linear-gradient(180deg, #f2dfb6 0%, #dfbd78 52%, #bd8d39 100%);
border-color: rgba(242, 223, 182, 0.5);
box-shadow: 0 12px 24px rgba(125, 84, 22, 0.18),
inset 0 1px 0 rgba(255, 255, 255, 0.36);
}
}
.recharge { .recharge {
background: #0b1520;
width: 100%; width: 100%;
min-height: 100vh; min-height: 100vh;
background: linear-gradient(180deg, #060505 0%, #0d0b09 100%);
color: #f7ecd0;
::v-deep .u-navbar {
background: rgba(0, 0, 0, 0.72) !important;
}
::v-deep .u-navbar__content {
background: transparent !important;
}
::v-deep .u-picker__view__column__item {
color: #f3e3b8 !important;
}
::v-deep .u-toolbar {
background: #15120f !important;
border-bottom-color: rgba(223, 189, 120, 0.12) !important;
}
::v-deep .u-toolbar__title {
color: #f4dfae !important;
}
.navbar-lab { .navbar-lab {
color: #fff; color: #fbf2de;
font-weight: 500; font-weight: 700;
font-size: 18px; font-size: 19px;
letter-spacing: 0.3px;
} }
.content { .content {
margin: 5px 5px; width: calc(100% - 24px);
border: 2px solid #947b2b; max-width: 760px;
background: #222222; margin: 10px auto 0;
padding: 18px 16px 22px;
box-sizing: border-box; box-sizing: border-box;
padding: 15px; border-radius: 24px;
background: linear-gradient(
180deg,
rgba(16, 13, 11, 0.96) 0%,
rgba(10, 8, 7, 0.96) 100%
);
border: 1px solid rgba(223, 189, 120, 0.18);
box-shadow: 0 18px 42px rgba(0, 0, 0, 0.24),
inset 0 1px 0 rgba(255, 245, 223, 0.03);
.picker-view { .picker-view {
border: 2px solid #947b2b; min-height: 56px;
padding: 8px; margin-bottom: 14px;
border-radius: 5px; padding: 0 14px;
margin-bottom: 20px; display: flex;
&.input { align-items: center;
border: 1px solid #dadbde; background: linear-gradient(
180deg,
rgba(25, 21, 18, 0.96) 0%,
rgba(17, 14, 12, 0.96) 100%
);
border: 1px solid rgba(223, 189, 120, 0.14);
border-radius: 16px;
box-shadow: inset 0 1px 0 rgba(255, 244, 220, 0.03),
inset 0 -1px 0 rgba(0, 0, 0, 0.12);
::v-deep .u-input {
flex: 1;
}
::v-deep .u-input__content {
min-height: 54px;
padding: 0;
}
::v-deep .u-input__content__field-wrapper {
width: 100%;
}
::v-deep input {
color: #f7ecd0 !important;
font-size: 15px !important;
letter-spacing: 0.2px;
}
::v-deep input::placeholder {
color: rgba(245, 228, 184, 0.4) !important;
}
::v-deep .u-text__value {
color: #baa67f !important;
font-size: 13px !important;
} }
} }
.list { .list {
margin-bottom: 14px;
padding: 14px;
border-radius: 16px;
background: linear-gradient(
180deg,
rgba(23, 19, 16, 0.92) 0%,
rgba(14, 12, 10, 0.92) 100%
);
border: 1px solid rgba(223, 189, 120, 0.1);
font-size: 14px; font-size: 14px;
text-align: center; text-align: center;
&.qrcode { &.qrcode {
display: flex; display: flex;
width: 100%; width: 100%;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
margin: 25px 0; padding: 20px 14px;
::v-deep .u-image {
border-radius: 18px !important;
overflow: hidden;
border: 1px solid rgba(223, 189, 120, 0.12);
background: #fff;
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.16);
} }
}
.lab { .lab {
color: #757272; color: #b9aa84;
margin: 10px 0; margin: 0 0 10px;
text-align: left;
font-size: 13px;
} }
.box {
::v-deep .u-input {
min-height: 48px;
padding: 0 12px;
background: rgba(255, 255, 255, 0.02);
border: 1px solid rgba(223, 189, 120, 0.12);
border-radius: 14px;
}
::v-deep .u-input__content {
min-height: 48px;
}
::v-deep input {
color: #f7ecd0 !important;
}
}
.btn { .btn {
height: 30px; min-width: 76px;
font-weight: 600; height: 34px;
color: #0b1520 !important; font-weight: 700;
border: none !important;
border-radius: 12px !important;
color: #231705 !important;
box-shadow: 0 8px 18px rgba(125, 84, 22, 0.18),
inset 0 1px 0 rgba(255, 255, 255, 0.28);
} }
.type { .type {
width: 70px; min-width: 86px;
height: 35px; height: 36px;
background: #e5b932; padding: 0 16px;
border-radius: 40px; display: inline-flex;
align-items: center;
justify-content: center;
background: linear-gradient(180deg, #f2dfb6 0%, #dfbd78 52%, #bd8d39 100%);
border-radius: 999px;
text-align: center; text-align: center;
line-height: 35px; line-height: 36px;
font-weight: 600; font-weight: 700;
margin: 10px auto; color: #231705;
box-shadow: 0 8px 18px rgba(125, 84, 22, 0.16),
inset 0 1px 0 rgba(255, 255, 255, 0.28);
margin: 0 auto;
} }
.button { .button {
line-height: 45px; height: 50px !important;
height: 45px; margin-top: 8px;
color: #0b1520 !important; margin-bottom: 2px;
font-weight: bold; border: none !important;
margin-top: 30px; border-radius: 16px !important;
margin-bottom: 10px; color: #231705 !important;
font-weight: 700;
letter-spacing: 0.3px;
box-shadow: 0 12px 24px rgba(125, 84, 22, 0.18),
inset 0 1px 0 rgba(255, 255, 255, 0.36);
} }
.tip { .tip {
color: #cc4c0e; color: #bca47a;
font-size: 13px; font-size: 13px;
text-align: justify; text-align: justify;
line-height: 1.6;
} }
} }
.mb60 {
margin-bottom: 0 !important;
}
} }
} }
/* ============ 内嵌 USDT / 银行二维码弹窗 ============ */
.epay-qr-box {
width: 620rpx;
padding: 34rpx 34rpx 28rpx;
background: linear-gradient(
180deg,
rgba(20, 16, 12, 0.98) 0%,
rgba(11, 9, 7, 0.98) 100%
);
border: 1rpx solid rgba(223, 189, 120, 0.18);
border-radius: 20rpx;
color: #f0dbab;
box-sizing: border-box;
position: relative;
box-shadow: 0 24rpx 60rpx rgba(0, 0, 0, 0.3);
}
.epay-qr-close {
position: absolute;
top: 12rpx;
right: 16rpx;
color: #b7a37d;
font-size: 38rpx;
line-height: 1;
padding: 10rpx 16rpx;
}
.epay-qr-title {
text-align: center;
font-size: 30rpx;
font-weight: 700;
margin-bottom: 10rpx;
color: #f7e6bd;
}
.epay-qr-status {
width: fit-content;
min-width: 180rpx;
margin: 0 auto 20rpx;
padding: 8rpx 18rpx;
text-align: center;
font-size: 22rpx;
border-radius: 999rpx;
background: rgba(255, 255, 255, 0.03);
&.waiting {
color: #e5b932;
}
&.success {
color: #7cd992;
}
&.expired {
color: #e67e72;
}
}
.epay-qr-img-wrap {
width: 340rpx;
height: 340rpx;
margin: 0 auto 24rpx;
background: #fff;
padding: 16rpx;
border-radius: 20rpx;
box-sizing: content-box;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 10rpx 26rpx rgba(0, 0, 0, 0.18);
}
.epay-qr-field {
margin-bottom: 16rpx;
}
.epay-qr-label {
color: #ab9770;
font-size: 22rpx;
margin-bottom: 8rpx;
}
.epay-qr-value {
display: flex;
align-items: center;
gap: 12rpx;
background: rgba(255, 255, 255, 0.03);
border: 1rpx solid rgba(223, 189, 120, 0.12);
border-radius: 14rpx;
padding: 14rpx 16rpx;
font-size: 24rpx;
word-break: break-all;
&.amount {
color: #fff8e6;
font-weight: 700;
font-size: 28rpx;
}
&.addr {
color: #f0dbab;
font-family: "Courier New", monospace;
font-size: 20rpx;
}
text {
flex: 1;
}
}
.epay-qr-btn {
flex-shrink: 0;
min-width: 90rpx;
text-align: center;
background: linear-gradient(180deg, #f2dfb6 0%, #dfbd78 52%, #bd8d39 100%);
color: #231705;
font-size: 22rpx;
padding: 8rpx 18rpx;
border-radius: 10rpx;
font-weight: 700;
}
.epay-qr-meta {
display: flex;
justify-content: space-between;
color: #b7a37d;
font-size: 24rpx;
margin: 20rpx 0 12rpx;
}
.epay-qr-countdown {
color: #e5b932;
font-weight: 700;
}
.epay-qr-tip {
color: #d58c65;
font-size: 22rpx;
text-align: center;
line-height: 1.6;
margin-top: 14rpx;
opacity: 0.92;
}
.alin-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
background: rgba(0, 0, 0, 0.68);
display: flex;
align-items: center;
justify-content: center;
backdrop-filter: blur(4px);
}
.alin-pay-box {
width: 92vw;
height: 85vh;
background: linear-gradient(180deg, #17130f 0%, #0d0b09 100%);
border: 1px solid rgba(223, 189, 120, 0.16);
border-radius: 20px;
overflow: hidden;
display: flex;
flex-direction: column;
box-shadow: 0 20px 46px rgba(0, 0, 0, 0.26);
}
.alin-pay-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px;
background: rgba(20, 17, 14, 0.96);
border-bottom: 1px solid rgba(223, 189, 120, 0.12);
}
.alin-pay-title {
color: #f4dca3;
font-size: 16px;
font-weight: 700;
}
.alin-iframe {
flex: 1;
width: 100%;
border: none;
background: #fff;
}
</style> </style>
+185 -34
View File
@@ -1,37 +1,101 @@
<template> <template>
<view class="register"> <view class="register">
<view class="content"> <view class="content">
<view class="logo-shell">
<view class="logo"> <view class="logo">
<u--image :showLoading="false" :src="loginLogo" width="125px" height="119px" mode="scaleToFill"></u--image> <u--image
:showLoading="false"
:src="loginLogo"
width="125px"
height="119px"
mode="scaleToFill"
></u--image>
</view> </view>
<u-input class="input" :focus='focusUsername' v-model="username" type="text" clearable :placeholder="$lang.enterAccount"> </view>
<view class="panel">
<u-input
class="input"
:focus="focusUsername"
v-model="username"
type="text"
clearable
border="none"
color="#f7ecd2"
:placeholder="$lang.enterAccount"
placeholderStyle="color: rgba(245, 228, 184, 0.42); font-size: 14px;"
>
<text class="text" slot="prefix">{{ $lang.account }}</text> <text class="text" slot="prefix">{{ $lang.account }}</text>
</u-input> </u-input>
<u-input class="input" :focus='focusPassword' v-model="password" :password="true" :placeholder="$lang.enterPassword" autocomplete="new-password"> <u-input
class="input"
:focus="focusPassword"
v-model="password"
:password="true"
border="none"
color="#f7ecd2"
:placeholder="$lang.enterPassword"
autocomplete="new-password"
placeholderStyle="color: rgba(245, 228, 184, 0.42); font-size: 14px;"
>
<text class="text" slot="prefix">{{ $lang.password }}</text> <text class="text" slot="prefix">{{ $lang.password }}</text>
</u-input> </u-input>
<u-input class="input" :focus='focusRepass' v-model="repass" :password="true" :placeholder="$lang.enterPasswordAgain"> <u-input
class="input"
:focus="focusRepass"
v-model="repass"
:password="true"
border="none"
color="#f7ecd2"
:placeholder="$lang.enterPasswordAgain"
placeholderStyle="color: rgba(245, 228, 184, 0.42); font-size: 14px;"
>
<text class="text" slot="prefix">{{ $lang.confirmPassword }}</text> <text class="text" slot="prefix">{{ $lang.confirmPassword }}</text>
</u-input> </u-input>
<u-input class="input" :focus='focusPhone' v-model="phone" type="number" clearable <u-input
:placeholder="`${$lang.enterPhone}`"> class="input"
:focus="focusPhone"
v-model="phone"
type="number"
clearable
border="none"
color="#f7ecd2"
:placeholder="`${$lang.enterPhone}`"
placeholderStyle="color: rgba(245, 228, 184, 0.42); font-size: 14px;"
>
<view class="phone-code" slot="prefix" @click="countryShow = true"> <view class="phone-code" slot="prefix" @click="countryShow = true">
{{ countryData.country_code }} {{ countryData.country_code }}
</view> </view>
</u-input> </u-input>
<u-input class="input" v-model="referral_code" placeholder="TC176852" :disabled="referral_disabled"> <u-input
class="input"
v-model="referral_code"
border="none"
color="#f7ecd2"
placeholder="TC176852"
placeholderStyle="color: rgba(245, 228, 184, 0.42); font-size: 14px;"
:disabled="referral_disabled"
>
<text class="text" slot="prefix">{{ $lang.invitationCode }}</text> <text class="text" slot="prefix">{{ $lang.invitationCode }}</text>
</u-input> </u-input>
<view class="btn-box"> <view class="btn-box">
<view class="btn" @tap="register()">{{ $lang.register }}</view> <view class="btn btn-primary" @tap="register()">{{
$lang.register
}}</view>
</view> </view>
<view class="tip" @tap="goLogin">{{ $lang.goLogin }}</view> <view class="tip" @tap="goLogin">{{ $lang.goLogin }}</view>
</view> </view>
</view>
<!-- 提示 --> <!-- 提示 -->
<u-toast ref="uToast" /> <u-toast ref="uToast" />
<!-- 区号 --> <!-- 区号 -->
<country-code class="country" :show="countryShow" :anchor="countryData.anchor_index" <country-code
:country="countryData.country_en" @select="selectCountryTap" @close="countryShow = false"></country-code> class="country"
:show="countryShow"
:anchor="countryData.anchor_index"
:country="countryData.country_en"
@select="selectCountryTap"
@close="countryShow = false"
></country-code>
<view class="mb60"></view> <view class="mb60"></view>
</view> </view>
</template> </template>
@@ -165,7 +229,7 @@
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.register { .register {
width: 100%; width: 100%;
height: 100%; height: 100%;
position: fixed; position: fixed;
@@ -177,35 +241,109 @@
overflow-y: auto; overflow-y: auto;
.content { .content {
width: 280px; width: 86%;
padding-bottom: 50px; max-width: 326px;
margin: 0 auto; margin: 0 auto;
padding: 94px 0 48px;
.logo-shell {
margin-bottom: 20px;
}
.logo { .logo {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
margin-bottom: 20px; width: 125px;
margin-top: 20%; height: 119px;
margin: 0 auto;
}
.panel {
position: relative;
padding: 20px 18px 22px;
border-radius: 24px;
background: linear-gradient(
180deg,
rgba(14, 11, 9, 0.9) 0%,
rgba(10, 8, 7, 0.8) 100%
);
border: 1px solid rgba(213, 181, 103, 0.22);
box-shadow: 0 18px 40px rgba(0, 0, 0, 0.24),
inset 0 1px 0 rgba(255, 255, 255, 0.03);
overflow: hidden;
&::before {
content: "";
position: absolute;
top: 0;
left: 18px;
right: 18px;
height: 1px;
background: linear-gradient(
90deg,
rgba(213, 181, 103, 0),
rgba(244, 221, 169, 0.82),
rgba(213, 181, 103, 0)
);
}
} }
.input { .input {
height: 30px; height: 50px;
line-height: 30px; line-height: 50px;
margin-bottom: 15px; margin-bottom: 14px;
background: #fff; background: rgba(24, 20, 17, 0.96);
border-radius: 8px; border: 1px solid rgba(213, 181, 103, 0.14);
border-radius: 15px;
overflow: hidden; overflow: hidden;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03),
inset 0 -1px 0 rgba(0, 0, 0, 0.16);
&:last-of-type {
margin-bottom: 0;
}
::v-deep .u-input__content {
min-height: 100%;
padding: 0 15px;
}
::v-deep .u-input__content__field-wrapper {
width: 100%;
}
::v-deep input {
color: #f7ecd2 !important;
font-size: 15px !important;
letter-spacing: 0.2px;
}
::v-deep input::placeholder {
color: rgba(245, 228, 184, 0.42) !important;
}
::v-deep .u-input__content__prefix-icon,
::v-deep .u-input__content__subfix-icon {
color: #e8d39b !important;
}
} }
.phone-code { .phone-code {
min-width: 50px; min-width: 58px;
margin-right: 12px;
padding-right: 12px;
text-align: center; text-align: center;
border-right: 1px solid #ddd; font-size: 13px;
color: #e8d39b;
border-right: 1px solid rgba(213, 181, 103, 0.18);
} }
.text { .text {
padding-right: 5px; min-width: 74px;
margin-right: 12px;
font-size: 13px;
color: rgba(232, 211, 155, 0.92);
} }
.btn-box { .btn-box {
@@ -216,16 +354,27 @@
height: 48px; height: 48px;
line-height: 48px; line-height: 48px;
text-align: center; text-align: center;
font-size: 16px; font-size: 14px;
background: url("~@/static/images/btn_bg.png") no-repeat; font-weight: 700;
background-size: 100% 100%; letter-spacing: 0.5px;
font-weight: 600; border-radius: 15px;
margin-top: 15px;
&:active { &:active {
opacity: 0.8; opacity: 0.86;
} }
} }
.btn-primary {
color: #241804;
background: linear-gradient(
180deg,
#f2dfb6 0%,
#dfbd78 52%,
#bd8d39 100%
);
box-shadow: 0 12px 24px rgba(125, 84, 22, 0.24),
inset 0 1px 0 rgba(255, 255, 255, 0.42);
}
} }
} }
@@ -237,14 +386,16 @@
.tip { .tip {
font-size: 12px; font-size: 12px;
color: #b38f3c; color: rgba(234, 214, 160, 0.92);
margin-top: 20px; margin-top: 16px;
padding-top: 14px;
border-top: 1px solid rgba(213, 181, 103, 0.1);
text-align: center; text-align: center;
margin-bottom: 20px; letter-spacing: 0.2px;
&:active { &:active {
opacity: 0.6; opacity: 0.7;
}
} }
} }
}
</style> </style>
+3
View File
@@ -44,6 +44,9 @@
{{ $lang.tableNumber }} {{ item.table_name }} {{ $lang.tableNumber }} {{ item.table_name }}
</view> </view>
<view class="box">{{ $lang.playingMethod }} {{ item.user_bet }}</view> <view class="box">{{ $lang.playingMethod }} {{ item.user_bet }}</view>
<view class="box" v-if="item.ximaliang"
>{{ $lang.ximaliang }} {{ item.ximaliang }}</view
>
<view class="box" v-if="item.maliang" <view class="box" v-if="item.maliang"
>{{ $lang.maliang }} {{ item.maliang }}</view >{{ $lang.maliang }} {{ item.maliang }}</view
> >
+462 -76
View File
@@ -1,70 +1,105 @@
<template> <template>
<view class="user"> <view class="user">
<view class="hero">
<view class="card"> <view class="card">
<view class="card-sheen"></view>
<view class="card-orb"></view>
<view class="card-grid"></view>
<view class="card-head">
<view class="uid">ID:{{ userInfo.username }}</view> <view class="uid">ID:{{ userInfo.username }}</view>
<view class="logo-shell">
<u--image <u--image
class="logo" class="logo"
:showLoading="true" :showLoading="true"
:src="loginLogo" :src="loginLogo"
width="50px" width="42px"
height="auto" height="42px"
mode="widthFix" mode="scaleToFill"
></u--image> ></u--image>
</view>
</view>
<view class="box"> <view class="box">
<view class="text">{{ $lang.userBalance }}</view> <view class="text">{{ $lang.userBalance }}</view>
<view class="money-row">
<view class="money-icon"></view>
<view class="money">{{ money }}</view> <view class="money">{{ money }}</view>
</view> </view>
<u--image </view>
:showLoading="false" </view>
:src="require('static/images/card_bg.png')"
width="100%"
height="auto"
mode="widthFix"
></u--image>
</view> </view>
<view class="content"> <view class="content">
<view class="section-title">{{ $lang.tip }}</view>
<view class="menu-panel">
<view <view
class="cell" class="cell"
v-for="(item, index) in userMenu" v-for="(item, index) in userMenu"
:key="index" :key="index"
@click="goPath(item)" @click="goPath(item)"
> >
<view class="cell-left">
<view class="cell-dot"></view>
<view class="lab">{{ item.name }}</view> <view class="lab">{{ item.name }}</view>
</view>
<u-icon <u-icon
class="icon" class="icon"
name="arrow-right" name="arrow-right"
color="#757272" color="#b9aa84"
size="16" size="16"
></u-icon> ></u-icon>
</view> </view>
</view>
<view class="logout" @tap="modalShow = true">{{ $lang.logout }}</view> <view class="logout" @tap="modalShow = true">{{ $lang.logout }}</view>
</view> </view>
<u-picker <u-popup
:title="$lang.languageSettings"
closeOnClickOverlay
:defaultIndex="defaultIndex"
:show="show" :show="show"
:columns="langList" mode="bottom"
:cancelText="$lang.cancel" round="20"
:confirmText="$lang.confirm" closeOnClickOverlay
keyName="name" @close="closeLangPopup"
@close="show = false"
@cancel="show = false"
@confirm="confirm"
></u-picker>
<u-modal
:show="modalShow"
:title="$lang.tip"
:confirmText="$lang.confirm"
:cancelText="$lang.cancel"
@confirm="confirmLogout"
@cancel="modalShow = false"
:showCancelButton="true"
ref="uModal"
:asyncClose="true"
> >
<view style="text-align: center">{{ $lang.logoutTip }}</view> <view class="lang-popup">
</u-modal> <view class="popup-header">
<view class="popup-action cancel" @click="closeLangPopup">{{
$lang.cancel
}}</view>
<view class="popup-title">{{ $lang.languageSettings }}</view>
<view class="popup-action confirm" @click="confirmLanguageSelection">{{
$lang.confirm
}}</view>
</view>
<scroll-view scroll-y class="popup-list">
<view
class="popup-item"
:class="{ active: tempLanguageKey === item.key }"
v-for="item in langList[0]"
:key="item.key"
@click="tempLanguageKey = item.key"
>
<text>{{ item.name }}</text>
<u-icon
v-if="tempLanguageKey === item.key"
name="checkmark"
color="#231705"
size="16"
></u-icon>
</view>
</scroll-view>
</view>
</u-popup>
<u-popup :show="modalShow" mode="center" round="20" @close="closeLogoutModal">
<view class="logout-modal">
<view class="logout-title">{{ $lang.tip }}</view>
<view class="logout-text">{{ $lang.logoutTip }}</view>
<view class="logout-actions">
<view class="logout-btn logout-btn-cancel" @click="closeLogoutModal">{{
$lang.cancel
}}</view>
<view class="logout-btn logout-btn-confirm" @click="confirmLogout">{{
$lang.confirm
}}</view>
</view>
</view>
</u-popup>
<view class="mb60"></view> <view class="mb60"></view>
</view> </view>
</template> </template>
@@ -78,6 +113,7 @@ export default {
modalShow: false, modalShow: false,
defaultIndex: [0], defaultIndex: [0],
tempLanguageKey: "cn",
langList: [ langList: [
[ [
{ key: "en", name: "English" }, { key: "en", name: "English" },
@@ -121,6 +157,7 @@ export default {
this.defaultIndex = [i]; this.defaultIndex = [i];
} }
}); });
this.tempLanguageKey = this.language;
this.getUserMoneyData() this.getUserMoneyData()
}, },
methods: { methods: {
@@ -128,8 +165,22 @@ export default {
this.$store.commit("app/updateLanguage", item.value[0].key); this.$store.commit("app/updateLanguage", item.value[0].key);
this.show = false; this.show = false;
}, },
closeLangPopup() {
this.tempLanguageKey = this.language;
this.show = false;
},
confirmLanguageSelection() {
if (this.tempLanguageKey) {
this.$store.commit("app/updateLanguage", this.tempLanguageKey);
}
this.show = false;
},
closeLogoutModal() {
this.modalShow = false;
},
goPath(item) { goPath(item) {
if (item.id == 0) { if (item.id == 0) {
this.tempLanguageKey = this.language;
this.show = true; this.show = true;
} else if (item.id == 4 || item.id == 5 || item.id == 6) { } else if (item.id == 4 || item.id == 5 || item.id == 6) {
uni.switchTab({ uni.switchTab({
@@ -149,8 +200,13 @@ export default {
} }
}, },
confirmLogout() { confirmLogout() {
this.modalShow = false;
localStorage.removeItem("userInfo"); localStorage.removeItem("userInfo");
this.$router.replace({ path: "/" }); localStorage.removeItem("uni_id_token");
sessionStorage.clear();
const backSteps = window.history.length - 1;
window.history.go(-backSteps);
setTimeout(() => { window.location.replace("/"); }, 200);
}, },
getUserMoneyData() { getUserMoneyData() {
var that = this var that = this
@@ -179,83 +235,413 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.user { .user {
background: #0b1520;
width: 100%; width: 100%;
min-height: 100vh; min-height: 100vh;
background: linear-gradient(180deg, #060505 0%, #0d0b09 100%);
color: #f7ecd0;
.hero {
padding: 14px 12px 0;
}
.card { .card {
width: 100%;
padding: 10px;
box-sizing: border-box;
position: relative; position: relative;
overflow: hidden;
border-radius: 28px;
min-height: 188px;
border: 1px solid rgba(226, 193, 117, 0.22);
box-shadow: 0 18px 42px rgba(0, 0, 0, 0.24),
inset 0 1px 0 rgba(255, 245, 223, 0.08);
background: linear-gradient(
180deg,
#f1d488 0%,
#ddaf4e 42%,
#c78f28 100%
);
&::before {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(
135deg,
rgba(255, 255, 255, 0.2) 0%,
rgba(255, 255, 255, 0.04) 26%,
rgba(133, 88, 16, 0.08) 60%,
rgba(78, 50, 8, 0.18) 100%
);
pointer-events: none;
}
.card-sheen {
position: absolute;
top: -22px;
right: -36px;
width: 180px;
height: 180px;
border-radius: 50%;
background: radial-gradient(
circle,
rgba(255, 247, 218, 0.34) 0%,
rgba(255, 247, 218, 0.06) 46%,
rgba(255, 247, 218, 0) 74%
);
pointer-events: none;
}
.card-orb {
position: absolute;
left: -34px;
bottom: -48px;
width: 150px;
height: 150px;
border-radius: 50%;
background: radial-gradient(
circle,
rgba(169, 107, 20, 0.24) 0%,
rgba(169, 107, 20, 0.08) 45%,
rgba(169, 107, 20, 0) 76%
);
pointer-events: none;
}
.card-grid {
position: absolute;
inset: 0;
background-image: linear-gradient(
135deg,
rgba(255, 241, 204, 0.14) 12%,
transparent 12%,
transparent 50%,
rgba(160, 107, 22, 0.08) 50%,
rgba(160, 107, 22, 0.08) 62%,
transparent 62%
),
linear-gradient(
28deg,
rgba(255, 247, 228, 0.08) 14%,
transparent 14%,
transparent 56%,
rgba(149, 98, 21, 0.08) 56%,
rgba(149, 98, 21, 0.08) 70%,
transparent 70%
);
background-size: 180px 180px, 220px 220px;
opacity: 0.7;
pointer-events: none;
}
.card-head {
position: absolute;
top: 16px;
left: 16px;
right: 16px;
z-index: 3;
display: flex;
align-items: center;
justify-content: space-between;
}
.uid { .uid {
position: absolute; max-width: calc(100% - 82px);
left: 30px; padding: 8px 14px;
top: 25px; border-radius: 999px;
z-index: 3; background: rgba(84, 64, 25, 0.38);
font-size: 14px; border: 1px solid rgba(113, 82, 24, 0.12);
color: #573d14; color: rgba(92, 61, 12, 0.92);
font-size: 13px;
font-weight: 700;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} }
.logo-shell {
width: 52px;
height: 52px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 16px;
background: rgba(255, 247, 224, 0.12);
border: 1px solid rgba(115, 81, 18, 0.1);
backdrop-filter: blur(2px);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18);
}
.logo { .logo {
position: absolute;
right: 25px;
top: 20px;
z-index: 3; z-index: 3;
opacity: 0.96;
border-radius: 14px;
} }
.box { .box {
position: absolute; position: absolute;
left: 50%; left: 50%;
top: 50%; top: 55%;
z-index: 3; z-index: 3;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
font-size: 18px; width: calc(100% - 52px);
font-weight: 600;
color: #573d14;
text-align: center; text-align: center;
.money { color: #5d4312;
padding-left: 38px;
padding-right: 36px; .text {
padding-top: 10px; font-size: 16px;
padding-bottom: 4px; font-weight: 600;
letter-spacing: 0.2px;
}
.money-row {
width: fit-content;
max-width: 100%;
margin: 10px auto 0;
display: flex;
align-items: center;
gap: 8px;
}
.money-icon {
width: 28px;
height: 28px;
flex-shrink: 0;
background: url("/static/images/balance_icon.png") no-repeat; background: url("/static/images/balance_icon.png") no-repeat;
background-size: 33px auto; background-size: 28px auto;
background-position: left top; background-position: center;
}
.money {
padding: 0;
font-size: 30px;
font-weight: 700;
line-height: 1.1;
white-space: nowrap;
letter-spacing: 0.3px;
} }
} }
} }
.content { .content {
margin: 20px 15px; margin: 18px 12px 0;
border-radius: 5px;
.section-title {
margin: 0 2px 12px;
font-size: 13px;
color: #a9956d;
letter-spacing: 0.3px;
}
.menu-panel {
border-radius: 24px;
overflow: hidden; overflow: hidden;
background: linear-gradient(
180deg,
rgba(16, 13, 11, 0.96) 0%,
rgba(10, 8, 7, 0.96) 100%
);
border: 1px solid rgba(223, 189, 120, 0.12);
box-shadow: 0 18px 42px rgba(0, 0, 0, 0.18),
inset 0 1px 0 rgba(255, 245, 223, 0.03);
}
.cell { .cell {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
font-size: 16px; min-height: 58px;
padding: 15px 10px; padding: 0 16px;
color: #deb366; color: #e1c483;
border-bottom: 1px solid #594522; border-bottom: 1px solid rgba(223, 189, 120, 0.08);
background: #151617; background: rgba(19, 17, 15, 0.82);
&:active { &:active {
opacity: 0.8; opacity: 0.82;
} }
&:last-child { &:last-child {
border-bottom: none; border-bottom: none;
} }
.cell-left {
display: flex;
align-items: center;
gap: 12px;
min-width: 0;
} }
.cell-dot {
width: 10px;
height: 10px;
border-radius: 50%;
background: linear-gradient(180deg, #f2dfb6 0%, #dfbd78 52%, #bd8d39 100%);
box-shadow: 0 0 0 4px rgba(223, 189, 120, 0.06);
}
.lab {
font-size: 15px;
font-weight: 600;
color: #e0c283;
}
.icon {
flex-shrink: 0;
}
}
.logout { .logout {
width: 100%; width: 100%;
height: 48px; height: 50px;
line-height: 48px; line-height: 50px;
text-align: center; text-align: center;
font-size: 16px; font-size: 15px;
background: #e5b932; color: #231705;
font-weight: 600; background: linear-gradient(180deg, #f2dfb6 0%, #dfbd78 52%, #bd8d39 100%);
margin: 20px auto; font-weight: 700;
border-radius: 5px; letter-spacing: 0.3px;
margin: 18px auto 0;
border-radius: 16px;
box-shadow: 0 12px 24px rgba(125, 84, 22, 0.18),
inset 0 1px 0 rgba(255, 255, 255, 0.36);
&:active { &:active {
opacity: 0.8; opacity: 0.86;
} }
} }
} }
.lang-popup {
background: linear-gradient(180deg, #17130f 0%, #0d0b09 100%);
border-top: 1px solid rgba(223, 189, 120, 0.14);
border-radius: 20px 20px 0 0;
overflow: hidden;
}
.popup-header {
display: flex;
align-items: center;
justify-content: space-between;
height: 54px;
padding: 0 16px;
border-bottom: 1px solid rgba(223, 189, 120, 0.1);
background: rgba(21, 18, 15, 0.96);
}
.popup-title {
font-size: 16px;
font-weight: 700;
color: #f4dfae;
}
.popup-action {
min-width: 52px;
font-size: 14px;
line-height: 1;
&.cancel {
color: #a9956d;
text-align: left;
}
&.confirm {
color: #dfbd78;
text-align: right;
}
}
.popup-list {
max-height: 50vh;
padding: 10px 12px calc(18px + env(safe-area-inset-bottom));
box-sizing: border-box;
}
.popup-item {
min-height: 48px;
padding: 0 14px;
margin-bottom: 10px;
border-radius: 14px;
display: flex;
align-items: center;
justify-content: space-between;
color: #d9c6a0;
font-size: 15px;
font-weight: 600;
background: linear-gradient(
180deg,
rgba(25, 21, 18, 0.96) 0%,
rgba(17, 14, 12, 0.96) 100%
);
border: 1px solid rgba(223, 189, 120, 0.12);
box-shadow: inset 0 1px 0 rgba(255, 244, 220, 0.03);
&:last-child {
margin-bottom: 0;
}
&.active {
color: #231705;
background: linear-gradient(180deg, #f2dfb6 0%, #dfbd78 52%, #bd8d39 100%);
border-color: rgba(242, 223, 182, 0.45);
box-shadow: 0 10px 20px rgba(125, 84, 22, 0.16),
inset 0 1px 0 rgba(255, 255, 255, 0.28);
}
}
.logout-modal {
width: 620rpx;
padding: 34rpx 34rpx 28rpx;
background: linear-gradient(
180deg,
rgba(20, 16, 12, 0.98) 0%,
rgba(11, 9, 7, 0.98) 100%
);
border: 1rpx solid rgba(223, 189, 120, 0.18);
border-radius: 20rpx;
box-sizing: border-box;
box-shadow: 0 24rpx 60rpx rgba(0, 0, 0, 0.3);
}
.logout-title {
text-align: center;
font-size: 30rpx;
font-weight: 700;
color: #f4dfae;
}
.logout-text {
margin-top: 18rpx;
color: #d9c6a0;
font-size: 24rpx;
line-height: 1.7;
text-align: center;
}
.logout-actions {
display: flex;
gap: 16rpx;
margin-top: 28rpx;
}
.logout-btn {
flex: 1;
height: 78rpx;
border-radius: 14rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 26rpx;
font-weight: 700;
&.logout-btn-cancel {
color: #d9c6a0;
background: rgba(255, 255, 255, 0.03);
border: 1rpx solid rgba(223, 189, 120, 0.12);
}
&.logout-btn-confirm {
color: #231705;
background: linear-gradient(180deg, #f2dfb6 0%, #dfbd78 52%, #bd8d39 100%);
box-shadow: 0 10rpx 20rpx rgba(125, 84, 22, 0.16),
inset 0 1px 0 rgba(255, 255, 255, 0.28);
}
}
} }
</style> </style>
+333 -80
View File
@@ -2,7 +2,7 @@
<view class="withdraw"> <view class="withdraw">
<u-navbar <u-navbar
title="" title=""
bgColor="#000" bgColor="transparent"
:placeholder="true" :placeholder="true"
:fixed="true" :fixed="true"
leftIcon="" leftIcon=""
@@ -24,7 +24,7 @@
<u-input <u-input
readonly readonly
:placeholder="$lang.pleaseChoose" :placeholder="$lang.pleaseChoose"
color="#93979b" color="#f7ecd0"
v-model="type" v-model="type"
border="none" border="none"
> >
@@ -37,7 +37,7 @@
<u-icon <u-icon
slot="suffix" slot="suffix"
name="arrow-down-fill" name="arrow-down-fill"
color="#757272" color="#b9aa84"
size="16" size="16"
></u-icon> ></u-icon>
</u-input> </u-input>
@@ -57,10 +57,10 @@
<view class="lable">{{ $lang.walletAddress }}</view> <view class="lable">{{ $lang.walletAddress }}</view>
<u-input <u-input
class="input" class="input"
color="#947b2b" color="#f7ecd0"
clearable clearable
:placeholder="$lang.enterWithdrawalAddress" :placeholder="$lang.enterWithdrawalAddress"
border="surround" border="none"
v-model="address" v-model="address"
></u-input> ></u-input>
</view> </view>
@@ -68,10 +68,10 @@
<view class="lable">{{ $lang.amount }}</view> <view class="lable">{{ $lang.amount }}</view>
<u-input <u-input
class="input" class="input"
color="#947b2b" color="#f7ecd0"
clearable clearable
:placeholder="$lang.enterWithdrawalamount" :placeholder="$lang.enterWithdrawalamount"
border="surround" border="none"
v-model="money" v-model="money"
></u-input> ></u-input>
</view> </view>
@@ -94,16 +94,16 @@
</template> </template>
<!-- 越南银行卡提现 --> <!-- 越南银行卡提现 -->
<template v-if="userInfo.pay_channel == 'ALIN_VN'"> <template v-if="userInfo.pay_channel == 'ALIN_VN'">
<view class="picker-view" @click="showBankPicker = true"> <view class="picker-view" @click="openBankPicker">
<u-input <u-input
readonly readonly
:placeholder="$lang.pleaseChoose || '请选择'" :placeholder="$lang.pleaseChoose"
color="#93979b" color="#f7ecd0"
v-model="bankName" v-model="bankName"
border="none" border="none"
> >
<u--text <u--text
:text="$lang.bankName || '银行名称'" :text="$lang.bankName"
slot="prefix" slot="prefix"
margin="0 3px 0 0" margin="0 3px 0 0"
type="tips" type="tips"
@@ -111,41 +111,66 @@
<u-icon <u-icon
slot="suffix" slot="suffix"
name="arrow-down-fill" name="arrow-down-fill"
color="#757272" color="#b9aa84"
size="16" size="16"
></u-icon> ></u-icon>
</u-input> </u-input>
</view> </view>
<u-picker <u-popup
:title="$lang.bankName || '选择银行'"
closeOnClickOverlay
:show="showBankPicker" :show="showBankPicker"
:columns="bankColumns" mode="bottom"
:cancelText="$lang.cancel" round="20"
:confirmText="$lang.confirm" closeOnClickOverlay
@cancel="showBankPicker = false" @close="closeBankPicker"
@close="showBankPicker = false" >
@confirm="confirmBank" <view class="bank-picker-popup">
></u-picker> <view class="bank-picker-header">
<view class="bank-picker-action cancel" @click="closeBankPicker">{{
$lang.cancel
}}</view>
<view class="bank-picker-title">{{ $lang.bankName }}</view>
<view class="bank-picker-action confirm" @click="confirmBankSelection">{{
$lang.confirm
}}</view>
</view>
<scroll-view scroll-y class="bank-picker-list">
<view
class="bank-picker-item"
:class="{ active: tempBankName === item.name }"
v-for="(item, index) in bankList"
:key="index"
@click="selectBankOption(item)"
>
<text>{{ item.name }}</text>
<u-icon
v-if="tempBankName === item.name"
name="checkmark"
color="#231705"
size="16"
></u-icon>
</view>
</scroll-view>
</view>
</u-popup>
<view class="list"> <view class="list">
<view class="lable">{{ $lang.accountName || '账户姓名' }}</view> <view class="lable">{{ $lang.accountName }}</view>
<u-input <u-input
class="input" class="input"
color="#947b2b" color="#f7ecd0"
clearable clearable
:placeholder="$lang.enterAccountName || '请输入账户姓名'" :placeholder="$lang.enterAccountName"
border="surround" border="none"
v-model="accountName" v-model="accountName"
></u-input> ></u-input>
</view> </view>
<view class="list"> <view class="list">
<view class="lable">{{ $lang.accountNumber || '银行卡号' }}</view> <view class="lable">{{ $lang.accountNumber }}</view>
<u-input <u-input
class="input" class="input"
color="#947b2b" color="#f7ecd0"
clearable clearable
:placeholder="$lang.enterAccountNumber || '请输入银行卡号'" :placeholder="$lang.enterAccountNumber"
border="surround" border="none"
v-model="accountNumber" v-model="accountNumber"
></u-input> ></u-input>
</view> </view>
@@ -153,11 +178,11 @@
<view class="lable">{{ $lang.amount }}</view> <view class="lable">{{ $lang.amount }}</view>
<u-input <u-input
class="input" class="input"
color="#947b2b" color="#f7ecd0"
clearable clearable
type="number" type="number"
:placeholder="'Tối thiểu 1,000,000 VND'" :placeholder="'Tối thiểu 1,000,000 VND'"
border="surround" border="none"
v-model="money" v-model="money"
></u-input> ></u-input>
</view> </view>
@@ -191,6 +216,7 @@ export default {
// 越南银行卡提现 // 越南银行卡提现
bankName: "", bankName: "",
bankCode: "", bankCode: "",
tempBankName: "",
accountName: "", accountName: "",
accountNumber: "", accountNumber: "",
showBankPicker: false, showBankPicker: false,
@@ -280,31 +306,45 @@ export default {
console.log(err); console.log(err);
}); });
}, },
openBankPicker() {
this.tempBankName = this.bankName;
this.showBankPicker = true;
},
closeBankPicker() {
this.showBankPicker = false;
},
selectBankOption(item) {
this.tempBankName = item.name;
},
// 选择银行 // 选择银行
confirmBank(chose) { confirmBankSelection() {
this.bankName = chose.value[0]; if (!this.tempBankName) {
this.bankCode = chose.value[0]; this.showBankPicker = false;
return;
}
this.bankName = this.tempBankName;
this.bankCode = this.tempBankName;
this.showBankPicker = false; this.showBankPicker = false;
}, },
// 越南银行卡提现 // 越南银行卡提现
applyWithdrawBank() { applyWithdrawBank() {
if (!this.bankName) { if (!this.bankName) {
this.$toast({ this.$toast({
message: this.$lang.bankName || '请选择银行', message: this.$lang.bankName,
duration: 2000, duration: 2000,
}); });
return; return;
} }
if (!this.accountName) { if (!this.accountName) {
this.$toast({ this.$toast({
message: this.$lang.enterAccountName || '请输入账户姓名', message: this.$lang.enterAccountName,
duration: 2000, duration: 2000,
}); });
return; return;
} }
if (!this.accountNumber) { if (!this.accountNumber) {
this.$toast({ this.$toast({
message: this.$lang.enterAccountNumber || '请输入银行卡号', message: this.$lang.enterAccountNumber,
duration: 2000, duration: 2000,
}); });
return; return;
@@ -325,7 +365,7 @@ export default {
} }
if (Number(this.money) > Number(this.userInfo.money)) { if (Number(this.money) > Number(this.userInfo.money)) {
this.$toast({ this.$toast({
message: this.$lang.insufficientBalance || 'Số dư không đủ', message: this.$lang.insufficientBalance,
duration: 2000, duration: 2000,
}); });
return; return;
@@ -340,7 +380,7 @@ export default {
}; };
this.$toast({ this.$toast({
type: "loading", type: "loading",
message: this.$lang.submittingApplication || '提交中...', message: this.$lang.submittingApplication,
duration: 200000, duration: 200000,
}); });
this.$api this.$api
@@ -377,80 +417,293 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.withdraw { .withdraw {
background: #0b1520;
width: 100%; width: 100%;
min-height: 100vh; min-height: 100vh;
background: linear-gradient(180deg, #060505 0%, #0d0b09 100%);
color: #f7ecd0;
::v-deep .u-navbar {
background: rgba(0, 0, 0, 0.72) !important;
}
::v-deep .u-navbar__content {
background: transparent !important;
}
::v-deep .u-picker__view__column__item {
color: #f3e3b8 !important;
font-size: 16px !important;
font-weight: 600;
}
::v-deep .u-toolbar {
background: #15120f !important;
border-bottom-color: rgba(223, 189, 120, 0.12) !important;
}
::v-deep .u-toolbar__title {
color: #f4dfae !important;
}
::v-deep .u-toolbar__wrapper__cancel {
color: #a9956d !important;
}
::v-deep .u-toolbar__wrapper__confirm {
color: #dfbd78 !important;
}
.navbar-lab { .navbar-lab {
color: #fff; color: #fbf2de;
font-weight: 500; font-weight: 700;
font-size: 18px; font-size: 19px;
letter-spacing: 0.3px;
} }
.content { .content {
margin: 5px 5px; width: calc(100% - 24px);
border: 2px solid #947b2b; max-width: 760px;
background: #222222; margin: 10px auto 0;
padding: 18px 16px 22px;
box-sizing: border-box; box-sizing: border-box;
padding: 15px; border-radius: 24px;
background: linear-gradient(
180deg,
rgba(16, 13, 11, 0.96) 0%,
rgba(10, 8, 7, 0.96) 100%
);
border: 1px solid rgba(223, 189, 120, 0.18);
box-shadow: 0 18px 42px rgba(0, 0, 0, 0.24),
inset 0 1px 0 rgba(255, 245, 223, 0.03);
min-height: 400px; min-height: 400px;
.picker-view { .picker-view {
border: 2px solid #947b2b; min-height: 56px;
padding: 8px; margin-bottom: 14px;
border-radius: 5px; padding: 0 14px;
display: flex;
align-items: center;
background: linear-gradient(
180deg,
rgba(25, 21, 18, 0.96) 0%,
rgba(17, 14, 12, 0.96) 100%
);
border: 1px solid rgba(223, 189, 120, 0.14);
border-radius: 16px;
box-shadow: inset 0 1px 0 rgba(255, 244, 220, 0.03),
inset 0 -1px 0 rgba(0, 0, 0, 0.12);
::v-deep .u-input {
flex: 1;
}
::v-deep .u-input__content {
min-height: 54px;
padding: 0;
}
::v-deep .u-input__content__field-wrapper {
width: 100%;
}
::v-deep input {
color: #f7ecd0 !important;
font-size: 15px !important;
letter-spacing: 0.2px;
}
::v-deep input::placeholder {
color: rgba(245, 228, 184, 0.4) !important;
}
::v-deep .u-text__value {
color: #baa67f !important;
font-size: 13px !important;
}
} }
.list { .list {
margin-bottom: 14px;
padding: 14px;
border-radius: 16px;
background: linear-gradient(
180deg,
rgba(23, 19, 16, 0.92) 0%,
rgba(14, 12, 10, 0.92) 100%
);
border: 1px solid rgba(223, 189, 120, 0.1);
font-size: 14px; font-size: 14px;
text-align: center; text-align: center;
.lab { .lab {
color: #757272; color: #b9aa84;
margin: 10px 0; margin: 0 0 10px;
text-align: left;
font-size: 13px;
} }
.lable { .lable {
text-align: left; text-align: left;
color: #ddd; color: #d9c6a0;
margin-top: 20px; margin-top: 0;
font-size: 16px; font-size: 15px;
margin-bottom: 10px; margin-bottom: 10px;
font-weight: 600;
} }
.money { .money {
font-size: 16px; min-height: 52px;
padding: 0 16px;
display: flex;
align-items: center;
justify-content: center;
font-size: 17px;
margin-top: 0; margin-top: 0;
padding: 15px 0; color: #f1d392;
color: #e5b932; font-weight: 700;
} border-radius: 16px;
.btn { background: linear-gradient(
height: 30px; 180deg,
font-weight: 600; rgba(27, 22, 18, 0.96) 0%,
color: #0b1520 !important; rgba(17, 14, 12, 0.96) 100%
);
border: 1px solid rgba(223, 189, 120, 0.14);
box-shadow: inset 0 1px 0 rgba(255, 244, 220, 0.04);
} }
.type { .type {
width: 70px; min-width: 86px;
height: 35px; height: 36px;
background: #e5b932; padding: 0 16px;
border-radius: 40px; display: inline-flex;
align-items: center;
justify-content: center;
background: linear-gradient(180deg, #f2dfb6 0%, #dfbd78 52%, #bd8d39 100%);
border-radius: 999px;
text-align: center; text-align: center;
line-height: 35px; line-height: 36px;
font-weight: 600; font-weight: 700;
margin: 10px auto; color: #231705;
box-shadow: 0 8px 18px rgba(125, 84, 22, 0.16),
inset 0 1px 0 rgba(255, 255, 255, 0.28);
margin: 0 auto;
} }
.input { .input {
line-height: 30px; min-height: 48px;
height: 30px; padding: 0 12px;
background: rgba(255, 255, 255, 0.02);
border: 1px solid rgba(223, 189, 120, 0.12);
border-radius: 14px;
::v-deep .u-input__content {
min-height: 48px;
padding: 0;
}
::v-deep .u-input__content__field-wrapper {
width: 100%;
}
::v-deep input {
color: #f7ecd0 !important;
font-size: 15px !important;
letter-spacing: 0.2px;
}
::v-deep input::placeholder {
color: rgba(245, 228, 184, 0.4) !important;
}
} }
.button { .button {
line-height: 45px; height: 50px !important;
height: 45px; margin-top: 8px;
color: #0b1520 !important; margin-bottom: 2px;
font-weight: bold; border: none !important;
margin-top: 30px; border-radius: 16px !important;
margin-bottom: 10px; color: #231705 !important;
font-weight: 700;
letter-spacing: 0.3px;
box-shadow: 0 12px 24px rgba(125, 84, 22, 0.18),
inset 0 1px 0 rgba(255, 255, 255, 0.36);
} }
.tip { .tip {
color: #cc4c0e; color: #bca47a;
font-size: 13px; font-size: 13px;
text-align: justify; text-align: justify;
line-height: 1.6;
} }
} }
} }
.bank-picker-popup {
background: linear-gradient(180deg, #17130f 0%, #0d0b09 100%);
border-top: 1px solid rgba(223, 189, 120, 0.14);
border-radius: 20px 20px 0 0;
overflow: hidden;
}
.bank-picker-header {
display: flex;
align-items: center;
justify-content: space-between;
height: 54px;
padding: 0 16px;
border-bottom: 1px solid rgba(223, 189, 120, 0.1);
background: rgba(21, 18, 15, 0.96);
}
.bank-picker-title {
font-size: 16px;
font-weight: 700;
color: #f4dfae;
}
.bank-picker-action {
min-width: 52px;
font-size: 14px;
line-height: 1;
&.cancel {
color: #a9956d;
text-align: left;
}
&.confirm {
color: #dfbd78;
text-align: right;
}
}
.bank-picker-list {
max-height: 52vh;
padding: 10px 12px calc(18px + env(safe-area-inset-bottom));
box-sizing: border-box;
}
.bank-picker-item {
min-height: 48px;
padding: 0 14px;
margin-bottom: 10px;
border-radius: 14px;
display: flex;
align-items: center;
justify-content: space-between;
color: #d9c6a0;
font-size: 15px;
font-weight: 600;
background: linear-gradient(
180deg,
rgba(25, 21, 18, 0.96) 0%,
rgba(17, 14, 12, 0.96) 100%
);
border: 1px solid rgba(223, 189, 120, 0.12);
box-shadow: inset 0 1px 0 rgba(255, 244, 220, 0.03);
&:last-child {
margin-bottom: 0;
}
&.active {
color: #231705;
background: linear-gradient(180deg, #f2dfb6 0%, #dfbd78 52%, #bd8d39 100%);
border-color: rgba(242, 223, 182, 0.45);
box-shadow: 0 10px 20px rgba(125, 84, 22, 0.16),
inset 0 1px 0 rgba(255, 255, 255, 0.28);
}
}
} }
</style> </style>
+16
View File
@@ -57,6 +57,22 @@ let api = {
alinDeposit: async (params) => { alinDeposit: async (params) => {
return await ajax.post("/alin_online_order", params); return await ajax.post("/alin_online_order", params);
}, },
// 彩虹易支付充值(USDT TRC20 / 支付宝 / 微信 等,默认 usdt)
epayDeposit: async (params) => {
return await ajax.post("/epay_online_order", params);
},
// 易支付订单状态轮询(内嵌二维码支付用)
epayOrderStatus: async (params) => {
return await ajax.post("/epay_order_status", params);
},
// CCpay越南银行QR充值
ccpayDeposit: async (params) => {
return await ajax.post("/ccpay_online_order", params);
},
// CCpay订单状态轮询
ccpayOrderStatus: async (params) => {
return await ajax.post("/ccpay_order_status", params);
},
// 越南银行卡提现 // 越南银行卡提现
applyWithdrawBank: async (params) => { applyWithdrawBank: async (params) => {
return await ajax.post("/apply_withdraw_bank", params); return await ajax.post("/apply_withdraw_bank", params);
Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 21 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 21 KiB