mirror of
https://github.com/ialley-workshop-open/uni-halo.git
synced 2026-09-12 16:40:40 +08:00
feat: 添加恋爱故事模块功能
1. 新增uhlove图标字体库与相关样式 2. 新增恋爱故事页面与恋爱主页 3. 修复投票组件多选限制逻辑bug 4. 优化导航栏组件自定义样式能力 5. 更新滚动置顶组件黑名单与样式 6. 开启本地开发调试模式
This commit is contained in:
+273
-327
@@ -1,363 +1,309 @@
|
||||
<script lang="ts" setup>
|
||||
/**
|
||||
* 恋爱主页(源自旧项目 pagesA/love/love.vue,新建复刻)
|
||||
* 情侣信息 + 恋爱计时 + 功能导航(恋爱故事/相册/清单)
|
||||
*/
|
||||
import { computed, onBeforeUnmount, ref } from 'vue'
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||||
import { useAppConfigStore } from '@/store/appConfig'
|
||||
import { checkAvatarUrl, checkImageUrl } from '@/utils/url'
|
||||
import { computed, onBeforeUnmount, ref } from 'vue'
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||||
import { useAppConfigStore } from '@/store/appConfig'
|
||||
import { checkAvatarUrl, checkImageUrl } from '@/utils/url'
|
||||
|
||||
definePage({
|
||||
style: {
|
||||
navigationBarTitleText: '恋爱日记',
|
||||
},
|
||||
})
|
||||
definePage({
|
||||
style: {
|
||||
navigationBarTitleText: '恋爱日记',
|
||||
navigationStyle: 'custom'
|
||||
},
|
||||
})
|
||||
|
||||
const appConfigStore = useAppConfigStore()
|
||||
const appConfigStore = useAppConfigStore()
|
||||
|
||||
/* ---------------- 恋爱配置 ---------------- */
|
||||
interface ILoveConfigPage {
|
||||
enabled: boolean
|
||||
loveDateTitle: string
|
||||
loveDate: string
|
||||
loveInfo: {
|
||||
boyNickname: string
|
||||
boyAvatar: string
|
||||
girlNickname: string
|
||||
girlAvatar: string
|
||||
}
|
||||
pageImages: {
|
||||
bgImageUrl: string
|
||||
waveImageUrl: string
|
||||
heartImageUrl: string
|
||||
}
|
||||
ourStory: { enabled: boolean, iconUrl: string }
|
||||
lovePhoto: { enabled: boolean, iconUrl: string }
|
||||
loveDaily: { enabled: boolean, iconUrl: string }
|
||||
[key: string]: unknown
|
||||
}
|
||||
/* ---------------- 恋爱配置 ---------------- */
|
||||
interface ILoveConfigPage {
|
||||
enabled : boolean
|
||||
loveDateTitle : string
|
||||
loveDate : string
|
||||
loveInfo : {
|
||||
boyNickname : string
|
||||
boyAvatar : string
|
||||
girlNickname : string
|
||||
girlAvatar : string
|
||||
}
|
||||
pageImages : {
|
||||
bgImageUrl : string
|
||||
waveImageUrl : string
|
||||
heartImageUrl : string
|
||||
}
|
||||
ourStory : { enabled : boolean, iconUrl : string }
|
||||
lovePhoto : { enabled : boolean, iconUrl : string }
|
||||
loveDaily : { enabled : boolean, iconUrl : string }
|
||||
[key : string] : unknown
|
||||
}
|
||||
|
||||
const loveConfig = ref<ILoveConfigPage>({
|
||||
enabled: false,
|
||||
loveDateTitle: '',
|
||||
loveDate: '',
|
||||
loveInfo: {
|
||||
boyNickname: '',
|
||||
boyAvatar: '',
|
||||
girlNickname: '',
|
||||
girlAvatar: '',
|
||||
},
|
||||
pageImages: {
|
||||
bgImageUrl: '',
|
||||
waveImageUrl: '',
|
||||
heartImageUrl: '',
|
||||
},
|
||||
ourStory: { enabled: false, iconUrl: '' },
|
||||
lovePhoto: { enabled: false, iconUrl: '' },
|
||||
loveDaily: { enabled: false, iconUrl: '' },
|
||||
})
|
||||
const loveConfig = ref<ILoveConfigPage>({
|
||||
enabled: false,
|
||||
loveDateTitle: '',
|
||||
loveDate: '',
|
||||
loveInfo: {
|
||||
boyNickname: '',
|
||||
boyAvatar: '',
|
||||
girlNickname: '',
|
||||
girlAvatar: '',
|
||||
},
|
||||
pageImages: {
|
||||
bgImageUrl: '',
|
||||
waveImageUrl: '',
|
||||
heartImageUrl: '',
|
||||
},
|
||||
ourStory: { enabled: false, iconUrl: '' },
|
||||
lovePhoto: { enabled: false, iconUrl: '' },
|
||||
loveDaily: { enabled: false, iconUrl: '' },
|
||||
})
|
||||
|
||||
const loveDayCount = ref({ d: 0, h: 0, m: 0, s: 0 })
|
||||
let loveDayTimer: ReturnType<typeof setTimeout> | null = null
|
||||
const loveDayCount = ref({ d: 0, h: 0, m: 0, s: 0 })
|
||||
let loveDayTimer : ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
const navList = ref<{ key: string, use: boolean, iconImageUrl: string, title: string, desc: string }[]>([])
|
||||
const navList = ref<{ key : string, use : boolean, iconPrefix : string, icon : string, title : string, desc : string }[]>([])
|
||||
|
||||
/* ---------------- 计算属性 ---------------- */
|
||||
const loveWrapStyle = computed(() => ({
|
||||
backgroundImage: `url(${checkImageUrl(loveConfig.value.pageImages.bgImageUrl)})`,
|
||||
}))
|
||||
|
||||
/* ---------------- 数据加载 ---------------- */
|
||||
/**
|
||||
* 恋爱配置数据统一来自 appConfig store(静态配置一次性拉取,设计见
|
||||
* .docs/static-config-unified-fetch-design.md):
|
||||
* - loveConfig(公开 /love-config 内容: enabled/纪念日/恋人信息, bootstrap 已拉取)
|
||||
* - configs.loveConfig(模块开关与页面图片, getConfigs 合成下发)
|
||||
* 页面不再自行发起 /love-config 请求,也不再需要接口失败降级分支(store 兜底默认)。
|
||||
*/
|
||||
function syncLoveConfigFromStore() {
|
||||
const storeLove = appConfigStore.loveConfig
|
||||
const appConfigs = appConfigStore.configs
|
||||
/* ---------------- 数据加载 ---------------- */
|
||||
function syncLoveConfigFromStore() {
|
||||
const storeLove = appConfigStore.loveConfig
|
||||
const appConfigs = appConfigStore.configs
|
||||
|
||||
loveConfig.value = {
|
||||
...loveConfig.value,
|
||||
...(storeLove.loveDateTitle ? { loveDateTitle: storeLove.loveDateTitle } : {}),
|
||||
...(storeLove.loveDate ? { loveDate: storeLove.loveDate } : {}),
|
||||
...(storeLove.enabled !== undefined ? { enabled: storeLove.enabled } : {}),
|
||||
loveInfo: {
|
||||
...loveConfig.value.loveInfo,
|
||||
...(storeLove.loveInfo || {}),
|
||||
},
|
||||
}
|
||||
loveConfig.value = {
|
||||
...loveConfig.value,
|
||||
...(storeLove.loveDateTitle ? { loveDateTitle: storeLove.loveDateTitle } : {}),
|
||||
...(storeLove.loveDate ? { loveDate: storeLove.loveDate } : {}),
|
||||
...(storeLove.enabled !== undefined ? { enabled: storeLove.enabled } : {}),
|
||||
loveInfo: {
|
||||
...loveConfig.value.loveInfo,
|
||||
...(storeLove.loveInfo || {}),
|
||||
},
|
||||
}
|
||||
|
||||
// 从 getConfigs.loveConfig 取模块开关与页面图片(缺省保留默认)
|
||||
const loveModuleConfig = appConfigs.loveConfig as Partial<ILoveConfigPage> | undefined
|
||||
if (loveModuleConfig) {
|
||||
loveConfig.value = {
|
||||
...loveConfig.value,
|
||||
pageImages: loveModuleConfig.pageImages || loveConfig.value.pageImages,
|
||||
ourStory: loveModuleConfig.ourStory || loveConfig.value.ourStory,
|
||||
lovePhoto: loveModuleConfig.lovePhoto || loveConfig.value.lovePhoto,
|
||||
loveDaily: loveModuleConfig.loveDaily || loveConfig.value.loveDaily,
|
||||
}
|
||||
}
|
||||
// 从 getConfigs.loveConfig 取模块开关与页面图片(缺省保留默认)
|
||||
const loveModuleConfig = appConfigs.loveConfig as Partial<ILoveConfigPage> | undefined
|
||||
if (loveModuleConfig) {
|
||||
loveConfig.value = {
|
||||
...loveConfig.value,
|
||||
pageImages: loveModuleConfig.pageImages || loveConfig.value.pageImages,
|
||||
ourStory: loveModuleConfig.ourStory || loveConfig.value.ourStory,
|
||||
lovePhoto: loveModuleConfig.lovePhoto || loveConfig.value.lovePhoto,
|
||||
loveDaily: loveModuleConfig.loveDaily || loveConfig.value.loveDaily,
|
||||
}
|
||||
}
|
||||
|
||||
initList()
|
||||
// 未配置纪念日(loveDate 为空)不启动倒计时,避免 NaN
|
||||
if (loveConfig.value.loveDate) {
|
||||
handleInitLoveDayCount()
|
||||
}
|
||||
}
|
||||
initList()
|
||||
// 未配置纪念日(loveDate 为空)不启动倒计时,避免 NaN
|
||||
if (loveConfig.value.loveDate) {
|
||||
handleInitLoveDayCount()
|
||||
}
|
||||
}
|
||||
|
||||
function initList() {
|
||||
const configs = loveConfig.value
|
||||
navList.value = [
|
||||
{
|
||||
key: 'journey',
|
||||
use: configs.ourStory.enabled,
|
||||
iconImageUrl: configs.ourStory.iconUrl,
|
||||
title: '恋爱故事',
|
||||
desc: '我们一起度过的那些经历',
|
||||
},
|
||||
{
|
||||
key: 'album',
|
||||
use: configs.lovePhoto.enabled,
|
||||
iconImageUrl: configs.lovePhoto.iconUrl,
|
||||
title: '恋爱相册',
|
||||
desc: '定格了我们的那些小美好',
|
||||
},
|
||||
{
|
||||
key: 'list',
|
||||
use: configs.loveDaily.enabled,
|
||||
iconImageUrl: configs.loveDaily.iconUrl,
|
||||
title: '恋爱清单',
|
||||
desc: '你我之间的约定我们都在努力实现',
|
||||
},
|
||||
]
|
||||
}
|
||||
function initList() {
|
||||
const configs = loveConfig.value
|
||||
navList.value = [
|
||||
{
|
||||
key: 'story',
|
||||
use: configs.ourStory.enabled,
|
||||
title: '恋爱故事',
|
||||
desc: '我们一起度过的那些经历',
|
||||
iconPrefix: 'uhlove-icon',
|
||||
icon: 'gushi',
|
||||
},
|
||||
{
|
||||
key: 'album',
|
||||
use: configs.lovePhoto.enabled,
|
||||
title: '恋爱相册',
|
||||
desc: '定格了我们的那些小美好',
|
||||
iconPrefix: 'uhlove-icon',
|
||||
icon: 'xiangce'
|
||||
},
|
||||
{
|
||||
key: 'list',
|
||||
use: configs.loveDaily.enabled,
|
||||
title: '恋爱清单',
|
||||
desc: '你我之间的约定我们都在努力实现',
|
||||
iconPrefix: 'uhlove-icon',
|
||||
icon: 'liebiao'
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
/* ---------------- 恋爱计时 ---------------- */
|
||||
function handleInitLoveDayCount() {
|
||||
if (loveDayTimer) {
|
||||
clearTimeout(loveDayTimer)
|
||||
}
|
||||
const countDownFn = () => {
|
||||
loveDayTimer = setTimeout(countDownFn, 1000)
|
||||
const formatStartDate = loveConfig.value.loveDate.replace(/-/g, '/')
|
||||
const start = new Date(formatStartDate)
|
||||
const now = new Date()
|
||||
const T = now.getTime() - start.getTime()
|
||||
const i = 24 * 60 * 60 * 1000
|
||||
const d = T / i
|
||||
const D = Math.floor(d)
|
||||
const h = (d - D) * 24
|
||||
const H = Math.floor(h)
|
||||
const m = (h - H) * 60
|
||||
const M = Math.floor(m)
|
||||
const s = (m - M) * 60
|
||||
const S = Math.floor(s)
|
||||
loveDayCount.value = { d: D, h: H, m: M, s: S }
|
||||
}
|
||||
countDownFn()
|
||||
}
|
||||
/* ---------------- 恋爱计时 ---------------- */
|
||||
function handleInitLoveDayCount() {
|
||||
if (loveDayTimer) {
|
||||
clearTimeout(loveDayTimer)
|
||||
}
|
||||
const countDownFn = () => {
|
||||
loveDayTimer = setTimeout(countDownFn, 1000)
|
||||
const formatStartDate = loveConfig.value.loveDate.replace(/-/g, '/')
|
||||
const start = new Date(formatStartDate)
|
||||
const now = new Date()
|
||||
const T = now.getTime() - start.getTime()
|
||||
const i = 24 * 60 * 60 * 1000
|
||||
const d = T / i
|
||||
const D = Math.floor(d)
|
||||
const h = (d - D) * 24
|
||||
const H = Math.floor(h)
|
||||
const m = (h - H) * 60
|
||||
const M = Math.floor(m)
|
||||
const s = (m - M) * 60
|
||||
const S = Math.floor(s)
|
||||
loveDayCount.value = { d: D, h: H, m: M, s: S }
|
||||
}
|
||||
countDownFn()
|
||||
}
|
||||
|
||||
/* ---------------- 跳转 ---------------- */
|
||||
function handleToPage(pageName: string) {
|
||||
uni.navigateTo({
|
||||
url: `/pages-blog/love/${pageName}`,
|
||||
})
|
||||
}
|
||||
/* ---------------- 跳转 ---------------- */
|
||||
function handleToPage(pageName : string) {
|
||||
uni.navigateTo({
|
||||
url: `/pages-blog/love/${pageName}`,
|
||||
})
|
||||
}
|
||||
|
||||
/* ---------------- 生命周期 ---------------- */
|
||||
onLoad(() => {
|
||||
uni.setNavigationBarTitle({ title: '恋爱日记' })
|
||||
// 先用 store 已有数据立即渲染(index 启动已 bootstrap 或持久化缓存恢复)
|
||||
syncLoveConfigFromStore()
|
||||
})
|
||||
/* ---------------- 生命周期 ---------------- */
|
||||
onLoad(() => {
|
||||
syncLoveConfigFromStore()
|
||||
})
|
||||
|
||||
// 每次进入页面:静态配置 TTL 内不重复请求(bootstrap 内部判定),刷新后重新合成视图
|
||||
onShow(async () => {
|
||||
await appConfigStore.bootstrap()
|
||||
syncLoveConfigFromStore()
|
||||
})
|
||||
onShow(async () => {
|
||||
await appConfigStore.bootstrap()
|
||||
syncLoveConfigFromStore()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (loveDayTimer) {
|
||||
clearTimeout(loveDayTimer)
|
||||
}
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
if (loveDayTimer) {
|
||||
clearTimeout(loveDayTimer)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="app-page min-h-screen w-screen">
|
||||
<!-- 情侣信息 -->
|
||||
<view class="lover-wrap relative h-[50vh] w-screen flex items-center justify-center" :style="[loveWrapStyle]">
|
||||
<view class="lover-card absolute left-1/2 top-[58%] z-2 w-[90vw] flex items-center justify-around rounded-xl -translate-x-1/2 -translate-y-1/2">
|
||||
<view class="boy">
|
||||
<image class="avatar box-border h-[180rpx] w-[180rpx] border-8 rounded-full" :style="{ borderColor: 'rgb(58 184 228 / 70%)' }" :src="checkAvatarUrl(loveConfig.loveInfo.boyAvatar)" mode="aspectFit" />
|
||||
<view class="name mt-2 text-center text-[32rpx] text-white font-bold tracking-[2rpx]">
|
||||
{{ loveConfig.loveInfo.boyNickname }}
|
||||
</view>
|
||||
</view>
|
||||
<image class="like h-[120rpx] w-[120rpx]" :src="checkImageUrl(loveConfig.pageImages.heartImageUrl)" mode="scaleToFill" />
|
||||
<view class="girl">
|
||||
<image class="avatar box-border h-[180rpx] w-[180rpx] border-8 rounded-full" :style="{ borderColor: 'rgb(245 122 179 / 70%)' }" :src="checkAvatarUrl(loveConfig.loveInfo.girlAvatar)" mode="aspectFit" />
|
||||
<view class="name mt-2 text-center text-[32rpx] text-white font-bold tracking-[2rpx]">
|
||||
{{ loveConfig.loveInfo.girlNickname }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<image class="wave-image absolute bottom-0 left-0 h-[120rpx] w-full" :src="checkImageUrl(loveConfig.pageImages.waveImageUrl)" mode="scaleToFill" />
|
||||
</view>
|
||||
<view class="bg-pink-100 min-h-screen w-screen">
|
||||
<uh-navbar default-title="恋爱日记" :need-placeholder="false" back-class="text-love"
|
||||
title-color="!text-love"></uh-navbar>
|
||||
|
||||
<!-- 恋爱记时 -->
|
||||
<view class="love-time-wrap mt-20 w-screen flex flex-col items-center justify-center">
|
||||
<view class="title text-[42rpx] text-[#333] font-bold">
|
||||
{{ loveConfig.loveDateTitle }}
|
||||
</view>
|
||||
<view class="content mt-6 flex items-center justify-center">
|
||||
<text class="text text-[28rpx]">
|
||||
第
|
||||
<text class="number mx-2 text-[46rpx] text-[#f83856] font-bold">{{ loveDayCount.d }}</text>
|
||||
天
|
||||
</text>
|
||||
<text class="text text-[28rpx]">
|
||||
<text class="number mx-2 text-[46rpx] text-[#f83856] font-bold">{{ loveDayCount.h }}</text>
|
||||
小时
|
||||
</text>
|
||||
<text class="text text-[28rpx]">
|
||||
<text class="number mx-2 text-[46rpx] text-[#f83856] font-bold">{{ loveDayCount.m }}</text>
|
||||
分钟
|
||||
</text>
|
||||
<text class="text text-[28rpx]">
|
||||
<text class="number mx-2 text-[46rpx] text-[#f83856] font-bold">{{ loveDayCount.s }}</text>
|
||||
秒
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 情侣信息 -->
|
||||
<view class="relative z-10 h-92 w-screen flex flex-col items-center justify-center">
|
||||
<view class="relative z-10 w-full h-full flex items-center justify-center rounded-xl">
|
||||
<view class="boy flex flex-col items-center justify-center translate-x-1">
|
||||
<image class="uh-global-card-glass border-3 box-border border-blue-400 h-26 w-26 rounded-full"
|
||||
:src="checkAvatarUrl(loveConfig.loveInfo.boyAvatar)" mode="aspectFill" />
|
||||
<view class="bg-blue-500 mt-2 text-center text-xs text-white font-bold px-2 py-1 rounded-lg">
|
||||
{{ loveConfig.loveInfo.boyNickname }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="girl flex flex-col items-center justify-center -translate-x-1">
|
||||
<image class="uh-global-card-glass border-3 box-border border-love h-26 w-26 rounded-full"
|
||||
:src="checkAvatarUrl(loveConfig.loveInfo.girlAvatar)" mode="aspectFill" />
|
||||
<view class="bg-love mt-2 text-center text-xs text-white font-bold px-2 py-1 rounded-lg">
|
||||
{{ loveConfig.loveInfo.girlNickname }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<image :src="checkImageUrl(loveConfig.pageImages.bgImageUrl)" class="absolute z-0 inset-0 w-full h-full"
|
||||
mode="aspectFill" />
|
||||
<view class="absolute z-2 left-0 bottom-0 w-full h-12 bg-gradient-to-b from-white/0 to-pink-100" />
|
||||
</view>
|
||||
|
||||
<!-- 功能导航 -->
|
||||
<view class="list-wrap mt-[75rpx] box-border flex flex-col items-center justify-center px-9">
|
||||
<block v-for="(nav, index) in navList" :key="index">
|
||||
<view v-if="nav.use" class="mb-8 box-border list-item w-full flex items-center justify-around rounded-[50rpx] bg-white px-8 py-7 shadow-sm" :class="`list-item-${index + 1}`" @click="handleToPage(nav.key)">
|
||||
<view class="left h-[120rpx] w-[120rpx]">
|
||||
<image class="icon h-full w-full" :src="checkImageUrl(nav.iconImageUrl)" mode="aspectFit" />
|
||||
</view>
|
||||
<view class="right box-border flex flex-1 flex-col justify-center pl-10">
|
||||
<view class="name text-[32rpx] text-[#333] font-bold">
|
||||
{{ nav.title }}
|
||||
</view>
|
||||
<view class="desc mt-2 text-[26rpx] text-[#777]">
|
||||
{{ nav.desc }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 恋爱记时 -->
|
||||
<view class="love-time-wrap mt-8 w-screen flex flex-col items-center justify-center">
|
||||
<view class="title text-xl text-love font-bold">
|
||||
{{ loveConfig.loveDateTitle }}
|
||||
</view>
|
||||
<view class="content mt-6 flex items-center justify-center">
|
||||
<text class="text text-sm">
|
||||
第
|
||||
<text class="number mx-2 text-2xl text-love font-bold">{{ loveDayCount.d }}</text>
|
||||
天
|
||||
</text>
|
||||
<text class="text text-sm">
|
||||
<text class="number mx-2 text-2xl text-blue-400 font-bold">{{ loveDayCount.h }}</text>
|
||||
小时
|
||||
</text>
|
||||
<text class="text text-sm">
|
||||
<text class="number mx-2 text-2xl text-love font-bold">{{ loveDayCount.m }}</text>
|
||||
分钟
|
||||
</text>
|
||||
<text class="text text-sm">
|
||||
<text class="number mx-2 text-2xl text-blue-400 font-bold">{{ loveDayCount.s }}</text>
|
||||
秒
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 功能导航 -->
|
||||
<view class="mt-6 box-border flex flex-col items-center justify-center gap-y-4 px-4">
|
||||
<block v-for="(nav, index) in navList" :key="index">
|
||||
<view v-if="nav.use"
|
||||
class="box-border list-item uh-global-card-glass bg-white/60 p-3 w-full flex items-center justify-around gap-x-4 rounded-2xl"
|
||||
:class="`list-item-${index + 1}`" @click="handleToPage(nav.key)">
|
||||
<view class="flex items-center justify-center h-12 w-12 rounded-xl opacity-70" :class="[index%2===0?'bg-pink-100':'bg-blue-100']">
|
||||
<wd-icon :class-prefix="nav.iconPrefix" :name="nav.icon" size="66rpx" />
|
||||
</view>
|
||||
<view class="box-border flex flex-1 flex-col justify-center gap-y-1">
|
||||
<view class="name text-md font-bold" :class="[index%2===0?'text-love':'text-blue-400']">
|
||||
{{ nav.title }}
|
||||
</view>
|
||||
<view class="text-xs truncate" :class="[index%2===0?'text-love/60':'text-blue-300']">
|
||||
{{ nav.desc }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="shrink-0">
|
||||
<wd-icon name="arrow-right" :class="[index%2===0?'text-love':'text-blue-400']"
|
||||
size="32rpx"></wd-icon>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.app-page {
|
||||
background: linear-gradient(
|
||||
-45deg,
|
||||
rgb(247 149 51 / 10%),
|
||||
rgb(243 112 85 / 10%) 15%,
|
||||
rgb(239 78 123 / 10%) 30%,
|
||||
rgb(161 102 171 / 10%) 44%,
|
||||
rgb(80 115 184 / 10%) 58%,
|
||||
rgb(16 152 173 / 10%) 72%,
|
||||
rgb(7 179 155 / 10%) 86%,
|
||||
rgb(109 186 130 / 10%)
|
||||
);
|
||||
}
|
||||
.list-item-1 {
|
||||
animation: listItemAni1 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.lover-wrap {
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 50% 50%;
|
||||
.list-item-2 {
|
||||
animation: listItemAni1 3s ease-in-out infinite;
|
||||
animation-delay: 1.5s;
|
||||
}
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
content: '';
|
||||
background-color: rgb(255 255 255 / 10%);
|
||||
z-index: 0;
|
||||
backdrop-filter: blur(4rpx);
|
||||
overflow: hidden;
|
||||
}
|
||||
.list-item-3 {
|
||||
animation: listItemAni1 3s ease-in-out infinite;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: -60rpx;
|
||||
width: 100vw;
|
||||
height: 60rpx;
|
||||
background-image: linear-gradient(to bottom, rgb(255 255 255), rgb(255 255 255 / 0%));
|
||||
}
|
||||
@keyframes likeani {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.like {
|
||||
animation: likeani 1s ease-in-out infinite;
|
||||
}
|
||||
25% {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
.wave-image {
|
||||
mix-blend-mode: screen;
|
||||
}
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
/* 列表项漂浮动画(无法用 UnoCSS 表达;模板已生成 list-item-N 类,避开 WXSS 不支持的 :nth-child) */
|
||||
.list-item-1 {
|
||||
animation: listItemAni1 3s ease-in-out infinite;
|
||||
}
|
||||
75% {
|
||||
transform: scale(1.3);
|
||||
}
|
||||
|
||||
.list-item-2 {
|
||||
animation: listItemAni1 3s ease-in-out infinite;
|
||||
animation-delay: 1.5s;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.list-item-3 {
|
||||
animation: listItemAni1 3s ease-in-out infinite;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
@keyframes listItemAni1 {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
@keyframes likeani {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-10rpx);
|
||||
}
|
||||
|
||||
25% {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
75% {
|
||||
transform: scale(1.3);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes listItemAni1 {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translateY(-10rpx);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user