feat(activity): 活动大厅全面以陪吃·陪唱·陪喝为主,增加品类快捷胶囊筛选并完善TDD门禁

这个提交包含在:
wikiboss
2026-09-16 20:18:34 +08:00
父节点 9fd7ea2c5a
当前提交 57b8aeebe4
共有 5 个文件被更改,包括 359 次插入 和 72 次删除

查看文件

@@ -1,5 +1,5 @@
<template>
<view class="activity-container">
<view class="activity-container" :class="{ 'theme-warm': currentThemeKey === 'warm' }">
<!-- 顶部模式切换选项卡 (矢量SVG模式图标) -->
<view class="tab-header">
<view
@@ -33,9 +33,24 @@
<!-- 顶部状态小提示 (矢量盾牌图标) -->
<view class="tips-bar">
<image class="tips-svg" :src="ICONS.shield" mode="aspectFit" />
<text class="tips-text">AA制活动人均AA平摊,项目制为房主全额悬赏或赛事奖池</text>
<text class="tips-text">同城组局主打美食陪吃、同城陪唱、下午茶陪喝,凭4位核销码现场签到履约</text>
</view>
<!-- 品类横滑筛选胶囊 -->
<scroll-view scroll-x class="cat-filter-scroll" :show-scrollbar="false">
<view class="cat-filter-list">
<view
v-for="cat in categoryOptions"
:key="cat.key"
class="cat-chip btn-active"
:class="{ active: currentCategory === cat.key }"
@click="selectCategory(cat.key)"
>
<text class="chip-text">{{ cat.label }}</text>
</view>
</view>
</scroll-view>
<!-- 活动列表 -->
<view class="activity-list">
<view
@@ -120,10 +135,38 @@ import { ICONS } from '@/common/icons.js';
const activities = ref(ACTIVITIES_LIST);
const currentTab = ref('ALL');
const currentCategory = ref('ALL');
const categoryOptions = [
{ key: 'ALL', label: '全部品类' },
{ key: 'MEAL', label: '美食陪吃' },
{ key: 'SING', label: '同城陪唱' },
{ key: 'DRINK', label: '下午茶陪喝' },
{ key: 'GAME', label: '电竞开黑' },
];
const selectCategory = (key) => {
currentCategory.value = key;
};
const filteredActivities = computed(() => {
if (currentTab.value === 'ALL') return activities.value;
return activities.value.filter(a => a.payType === currentTab.value);
let list = activities.value;
if (currentTab.value !== 'ALL') {
list = list.filter(a => a.payType === currentTab.value);
}
if (currentCategory.value !== 'ALL') {
const map = {
MEAL: '美食陪吃',
SING: '同城陪唱',
DRINK: '下午茶陪喝',
GAME: '王者荣耀',
};
const target = map[currentCategory.value];
if (target) {
list = list.filter(a => a.game === target);
}
}
return list;
});
const switchTab = (tab) => {
@@ -225,6 +268,40 @@ const createActivity = () => {
}
}
.cat-filter-scroll {
white-space: nowrap;
margin-bottom: 24rpx;
.cat-filter-list {
display: flex;
gap: 16rpx;
.cat-chip {
padding: 10rpx 24rpx;
border-radius: 28rpx;
background: rgba(255, 255, 255, 0.04);
border: 1px solid rgba(255, 255, 255, 0.08);
transition: all 0.2s ease;
.chip-text {
font-size: 24rpx;
color: #94A3B8;
font-weight: 500;
}
&.active {
background: rgba(99, 102, 241, 0.2);
border-color: #6366F1;
.chip-text {
color: #FFF;
font-weight: 700;
}
}
}
}
}
.activity-list {
display: flex;
flex-direction: column;

查看文件

@@ -1,5 +1,5 @@
<template>
<view class="index-container">
<view class="index-container" :class="{ 'theme-warm': currentThemeKey === 'warm' }">
<!-- 顶部搜索栏 (矢量SVG搜索图标,交互聚焦微动效) -->
<view class="header-search">
<view class="search-box">
@@ -142,15 +142,30 @@
</template>
<script setup>
import { ref, computed } from 'vue';
import { ref, computed, onMounted, onUnmounted } from 'vue';
import { GAMES_LIST, BANNERS, EXPERTS_LIST } from '@/common/mock.js';
import { ICONS } from '@/common/icons.js';
import { getCurrentThemeKey } from '@/common/theme.js';
const games = ref(GAMES_LIST);
const banners = ref(BANNERS);
const experts = ref(EXPERTS_LIST);
const currentCategory = ref('all');
const playingId = ref(null);
const currentThemeKey = ref(getCurrentThemeKey());
const onThemeChanged = (key) => {
currentThemeKey.value = key;
};
onMounted(() => {
currentThemeKey.value = getCurrentThemeKey();
uni.$on('theme-change', onThemeChanged);
});
onUnmounted(() => {
uni.$off('theme-change', onThemeChanged);
});
const filteredExperts = computed(() => {
if (currentCategory.value === 'all') return experts.value;
@@ -685,6 +700,35 @@ const navTo = (url) => {
}
}
.index-container.theme-warm {
background-color: #140E0A;
.header-search {
background-color: #140E0A;
.search-box {
background-color: #221711;
border-color: rgba(249, 115, 22, 0.15);
&:focus-within {
border-color: #F97316;
box-shadow: 0 0 16rpx rgba(249, 115, 22, 0.35);
}
}
}
.category-scroll .category-item.active {
background: linear-gradient(135deg, rgba(249, 115, 22, 0.25), rgba(245, 158, 11, 0.1));
border-color: #F97316;
.cat-name {
color: #FB923C;
}
}
.expert-grid .expert-card {
background-color: #221711;
border-color: rgba(249, 115, 22, 0.12);
}
}
@keyframes pulse {
0% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7); }
70% { transform: scale(1); box-shadow: 0 0 0 8rpx rgba(255, 255, 255, 0); }