Commit ca761014 by lijiabin

【需求 20331】 feat: 完成关于首次上线的活动相关的功能

parent dffcec96
<template>
<span @click="handleClick">
<slot></slot>
</span>
</template>
<script setup lang="ts">
import { useActivityStore } from '@/stores/activity'
import { RewardButtonEnum } from '@/constants'
const { pageKey } = defineProps<{
pageKey: RewardButtonEnum
}>()
const activityStore = useActivityStore()
// 调用接口让他跳出动画
const handleClick = () => {
console.log('点击了')
activityStore.triggerPageReward(pageKey)
}
</script>
<template>
<Teleport to="body">
<Transition name="reward-toast">
<div
v-if="activityStore.showRewardAnimation"
class="fixed inset-0 z-9999 flex items-center justify-center pointer-events-none"
>
<div class="relative flex flex-col items-center gap-4">
<!-- 光晕背景 -->
<div class="absolute inset--20 rounded-full bg-amber-400/10 blur-3xl animate-pulse" />
<!-- 碎片 +1 -->
<div class="reward-item reward-item-1">
<div
class="flex items-center gap-2.5 px-6 py-3 rounded-full bg-gradient-to-r from-indigo-500 to-purple-500 shadow-[0_4px_24px_rgba(99,102,241,0.5)]"
>
<span class="text-2xl">🧩</span>
<span class="text-white text-lg font-bold tracking-wide"
>碎片 +{{ activityStore.rewardText.fragment }}</span
>
</div>
</div>
<!-- 亚币 +2 -->
<div class="reward-item reward-item-2">
<div
class="flex items-center gap-2.5 px-6 py-3 rounded-full bg-gradient-to-r from-amber-400 to-orange-500 shadow-[0_4px_24px_rgba(245,158,11,0.5)]"
>
<span class="text-2xl">💰</span>
<span class="text-white text-lg font-bold tracking-wide"
>亚币 +{{ activityStore.rewardText.yabi }}</span
>
</div>
</div>
<!-- 星星粒子效果 -->
<div class="absolute inset--10">
<span v-for="i in 8" :key="i" class="particle" :style="getParticleStyle(i)" />
</div>
</div>
</div>
</Transition>
</Teleport>
</template>
<script setup lang="ts">
import { useActivityStore } from '@/stores'
const activityStore = useActivityStore()
const getParticleStyle = (index: number) => {
const angle = (index / 8) * 360
const delay = index * 0.1
return {
'--angle': `${angle}deg`,
'--delay': `${delay}s`,
}
}
</script>
<style scoped>
.reward-toast-enter-active {
transition: opacity 0.3s ease;
}
.reward-toast-leave-active {
transition: opacity 0.5s ease 1.8s;
}
.reward-toast-enter-from,
.reward-toast-leave-to {
opacity: 0;
}
.reward-item {
opacity: 0;
animation: rewardSlideUp 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}
.reward-item-1 {
animation-delay: 0.1s;
}
.reward-item-2 {
animation-delay: 0.35s;
}
@keyframes rewardSlideUp {
0% {
opacity: 0;
transform: translateY(30px) scale(0.7);
}
60% {
opacity: 1;
transform: translateY(-8px) scale(1.05);
}
100% {
opacity: 1;
transform: translateY(0) scale(1);
}
}
.particle {
position: absolute;
top: 50%;
left: 50%;
width: 6px;
height: 6px;
border-radius: 50%;
background: linear-gradient(135deg, #fbbf24, #a78bfa);
opacity: 0;
animation: particleBurst 1.2s ease-out var(--delay) forwards;
}
@keyframes particleBurst {
0% {
opacity: 1;
transform: translate(-50%, -50%) rotate(var(--angle)) translateX(0) scale(1);
}
70% {
opacity: 0.8;
transform: translate(-50%, -50%) rotate(var(--angle)) translateX(80px) scale(0.8);
}
100% {
opacity: 0;
transform: translate(-50%, -50%) rotate(var(--angle)) translateX(120px) scale(0);
}
}
</style>
<template>
<el-dialog
v-model="activityStore.showSurvey"
title=""
width="480px"
:close-on-click-modal="false"
class="satisfaction-survey-dialog"
@close="handleClose"
>
<div class="flex flex-col gap-5">
<!-- 头部 -->
<div class="text-center">
<div class="text-2xl mb-2">📋</div>
<h3 class="text-lg font-bold text-gray-800 mb-1">使用体验反馈</h3>
<p class="text-xs text-gray-400">您的反馈对我们非常重要,仅需1分钟</p>
</div>
<!-- Q1: 满意度评分 -->
<div class="flex flex-col gap-2">
<label class="text-sm font-medium text-gray-700">整体满意度</label>
<div class="flex items-center justify-center gap-2">
<button
v-for="star in 5"
:key="star"
class="text-2xl transition-all duration-200 cursor-pointer hover:scale-125 border-none bg-transparent p-1"
:class="star <= form.rating ? 'grayscale-0' : 'grayscale opacity-30'"
@click="form.rating = star"
>
</button>
</div>
<div class="text-center text-xs text-gray-400">
{{ ratingLabels[form.rating] || '请点击星星评分' }}
</div>
</div>
<!-- Q2: 最喜欢的功能 -->
<div class="flex flex-col gap-2">
<label class="text-sm font-medium text-gray-700">最喜欢的功能(可多选)</label>
<div class="flex flex-wrap gap-2">
<button
v-for="feat in featureOptions"
:key="feat.value"
class="px-3 py-1.5 rounded-full text-xs border transition-all duration-200 cursor-pointer"
:class="
form.favoriteFeatures.includes(feat.value)
? 'bg-indigo-50 border-indigo-300 text-indigo-600'
: 'bg-white border-gray-200 text-gray-500 hover:border-gray-300'
"
@click="toggleFeature(feat.value)"
>
{{ feat.label }}
</button>
</div>
</div>
<!-- Q3: 改进建议 -->
<div class="flex flex-col gap-2">
<label class="text-sm font-medium text-gray-700">改进建议(选填)</label>
<el-input
v-model="form.suggestion"
type="textarea"
:rows="3"
placeholder="说说您的想法,帮助我们做得更好..."
maxlength="300"
show-word-limit
/>
</div>
<!-- 提交按钮 -->
<div class="flex gap-3 mt-1">
<el-button class="flex-1" @click="handleClose">下次再说</el-button>
<el-button
type="primary"
class="flex-1 bg-gradient-to-r from-indigo-500 to-purple-500! border-none!"
:disabled="form.rating === 0"
@click="handleSubmit"
>
提交反馈
</el-button>
</div>
</div>
</el-dialog>
</template>
<script setup lang="ts">
import { useActivityStore } from '@/stores'
import { submitSurvey } from '@/api'
import { push } from 'notivue'
const activityStore = useActivityStore()
const form = reactive({
rating: 0,
favoriteFeatures: [] as string[],
suggestion: '',
})
const ratingLabels: Record<number, string> = {
1: '非常不满意',
2: '不太满意',
3: '一般',
4: '比较满意',
5: '非常满意',
}
const featureOptions = [
{ value: 'post', label: '帖子/实践' },
{ value: 'video', label: '视频' },
{ value: 'question', label: '问吧' },
{ value: 'sign', label: '签到/任务' },
{ value: 'store', label: '积分商城' },
{ value: 'auction', label: '限时竞拍' },
{ value: 'lottery', label: '每日抽奖' },
{ value: 'column', label: '专栏/专访' },
]
const toggleFeature = (value: string) => {
const idx = form.favoriteFeatures.indexOf(value)
if (idx >= 0) {
form.favoriteFeatures.splice(idx, 1)
} else {
form.favoriteFeatures.push(value)
}
}
const handleSubmit = async () => {
if (form.rating === 0) return
try {
await submitSurvey({
rating: form.rating,
favoriteFeatures: form.favoriteFeatures,
suggestion: form.suggestion,
})
push.success('感谢您的反馈!')
activityStore.markSurveySubmitted()
} catch {
push.success('感谢您的反馈!')
activityStore.markSurveySubmitted()
}
}
const handleClose = () => {
activityStore.showSurvey = false
}
</script>
<style>
.satisfaction-survey-dialog .el-dialog__header {
display: none;
}
.satisfaction-survey-dialog .el-dialog__body {
padding: 24px;
}
</style>
import type { SetupContext } from 'vue' import type { SetupContext } from 'vue'
import RewardButton from '@/components/common/RewardButton/index.vue'
import { RewardButtonEnum } from '@/constants'
type TypeOfValue = string | number type TypeOfValue = string | number
interface TabsProps<T> { interface TabsProps<T> {
tabs: { tabs: {
label: string label: string
value: T value: T
pageKey?: RewardButtonEnum
}[] }[]
modelValue: T modelValue: T
} }
...@@ -25,7 +28,9 @@ export default function Tabs<T extends TypeOfValue>( ...@@ -25,7 +28,9 @@ export default function Tabs<T extends TypeOfValue>(
{ tabs, modelValue }: TabsProps<T>, { tabs, modelValue }: TabsProps<T>,
{ emit }: SetupContext<TabsEmits<T>>, { emit }: SetupContext<TabsEmits<T>>,
) { ) {
return tabs.map((tab) => ( return tabs.map((tab) =>
tab.pageKey ? (
<RewardButton pageKey={tab.pageKey}>
<div <div
key={tab.value} key={tab.value}
class={[ class={[
...@@ -41,5 +46,23 @@ export default function Tabs<T extends TypeOfValue>( ...@@ -41,5 +46,23 @@ export default function Tabs<T extends TypeOfValue>(
> >
{tab.label} {tab.label}
</div> </div>
)) </RewardButton>
) : (
<div
key={tab.value}
class={[
BASE_TAB_CALASSES,
{
[ACTIVE_TAB_CLASSES]: modelValue === tab.value,
},
]}
onClick={() => {
emit('update:modelValue', tab.value)
emit('change', tab.value)
}}
>
{tab.label}
</div>
),
)
} }
<template> <template>
<transition name="online-time">
<Draggable <Draggable
v-show="showOnlineTime" v-show="showOnlineTime"
:initial-value="{ x: x, y: y }" :initial-value="{ x: x, y: y }"
...@@ -37,6 +38,7 @@ ...@@ -37,6 +38,7 @@
</div> </div>
</div> </div>
</Draggable> </Draggable>
</transition>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
...@@ -86,3 +88,15 @@ onUnmounted(() => { ...@@ -86,3 +88,15 @@ onUnmounted(() => {
clearInterval(timer2) clearInterval(timer2)
}) })
</script> </script>
<style lang="scss" scoped>
.online-time-enter-from,
.online-time-leave-to {
opacity: 0;
transform: translateY(10px);
}
.online-time-enter-active,
.online-time-leave-active {
transition: all 0.3s ease;
}
</style>
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
</div> </div>
<!-- 右侧菜单 --> <!-- 右侧菜单 -->
<div class="flex items-center gap-1 flex-shrink-0 sm:gap-2 lg:gap-4"> <div class="flex items-center gap-1 flex-shrink-0 sm:gap-2 lg:gap-4">
<RewardButton :pageKey="RewardButtonEnum.USER_PAGE">
<div <div
class="group h-80% flex items-center cursor-pointer px-2 py-1 sm:px-3 sm:py-2 rounded-lg transition-all duration-200 hover:shadow-lg hover:bg-white/60" class="group h-80% flex items-center cursor-pointer px-2 py-1 sm:px-3 sm:py-2 rounded-lg transition-all duration-200 hover:shadow-lg hover:bg-white/60"
@click="router.push('/userPage')" @click="router.push('/userPage')"
...@@ -52,6 +53,8 @@ ...@@ -52,6 +53,8 @@
个人中心 个人中心
</span> </span>
</div> </div>
</RewardButton>
<div <div
class="group flex items-center cursor-pointer px-2 py-1 sm:px-3 sm:py-2 rounded-lg transition-all duration-200 hover:shadow-lg hover:bg-white/60" class="group flex items-center cursor-pointer px-2 py-1 sm:px-3 sm:py-2 rounded-lg transition-all duration-200 hover:shadow-lg hover:bg-white/60"
@click="router.push('/auction')" @click="router.push('/auction')"
...@@ -89,20 +92,42 @@ ...@@ -89,20 +92,42 @@
</button> </button>
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item :command="ArticleTypeEnum.POST">帖子</el-dropdown-item> <el-dropdown-item :command="ArticleTypeEnum.POST">
<el-dropdown-item :command="ArticleTypeEnum.PRACTICE">实践</el-dropdown-item> <RewardButton :pageKey="RewardButtonEnum.PUBLISH_LONG_ARTICLE">
<el-dropdown-item :command="ArticleTypeEnum.VIDEO">视频</el-dropdown-item> 帖子
<el-dropdown-item :command="ArticleTypeEnum.QUESTION">问吧</el-dropdown-item> </RewardButton>
</el-dropdown-item>
<el-dropdown-item :command="ArticleTypeEnum.PRACTICE">
<RewardButton :pageKey="RewardButtonEnum.PUBLISH_LONG_ARTICLE">
实践
</RewardButton>
</el-dropdown-item>
<el-dropdown-item :command="ArticleTypeEnum.VIDEO">
<RewardButton :pageKey="RewardButtonEnum.PUBLISH_LONG_ARTICLE">
视频
</RewardButton>
</el-dropdown-item>
<el-dropdown-item :command="ArticleTypeEnum.QUESTION">
<RewardButton :pageKey="RewardButtonEnum.PUBLISH_LONG_ARTICLE">
问吧
</RewardButton>
</el-dropdown-item>
<el-dropdown-item <el-dropdown-item
v-if="userInfo.isOfficialAccount || userInfo.isAdmin" v-if="userInfo.isOfficialAccount || userInfo.isAdmin"
:command="ArticleTypeEnum.COLUMN" :command="ArticleTypeEnum.COLUMN"
>专栏</el-dropdown-item
> >
<RewardButton :pageKey="RewardButtonEnum.PUBLISH_LONG_ARTICLE">
专栏
</RewardButton>
</el-dropdown-item>
<el-dropdown-item <el-dropdown-item
v-if="userInfo.isOfficialAccount || userInfo.isAdmin" v-if="userInfo.isOfficialAccount || userInfo.isAdmin"
:command="ArticleTypeEnum.INTERVIEW" :command="ArticleTypeEnum.INTERVIEW"
>专访</el-dropdown-item
> >
<RewardButton :pageKey="RewardButtonEnum.PUBLISH_LONG_ARTICLE">
专访
</RewardButton>
</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</template> </template>
</el-dropdown> </el-dropdown>
...@@ -110,7 +135,10 @@ ...@@ -110,7 +135,10 @@
</div> </div>
</div> </div>
<div class="flex-1 w-full flex items-center justify-center"> <div class="flex-1 w-full flex items-center justify-center">
<div class="container max-h-none transition-all duration-300 min-h-[calc(100vh-96px)]"> <div
class="container max-h-none transition-all duration-300 min-h-[calc(100vh-96px)]"
:class="{ 'px-10!': !isHomePage }"
>
<router-view v-slot="{ Component, route }"> <router-view v-slot="{ Component, route }">
<transition name="fade" mode="out-in"> <transition name="fade" mode="out-in">
<!-- 注释不能放到keep-alive下面 route是最终的路由信息 Component是当前n级路由的组件 二级路由 homePage videoDetail --> <!-- 注释不能放到keep-alive下面 route是最终的路由信息 Component是当前n级路由的组件 二级路由 homePage videoDetail -->
...@@ -123,27 +151,37 @@ ...@@ -123,27 +151,37 @@
</div> </div>
</div> </div>
<OnlineTime v-if="showOnlineTime" /> <OnlineTime v-if="showOnlineTime" />
<PublishDialog ref="PublishDialogRef" /> <!-- 活动相关全局组件 -->
<CgGuide />
<RewardToast />
<!-- <SatisfactionSurvey /> -->
</template> </template>
<script setup lang="tsx" name="CultureLayout"> <script setup lang="tsx" name="CultureLayout">
import { Search } from '@element-plus/icons-vue' import { Search } from '@element-plus/icons-vue'
import OnlineTime from './components/onlineTime.vue' import OnlineTime from './components/onlineTime.vue'
import type { RouteLocationNormalizedLoadedGeneric } from 'vue-router' import type { RouteLocationNormalizedLoadedGeneric } from 'vue-router'
import PublishDialog from './components/publishDialog.vue' import CgGuide from '@/components/common/CgGuide/index.vue'
import RewardToast from '@/components/common/RewardToast/index.vue'
// import SatisfactionSurvey from '@/components/common/SatisfactionSurvey/index.vue'
import { ArticleTypeEnum } from '@/constants' import { ArticleTypeEnum } from '@/constants'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useUserStore } from '@/stores/user' import { useUserStore } from '@/stores/user'
import { useActivityStore } from '@/stores/activity'
import RewardButton from '@/components/common/RewardButton/index.vue'
import { RewardButtonEnum } from '@/constants'
const userStore = useUserStore() const userStore = useUserStore()
const activityStore = useActivityStore()
const { userInfo } = storeToRefs(userStore) const { userInfo } = storeToRefs(userStore)
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
const isHomePage = computed(() => route.path.includes('/homePage'))
const search = ref('') const search = ref('')
const PublishDialogRef = useTemplateRef<InstanceType<typeof PublishDialog>>('PublishDialogRef')
console.log(route)
const showSearchInupt = computed(() => route.path !== '/searchPage') const showSearchInupt = computed(() => route.path !== '/searchPage')
// 获取二级路由的 key // 获取二级路由的 key
const getSecondLevelKey = (route: RouteLocationNormalizedLoadedGeneric) => { const getSecondLevelKey = (route: RouteLocationNormalizedLoadedGeneric) => {
...@@ -174,12 +212,17 @@ const handlePost = async (type: ArticleTypeEnum) => { ...@@ -174,12 +212,17 @@ const handlePost = async (type: ArticleTypeEnum) => {
router.push(`/publishLongArticle/${type}`) router.push(`/publishLongArticle/${type}`)
} else if (type === ArticleTypeEnum.PRACTICE) { } else if (type === ArticleTypeEnum.PRACTICE) {
router.push(`/publishLongArticle/${type}`) router.push(`/publishLongArticle/${type}`)
// PublishDialogRef.value?.open(type)
} else { } else {
router.push(`/publishLongArticle/${type}`) router.push(`/publishLongArticle/${type}`)
} }
} }
const isDropdownHover = ref(false) const isDropdownHover = ref(false)
// 首页触发CG相关引导
onMounted(() => {
console.log(1222)
activityStore.triggerCgGuide()
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.layout-culture { .layout-culture {
......
import { defineStore } from 'pinia'
import { getUserLaunchCampaignStatus, markUserGuide, markUserClickedRewardButton } from '@/api'
import dayjs from 'dayjs'
import { RewardButtonEnum } from '@/constants'
import { useYaBiStore } from './yabi'
const STORAGE_KEYS = {
CG_WATCHED: 'activity_cg_watched',
CLAIMED_PAGES: 'activity_claimed_pages',
CLICK_COUNT: 'activity_click_count',
SURVEY_SUBMITTED: 'activity_survey_submitted',
} as const
export const useActivityStore = defineStore('activity', () => {
// ========== CG 引导 ==========
const isLaunchCampaignTime = ref(false)
// 2026.3.16 00:00:00 - 2026.3.22 23:59:59
const launchCampaignRange: [number, number] = [
dayjs('2026-03-16 00:00:00').unix(),
dayjs('2026-03-22 23:59:59').unix(),
]
// cg动画引导是否显示
const showCgGuide = ref(false)
// 普通的动画引导
const showCommonGuide = ref(false)
const markUserGuideWatched = async (key: 'isView' | 'isViewGuide') => {
await markUserGuide(key)
}
const triggerCgGuide = async () => {
const { data } = await getUserLaunchCampaignStatus()
// 用户是否观看过CG
if (!data.isView) {
showCgGuide.value = true
}
if (!data.isViewGuide) {
showCommonGuide.value = true
}
// 是否在活动期间
if (data.currentTime >= launchCampaignRange[0] && data.currentTime <= launchCampaignRange[1]) {
isLaunchCampaignTime.value = true
}
}
// ========== 碎片奖励动画 ==========
const showRewardAnimation = ref(false)
const rewardText = ref({ fragment: 1, yabi: 2 })
const triggerPageReward = async (pageKey: RewardButtonEnum) => {
const { data } = await markUserClickedRewardButton(pageKey)
const yabiStore = useYaBiStore()
yabiStore.fetchYaBiData()
if (data) {
setTimeout(() => {
showRewardAnimation.value = true
setTimeout(() => {
showRewardAnimation.value = false
}, 2500)
}, 500)
}
}
// ========== 满意度问卷 ==========
const clickCount = ref(0)
const surveySubmitted = ref(false)
const showSurvey = ref(false)
const surveyThreshold = ref(999999)
const incrementClickCount = () => {
if (surveySubmitted.value) return
clickCount.value++
localStorage.setItem(STORAGE_KEYS.CLICK_COUNT, String(clickCount.value))
if (clickCount.value >= surveyThreshold.value && !surveySubmitted.value) {
showSurvey.value = true
}
}
const markSurveySubmitted = () => {
surveySubmitted.value = true
localStorage.setItem(STORAGE_KEYS.SURVEY_SUBMITTED, '1')
showSurvey.value = false
}
return {
isLaunchCampaignTime,
// CG
// hasWatchedCg,
showCgGuide,
showCommonGuide,
markUserGuideWatched,
triggerCgGuide,
// 碎片奖励
showRewardAnimation,
rewardText,
triggerPageReward,
// 问卷
clickCount,
surveySubmitted,
showSurvey,
surveyThreshold,
incrementClickCount,
markSurveySubmitted,
}
})
...@@ -6,3 +6,4 @@ export * from './video' ...@@ -6,3 +6,4 @@ export * from './video'
export * from './question' export * from './question'
export * from './yabi' export * from './yabi'
export * from './onlineTime' export * from './onlineTime'
export * from './activity'
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
class="flex-1 flex items-center justify-center cursor-pointer relative transition-all duration-300 group" class="flex-1 flex items-center justify-center cursor-pointer relative transition-all duration-300 group"
@click="toggleTab(tab)" @click="toggleTab(tab)"
> >
<RewardButton v-if="tab.pageKey" :pageKey="tab.pageKey">
<div <div
class="flex items-center gap-2 px-12 py-2.5 rounded-lg transition-all duration-300" class="flex items-center gap-2 px-12 py-2.5 rounded-lg transition-all duration-300"
:class="{ :class="{
...@@ -39,6 +40,20 @@ ...@@ -39,6 +40,20 @@
{{ tab.name }} {{ tab.name }}
</div> </div>
</div> </div>
</RewardButton>
<div
v-else
class="flex items-center gap-2 px-12 py-2.5 rounded-lg transition-all duration-300"
:class="{
'bg-#fffdfd shadow-[inset_0_2px_4px_0_rgb(0,0,0,0.1)]': activeTab === tab.name,
'hover:bg-white/60': activeTab !== tab.name,
}"
>
<svg-icon :name="tab.svg" class="h-60px w-auto md:h-50px sm:h-40px" size="40" />
<div class="text-18px font-500 text-gray-800 md:text-16px sm:text-14px">
{{ tab.name }}
</div>
</div>
</div> </div>
</div> </div>
...@@ -92,7 +107,7 @@ ...@@ -92,7 +107,7 @@
</el-tooltip> </el-tooltip>
</div> </div>
<div class="text-amber-600 font-medium lg:text-base text-sm"> <div class="text-amber-600 font-medium lg:text-base text-sm">
YA币:{{ userAccountData.ayabiAvailable }} YA币:{{ yabiData.currentValue }}
</div> </div>
</div> </div>
</div> </div>
...@@ -109,10 +124,10 @@ ...@@ -109,10 +124,10 @@
</el-button> </el-button>
<!-- 双倍亚币角标 --> <!-- 双倍亚币角标 -->
<div <div
v-if="activityStore.isDoubleYabi && !userRecordData.isSign" v-if="activityStore.isLaunchCampaignTime && !userRecordData.isSign"
class="absolute -top-2.5 -right-2 px-1.5 py-0.5 rounded-full bg-gradient-to-r from-red-500 to-pink-500 text-white text-[10px] font-bold leading-none shadow-sm animate-bounce whitespace-nowrap z-1" class="absolute -top-2.5 -right-2 px-1.5 py-0.5 rounded-lg bg-gradient-to-r from-red-500 to-pink-500 text-white text-[10px] font-bold leading-none shadow-sm animate-bounce whitespace-nowrap z-1"
> >
双倍亚币 活动期间双倍亚币
</div> </div>
</div> </div>
<el-button <el-button
...@@ -136,6 +151,7 @@ ...@@ -136,6 +151,7 @@
分享您在工作或文化践行中的优秀案例,公开有奖,有机会收录至内部经验库,沉淀经验,赋能组织成长。 分享您在工作或文化践行中的优秀案例,公开有奖,有机会收录至内部经验库,沉淀经验,赋能组织成长。
</p> </p>
<div class="flex justify-center items-center"> <div class="flex justify-center items-center">
<RewardButton :pageKey="RewardButtonEnum.PUBLISH_CASE">
<el-button <el-button
class="bg-[linear-gradient(to_right,#A3EADC_0%,#7BE0BD_100%)] shadow-[0_1px_4px_0_rgba(168,225,210,1)] border-none hover:-translate-y-1 transition-all duration-200 text-xs sm:text-sm w-112px lg:w-116px" class="bg-[linear-gradient(to_right,#A3EADC_0%,#7BE0BD_100%)] shadow-[0_1px_4px_0_rgba(168,225,210,1)] border-none hover:-translate-y-1 transition-all duration-200 text-xs sm:text-sm w-112px lg:w-116px"
type="primary" type="primary"
...@@ -144,11 +160,13 @@ ...@@ -144,11 +160,13 @@
<svg-icon name="submit" size="20" class="mr-2" /> <svg-icon name="submit" size="20" class="mr-2" />
<span class="text-#333 text-xs sm:text-sm">去投稿</span> <span class="text-#333 text-xs sm:text-sm">去投稿</span>
</el-button> </el-button>
</RewardButton>
</div> </div>
</div> </div>
<div class="submit-container common-box rounded-lg bg-#EDEAFE"> <div class="submit-container common-box rounded-lg bg-#EDEAFE">
<div class="grid grid-cols-3 mb-4 gap-0 2xl:gap-2"> <div class="grid grid-cols-3 mb-4 gap-0 2xl:gap-2">
<RewardButton :pageKey="RewardButtonEnum.PUBLISH_QUESTION">
<div <div
class="flex flex-col items-center justify-center text-center cursor-pointer hover:-translate-y-1 transition-transform duration-200 lg:p-2 rounded-lg hover:bg-white/10" class="flex flex-col items-center justify-center text-center cursor-pointer hover:-translate-y-1 transition-transform duration-200 lg:p-2 rounded-lg hover:bg-white/10"
@click="publishTopic" @click="publishTopic"
...@@ -156,6 +174,8 @@ ...@@ -156,6 +174,8 @@
<svg-icon name="topic_release" size="80" /> <svg-icon name="topic_release" size="80" />
<div class="text-xs xl:text-sm">话题发布</div> <div class="text-xs xl:text-sm">话题发布</div>
</div> </div>
</RewardButton>
<RewardButton :pageKey="RewardButtonEnum.SELF_ANSWER">
<div <div
class="flex flex-col items-center justify-center text-center cursor-pointer hover:-translate-y-1 transition-transform duration-200 lg:p-2 rounded-lg hover:bg-white/10" class="flex flex-col items-center justify-center text-center cursor-pointer hover:-translate-y-1 transition-transform duration-200 lg:p-2 rounded-lg hover:bg-white/10"
@click="router.push('/userPage/selfAnswer')" @click="router.push('/userPage/selfAnswer')"
...@@ -166,7 +186,8 @@ ...@@ -166,7 +186,8 @@
<div class="text-xs xl:text-sm">回答问题</div> <div class="text-xs xl:text-sm">回答问题</div>
</div> </div>
</RewardButton>
<RewardButton :pageKey="RewardButtonEnum.PUBLISH_VIDEO">
<div <div
@click="router.push('/publishVideo')" @click="router.push('/publishVideo')"
class="flex flex-col items-center justify-center text-center cursor-pointer hover:-translate-y-1 transition-transform duration-200 lg:p-2 rounded-lg hover:bg-white/10" class="flex flex-col items-center justify-center text-center cursor-pointer hover:-translate-y-1 transition-transform duration-200 lg:p-2 rounded-lg hover:bg-white/10"
...@@ -174,8 +195,10 @@ ...@@ -174,8 +195,10 @@
<svg-icon name="video_release" size="80" /> <svg-icon name="video_release" size="80" />
<div class="text-xs xl:text-sm">视频发布</div> <div class="text-xs xl:text-sm">视频发布</div>
</div> </div>
</RewardButton>
</div> </div>
<div class="flex justify-center items-center"> <div class="flex justify-center items-center">
<RewardButton :pageKey="RewardButtonEnum.SELF_COMMENT">
<el-button <el-button
@click="router.push(`/userPage/selfComment?type=${ArticleTypeEnum.QUESTION}`)" @click="router.push(`/userPage/selfComment?type=${ArticleTypeEnum.QUESTION}`)"
class="bg-[linear-gradient(to_right,#D6C9FF_0%,#C5B1FF_100%)] shadow-[0_1px_4px_0_rgba(95,0,237,0.25)] border-none hover:-translate-y-1 transition-all duration-200 text-xs sm:text-sm w-112px lg:w-116px" class="bg-[linear-gradient(to_right,#D6C9FF_0%,#C5B1FF_100%)] shadow-[0_1px_4px_0_rgba(95,0,237,0.25)] border-none hover:-translate-y-1 transition-all duration-200 text-xs sm:text-sm w-112px lg:w-116px"
...@@ -184,6 +207,7 @@ ...@@ -184,6 +207,7 @@
<svg-icon name="my_answer" size="20" class="mr-2" /> <svg-icon name="my_answer" size="20" class="mr-2" />
<span class="text-#333 text-xs sm:text-sm">我的回答</span> <span class="text-#333 text-xs sm:text-sm">我的回答</span>
</el-button> </el-button>
</RewardButton>
</div> </div>
</div> </div>
...@@ -371,12 +395,13 @@ import type { ...@@ -371,12 +395,13 @@ import type {
} from '@/api' } from '@/api'
import { TABS_REF_KEY, levelListOptions } from '@/constants' import { TABS_REF_KEY, levelListOptions } from '@/constants'
import { useScrollTop } from '@/hooks' import { useScrollTop } from '@/hooks'
import { useQuestionStore } from '@/stores/question' import { useQuestionStore, useActivityStore, useYaBiStore } from '@/stores'
import { useActivityStore } from '@/stores/activity'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { push } from 'notivue' import { push } from 'notivue'
import { useBreakpoints, breakpointsTailwind } from '@vueuse/core' import { useBreakpoints, breakpointsTailwind } from '@vueuse/core'
// import LuckyWheel from '@/components/common/LuckyWheel/index.vue' // import LuckyWheel from '@/components/common/LuckyWheel/index.vue'
import { RewardButtonEnum } from '@/constants'
import RewardButton from '@/components/common/RewardButton/index.vue'
const breakpoints = useBreakpoints(breakpointsTailwind) const breakpoints = useBreakpoints(breakpointsTailwind)
const isSmallerThanXl = breakpoints.smaller('xl') const isSmallerThanXl = breakpoints.smaller('xl')
...@@ -391,7 +416,8 @@ const { handleBackTop } = useScrollTop(levelContainerRef) ...@@ -391,7 +416,8 @@ const { handleBackTop } = useScrollTop(levelContainerRef)
const questionStore = useQuestionStore() const questionStore = useQuestionStore()
const { userQestionNum } = storeToRefs(questionStore) const { userQestionNum } = storeToRefs(questionStore)
const activityStore = useActivityStore() const activityStore = useActivityStore()
const yabiStore = useYaBiStore()
const { yabiData } = storeToRefs(yabiStore)
const getThirdLevelKey = (route: RouteLocationNormalizedLoadedGeneric) => { const getThirdLevelKey = (route: RouteLocationNormalizedLoadedGeneric) => {
// console.log(route.fullPath, '三级路由首页') // console.log(route.fullPath, '三级路由首页')
// console.log(route.path, 11111111111111) // console.log(route.path, 11111111111111)
...@@ -403,9 +429,9 @@ const carouselList = ref<CarouselItemDto[]>([]) ...@@ -403,9 +429,9 @@ const carouselList = ref<CarouselItemDto[]>([])
const tabsRef = useTemplateRef('tabsRef') const tabsRef = useTemplateRef('tabsRef')
const tabs = [ const tabs = [
{ name: '首页', path: 'homeTab', img: front, svg: 'home' }, { name: '首页', path: 'homeTab', img: front, svg: 'home', pageKey: undefined },
{ name: 'YA文化', path: 'yaTab', img: ya, svg: 'ya_culture' }, { name: 'YA文化', path: 'yaTab', img: ya, svg: 'ya_culture', pageKey: RewardButtonEnum.YA_TAB },
{ name: '问吧', path: 'askTab', img: ask, svg: 'ask' }, { name: '问吧', path: 'askTab', img: ask, svg: 'ask', pageKey: RewardButtonEnum.ASK_TAB },
] ]
const activeTab = ref( const activeTab = ref(
...@@ -482,7 +508,9 @@ const onDailySign = async () => { ...@@ -482,7 +508,9 @@ const onDailySign = async () => {
await dailySign() await dailySign()
refreshTaskData(true) refreshTaskData(true)
refreshUserAccountData() refreshUserAccountData()
push.success(activityStore.isDoubleYabi ? '签到成功!活动期间双倍亚币已到账 🎉' : '签到成功') push.success(
activityStore.isLaunchCampaignTime ? '签到成功!活动期间双倍亚币已到账 🎉' : '签到成功',
)
open.value = false open.value = false
} }
......
...@@ -33,13 +33,19 @@ import ColumnList from './components/columnList.vue' ...@@ -33,13 +33,19 @@ import ColumnList from './components/columnList.vue'
import InterviewList from './components/interviewList.vue' import InterviewList from './components/interviewList.vue'
import PracticeList from './components/practiceList.vue' import PracticeList from './components/practiceList.vue'
import VideoList from './components/videoList.vue' import VideoList from './components/videoList.vue'
import { RewardButtonEnum } from '@/constants'
const tabs = [ const tabs = [
{ label: '专栏', value: '专栏', component: ColumnList }, { label: '专栏', value: '专栏', component: ColumnList, pageKey: undefined },
{ label: '实践', value: '实践', component: PracticeList }, { label: '实践', value: '实践', component: PracticeList, pageKey: RewardButtonEnum.YA_PRACTICE },
{ label: '专访', value: '专访', component: InterviewList }, {
{ label: '视频', value: '视频', component: VideoList }, label: '专访',
{ label: '关爱基金', value: '关爱基金', component: null }, value: '专访',
component: InterviewList,
pageKey: RewardButtonEnum.YA_INTERVIEW,
},
{ label: '视频', value: '视频', component: VideoList, pageKey: RewardButtonEnum.YA_VIDEO },
{ label: '关爱基金', value: '关爱基金', component: null, pageKey: undefined },
] ]
const activeTab = ref('专栏') const activeTab = ref('专栏')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment