feat: 语言切换和布局配置

This commit is contained in:
hzj 2025-10-29 21:23:23 +08:00
parent 92b0e65a85
commit 620dca97b0
3 changed files with 336 additions and 180 deletions

View File

@ -16,7 +16,12 @@
<!-- 返回键 --> <!-- 返回键 -->
<div style="width: 10%; display: flex; align-items: center"> <div style="width: 10%; display: flex; align-items: center">
<button v-if="showBack" class="back-btn" @click="handleBack"> <button v-if="showBack" class="back-btn" @click="handleBack">
<img :src="backImg" alt="" style="width: 100%; aspect-ratio: 1/1; display: block" /> <img
class="flipImg"
:src="backImg"
alt=""
style="width: 100%; aspect-ratio: 1/1; display: block"
/>
</button> </button>
</div> </div>
@ -75,6 +80,7 @@
border-radius: 10px; border-radius: 10px;
margin-top: 5px; margin-top: 5px;
backdrop-filter: blur(8px); backdrop-filter: blur(8px);
z-index: 999999;
" "
v-show="visibleList" v-show="visibleList"
class="extraList" class="extraList"
@ -235,6 +241,10 @@ onMounted(() => {
transform: scale(0.9); transform: scale(0.9);
} }
[dir='rtl'] .flipImg {
transform: scaleX(-1);
}
@media screen and (max-width: 360px) { @media screen and (max-width: 360px) {
* { * {
font-size: 10px; font-size: 10px;

View File

@ -1,21 +1,7 @@
<template> <template>
<div style="position: relative; width: 100%"> <div style="position: relative; width: 100%">
<img :src="whiteBox" alt="" width="100%" style="display: block" /> <img class="flipImg" :src="whiteBox" alt="" width="100%" style="display: block" />
<div <div :style="{ backgroundImage }" class="status-background">
style="
width: 48%;
height: 46%;
border-radius: 12px;
margin: 2.5%;
position: absolute;
top: 0;
right: 0;
z-index: -1;
display: flex;
justify-content: flex-end;
"
:style="{ backgroundImage }"
>
<div <div
style="width: 50%; height: 50%; display: flex; justify-content: center; align-items: center" style="width: 50%; height: 50%; display: flex; justify-content: center; align-items: center"
> >
@ -28,12 +14,12 @@
> >
<div class="contentTime">{{ date }}</div> <div class="contentTime">{{ date }}</div>
<div style="display: grid; grid-template-columns: repeat(2, 1fr)"> <div style="display: grid; grid-template-columns: repeat(2, 1fr)">
<div class="contentText">Target: {{ target }}</div> <div class="contentText">{{ t('target') }}: {{ target }}</div>
<div class="contentText">Salary: ${{ salary }}</div> <div class="contentText">{{ t('salary') }}: ${{ salary }}</div>
</div> </div>
<div style="display: grid; grid-template-columns: repeat(2, 1fr)"> <div style="display: grid; grid-template-columns: repeat(2, 1fr)">
<div class="contentText">Time(Days):{{ days }}</div> <div class="contentText">{{ t('time_days') }}: {{ days }}</div>
<div class="contentText" v-if="income">Total income:{{ income }}</div> <div class="contentText" v-if="income">{{ t('total_income') }}: {{ income }}</div>
</div> </div>
</div> </div>
<div <div
@ -42,7 +28,7 @@
style="position: absolute; bottom: 8%; right: 4%; color: #bb92ff; font-weight: 500" style="position: absolute; bottom: 8%; right: 4%; color: #bb92ff; font-weight: 500"
@click="btMore" @click="btMore"
> >
More > {{ t('more') }} >
</div> </div>
</div> </div>
</div> </div>
@ -50,6 +36,9 @@
<script setup> <script setup>
import { computed, ref, watch } from 'vue' import { computed, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const whiteBox = new URL('../../assets/images/HostCenter/whitebox.png', import.meta.url).href const whiteBox = new URL('../../assets/images/HostCenter/whitebox.png', import.meta.url).href
const props = defineProps({ const props = defineProps({
@ -100,19 +89,19 @@ const fontSize = ref('')
watch( watch(
() => props.type, () => props.type,
(newType) => { (newType) => {
if (newType == 'In Progress') { if (newType == t('in_progress')) {
backgroundImage.value = 'linear-gradient(112deg, #759CFF 5.66%, #3D73FF 42.49%)' backgroundImage.value = 'linear-gradient(112deg, #759CFF 5.66%, #3D73FF 42.49%)'
fontSize.value = '0.9em' fontSize.value = '0.9em'
} }
if (newType == 'Pending') { if (newType == t('pending')) {
backgroundImage.value = 'linear-gradient(112deg, #FF7578 5.66%, #FF3D40 42.49%)' backgroundImage.value = 'linear-gradient(112deg, #FF7578 5.66%, #FF3D40 42.49%)'
fontSize.value = '1em' fontSize.value = '1em'
} }
if (newType == 'Completed') { if (newType == t('completed')) {
backgroundImage.value = 'linear-gradient(112deg, #75FF98 5.66%, #3DFF54 42.49%)' backgroundImage.value = 'linear-gradient(112deg, #75FF98 5.66%, #3DFF54 42.49%)'
fontSize.value = '1em' fontSize.value = '1em'
} }
if (newType == 'Out Of Account') { if (newType == t('out_of_account')) {
backgroundImage.value = 'linear-gradient(112deg, #BDBDBD 5.66%, #AEAEAE 42.49%)' backgroundImage.value = 'linear-gradient(112deg, #BDBDBD 5.66%, #AEAEAE 42.49%)'
fontSize.value = '0.7em' fontSize.value = '0.7em'
} }
@ -146,6 +135,43 @@ watch(
font-size: 1em; font-size: 1em;
} }
.flipImg {
width: 100%;
height: auto;
}
.status-background {
width: 48%;
height: 46%;
border-radius: 12px;
margin: 2.5%;
position: absolute;
top: 0;
right: 0;
z-index: -1;
display: flex;
justify-content: flex-end;
}
[dir='rtl'] .flipImg {
transform: scaleX(-1);
}
[dir='rtl'] .status-background {
right: auto;
left: 0;
}
/* RTL支持 */
[dir='rtl'] .contentText {
text-align: right;
}
[dir='rtl'] .moreBt {
right: auto;
left: 4%;
}
@media screen and (max-width: 360px) { @media screen and (max-width: 360px) {
* { * {
font-size: 10px; font-size: 10px;

View File

@ -1,41 +1,27 @@
<template> <template>
<div class="host-center gradient-background-circles"> <div class="host-center gradient-background-circles">
<!-- 顶部导航 --> <!-- 顶部导航 -->
<MobileHeader title="Host Center" :isHomePage="true" /> <GeneralHeader
:title="t('host_center')"
:isHomePage="true"
:showLanguageList="true"
color="black"
style="border-bottom: 1px solid #e5e5e5; z-index: 999"
@help="goToHelp"
/>
<!-- 主要内容 --> <!-- 主要内容 -->
<div class="content"> <div class="content">
<!-- 身份 --> <!-- 身份 -->
<div <div class="section-title">
style=" {{ t('my_account') }}
margin: 0 1%; <img src="../assets/icon/host.png" alt="" class="title-icon" />
margin-bottom: 12px;
font-weight: 600;
display: flex;
align-items: center;
font-size: 1.3em;
"
>
My account
<img src="../assets/icon/host.png" alt="" height="20px" style="margin-left: 10px" />
</div> </div>
<!-- 用户信息卡片 --> <!-- 用户信息卡片 -->
<div <div class="user-card">
style="
background-color: white;
padding: 16px;
border-radius: 12px;
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
margin: 0 1%;
margin-bottom: 12px;
display: flex;
flex-direction: column;
justify-content: space-between;
"
>
<!-- 头像信息 --> <!-- 头像信息 -->
<div style="display: flex; align-items: center; margin-bottom: 12px"> <div class="user-header">
<div class="avatar"> <div class="avatar">
<img <img
v-if="userInfo.userAvatar" v-if="userInfo.userAvatar"
@ -45,126 +31,64 @@
/> />
<span v-else class="avatar-placeholder">{{ getAvatarPlaceholder() }}</span> <span v-else class="avatar-placeholder">{{ getAvatarPlaceholder() }}</span>
</div> </div>
<div style="flex: 1"> <div class="user-info">
<div style="margin: 0 0 4px 0; font-size: 16px; font-weight: 600; color: #333"> <div class="user-name">{{ userInfo.userNickname || userInfo.name }}</div>
{{ userInfo.userNickname || userInfo.name }} <div class="user-id">ID: {{ userInfo.id }}</div>
</div>
<div style="margin: 0; font-size: 14px; color: #666">ID: {{ userInfo.id }}</div>
</div> </div>
<button <button class="edit-btn" @click="goToNotification">
style="width: 32px; height: 32px; border: none; background: none; font-size: 16px" <img src="../assets/icon/edit.png" alt="" class="edit-icon" />
@click="goToNotification"
>
<img src="../assets/icon/edit.png" alt="" width="70%" />
</button> </button>
</div> </div>
<!-- 我的薪资 --> <!-- 我的薪资 -->
<div> <div class="salary-section">
<div style="display: flex; justify-content: space-between; margin-bottom: 5px"> <div class="salary-header">
<div style="font-weight: 600">My salary:</div> <div class="salary-title">{{ t('my_salary') }}</div>
<button <button class="salary-link" @click="showDatePicker">
style=" {{ t('personal_salary') }}
font-weight: 500;
color: rgba(0, 0, 0, 0.4);
border: 0;
background-color: transparent;
"
@click="showDatePicker"
>
Personal Salary >
</button> </button>
</div> </div>
</div> </div>
<!-- 历史薪资 --> <!-- 历史薪资 -->
<div style="display: grid; grid-template-columns: repeat(2, 1fr)"> <div class="salary-grid">
<div> <div class="salary-item">
<div style="font-weight: 500; color: rgba(0, 0, 0, 0.4); margin-bottom: 5px"> <div class="salary-label">{{ t('history_salary') }}</div>
History Salary: <div class="salary-value">${{ salaryInfo.hostSalary }}</div>
</div>
<div style="font-weight: 600">${{ salaryInfo.hostSalary }}</div>
</div> </div>
<div> <div class="salary-item">
<div style="font-weight: 500; color: rgba(0, 0, 0, 0.4); margin-bottom: 5px"> <div class="salary-label">{{ t('current_salary') }}</div>
Current Salary: <div class="salary-value">${{ salaryInfo.currentSalary }}</div>
</div>
<div style="font-weight: 600">${{ salaryInfo.currentSalary }}</div>
</div> </div>
</div> </div>
</div> </div>
<!-- 今日任务 --> <!-- 今日任务 -->
<div <div class="task-card">
style=" <div class="task-header">
display: flex; <div class="task-title">{{ t('todays_task') }}</div>
flex-direction: column; <button class="policy-link" @click="goToPlatformPolicy">
justify-content: space-between; {{ t('platform_policy') }}
gap: 5px;
background-color: white;
padding: 3%;
border-radius: 12px;
margin: 0 1%;
margin-bottom: 12px;
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
"
>
<div style="display: flex; justify-content: space-between">
<div style="font-weight: 600">Today's Task:</div>
<button
style="
font-weight: 500;
color: rgba(0, 0, 0, 0.4);
border: 0;
background-color: transparent;
"
@click="goToPlatformPolicy"
>
Platform Policy >
</button> </button>
</div> </div>
<div style="display: flex"> <div class="task-content">
<div style="flex: 1"> <div class="task-item">
<div <div class="task-label">{{ t('host_type') }}</div>
style=" <div class="task-value">{{ taskInfo.anchorType }}</div>
width: max-content;
display: flex;
flex-direction: column;
align-items: center;
gap: 5px;
"
>
<div style="font-weight: 600">Anchor Type</div>
<div style="font-weight: 600">{{ taskInfo.anchorType }}</div>
</div>
</div> </div>
<div <div class="task-item">
style="flex: 1; display: flex; flex-direction: column; align-items: center; gap: 5px" <div class="task-label">{{ t('minutes') }}</div>
> <div class="task-value">{{ taskInfo.minutesProgress }}/{{ taskInfo.minutesTotal }}</div>
<div style="font-weight: 600">Minutes</div>
<div style="font-weight: 600">
{{ taskInfo.minutesProgress }}/{{ taskInfo.minutesTotal }}
</div>
</div> </div>
<div style="flex: 1; display: flex; justify-content: flex-end"> <div class="task-item">
<div <div class="task-label">{{ t('gift_task') }}</div>
style=" <div class="task-value">{{ taskInfo.giftTask }}</div>
width: max-content;
display: flex;
flex-direction: column;
align-items: center;
gap: 5px;
"
>
<div style="font-weight: 600">Gift Task</div>
<div style="font-weight: 600">{{ taskInfo.giftTask }}</div>
</div>
</div> </div>
</div> </div>
</div> </div>
<!-- 进度信息 --> <!-- 进度信息 -->
<workReportBox <workReportBox
style="margin-bottom: 10px" class="work-report"
:type="progressInfo.status" :type="progressInfo.status"
:date="progressInfo.date" :date="progressInfo.date"
:target="progressInfo.target" :target="progressInfo.target"
@ -175,13 +99,12 @@
<!-- 操作按钮 --> <!-- 操作按钮 -->
<div class="action-buttons"> <div class="action-buttons">
<button class="action-btn exchange-btn" @click="exchangeGoldCoins">Exchange</button> <button class="action-btn exchange-btn" @click="exchangeGoldCoins">
<button class="action-btn transfer-btn" @click="transfer">Transfer</button> {{ t('exchange') }}
<!-- </button>
<button class="action-btn withdraw-btn" @click="cashWithdraw"> <button class="action-btn transfer-btn" @click="transfer">
Cash<br>Withdraw {{ t('transfer') }}
</button> </button>
-->
</div> </div>
</div> </div>
</div> </div>
@ -189,8 +112,9 @@
<script setup> <script setup>
import { onMounted, reactive } from 'vue' import { onMounted, reactive } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import MobileHeader from '../components/MobileHeader.vue' import GeneralHeader from '@/components/GeneralHeader.vue'
import { usePageInitializationWithConfig } from '@/utils/pageConfig.js' import { usePageInitializationWithConfig } from '@/utils/pageConfig.js'
import { isInApp } from '@/utils/appBridge.js' import { isInApp } from '@/utils/appBridge.js'
import { getTeamMemberWork } from '@/api/teamBill.js' import { getTeamMemberWork } from '@/api/teamBill.js'
@ -198,9 +122,14 @@ import { getUserId } from '@/utils/userStore.js'
import { getUserIdentity } from '@/api/wallet.js' import { getUserIdentity } from '@/api/wallet.js'
import { clearSelectedPayee } from '../utils/payeeStore.js' import { clearSelectedPayee } from '../utils/payeeStore.js'
import workReportBox from '@/components/HostCenter/workReportBox.vue' import workReportBox from '@/components/HostCenter/workReportBox.vue'
import { setDocumentDirection } from '@/locales/i18n'
const { t, locale } = useI18n()
const router = useRouter() const router = useRouter()
//
locale.value && setDocumentDirection(locale.value)
// //
const progressInfo = reactive({ const progressInfo = reactive({
date: '', date: '',
@ -241,10 +170,10 @@ const fetchMemberWorkData = async () => {
// //
const formatStatus = (status) => { const formatStatus = (status) => {
const statusMap = { const statusMap = {
SETTLED: 'Completed', SETTLED: t('completed'),
UNPAID: 'In Progress', UNPAID: t('in_progress'),
HANG_UP: 'Out of Account', HANG_UP: t('out_of_account'),
PAY_OUT: 'Completed', PAY_OUT: t('completed'),
} }
return statusMap[status] || status return statusMap[status] || status
} }
@ -304,6 +233,11 @@ const goToNotification = () => {
router.push('/host-setting') router.push('/host-setting')
} }
const goToHelp = () => {
//
console.log('Help clicked')
}
const exchangeGoldCoins = () => { const exchangeGoldCoins = () => {
router.push('/exchange-gold-coins') router.push('/exchange-gold-coins')
} }
@ -331,20 +265,50 @@ onMounted(() => {
font-family: 'SF Pro Text'; font-family: 'SF Pro Text';
} }
.host-center {
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
width: 100vw;
min-height: 100vh;
background-color: #ffffff;
background-image: url(../assets/images/secondBg.png);
}
.content { .content {
padding: 16px; padding: 16px;
position: relative; position: relative;
z-index: 2; z-index: 2;
} }
@keyframes pulse { .section-title {
0%, margin: 0 1%;
100% { margin-bottom: 12px;
opacity: 1; font-weight: 600;
} display: flex;
50% { align-items: center;
opacity: 0.5; font-size: 1.3em;
} }
.title-icon {
height: 20px;
margin-left: 10px;
}
.user-card {
background-color: white;
padding: 16px;
border-radius: 12px;
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
margin: 0 1%;
margin-bottom: 12px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.user-header {
display: flex;
align-items: center;
margin-bottom: 12px;
} }
.avatar { .avatar {
@ -376,27 +340,132 @@ onMounted(() => {
font-weight: 600; font-weight: 600;
} }
/* 任务区域头部样式 */ .user-info {
.task-header { flex: 1;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
} }
.task-header h3 { .user-name {
margin: 0; margin: 0 0 4px 0;
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
color: #333; color: #333;
} }
/* 任务表格 */ .user-id {
.task-table { margin: 0;
border: 1px solid #e5e7eb; font-size: 14px;
border-radius: 8px; color: #666;
overflow: hidden; }
.edit-btn {
width: 32px;
height: 32px;
border: none;
background: none;
font-size: 16px;
}
.edit-icon {
width: 70%;
}
.salary-section {
margin-bottom: 10px;
}
.salary-header {
display: flex;
justify-content: space-between;
margin-bottom: 5px;
}
.salary-title {
font-weight: 600;
}
.salary-link {
font-weight: 500;
color: rgba(0, 0, 0, 0.4);
border: 0;
background-color: transparent;
cursor: pointer;
}
.salary-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
}
.salary-item {
display: flex;
flex-direction: column;
}
.salary-label {
font-weight: 500;
color: rgba(0, 0, 0, 0.4);
margin-bottom: 5px;
}
.salary-value {
font-weight: 600;
}
.task-card {
display: flex;
flex-direction: column;
justify-content: space-between;
gap: 5px;
background-color: white;
padding: 3%;
border-radius: 12px;
margin: 0 1%;
margin-bottom: 12px; margin-bottom: 12px;
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
}
.task-header {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
}
.task-title {
font-weight: 600;
}
.policy-link {
font-weight: 500;
color: rgba(0, 0, 0, 0.4);
border: 0;
background-color: transparent;
cursor: pointer;
}
.task-content {
display: flex;
justify-content: space-between;
}
.task-item {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
}
.task-label {
font-weight: 600;
margin-bottom: 5px;
}
.task-value {
font-weight: 600;
}
.work-report {
margin-bottom: 10px;
} }
/* 操作按钮 */ /* 操作按钮 */
@ -404,6 +473,7 @@ onMounted(() => {
display: grid; display: grid;
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
gap: 12px; gap: 12px;
margin: 0 1%;
} }
.action-btn { .action-btn {
@ -416,6 +486,7 @@ onMounted(() => {
line-height: 1.2; line-height: 1.2;
transition: all 0.2s; transition: all 0.2s;
width: 100%; width: 100%;
cursor: pointer;
} }
.action-btn:active { .action-btn:active {
@ -438,6 +509,16 @@ onMounted(() => {
color: white; color: white;
} }
@keyframes pulse {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
@media screen and (max-width: 360px) { @media screen and (max-width: 360px) {
* { * {
font-size: 10px; font-size: 10px;
@ -455,4 +536,43 @@ onMounted(() => {
font-size: 24px; font-size: 24px;
} }
} }
/* RTL支持 */
[dir='rtl'] .section-title {
text-align: right;
}
[dir='rtl'] .avatar {
margin-right: 0;
margin-left: 12px;
}
[dir='rtl'] .title-icon {
margin-left: 0;
margin-right: 10px;
}
[dir='rtl'] .user-header {
/* flex-direction: row-reverse; */
}
[dir='rtl'] .user-info {
text-align: right;
}
[dir='rtl'] .salary-header {
/* flex-direction: row-reverse; */
}
[dir='rtl'] .task-header {
/* flex-direction: row-reverse; */
}
[dir='rtl'] .task-content {
/* flex-direction: row-reverse; */
}
[dir='rtl'] .action-buttons {
grid-template-columns: 1fr 1fr;
}
</style> </style>