427 lines
8.6 KiB
Vue
427 lines
8.6 KiB
Vue
<template>
|
||
<div class="platform-policy gradient-background-circles">
|
||
<!-- 使用 GeneralHeader 组件替换 MobileHeader -->
|
||
<GeneralHeader
|
||
:title="t('platform_policy')"
|
||
:showBack="true"
|
||
:showLanguageList="true"
|
||
color="black"
|
||
style="box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); z-index: 999"
|
||
/>
|
||
|
||
<div class="content">
|
||
<!-- 政策列表 -->
|
||
<div v-if="policies.length > 0" style="display: flex; flex-direction: column; gap: 16px">
|
||
<div
|
||
style="
|
||
background-color: white;
|
||
padding: 16px;
|
||
border-radius: 12px;
|
||
margin-bottom: 12px;
|
||
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
gap: 5px;
|
||
"
|
||
v-for="policy in policies"
|
||
:key="policy.level"
|
||
>
|
||
<div style="font-weight: 600; font-size: 1.2em">Lv.{{ policy.level }}</div>
|
||
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px">
|
||
<div
|
||
style="
|
||
width: max-content;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 5px;
|
||
"
|
||
>
|
||
<div style="font-weight: 600">{{ t('time') }} ({{ t('hours') }})</div>
|
||
<div style="font-weight: 500">{{ policy.onlineTime || 0 }}</div>
|
||
</div>
|
||
<div style="display: flex; flex-direction: column; align-items: center; gap: 5px">
|
||
<div style="font-weight: 600">{{ t('target') }}</div>
|
||
<div style="font-weight: 500">
|
||
{{ formatTarget(policy.target) }}
|
||
</div>
|
||
</div>
|
||
<div style="display: flex; justify-content: flex-end">
|
||
<div
|
||
style="
|
||
width: max-content;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 5px;
|
||
"
|
||
>
|
||
<div style="font-weight: 600">{{ t('host_salary') }}</div>
|
||
<div style="font-weight: 500">${{ policy.memberSalary || 0 }}</div>
|
||
</div>
|
||
</div>
|
||
<!-- 第二行 -->
|
||
<div
|
||
style="
|
||
width: max-content;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 5px;
|
||
"
|
||
>
|
||
<div style="font-weight: 600">{{ t('agent_salary') }}</div>
|
||
<div style="font-weight: 500">${{ policy.ownSalary || 0 }}</div>
|
||
</div>
|
||
<div style="display: flex; flex-direction: column; align-items: center; gap: 5px">
|
||
<div style="font-weight: 600">{{ t('total_salary') }}</div>
|
||
<div style="font-weight: 500">${{ policy.totalSalary || 0 }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 空状态 -->
|
||
<div v-else class="empty-state">
|
||
<div class="empty-icon">📋</div>
|
||
<p>{{ t('no_policy_data_available') }}</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, onMounted } from 'vue'
|
||
import { useI18n } from 'vue-i18n'
|
||
import GeneralHeader from '@/components/GeneralHeader.vue'
|
||
import { get } from '../utils/http.js'
|
||
import { getTeamId } from '@/utils/userStore.js'
|
||
import { setDocumentDirection } from '@/locales/i18n'
|
||
|
||
const { t, locale } = useI18n()
|
||
|
||
// 监听语言变化并设置文档方向
|
||
locale.value && setDocumentDirection(locale.value)
|
||
|
||
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: t('avatar_frame'),
|
||
RIDE: t('ride_effect'),
|
||
THEME: t('theme'),
|
||
BADGE: t('badge'),
|
||
GIFT: t('gift'),
|
||
}
|
||
return typeMap[type] || type
|
||
}
|
||
|
||
// 组件挂载时获取数据
|
||
onMounted(() => {
|
||
fetchTeamPolicy()
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
* {
|
||
color: rgba(0, 0, 0, 0.8);
|
||
font-family: 'SF Pro Text';
|
||
}
|
||
|
||
.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;
|
||
}
|
||
}
|
||
|
||
@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'] .policy-grid {
|
||
direction: rtl;
|
||
}
|
||
</style>
|