Files
Portal/pages/user/index.vue
T

648 lines
15 KiB
Vue

<template>
<view class="user">
<view class="hero">
<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="logo-shell">
<u--image
class="logo"
:showLoading="true"
:src="loginLogo"
width="42px"
height="42px"
mode="scaleToFill"
></u--image>
</view>
</view>
<view class="box">
<view class="text">{{ $lang.userBalance }}</view>
<view class="money-row">
<view class="money-icon"></view>
<view class="money">{{ money }}</view>
</view>
</view>
</view>
</view>
<view class="content">
<view class="section-title">{{ $lang.tip }}</view>
<view class="menu-panel">
<view
class="cell"
v-for="(item, index) in userMenu"
:key="index"
@click="goPath(item)"
>
<view class="cell-left">
<view class="cell-dot"></view>
<view class="lab">{{ item.name }}</view>
</view>
<u-icon
class="icon"
name="arrow-right"
color="#b9aa84"
size="16"
></u-icon>
</view>
</view>
<view class="logout" @tap="modalShow = true">{{ $lang.logout }}</view>
</view>
<u-popup
:show="show"
mode="bottom"
round="20"
closeOnClickOverlay
@close="closeLangPopup"
>
<view class="lang-popup">
<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>
</template>
<script>
import { mapState } from "vuex";
export default {
data() {
return {
show: false,
modalShow: false,
defaultIndex: [0],
tempLanguageKey: "cn",
langList: [
[
{ key: "en", name: "English" },
{ key: "tw", name: "繁體中文" },
{ key: "cn", name: "简体中文" },
{ key: "yn", name: "Việt nam" },
{ key: "kr", name: "한국어" },
{ key: "tl", name: "แบบไทย" },
{ key: "in", name: "Indonesia" },
],
],
money:0
};
},
computed: {
...mapState({
userInfo: (state) => state.app.userInfo,
language: (state) => state.app.language,
$lang: (state) => state.app.lang[state.app.language],
loginLogo: (state) => state.app.loginLogo,
userMenu: (state) => {
let list = [];
const lang = state.app.lang[state.app.language];
const userInfo = state.app.userInfo;
if (userInfo.pay_channel) {
list = lang.userMenu.filter(
(v) => v.id != 1
);
} else {
list = lang.userMenu.filter(
(v) => v.id != 1 && v.id != 2 && v.id != 4 && v.id != 5
);
}
return list;
},
}),
},
onLoad() {
this.langList[0].forEach((v, i) => {
if (v.key == this.language) {
this.defaultIndex = [i];
}
});
this.tempLanguageKey = this.language;
this.getUserMoneyData()
},
methods: {
confirm(item) {
this.$store.commit("app/updateLanguage", item.value[0].key);
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) {
if (item.id == 0) {
this.tempLanguageKey = this.language;
this.show = true;
} else if (item.id == 4 || item.id == 5 || item.id == 6) {
uni.switchTab({
url: item.path,
});
} else {
if (this.userInfo.is_sw == 1) {
this.$toast({
message: this.$lang.is_sw,
duration: 2000,
});
} else {
uni.navigateTo({
url: item.path,
});
}
}
},
confirmLogout() {
this.modalShow = false;
localStorage.removeItem("userInfo");
localStorage.removeItem("uni_id_token");
sessionStorage.clear();
const backSteps = window.history.length - 1;
window.history.go(-backSteps);
setTimeout(() => { window.location.replace("/"); }, 200);
},
getUserMoneyData() {
var that = this
const params = {
user_id: this.userInfo.id,
api_token: this.userInfo.api_token,
};
this.$api['getUserMoney'](params)
.then((res) => {
if (res.Success) {
that.money = parseFloat(res.Data.money).toFixed(2)
} else {
this.$toast({
message: res.Msg,
duration: 2000,
});
}
})
.catch((err) => {
console.log(err);
});
}
},
};
</script>
<style lang="scss" scoped>
.user {
width: 100%;
min-height: 100vh;
background: linear-gradient(180deg, #060505 0%, #0d0b09 100%);
color: #f7ecd0;
.hero {
padding: 14px 12px 0;
}
.card {
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 {
max-width: calc(100% - 82px);
padding: 8px 14px;
border-radius: 999px;
background: rgba(84, 64, 25, 0.38);
border: 1px solid rgba(113, 82, 24, 0.12);
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 {
z-index: 3;
opacity: 0.96;
border-radius: 14px;
}
.box {
position: absolute;
left: 50%;
top: 55%;
z-index: 3;
transform: translate(-50%, -50%);
width: calc(100% - 52px);
text-align: center;
color: #5d4312;
.text {
font-size: 16px;
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-size: 28px auto;
background-position: center;
}
.money {
padding: 0;
font-size: 30px;
font-weight: 700;
line-height: 1.1;
white-space: nowrap;
letter-spacing: 0.3px;
}
}
}
.content {
margin: 18px 12px 0;
.section-title {
margin: 0 2px 12px;
font-size: 13px;
color: #a9956d;
letter-spacing: 0.3px;
}
.menu-panel {
border-radius: 24px;
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 {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 58px;
padding: 0 16px;
color: #e1c483;
border-bottom: 1px solid rgba(223, 189, 120, 0.08);
background: rgba(19, 17, 15, 0.82);
&:active {
opacity: 0.82;
}
&:last-child {
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 {
width: 100%;
height: 50px;
line-height: 50px;
text-align: center;
font-size: 15px;
color: #231705;
background: linear-gradient(180deg, #f2dfb6 0%, #dfbd78 52%, #bd8d39 100%);
font-weight: 700;
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 {
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>