feat(主播申请页): UI更新

This commit is contained in:
hzj 2025-10-09 17:59:05 +08:00
parent 109cf3459f
commit 83f05c0d3a

View File

@ -1,16 +1,25 @@
<template>
<div class="apply-view">
<MobileHeader title="Apply to join the team" :showBack="false" :showHelp="true" @help="showHelp" />
<MobileHeader
title="Apply to join the team"
:showBack="false"
:showHelp="true"
@help="showHelp"
/>
<div class="content">
<!-- 申请说明 -->
<div class="reminder-section">
<h3>Reminder before application:</h3>
<p>Enter the ID of your agent, and you will become the host after the host apply is approved. After becoming an host, your income will be entrusted to your agent</p>
<p>
Enter the ID of your agent, and you will become the host after the host apply is approved.
After becoming an host, your income will be entrusted to your agent
</p>
</div>
<!-- 申请表单 -->
<div class="application-form">
<!-- 输入框 -->
<div class="input-group">
<label>Apply ID:</label>
<input
@ -21,11 +30,6 @@
/>
</div>
<!-- 错误提示 -->
<div v-if="errorMessage" class="error-message">
{{ errorMessage }}
</div>
<!-- 申请按钮 -->
<button
v-if="applyRecords.length === 0"
@ -35,46 +39,42 @@
>
{{ isLoading ? 'Applying...' : 'Apply' }}
</button>
<!-- 已有申请记录时的提示 -->
<div v-else class="existing-application">
<p>You already have an application in process, please wait for the review result.</p>
</div>
</div>
</div>
<!-- 申请记录 -->
<div v-if="applyRecords.length > 0" class="records-section">
<h3>Application Records</h3>
<div class="record-list">
<div v-for="record in applyRecords" :key="record.messageId" class="record-item">
<div class="record-info">
<div class="team-info">
<p class="team-label">Apply to join team:</p>
<p class="team-id">Team ID: {{ record.teamProfile?.id }}</p>
<p class="team-country">{{ record.teamProfile?.country?.countryName }} ({{ record.teamProfile?.country?.countryCode }})</p>
</div>
<div class="owner-info">
<p class="owner-label">Team owner:</p>
<div class="owner-profile">
<img v-if="record.ownUserProfile?.userAvatar" :src="record.ownUserProfile.userAvatar" class="owner-avatar" />
<div>
<p class="owner-name">{{ record.ownUserProfile?.userNickname }}</p>
<p class="owner-account">ID: {{ record.ownUserProfile?.account }}</p>
</div>
</div>
</div>
</div>
<div class="record-actions">
<span class="record-status status-pending">
Pending
</span>
<button
class="cancel-btn"
@click="handleCancelApply(record)"
>
Cancel
</button>
<h3>Application Records</h3>
<div class="record-list">
<div v-for="record in applyRecords" :key="record.messageId" class="record-item">
<div class="record-info">
<div class="team-info">
<p class="team-label">Apply to join team:</p>
<p class="team-id">Team ID: {{ record.teamProfile?.id }}</p>
<p class="team-country">
{{ record.teamProfile?.country?.countryName }} ({{
record.teamProfile?.country?.countryCode
}})
</p>
</div>
<div class="owner-info">
<p class="owner-label">Team owner:</p>
<div class="owner-profile">
<img
v-if="record.ownUserProfile?.userAvatar"
:src="record.ownUserProfile.userAvatar"
class="owner-avatar"
/>
<div>
<p class="owner-name">{{ record.ownUserProfile?.userNickname }}</p>
<p class="owner-account">ID: {{ record.ownUserProfile?.account }}</p>
</div>
</div>
</div>
</div>
<div class="record-actions">
<span class="record-status status-pending"> Pending </span>
<button class="cancel-btn" @click="handleCancelApply(record)">Cancel</button>
</div>
</div>
</div>
@ -95,10 +95,15 @@
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import MobileHeader from '../components/MobileHeader.vue'
import { sendTeamApplyJoin, getWaitApplyRecord, cancelApply, searchTeamByAccount } from '../api/wallet.js'
import {showError, showWarning, showInfo, showSuccess} from "@/utils/toast.js";
import { ApiError } from '@/utils/http.js';
import {usePageInitializationWithConfig} from "@/utils/pageConfig.js";
import {
sendTeamApplyJoin,
getWaitApplyRecord,
cancelApply,
searchTeamByAccount,
} from '../api/wallet.js'
import { showError, showWarning, showInfo, showSuccess } from '@/utils/toast.js'
import { ApiError } from '@/utils/http.js'
import { usePageInitializationWithConfig } from '@/utils/pageConfig.js'
const router = useRouter()
@ -123,10 +128,8 @@ const fetchApplyRecords = async () => {
}
}
//
const handleCancelApply = async (record) => {
try {
const response = await cancelApply(record.messageId)
if (response.status) {
@ -147,13 +150,22 @@ const handleCancelApply = async (record) => {
showError('Application record not found', 'Cancellation failed')
break
case 6003: //
showError('Application has been processed and cannot be canceled', 'Cancellation failed')
showError(
'Application has been processed and cannot be canceled',
'Cancellation failed'
)
break
default:
showError(error.errorMsg || error.message || 'Cancellation failed, please try again', 'Cancellation failed')
showError(
error.errorMsg || error.message || 'Cancellation failed, please try again',
'Cancellation failed'
)
}
} else {
showError('Network error, please check your connection and try again', 'Cancellation failed')
showError(
'Network error, please check your connection and try again',
'Cancellation failed'
)
}
} else {
showError('Cancellation failed, please try again')
@ -178,7 +190,6 @@ const searchTeamAccount = async (account) => {
} catch (error) {
searchedTeamInfo.value = null
showError(error.errorMsg)
}
}
@ -204,7 +215,7 @@ const submitApplication = async () => {
console.debug('📝 Step 2: Submitting application...')
const applicationData = {
teamId: teamId, // 使teamId
reason: 'JOIN'
reason: 'JOIN',
}
const response = await sendTeamApplyJoin(applicationData)
@ -222,7 +233,6 @@ const submitApplication = async () => {
if (error instanceof ApiError) {
if (error.type === 'business') {
showError('business error!' + error.errorMsg)
} else if (error.type === 'http') {
// HTTP
if (error.status === 406) {
@ -251,9 +261,9 @@ const closeHelp = () => {
//
const getStatusText = (status) => {
const statusMap = {
'WAIT': 'Pending',
'AGREE': 'Approved',
'REJECT': 'Rejected'
WAIT: 'Pending',
AGREE: 'Approved',
REJECT: 'Rejected',
}
return statusMap[status] || status
}
@ -261,9 +271,9 @@ const getStatusText = (status) => {
//
const getStatusClass = (status) => {
const classMap = {
'WAIT': 'status-pending',
'AGREE': 'status-approved',
'REJECT': 'status-rejected'
WAIT: 'status-pending',
AGREE: 'status-approved',
REJECT: 'status-rejected',
}
return classMap[status] || ''
}
@ -276,99 +286,109 @@ usePageInitializationWithConfig('APPLY', {
needsRouteGuard: true,
onDataLoaded: () => {
fetchApplyRecords()
}
},
})
</script>
<style scoped>
* {
color: rgba(0, 0, 0, 0.8);
font-family: 'SF Pro Text';
}
.apply-view {
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
width: 100vw;
min-height: 100vh;
background-color: #f5f5f5;
background-color: #ffffff;
background-image: url(../assets/images/secondBg.png);
}
.content {
padding: 20px 16px;
padding: 16px 10px;
}
.reminder-section {
background-color: white;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
}
.reminder-section h3 {
margin: 0 0 12px 0;
margin-bottom: 4px;
font-size: 16px;
font-weight: 600;
color: #333;
color: rgba(0, 0, 0, 0.4);
}
.reminder-section p {
margin: 0;
font-size: 14px;
line-height: 1.5;
color: #666;
font-weight: 510;
}
.application-form {
background-color: white;
padding: 20px;
border-radius: 8px;
display: flex;
gap: 8px;
}
.input-group {
margin-bottom: 20px;
width: 100%;
border-radius: 8px;
background: #fff;
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
white-space: nowrap;
display: flex;
align-items: center;
padding: 8px;
}
.input-group label {
display: block;
font-size: 16px;
font-weight: 600;
color: #333;
margin-bottom: 8px;
}
.agent-input {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
padding: 4px;
border: none;
border-radius: 6px;
font-size: 16px;
box-sizing: border-box;
color: rgba(0, 0, 0, 0.4);
}
.agent-input:focus {
outline: none;
border-color: #8B5CF6;
}
.agent-input::placeholder {
color: rgba(0, 0, 0, 0.4);
font-weight: 590;
}
.error-message {
margin-bottom: 16px;
padding: 12px;
background-color: #FEE2E2;
border: 1px solid #FECACA;
background-color: #fee2e2;
border: 1px solid #fecaca;
border-radius: 6px;
color: #DC2626;
color: #dc2626;
font-size: 14px;
}
.apply-btn {
width: 100%;
padding: 14px;
background-color: #8B5CF6;
padding: 4px 8px;
color: white;
border: none;
border-radius: 6px;
border-radius: 8px;
background: linear-gradient(135deg, #bb92ff 2.82%, #8b45ff 99.15%);
box-shadow: 0 0 4px 0 rgba(198, 112, 255, 0.25);
font-size: 16px;
font-weight: 600;
cursor: pointer;
}
.apply-btn:disabled {
background-color: #D1D5DB;
background-color: #d1d5db;
cursor: not-allowed;
}
@ -411,7 +431,7 @@ usePageInitializationWithConfig('APPLY', {
.close-btn {
width: 100%;
padding: 10px;
background-color: #8B5CF6;
background-color: #8b5cf6;
color: white;
border: none;
border-radius: 6px;
@ -461,7 +481,7 @@ usePageInitializationWithConfig('APPLY', {
.cancel-btn {
padding: 4px 8px;
background-color: #EF4444;
background-color: #ef4444;
color: white;
border: none;
border-radius: 4px;
@ -481,18 +501,21 @@ usePageInitializationWithConfig('APPLY', {
color: #666;
}
.team-info, .owner-info {
.team-info,
.owner-info {
margin-bottom: 12px;
}
.team-label, .owner-label {
.team-label,
.owner-label {
margin: 0 0 4px 0;
font-size: 14px;
font-weight: 600;
color: #333;
}
.team-id, .team-country {
.team-id,
.team-country {
margin: 0 0 2px 0;
font-size: 12px;
color: #666;
@ -532,24 +555,24 @@ usePageInitializationWithConfig('APPLY', {
}
.status-pending {
background-color: #FEF3C7;
color: #D97706;
background-color: #fef3c7;
color: #d97706;
}
.status-approved {
background-color: #D1FAE5;
background-color: #d1fae5;
color: #059669;
}
.status-rejected {
background-color: #FEE2E2;
color: #DC2626;
background-color: #fee2e2;
color: #dc2626;
}
.existing-application {
padding: 12px;
background-color: #FEF3C7;
border: 1px solid #F59E0B;
background-color: #fef3c7;
border: 1px solid #f59e0b;
border-radius: 6px;
text-align: center;
}
@ -557,6 +580,6 @@ usePageInitializationWithConfig('APPLY', {
.existing-application p {
margin: 0;
font-size: 14px;
color: #D97706;
color: #d97706;
}
</style>