380 lines
7.9 KiB
Vue
380 lines
7.9 KiB
Vue
<template>
|
||
<div class="platform-policy gradient-background-circles">
|
||
<MobileHeader title="Platform Policy" />
|
||
|
||
<div class="content">
|
||
<!-- 加载状态 -->
|
||
<div v-if="loading" class="loading-container">
|
||
<div class="loading-spinner"></div>
|
||
<p>Loading policy...</p>
|
||
</div>
|
||
|
||
<!-- 政策列表 -->
|
||
<div v-else-if="policies.length > 0" class="policy-list">
|
||
<div
|
||
v-for="policy in policies"
|
||
:key="policy.level"
|
||
class="policy-item"
|
||
>
|
||
<div class="policy-header">
|
||
<h3>Lv.{{ policy.level }}</h3>
|
||
</div>
|
||
|
||
<div class="policy-details">
|
||
<div class="policy-grid">
|
||
<div class="policy-cell">
|
||
<span class="cell-label">Time (hours)</span>
|
||
<span class="cell-value">{{ policy.onlineTime || 0 }}</span>
|
||
</div>
|
||
<div class="policy-cell">
|
||
<span class="cell-label">Target</span>
|
||
<span class="cell-value">{{ formatTarget(policy.target) }}</span>
|
||
</div>
|
||
<div class="policy-cell">
|
||
<span class="cell-label">Member Salary</span>
|
||
<span class="cell-value salary">${{ policy.memberSalary || 0 }}</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 只有角色是 OWN 时才显示额外的薪资信息 -->
|
||
<div v-if="role === 'OWN'" class="policy-grid bottom-row">
|
||
<div class="policy-cell">
|
||
<span class="cell-label">Owner Salary</span>
|
||
<span class="cell-value salary">${{ policy.ownSalary || 0 }}</span>
|
||
</div>
|
||
<div class="policy-cell">
|
||
<span class="cell-label">Total Salary</span>
|
||
<span class="cell-value salary">${{ policy.totalSalary || 0 }}</span>
|
||
</div>
|
||
<div class="policy-cell empty"></div>
|
||
</div>
|
||
|
||
<!-- 道具奖励区域 -->
|
||
<div v-if="policy.propsRewards && policy.propsRewards.length > 0" class="rewards-section">
|
||
<div class="rewards-divider"></div>
|
||
<div class="rewards-header">
|
||
<span class="rewards-title">Rewards:</span>
|
||
</div>
|
||
<div class="rewards-list">
|
||
<div
|
||
v-for="(reward, index) in policy.propsRewards"
|
||
:key="index"
|
||
class="reward-item"
|
||
>
|
||
<div class="reward-info">
|
||
<span class="reward-name">{{ reward.name }}</span>
|
||
<span class="reward-type">{{ formatRewardType(reward.type) }}</span>
|
||
</div>
|
||
<div class="reward-amount">${{ reward.amount || 0 }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 空状态 -->
|
||
<div v-else class="empty-state">
|
||
<div class="empty-icon">📋</div>
|
||
<p>No policy data available</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, onMounted } from 'vue'
|
||
import { useRouter } from 'vue-router'
|
||
import MobileHeader from '../components/MobileHeader.vue'
|
||
import { get } from '../utils/http.js'
|
||
import {getTeamId} from "@/utils/userStore.js";
|
||
|
||
const router = useRouter()
|
||
const loading = ref(false)
|
||
const policies = ref([])
|
||
const role = ref('')
|
||
|
||
// 获取团队政策数据
|
||
const fetchTeamPolicy = async () => {
|
||
try {
|
||
loading.value = true
|
||
|
||
// 从路由参数获取 teamId 和 role,如果没有则使用默认值
|
||
const teamId = getTeamId()
|
||
const response = await get(`/team/release/policy?id=${teamId}`)
|
||
|
||
if (response.status && response.body && response.body.policy) {
|
||
policies.value = response.body.policy || []
|
||
} else {
|
||
policies.value = []
|
||
}
|
||
} catch (error) {
|
||
console.error('Failed to fetch team policy:', error)
|
||
policies.value = []
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
// 格式化目标值显示
|
||
const formatTarget = (target) => {
|
||
if (!target) return '0'
|
||
const numTarget = parseFloat(target)
|
||
if (isNaN(numTarget)) return target
|
||
|
||
if (numTarget >= 1000000) {
|
||
return `${(numTarget / 1000000).toFixed(1)}M`
|
||
} else if (numTarget >= 1000) {
|
||
return `${(numTarget / 1000).toFixed(1)}K`
|
||
}
|
||
return numTarget.toString()
|
||
}
|
||
|
||
// 格式化奖励类型
|
||
const formatRewardType = (type) => {
|
||
const typeMap = {
|
||
'AVATAR_FRAME': 'Avatar Frame',
|
||
'RIDE': 'Ride Effect',
|
||
'THEME': 'Theme',
|
||
'BADGE': 'Badge',
|
||
'GIFT': 'Gift'
|
||
}
|
||
return typeMap[type] || type
|
||
}
|
||
|
||
// 组件挂载时获取数据
|
||
onMounted(() => {
|
||
fetchTeamPolicy()
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
.platform-policy {
|
||
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
|
||
min-height: 100vh;
|
||
background-color: #f1f2f3;
|
||
}
|
||
|
||
.content {
|
||
padding: 16px;
|
||
position: relative;
|
||
z-index: 2;
|
||
}
|
||
|
||
/* 加载状态 */
|
||
.loading-container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding: 60px 20px;
|
||
color: #666;
|
||
}
|
||
|
||
.loading-spinner {
|
||
width: 32px;
|
||
height: 32px;
|
||
border: 3px solid #f3f3f3;
|
||
border-top: 3px solid #8B5CF6;
|
||
border-radius: 50%;
|
||
animation: spin 1s linear infinite;
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
@keyframes spin {
|
||
0% { transform: rotate(0deg); }
|
||
100% { transform: rotate(360deg); }
|
||
}
|
||
|
||
/* 政策列表 */
|
||
.policy-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 16px;
|
||
}
|
||
|
||
.policy-item {
|
||
background-color: white;
|
||
border-radius: 12px;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||
overflow: hidden;
|
||
}
|
||
|
||
.policy-header {
|
||
padding: 16px 16px 8px 16px;
|
||
background-color: #f8f9fa;
|
||
border-bottom: 1px solid #e9ecef;
|
||
}
|
||
|
||
.policy-header h3 {
|
||
margin: 0;
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
color: #333;
|
||
}
|
||
|
||
.policy-details {
|
||
padding: 16px;
|
||
}
|
||
|
||
.policy-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr 1fr;
|
||
gap: 16px;
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.policy-grid.bottom-row {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.policy-cell {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
text-align: center;
|
||
padding: 12px 8px;
|
||
background-color: #f1f2f3;
|
||
border-radius: 8px;
|
||
}
|
||
|
||
.policy-cell.empty {
|
||
visibility: hidden;
|
||
}
|
||
|
||
.cell-label {
|
||
font-size: 12px;
|
||
color: #666;
|
||
margin-bottom: 8px;
|
||
line-height: 1.3;
|
||
}
|
||
|
||
.cell-value {
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
color: #333;
|
||
}
|
||
|
||
.cell-value.salary {
|
||
color: #FF6600;
|
||
font-weight: 700;
|
||
}
|
||
|
||
/* 奖励区域 */
|
||
.rewards-section {
|
||
margin-top: 16px;
|
||
padding-top: 16px;
|
||
border-top: 1px solid #e9ecef;
|
||
}
|
||
|
||
.rewards-divider {
|
||
height: 2px;
|
||
background: linear-gradient(90deg, #c2d9f0 0%, #03dbb8 100%);
|
||
margin-bottom: 12px;
|
||
border-radius: 1px;
|
||
}
|
||
|
||
.rewards-header {
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
.rewards-title {
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
color: #333;
|
||
}
|
||
|
||
.rewards-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
}
|
||
|
||
.reward-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 12px;
|
||
background: linear-gradient(135deg, #c2d9f0 0%, #03dbb8 100%);
|
||
border-radius: 8px;
|
||
color: white;
|
||
}
|
||
|
||
.reward-info {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 2px;
|
||
}
|
||
|
||
.reward-name {
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.reward-type {
|
||
font-size: 12px;
|
||
opacity: 0.9;
|
||
}
|
||
|
||
.reward-amount {
|
||
font-size: 14px;
|
||
font-weight: 700;
|
||
color: white;
|
||
}
|
||
|
||
/* 空状态 */
|
||
.empty-state {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 60px 20px;
|
||
color: #666;
|
||
text-align: center;
|
||
}
|
||
|
||
.empty-icon {
|
||
font-size: 48px;
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.empty-state p {
|
||
margin: 0;
|
||
font-size: 16px;
|
||
}
|
||
|
||
/* 响应式调整 */
|
||
@media (max-width: 480px) {
|
||
.policy-grid {
|
||
gap: 12px;
|
||
}
|
||
|
||
.cell-label {
|
||
font-size: 11px;
|
||
}
|
||
|
||
.cell-value {
|
||
font-size: 13px;
|
||
}
|
||
|
||
.policy-cell {
|
||
padding: 8px 4px;
|
||
}
|
||
|
||
.reward-item {
|
||
padding: 10px;
|
||
}
|
||
|
||
.reward-name {
|
||
font-size: 13px;
|
||
}
|
||
|
||
.reward-type {
|
||
font-size: 11px;
|
||
}
|
||
|
||
.reward-amount {
|
||
font-size: 13px;
|
||
}
|
||
}
|
||
</style>
|