564 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="host-center gradient-background-circles">
<!-- 顶部导航 -->
<GeneralHeader
:isHomePage="true"
:showLanguageList="true"
:title="t('host_center')"
color="black"
style="box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); z-index: 999"
@help="goToHelp"
/>
<!-- 主要内容 -->
<div class="content">
<!-- 身份 -->
<div class="section-title">
{{ t('my_account') }}
<img src="../../assets/icon/identity/host.png" alt="" class="title-icon" />
</div>
<!-- 用户信息卡片 -->
<div class="user-card">
<!-- 头像信息 -->
<div class="user-header">
<div class="avatar">
<img
v-if="userInfo.userAvatar"
:src="userInfo.userAvatar"
:alt="userInfo.name"
@error="handleImageError"
/>
<span v-else class="avatar-placeholder">{{ getAvatarPlaceholder() }}</span>
</div>
<div class="user-info">
<div class="user-name">
{{ userInfo.userNickname || userInfo.name }}
</div>
<div class="user-id">{{ t('user_id_prefix') }} {{ userInfo.id }}</div>
</div>
<button class="edit-btn" @click="goToNotification">
<img src="../../assets/icon/edit.png" alt="" class="edit-icon" />
</button>
</div>
<!-- 我的薪资 -->
<div class="salary-section">
<div class="salary-header">
<div class="salary-title">{{ t('my_salary') }}</div>
<button class="salary-link" @click="showDatePicker">
{{ t('personal_salary') }} >
</button>
</div>
</div>
<!-- 历史薪资 -->
<div class="salary-grid">
<div class="salary-item">
<div class="salary-label">{{ t('history_salary') }}</div>
<div class="salary-value">${{ historySalary.toFixed(2) }}</div>
</div>
<div class="salary-item">
<div class="salary-label">{{ t('current_salary') }}</div>
<div class="salary-value">${{ salaryInfo.currentSalary }}</div>
</div>
</div>
</div>
<!-- 今日任务 -->
<div class="task-card">
<div class="task-header">
<div class="task-title">{{ t('todays_task') }}</div>
<button class="policy-link" @click="goToPlatformPolicy">
{{ t('platform_policy') }} >
</button>
</div>
<div class="task-content">
<div class="task-item">
<div class="task-label">{{ t('host_type') }}</div>
<div class="task-value">{{ taskInfo.anchorType }}</div>
</div>
<div class="task-item">
<div class="task-label">{{ t('minutes') }}</div>
<div class="task-value">{{ taskInfo.minutesProgress }}/{{ taskInfo.minutesTotal }}</div>
</div>
<div class="task-item">
<div class="task-label">{{ t('gift_task') }}</div>
<div class="task-value">{{ taskInfo.giftTask }}</div>
</div>
</div>
</div>
<!-- 进度信息 -->
<workReportBox
class="work-report"
:type="progressInfo.status"
:date="progressInfo.date"
:target="progressInfo.target"
:salary="progressInfo.salary"
:income="progressInfo.income"
:days="progressInfo.timeDays"
></workReportBox>
<!-- 操作按钮 -->
<div class="action-buttons">
<button class="action-btn exchange-btn" @click="exchangeGoldCoins">
{{ t('exchange') }}
</button>
<button class="action-btn transfer-btn" @click="transfer">
{{ t('transfer') }}
</button>
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { setDocumentDirection } from '@/locales/i18n'
import { usePageInitializationWithConfig } from '@/utils/pageConfig.js'
import { getUserId } from '@/utils/userStore.js'
import { clearSelectedPayee } from '@/utils/payeeStore.js'
import { getTeamMemberWork } from '@/api/teamBill.js'
import { getUserIdentity } from '@/api/wallet.js'
import GeneralHeader from '@/components/GeneralHeader.vue'
import workReportBox from '@/components/workReportBox.vue'
const { t, locale } = useI18n()
const router = useRouter()
// 监听语言变化并设置文档方向
locale.value && setDocumentDirection(locale.value)
// 进度信息
const progressInfo = reactive({
date: '',
status: '',
target: '',
salary: '',
timeDays: '',
hostSalary: '',
agentSalary: '',
total: '',
})
const loadingProgressInfo = reactive({ value: false })
const historySalary = ref(0)
// 获取成员工作数据
const fetchMemberWorkData = async () => {
try {
loadingProgressInfo.value = true
const userId = getUserId()
if (!userId) {
console.warn('No user ID available')
return
}
const response = await getTeamMemberWork(userId)
if (response && response.status && response.body) {
const data = response.body
historySalary.value = data.historySalary
// 取第一条target数据最新的工作数据
if (data.targets && data.targets.length > 0) {
const latestTarget = data.targets[0]
// 格式化日期202508 -> 08/2025
const billBelong = latestTarget.billBelong.toString()
const year = billBelong.substring(0, 4)
const month = billBelong.substring(4, 6)
const day = billBelong.substring(6, 8)
// 格式化状态
const formatStatus = (status) => {
const statusMap = {
SETTLED: 'Completed',
UNPAID: 'In Progress',
HANG_UP: 'Out of account',
PAY_OUT: 'Completed',
}
return statusMap[status] || status
}
// 获取level值
const level =
latestTarget.target?.settlementResult?.level || latestTarget.target?.level || ''
const userIdentity = await getUserIdentity()
// 更新数据
Object.assign(progressInfo, {
date: `${year}.${month}.${day}`,
status: formatStatus(latestTarget.status),
target: level,
salary:
formatSalaryValue(
userIdentity.body?.agent
? (latestTarget.target?.settlementResult?.ownSalary || 0) +
(latestTarget.target?.settlementResult?.memberSalary || 0)
: userIdentity.body?.anchor
? latestTarget.target?.settlementResult?.memberSalary
: null
) || '-',
income: latestTarget.target?.settlementResult?.acceptGiftValue,
timeDays: latestTarget.target?.effectiveDay || '',
})
} else {
console.warn('No targets data available')
}
} else {
console.warn('No member work data available')
}
} catch (error) {
console.error('Failed to fetch member work data:', error)
} finally {
loadingProgressInfo.value = false
}
}
// 格式化薪资数值(与 TeamBillView 保持一致)
const formatSalaryValue = (value) => {
if (!value || value === '0' || value === 0) return '0.00'
const numValue = parseFloat(value)
return numValue.toFixed(2)
}
const showDatePicker = () => {
router.push('/history-salary')
}
const goToPlatformPolicy = () => {
router.push('/platform-policy?from=hostcenter')
}
const goToNotification = () => {
router.push('/host-setting')
}
const goToHelp = () => {
// 可以添加帮助页面的路由
console.log('Help clicked')
}
const exchangeGoldCoins = () => {
router.push('/exchange-gold-coins')
}
const transfer = () => {
router.push('/transfer')
}
const { appConnected, userInfo, salaryInfo, taskInfo, handleImageError, getAvatarPlaceholder } =
usePageInitializationWithConfig('HOST_CENTER', {
needsTeamInfo: true,
forceRefresh: true, // 强制刷新
onDataLoaded: () => {
fetchMemberWorkData() // 新增:获取成员工作数据
},
})
onMounted(() => {
clearSelectedPayee() //清除选中的收款人
})
</script>
<style scoped>
* {
color: rgba(0, 0, 0, 0.8);
}
.host-center {
width: 100vw;
min-height: 100vh;
background-color: #ffffff;
background-image: url(../../assets/images/secondBg.png);
}
.content {
padding: 16px;
position: relative;
z-index: 2;
}
.section-title {
margin: 0 1%;
margin-bottom: 12px;
font-weight: 600;
display: flex;
align-items: center;
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 {
width: 50px;
height: 50px;
border-radius: 25px;
background-color: #8b5cf6;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 20px;
font-weight: 600;
margin-right: 12px;
overflow: hidden;
position: relative;
}
.avatar img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 25px;
}
.avatar .avatar-placeholder {
color: white;
font-size: 20px;
font-weight: 600;
}
.user-info {
flex: 1;
min-width: 0;
}
.user-name {
margin: 0 0 4px 0;
font-weight: 600;
color: #333;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
}
.user-id {
margin: 0;
font-size: 0.9em;
color: #666;
}
.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;
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;
}
/* 操作按钮 */
.action-buttons {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
margin: 0 1%;
}
.action-btn {
padding: 14px 12px;
border: none;
border-radius: 12px;
font-size: 14px;
font-weight: 600;
text-align: center;
line-height: 1.2;
transition: all 0.2s;
width: 100%;
cursor: pointer;
}
.action-btn:active {
transform: scale(0.98);
}
.exchange-btn {
background: linear-gradient(135deg, #f1eca6 2.82%, #ffd22f 99.15%), #fff;
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
color: white;
}
.transfer-btn {
background: linear-gradient(135deg, #a6aaf1 2.82%, #592fff 99.15%), #fff;
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
color: white;
}
.withdraw-btn {
color: white;
}
@media screen and (max-width: 360px) {
* {
font-size: 10px;
}
}
@media screen and (min-width: 360px) {
* {
font-size: 12px;
}
}
@media screen and (min-width: 768px) {
* {
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-info {
text-align: right;
}
[dir='rtl'] .action-buttons {
grid-template-columns: 1fr 1fr;
}
</style>