test(cache): 修复CacheConfigTest边界值测试
- 修改 shouldVerifyCacheManager_withMaximumIntegerTtl 为 shouldVerifyCacheManager_withMaximumAllowedTtl - 使用正确的最大TTL值(10080分钟,7天)而不是 Integer.MAX_VALUE - 新增 shouldThrowException_whenTtlExceedsMaximum 测试验证边界检查 - 所有1266个测试用例通过 - 覆盖率: 指令81.89%, 行88.48%, 分支51.55% docs: 添加项目状态报告 - 生成 PROJECT_STATUS_REPORT.md 详细记录项目当前状态 - 包含质量指标、已完成功能、待办事项和技术债务
This commit is contained in:
166
frontend/h5/src/views/ShareView.vue
Normal file
166
frontend/h5/src/views/ShareView.vue
Normal file
@@ -0,0 +1,166 @@
|
||||
<template>
|
||||
<section class="mx-auto max-w-md px-4 pb-28 pt-6 space-y-6">
|
||||
<!-- Header -->
|
||||
<header class="flex items-center gap-3">
|
||||
<div class="w-12 h-12 rounded-2xl bg-gradient-to-br from-mosquito-primary to-mosquito-primary-light flex items-center justify-center text-white shadow-lg">
|
||||
<Icons name="share" class="w-6 h-6" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="mos-title text-2xl font-bold">分享推广</h1>
|
||||
<p class="text-sm text-mosquito-muted">生成专属链接,邀请好友参与</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Auth Warning -->
|
||||
<div v-if="!hasAuth" class="mos-card border-2 border-dashed border-mosquito-warning/30 bg-mosquito-warning/5 p-5">
|
||||
<div class="flex items-start gap-3">
|
||||
<div class="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-mosquito-warning/20 text-mosquito-warning">
|
||||
<Icons name="zap" class="w-5 h-5" />
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold text-mosquito-ink">请先配置鉴权信息</div>
|
||||
<div class="text-sm text-mosquito-muted mt-1">需要 API Key 与用户令牌才可生成链接与海报</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Share Link Card -->
|
||||
<div class="mos-card-gradient p-6 space-y-4">
|
||||
<div class="flex items-center gap-2 text-white/90">
|
||||
<Icons name="rocket" class="w-4 h-4" />
|
||||
<span class="text-xs font-bold uppercase tracking-wider">默认模板</span>
|
||||
<span class="text-xs opacity-75">· {{ activityLabel }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap items-center gap-3">
|
||||
<template v-if="hasAuth">
|
||||
<MosquitoShareButton :activity-id="activityId" :user-id="userId" />
|
||||
<button class="mos-btn mos-btn-accent !py-2 !px-4">
|
||||
<Icons name="copy" class="w-4 h-4" />
|
||||
复制链接
|
||||
</button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<button class="mos-btn mos-btn-accent !py-2 !px-4 opacity-50 cursor-not-allowed" disabled>
|
||||
<Icons name="copy" class="w-4 h-4" />
|
||||
复制链接
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<p class="text-xs text-white/70 flex items-center gap-1">
|
||||
<Icons name="check-circle" class="w-3 h-3" />
|
||||
分享按钮会自动复制链接,方便一键转发
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Poster Card -->
|
||||
<div class="mos-card p-5">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="w-8 h-8 rounded-lg bg-gradient-to-br from-mosquito-accent to-mosquito-accent-light flex items-center justify-center">
|
||||
<Icons name="gift" class="w-4 h-4 text-mosquito-ink" />
|
||||
</div>
|
||||
<h2 class="mos-title text-base font-bold">分享海报</h2>
|
||||
</div>
|
||||
<span class="mos-pill mos-pill-secondary">点击可重试</span>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-center bg-mosquito-bg rounded-2xl p-4">
|
||||
<MosquitoPosterCard
|
||||
v-if="hasAuth"
|
||||
:activity-id="activityId"
|
||||
:user-id="userId"
|
||||
template="default"
|
||||
width="280px"
|
||||
height="380px"
|
||||
/>
|
||||
<div v-else class="flex h-[380px] w-[280px] items-center justify-center rounded-xl border border-dashed border-mosquito-muted/40 text-sm text-mosquito-muted">
|
||||
配置鉴权后可预览海报
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Guide Card -->
|
||||
<div class="mos-card space-y-4 p-5">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="w-8 h-8 rounded-lg bg-mosquito-secondary/10 flex items-center justify-center text-mosquito-secondary-dark">
|
||||
<Icons name="target" class="w-4 h-4" />
|
||||
</div>
|
||||
<h3 class="mos-title text-base font-bold">分享指引</h3>
|
||||
</div>
|
||||
|
||||
<ul class="space-y-3">
|
||||
<li v-for="(step, index) in guideSteps" :key="index" class="flex gap-3 items-start">
|
||||
<span class="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-mosquito-primary text-white text-xs font-bold">
|
||||
{{ index + 1 }}
|
||||
</span>
|
||||
<span class="text-sm text-mosquito-ink-light">{{ step }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Error Message -->
|
||||
<div v-if="loadError" class="mos-card border-2 border-mosquito-error/30 bg-mosquito-error/5 p-4">
|
||||
<div class="flex items-center gap-2 text-mosquito-error">
|
||||
<ZapIcon class="w-4 h-4" />
|
||||
<span class="text-sm font-medium">{{ loadError }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import MosquitoShareButton from '../../../components/MosquitoShareButton.vue'
|
||||
import MosquitoPosterCard from '../../../components/MosquitoPosterCard.vue'
|
||||
import { MosquitoError, useMosquito } from '../../../index'
|
||||
import { getUserIdFromToken, parseUserId } from '../../../shared/auth'
|
||||
import Icons from '../components/Icons.vue'
|
||||
|
||||
type ActivitySummary = {
|
||||
id: number
|
||||
name: string
|
||||
}
|
||||
|
||||
const route = useRoute()
|
||||
const { getActivities } = useMosquito()
|
||||
const apiKey = import.meta.env.VITE_MOSQUITO_API_KEY
|
||||
const userToken = import.meta.env.VITE_MOSQUITO_USER_TOKEN
|
||||
const routeUserId = computed(() => parseUserId(route.query.userId ?? route.params.userId))
|
||||
const userId = computed(() => getUserIdFromToken(userToken) ?? routeUserId.value ?? 0)
|
||||
const activityId = ref(1)
|
||||
const activityLabel = computed(() => `活动 #${activityId.value}`)
|
||||
const loadError = ref('')
|
||||
const hasAuth = computed(() => Boolean(apiKey && userToken && userId.value))
|
||||
|
||||
const guideSteps = [
|
||||
'点击"分享给好友"生成专属链接',
|
||||
'发送给好友,完成注册后即可计入转化',
|
||||
'回到首页查看最新排行和奖励进度'
|
||||
]
|
||||
|
||||
const loadActivity = async () => {
|
||||
if (!hasAuth.value) {
|
||||
return
|
||||
}
|
||||
loadError.value = ''
|
||||
try {
|
||||
const list: ActivitySummary[] = await getActivities()
|
||||
if (list.length) {
|
||||
activityId.value = list[0].id
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof MosquitoError && error.statusCode === 401) {
|
||||
loadError.value = '鉴权失败:无法加载活动信息'
|
||||
return
|
||||
}
|
||||
loadError.value = '活动信息加载失败'
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadActivity()
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user