接口处理

This commit is contained in:
2025-12-30 06:50:01 -08:00
parent c7bfc2729c
commit 346ad0a4ec
7 changed files with 252 additions and 73 deletions
+67 -13
View File
@@ -5,7 +5,9 @@
<img src="../avatar.png" class="size-[60px]" alt="" />
<div class="flex h-full flex-col justify-center text-white">
<div class="text-xl font-semibold">{{ userInfo.email }}</div>
<div class="text-xs">到期时间 {{ userInfo.expireDate }}</div>
<div class="text-xs" :class="{ 'text-[#FF00B7]': expireDateInfo.highlight }">
{{ expireDateInfo.text }}
</div>
</div>
</div>
@@ -15,20 +17,25 @@
<div class="overflow-hidden rounded-4xl bg-[#A8FF53]">
<PlanCard :plans="plans" :currentPlanIndex="currentPlanIndex" @select="handlePlanSelect" />
<div class="pt-2">
<PaymentMethod :methods="payments" />
<PaymentMethod
:methods="payments"
:selectedPlan="selectedPlan"
@pay="(id: number | string) => $emit('pay', id)"
/>
</div>
</div>
<div class="pt-8 pb-[calc(50px+env(safe-area-inset-bottom))]">
<Button
<div class="px-6 pt-8 pb-[calc(50px+env(safe-area-inset-bottom))]">
<!-- <Button
variant="outline"
class="mb-[10px] h-[50px] w-full rounded-[32px] border-2 border-[#FF00B7] bg-transparent text-xl font-bold text-[#FF00B7] transition-all hover:bg-[#FF00FF]/90 active:scale-[0.98]"
>
注销账户
</Button>
</Button>-->
<Button
variant="outline"
@click="logout"
class="h-[50px] w-full rounded-[32px] border-2 border-white bg-transparent text-xl font-bold text-white transition-all hover:bg-white/90 active:scale-[0.98]"
>
退出登录
@@ -38,28 +45,75 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { computed } from 'vue'
import PlanCard from '@/components/user-center/PlanCard.vue'
import DeviceList from '@/components/user-center/DeviceList.vue'
import PaymentMethod from '@/components/user-center/PaymentMethod.vue'
import { Button } from '@/components/ui/button'
import { toast } from 'vue-sonner'
import { useRouter } from 'vue-router'
const router = useRouter()
const props = defineProps<{
devices: any[]
plans: any[]
payments: any[]
userInfo: { email: string; expireDate: string }
alreadySubscribed: any[]
userInfo: { email: string }
selectedPlanId: string
selectedPlan: any
}>()
// --- State ---
const selectedPlanId = ref('p2')
const selectedPayment = ref('alipay')
const emit = defineEmits(['select-plan', 'pay'])
// --- Handlers ---
const handlePlanSelect = (id: string) => {
selectedPlanId.value = id
emit('select-plan', id)
}
const currentPlanIndex = computed(() => {
return props.plans.findIndex((p) => p.id === props.selectedPlanId)
})
const expireDateInfo = computed(() => {
const first = props.alreadySubscribed[0]
let text = ''
let highlight = false
if (!first || !first.expireDate) {
text = '尚未购买套餐'
highlight = true
} else {
// 尝试解析日期,兼容多种格式
const dateStr = first.expireDate.replace(/ /g, 'T')
const expireDateTime = new Date(dateStr)
if (isNaN(expireDateTime.getTime())) {
text = '套餐信息无效'
} else if (expireDateTime < new Date()) {
const year = expireDateTime.getFullYear()
const month = String(expireDateTime.getMonth() + 1).padStart(2, '0')
const day = String(expireDateTime.getDate()).padStart(2, '0')
text = `已于 ${year}/${month}/${day} 到期`
highlight = true
} else {
const year = expireDateTime.getFullYear()
const month = String(expireDateTime.getMonth() + 1).padStart(2, '0')
const day = String(expireDateTime.getDate()).padStart(2, '0')
const hour = String(expireDateTime.getHours()).padStart(2, '0')
const minute = String(expireDateTime.getMinutes()).padStart(2, '0')
const second = String(expireDateTime.getSeconds()).padStart(2, '0')
text = `到期时间:${year}/${month}/${day} ${hour}:${minute}:${second}`
highlight = false
}
}
return { text, highlight }
})
function logout() {
router.push('/')
localStorage.removeItem('Authorization')
toast.success('退出成功')
}
const currentPlanIndex = ref(3)
</script>
<style scoped>
+105 -26
View File
@@ -21,17 +21,22 @@
<!-- Main Neon Green Card -->
<div class="px-[18px]">
<MobileLayout
:already-subscribed="alreadySubscribed"
:devices="devices"
:plans="plans"
:payments="payments"
:user-info="userSubInfo"
:selected-plan-id="selectedPlanId"
:selected-plan="activePlan"
@select-plan="handlePlanSelect"
@pay="handlePay"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { ref, computed } from 'vue'
import MobileLayout from './MobileLayout/index.vue'
import Logo from '@/pages/Home/logo.svg?component'
import MobileLogo from '@/pages/Home/mobile-logo.svg?component'
@@ -39,51 +44,125 @@ import request from '@/utils/request'
// --- State ---
const selectedPlanId = ref('p2')
const selectedPayment = ref('alipay')
const selectedPayment = ref('alipay') // This variable is no longer directly used for payment selection in the UI, but kept for potential future use or if other parts of the app rely on it.
const devices = ref([])
const plans = ref([])
const payments = ref([])
const devices = ref<any[]>([])
const plans = ref<any[]>([])
const payments = ref<any[]>([])
const alreadySubscribed = ref<any[]>([])
const userSubInfo = ref({
email: '',
expireDate: '',
})
// --- Data Mapping ---
const mapPlans = (apiList: any[]) => {
const flattened: any[] = []
let globalIndex = 0
apiList.forEach((item: any) => {
const unitDays = item.unit_time === 'Day' ? 1 : 365
if (!item.discount || item.discount.length === 0) {
flattened.push({
id: item.id.toString(),
planId: item.id,
quantity: 1,
days: unitDays,
price: (item.unit_price / 100).toFixed(2),
daily: (item.unit_price / 100 / unitDays).toFixed(2),
discount: '',
})
globalIndex++
} else {
item.discount.forEach((opt: any) => {
const totalDays = opt.quantity * unitDays
const ratioToPay = opt.discount === 0 || opt.discount === undefined ? 100 : opt.discount
const totalPrice = (item.unit_price / 100) * opt.quantity * (ratioToPay / 100)
flattened.push({
id: `${item.id}-${opt.quantity}`,
planId: item.id,
quantity: opt.quantity,
days: totalDays,
price: totalPrice.toFixed(2),
daily: (totalPrice / totalDays).toFixed(2),
discount:
globalIndex > 0 && ratioToPay < 100 ? `${Math.ceil(100 - ratioToPay)}% off` : '',
})
globalIndex++
})
}
})
return flattened
}
// --- Handlers ---
const activePlan = computed(() => {
return plans.value.find((p) => p.id === selectedPlanId.value)
})
const handlePlanSelect = (id: string) => {
selectedPlanId.value = id
}
const handlePay = (methodId: number | string) => {
const plan = plans.value.find((p) => p.id === selectedPlanId.value)
if (!plan) return
const already = alreadySubscribed.value.find((s: any) => s.subscribe_id === plan.planId)
const isRenewal = !!already
const api = isRenewal ? '/api/v1//public/order/renewal' : '/api/v1/public/order/purchase'
const params: any = {
subscribe_id: plan.planId,
quantity: plan.quantity,
payment: methodId,
}
if (isRenewal) {
params.user_subscribe_id = already.id
}
console.log(params)
request.post(api, params).then((res: any) => {
request
.post('/api/v1/public/portal/order/checkout', {
orderNo: res.order_no,
returnUrl: window.location.origin,
})
.then((checkoutRes: any) => {
if (checkoutRes.type === 'url' && checkoutRes.checkout_url) {
window.location.href = checkoutRes.checkout_url
}
})
})
}
function init() {
// 设备列表
// request.get('/public/user/devices').then((res: any) => {
// devices.value =
// res.list?.map((item: any) => ({
// id: item.id,
// name: item.user_agent || 'Unknown Device',
// type: item.user_agent?.toLowerCase().includes('android') ? 'mobile' : 'desktop',
// deviceId: item.id,
// })) || []
// })
// 用户信息
request.get('/public/user/info').then((res: any) => {
const emailInfo = res.auth_methods?.find((item: any) => item.auth_type === 'email')
// 用户信息 & 设备列表
request.get('/api/v1/public/user/info').then((res: any) => {
devices.value = res.user_devices
console.log(res.user_devices)
const emailInfo = res.auth_methods?.find((item: any) => item.auth_type === 'email')
if (emailInfo) {
userSubInfo.value.email = emailInfo.auth_identifier
}
})
// 订阅详情
request.get('/public/subscribe/list').then((res: any) => {
plans.value = res.list
console.log(plans.value)
// 已订阅列表
request.get('/api/v1/public/user/subscribe').then((res: any) => {
alreadySubscribed.value = res.list || []
})
// 订阅套餐列表
request.get('/api/v1/public/subscribe/list').then((res: any) => {
plans.value = mapPlans(res.list || [])
if (plans.value.length > 0) {
selectedPlanId.value = plans.value[0].id
}
})
// 获取支付方式
request.get('/public/payment/methods').then((res: any) => {
payments.value = res.list || []
request.get('/api/v1/public/payment/methods').then((res: any) => {
console.log(res)
payments.value = res.list?.filter((p: any) => p.platform !== 'apple_iap') || []
})
}
init()