|
...
|
...
|
@@ -4,18 +4,14 @@ |
|
|
|
<view class="banner-wrapper">
|
|
|
|
<swiper class="swiper">
|
|
|
|
<swiper-item class="swiper-item">
|
|
|
|
<image
|
|
|
|
class="img"
|
|
|
|
<image class="img"
|
|
|
|
src="https://fitness-hcxtec-bucket.oss-cn-shenzhen.aliyuncs.com/20260316/37_1773628025534.png"
|
|
|
|
mode="aspectFill"
|
|
|
|
/>
|
|
|
|
mode="aspectFill" />
|
|
|
|
</swiper-item>
|
|
|
|
<swiper-item class="swiper-item">
|
|
|
|
<image
|
|
|
|
class="img"
|
|
|
|
<image class="img"
|
|
|
|
src="https://fitness-hcxtec-bucket.oss-cn-shenzhen.aliyuncs.com/20260316/38_1773628032712.png"
|
|
|
|
mode="aspectFill"
|
|
|
|
/>
|
|
|
|
mode="aspectFill" />
|
|
|
|
</swiper-item>
|
|
|
|
</swiper>
|
|
|
|
</view>
|
|
...
|
...
|
@@ -23,41 +19,26 @@ |
|
|
|
<!-- 筛选条 -->
|
|
|
|
<!-- 后端计划分类的计划列表只返回了难度字段,所有只有这个字段的筛选生效了 -->
|
|
|
|
<view class="filter-bar">
|
|
|
|
<view
|
|
|
|
v-for="(item, index) in filterList"
|
|
|
|
:key="index"
|
|
|
|
class="filter-item"
|
|
|
|
:class="{ active: activeFilter === index }"
|
|
|
|
@click="
|
|
|
|
<view v-for="(item, index) in filterList" :key="index" class="filter-item"
|
|
|
|
:class="{ active: activeFilter === index }" @click="
|
|
|
|
activeFilter = index;
|
|
|
|
toggleDrawer(index);
|
|
|
|
"
|
|
|
|
>
|
|
|
|
toggleDrawer(index);
|
|
|
|
">
|
|
|
|
<text class="text">{{
|
|
|
|
selectedFilters[item] === '不限' ? item : `${selectedFilters[item]}`
|
|
|
|
}}</text>
|
|
|
|
<uni-icons type="bottom" size="14" color="#666" />
|
|
|
|
</view>
|
|
|
|
<view class="filter-search">
|
|
|
|
<uni-icons
|
|
|
|
type="search"
|
|
|
|
size="20"
|
|
|
|
color="#333"
|
|
|
|
style="border: 1px solid #c5c5c5; border-radius: 30rpx; padding: 4rpx 6rpx"
|
|
|
|
@click="navigateToSearch"
|
|
|
|
/>
|
|
|
|
<uni-icons type="search" size="20" color="#333"
|
|
|
|
style="border: 1px solid #c5c5c5; border-radius: 30rpx; padding: 4rpx 6rpx" @click="navigateToSearch" />
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<!-- 下拉抽屉组件 -->
|
|
|
|
<view class="filter-drawer" v-show="drawerShow" @click.stop>
|
|
|
|
<view class="drawer-content">
|
|
|
|
<view
|
|
|
|
v-for="(item, idx) in filterDrawerData"
|
|
|
|
:key="idx"
|
|
|
|
class="drawer-item"
|
|
|
|
@click="selectDrawerItem(item)"
|
|
|
|
>
|
|
|
|
<view v-for="(item, idx) in filterDrawerData" :key="idx" class="drawer-item" @click="selectDrawerItem(item)">
|
|
|
|
<text class="drawer-item-text">{{ item }}</text>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
...
|
...
|
@@ -67,33 +48,19 @@ |
|
|
|
<view class="content-layout">
|
|
|
|
<!-- 左侧分类 -->
|
|
|
|
<scroll-view class="sidebar" scroll-y enable-flex>
|
|
|
|
<view
|
|
|
|
v-for="(item, index) in categoryList"
|
|
|
|
:key="item.id"
|
|
|
|
class="category-item"
|
|
|
|
:class="{ active: activeCategory === index }"
|
|
|
|
@click="switchCategory(index)"
|
|
|
|
>
|
|
|
|
<view v-for="(item, index) in categoryList" :key="item.id" class="category-item"
|
|
|
|
:class="{ active: activeCategory === index }" @click="switchCategory(index)">
|
|
|
|
<text class="text">{{ item.name }}</text>
|
|
|
|
</view>
|
|
|
|
</scroll-view>
|
|
|
|
|
|
|
|
<!-- 右侧计划列表 -->
|
|
|
|
<scroll-view class="plan-list-wrap" scroll-y enable-flex>
|
|
|
|
<view
|
|
|
|
v-for="plan in currentPlanList"
|
|
|
|
:key="plan.id"
|
|
|
|
class="plan-card"
|
|
|
|
@tap="navigateToDetail(plan)"
|
|
|
|
>
|
|
|
|
<view v-for="plan in currentPlanList" :key="plan.id" class="plan-card" @tap="navigateToDetail(plan)">
|
|
|
|
<image class="plan-cover" :src="plan.cover" mode="aspectFill" />
|
|
|
|
<view class="plan-info">
|
|
|
|
<view class="plan-tag-row">
|
|
|
|
<view
|
|
|
|
v-if="plan.tag"
|
|
|
|
class="plan-tag"
|
|
|
|
:class="plan.tag === '火爆' ? 'tag-hot' : 'tag-new'"
|
|
|
|
>
|
|
|
|
<view v-if="plan.tag" class="plan-tag" :class="plan.tag === '火爆' ? 'tag-hot' : 'tag-new'">
|
|
|
|
<text>{{ plan.tag }}</text>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
...
|
...
|
@@ -113,438 +80,449 @@ |
|
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
import { computed, onMounted, ref } from 'vue';
|
|
|
|
// ✅ getCurrentPages 是全局 API,无需 import
|
|
|
|
import QueryPlanApi from '@/sheep/api/plan/queryplan';
|
|
|
|
|
|
|
|
// ====== 筛选相关(保持原样)======
|
|
|
|
const filterList = ref(['频率', '难度', '场景', '人群']);
|
|
|
|
const drawerShow = ref(false);
|
|
|
|
const activeFilter = ref(null);
|
|
|
|
const selectedFilters = ref({
|
|
|
|
频率: '不限',
|
|
|
|
难度: '不限',
|
|
|
|
场景: '不限',
|
|
|
|
人群: '不限',
|
|
|
|
});
|
|
|
|
const filterOptionsMap = {
|
|
|
|
频率: ['不限', '1练/周', '2练/周', '3练/周', '4练/周', '5练/周'],
|
|
|
|
难度: ['不限', '初阶', '中阶', '高阶'],
|
|
|
|
场景: ['不限', '健身房', '仅哑铃', '仅哑铃+杠铃'],
|
|
|
|
人群: ['不限', '青少年', '成年人', '中老年', '运动损伤'],
|
|
|
|
};
|
|
|
|
|
|
|
|
const filterDrawerData = computed(() => {
|
|
|
|
const currentFilterName = filterList.value[activeFilter.value];
|
|
|
|
return filterOptionsMap[currentFilterName] || [];
|
|
|
|
});
|
|
|
|
|
|
|
|
const toggleDrawer = (index) => {
|
|
|
|
if (activeFilter.value === index) {
|
|
|
|
drawerShow.value = !drawerShow.value;
|
|
|
|
} else {
|
|
|
|
drawerShow.value = true;
|
|
|
|
}
|
|
|
|
activeFilter.value = index;
|
|
|
|
};
|
|
|
|
|
|
|
|
const selectDrawerItem = (item) => {
|
|
|
|
const currentFilterName = filterList.value[activeFilter.value];
|
|
|
|
selectedFilters.value[currentFilterName] = item;
|
|
|
|
drawerShow.value = false;
|
|
|
|
console.log('筛选条件更新:', selectedFilters.value);
|
|
|
|
};
|
|
|
|
|
|
|
|
// ====== 分类与计划 ======
|
|
|
|
const categoryList = ref([]);
|
|
|
|
const activeCategory = ref(0);
|
|
|
|
const planData = ref([]); // 存储所有已加载的计划(带 _categoryId)
|
|
|
|
const difficultyText = { 1: '初阶', 2: '中阶', 3: '高阶' };
|
|
|
|
// 完全匹配你后台的数字,复制这一段!
|
|
|
|
const filterMap = {
|
|
|
|
频率: {
|
|
|
|
不限: 0,
|
|
|
|
'1练/周': 1,
|
|
|
|
'2练/周': 2,
|
|
|
|
'3练/周': 3,
|
|
|
|
'4练/周': 4,
|
|
|
|
'5练/周': 5,
|
|
|
|
'6练/周': 6,
|
|
|
|
'7练/周': 7,
|
|
|
|
},
|
|
|
|
难度: { 不限: 0, 初阶: 1, 中阶: 2, 高阶: 3 },
|
|
|
|
场景: { 不限: 1, 健身房: 2, 仅哑铃: 3, '仅哑铃+杠铃': 4 },
|
|
|
|
人群: { 不限: 1, 青少年: 2, 成年人: 3, 中老年: 4, 运动损伤: 5 },
|
|
|
|
};
|
|
|
|
const currentPlanList = computed(() => {
|
|
|
|
const categoryId = categoryList.value[activeCategory.value]?.id;
|
|
|
|
if (categoryId == null) return [];
|
|
|
|
|
|
|
|
let list = planData.value.filter((p) => p._categoryId === categoryId);
|
|
|
|
|
|
|
|
// 频率
|
|
|
|
if (selectedFilters.value.频率 !== '不限') {
|
|
|
|
const val = filterMap.频率[selectedFilters.value.频率];
|
|
|
|
list = list.filter((item) => item.frequency === val);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 难度
|
|
|
|
if (selectedFilters.value.难度 !== '不限') {
|
|
|
|
const val = filterMap.难度[selectedFilters.value.难度];
|
|
|
|
list = list.filter((item) => item.difficultyLevel === val);
|
|
|
|
}
|
|
|
|
import { computed, onMounted, ref } from 'vue';
|
|
|
|
// ✅ getCurrentPages 是全局 API,无需 import
|
|
|
|
import QueryPlanApi from '@/sheep/api/plan/queryplan';
|
|
|
|
|
|
|
|
// ====== 筛选相关(保持原样)======
|
|
|
|
const filterList = ref(['频率', '难度', '场景', '人群']);
|
|
|
|
const drawerShow = ref(false);
|
|
|
|
const activeFilter = ref(null);
|
|
|
|
const selectedFilters = ref({
|
|
|
|
频率: '不限',
|
|
|
|
难度: '不限',
|
|
|
|
场景: '不限',
|
|
|
|
人群: '不限',
|
|
|
|
});
|
|
|
|
const filterOptionsMap = {
|
|
|
|
频率: ['不限', '1练/周', '2练/周', '3练/周', '4练/周', '5练/周'],
|
|
|
|
难度: ['不限', '初阶', '中阶', '高阶'],
|
|
|
|
场景: ['不限', '健身房', '仅哑铃', '仅哑铃+杠铃'],
|
|
|
|
人群: ['不限', '青少年', '成年人', '中老年', '运动损伤'],
|
|
|
|
};
|
|
|
|
|
|
|
|
const filterDrawerData = computed(() => {
|
|
|
|
const currentFilterName = filterList.value[activeFilter.value];
|
|
|
|
return filterOptionsMap[currentFilterName] || [];
|
|
|
|
});
|
|
|
|
|
|
|
|
const toggleDrawer = (index) => {
|
|
|
|
if (activeFilter.value === index) {
|
|
|
|
drawerShow.value = !drawerShow.value;
|
|
|
|
} else {
|
|
|
|
drawerShow.value = true;
|
|
|
|
}
|
|
|
|
activeFilter.value = index;
|
|
|
|
};
|
|
|
|
|
|
|
|
const selectDrawerItem = (item) => {
|
|
|
|
const currentFilterName = filterList.value[activeFilter.value];
|
|
|
|
selectedFilters.value[currentFilterName] = item;
|
|
|
|
drawerShow.value = false;
|
|
|
|
console.log('筛选条件更新:', selectedFilters.value);
|
|
|
|
};
|
|
|
|
|
|
|
|
// ====== 分类与计划 ======
|
|
|
|
const categoryList = ref([]);
|
|
|
|
const activeCategory = ref(0);
|
|
|
|
const planData = ref([]); // 存储所有已加载的计划(带 _categoryId)
|
|
|
|
const difficultyText = { 1: '初阶', 2: '中阶', 3: '高阶' };
|
|
|
|
// 完全匹配你后台的数字,复制这一段!
|
|
|
|
const filterMap = {
|
|
|
|
频率: {
|
|
|
|
不限: 0,
|
|
|
|
'1练/周': 1,
|
|
|
|
'2练/周': 2,
|
|
|
|
'3练/周': 3,
|
|
|
|
'4练/周': 4,
|
|
|
|
'5练/周': 5,
|
|
|
|
'6练/周': 6,
|
|
|
|
'7练/周': 7,
|
|
|
|
},
|
|
|
|
难度: { 不限: 0, 初阶: 1, 中阶: 2, 高阶: 3 },
|
|
|
|
场景: { 不限: 1, 健身房: 2, 仅哑铃: 3, '仅哑铃+杠铃': 4 },
|
|
|
|
人群: { 不限: 1, 青少年: 2, 成年人: 3, 中老年: 4, 运动损伤: 5 },
|
|
|
|
};
|
|
|
|
const currentPlanList = computed(() => {
|
|
|
|
const categoryId = categoryList.value[activeCategory.value]?.id;
|
|
|
|
if (categoryId == null) return [];
|
|
|
|
|
|
|
|
let list = planData.value.filter((p) => p._categoryId === categoryId);
|
|
|
|
|
|
|
|
// 频率
|
|
|
|
if (selectedFilters.value.频率 !== '不限') {
|
|
|
|
const val = filterMap.频率[selectedFilters.value.频率];
|
|
|
|
list = list.filter((item) => item.frequency === val);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 场景
|
|
|
|
if (selectedFilters.value.场景 !== '不限') {
|
|
|
|
const val = filterMap.场景[selectedFilters.value.场景];
|
|
|
|
list = list.filter((item) => item.scene === val);
|
|
|
|
}
|
|
|
|
// 难度
|
|
|
|
if (selectedFilters.value.难度 !== '不限') {
|
|
|
|
const val = filterMap.难度[selectedFilters.value.难度];
|
|
|
|
list = list.filter((item) => item.difficultyLevel === val);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 人群
|
|
|
|
if (selectedFilters.value.人群 !== '不限') {
|
|
|
|
const val = filterMap.人群[selectedFilters.value.人群];
|
|
|
|
list = list.filter((item) => item.population === val);
|
|
|
|
}
|
|
|
|
// 场景
|
|
|
|
if (selectedFilters.value.场景 !== '不限') {
|
|
|
|
const val = filterMap.场景[selectedFilters.value.场景];
|
|
|
|
list = list.filter((item) => item.scene === val);
|
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
});
|
|
|
|
// 人群
|
|
|
|
if (selectedFilters.value.人群 !== '不限') {
|
|
|
|
const val = filterMap.人群[selectedFilters.value.人群];
|
|
|
|
list = list.filter((item) => item.population === val);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ✅ 切换分类时加载数据
|
|
|
|
const switchCategory = async (index) => {
|
|
|
|
activeCategory.value = index;
|
|
|
|
const categoryId = categoryList.value[index]?.id;
|
|
|
|
if (categoryId != null) {
|
|
|
|
// 检查是否已加载过该分类
|
|
|
|
const isLoaded = planData.value.some((p) => p._categoryId === categoryId);
|
|
|
|
if (!isLoaded) {
|
|
|
|
await loadPlansByCategory(categoryId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// ====== 数据加载 ======
|
|
|
|
const loadCategories = async () => {
|
|
|
|
try {
|
|
|
|
// 获得计划分类,左侧导航栏显示用
|
|
|
|
const res = await QueryPlanApi.getCategories();
|
|
|
|
categoryList.value = res.data || [];
|
|
|
|
console.log('加载计划列表categoryList.value:', categoryList.value);
|
|
|
|
if (categoryList.value.length > 0) {
|
|
|
|
await switchCategory(0); // 加载第一个分类
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
console.error('加载分类失败:', err);
|
|
|
|
uni.showToast({ title: '加载分类失败', icon: 'none' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// ✅ 核心:加载计划,并手动附加 _categoryId
|
|
|
|
const loadPlansByCategory = async (categoryId) => {
|
|
|
|
try {
|
|
|
|
// 根据计划分类ID获得计划列表,右侧计划列表显示用
|
|
|
|
const res = await QueryPlanApi.getPlanList(categoryId);
|
|
|
|
console.log('加载计划列表res.data:', res.data);
|
|
|
|
const plans = (res.data || []).map((item) => ({
|
|
|
|
id: item.id,
|
|
|
|
title: item.name,
|
|
|
|
meta: `${difficultyText[item.difficultyLevel] || '初阶'} · ${item.enrollmentCount}人练过`,
|
|
|
|
tag: item.enrollmentCount > 500 ? '火爆' : item.enrollmentCount > 0 ? 'New' : '',
|
|
|
|
cover: item.urlCover || '默认图',
|
|
|
|
_categoryId: categoryId,
|
|
|
|
frequency: item.frequencyPerWeek, // 新增
|
|
|
|
difficultyLevel: item.difficultyLevel, // 新增
|
|
|
|
scene: item.trainingScene, // 新增
|
|
|
|
population: item.targetPeople, // 新增
|
|
|
|
}));
|
|
|
|
// 合并数据(避免重复)
|
|
|
|
planData.value = [...planData.value.filter((p) => p._categoryId !== categoryId), ...plans];
|
|
|
|
// 打印planData
|
|
|
|
console.log('加载计划列表planData.value:', planData.value);
|
|
|
|
} catch (err) {
|
|
|
|
console.error('加载计划失败:', err);
|
|
|
|
uni.showToast({ title: '加载计划失败', icon: 'none' });
|
|
|
|
return list;
|
|
|
|
});
|
|
|
|
|
|
|
|
// ✅ 切换分类时加载数据
|
|
|
|
const switchCategory = async (index) => {
|
|
|
|
activeCategory.value = index;
|
|
|
|
const categoryId = categoryList.value[index]?.id;
|
|
|
|
if (categoryId != null) {
|
|
|
|
// 检查是否已加载过该分类
|
|
|
|
const isLoaded = planData.value.some((p) => p._categoryId === categoryId);
|
|
|
|
if (!isLoaded) {
|
|
|
|
await loadPlansByCategory(categoryId);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// 跳转到搜索页面
|
|
|
|
const navigateToSearch = () => {
|
|
|
|
const app = getApp();
|
|
|
|
app.globalData.allPlansForSearch = planData.value;
|
|
|
|
uni.navigateTo({
|
|
|
|
url: '/pages4/pages/xunji/jihua-search',
|
|
|
|
});
|
|
|
|
};
|
|
|
|
// 跳转到计划详情页
|
|
|
|
const navigateToDetail = (plan) => {
|
|
|
|
uni.navigateTo({
|
|
|
|
url: `/pages4/pages/xunji/xunji-xunlian-jihua?planid=${plan.id}`,
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
// ====== 返回按钮 ======
|
|
|
|
const back = () => {
|
|
|
|
const pages = getCurrentPages();
|
|
|
|
if (pages.length > 1) {
|
|
|
|
uni.navigateBack();
|
|
|
|
} else {
|
|
|
|
uni.switchTab({ url: '/pages/index/index' }); // 请替换为你的首页路径
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// ====== 数据加载 ======
|
|
|
|
const loadCategories = async () => {
|
|
|
|
try {
|
|
|
|
// 获得计划分类,左侧导航栏显示用
|
|
|
|
const res = await QueryPlanApi.getCategories();
|
|
|
|
categoryList.value = res.data || [];
|
|
|
|
console.log('加载计划列表categoryList.value:', categoryList.value);
|
|
|
|
if (categoryList.value.length > 0) {
|
|
|
|
await switchCategory(0); // 加载第一个分类
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
loadCategories();
|
|
|
|
} catch (err) {
|
|
|
|
console.error('加载分类失败:', err);
|
|
|
|
uni.showToast({ title: '加载分类失败', icon: 'none' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// ✅ 核心:加载计划,并手动附加 _categoryId
|
|
|
|
const loadPlansByCategory = async (categoryId) => {
|
|
|
|
try {
|
|
|
|
// 根据计划分类ID获得计划列表,右侧计划列表显示用
|
|
|
|
const res = await QueryPlanApi.getPlanList(categoryId);
|
|
|
|
console.log('加载计划列表res.data:', res.data);
|
|
|
|
const plans = (res.data || []).map((item) => ({
|
|
|
|
id: item.id,
|
|
|
|
title: item.name,
|
|
|
|
meta: `${difficultyText[item.difficultyLevel] || '初阶'} · ${item.enrollmentCount}人练过`,
|
|
|
|
tag: item.enrollmentCount > 500 ? '火爆' : item.enrollmentCount > 0 ? 'New' : '',
|
|
|
|
cover: item.urlCover || '默认图',
|
|
|
|
_categoryId: categoryId,
|
|
|
|
frequency: item.frequencyPerWeek, // 新增
|
|
|
|
difficultyLevel: item.difficultyLevel, // 新增
|
|
|
|
scene: item.trainingScene, // 新增
|
|
|
|
population: item.targetPeople, // 新增
|
|
|
|
}));
|
|
|
|
// 合并数据(避免重复)
|
|
|
|
planData.value = [...planData.value.filter((p) => p._categoryId !== categoryId), ...plans];
|
|
|
|
// 打印planData
|
|
|
|
console.log('加载计划列表planData.value:', planData.value);
|
|
|
|
} catch (err) {
|
|
|
|
console.error('加载计划失败:', err);
|
|
|
|
uni.showToast({ title: '加载计划失败', icon: 'none' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// 跳转到搜索页面
|
|
|
|
const navigateToSearch = () => {
|
|
|
|
const app = getApp();
|
|
|
|
app.globalData.allPlansForSearch = planData.value;
|
|
|
|
uni.navigateTo({
|
|
|
|
url: '/pages4/pages/xunji/jihua-search',
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
/* ========== 新增:页面头部样式 ========== */
|
|
|
|
.page-header {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
padding: 30rpx;
|
|
|
|
background: #fff;
|
|
|
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
|
|
|
|
position: sticky;
|
|
|
|
top: 0;
|
|
|
|
z-index: 999;
|
|
|
|
};
|
|
|
|
// 跳转到计划详情页
|
|
|
|
const navigateToDetail = (plan) => {
|
|
|
|
uni.navigateTo({
|
|
|
|
url: `/pages4/pages/xunji/xunji-xunlian-jihua?planid=${plan.id}`,
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
// ====== 返回按钮 ======
|
|
|
|
const back = () => {
|
|
|
|
const pages = getCurrentPages();
|
|
|
|
if (pages.length > 1) {
|
|
|
|
uni.navigateBack();
|
|
|
|
} else {
|
|
|
|
uni.switchTab({ url: '/pages/index/index' }); // 请替换为你的首页路径
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
.page-title {
|
|
|
|
font-size: 32rpx;
|
|
|
|
font-weight: bold;
|
|
|
|
color: #333;
|
|
|
|
flex: 1;
|
|
|
|
text-align: center;
|
|
|
|
}
|
|
|
|
onMounted(() => {
|
|
|
|
loadCategories();
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
|
|
|
|
/* ========== 以下是你原有的全部样式(完全保留) ========== */
|
|
|
|
.plan-page {
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
/* ========== 新增:页面头部样式 ========== */
|
|
|
|
// .page-header {
|
|
|
|
// display: flex;
|
|
|
|
// align-items: center;
|
|
|
|
// padding: 30rpx;
|
|
|
|
// background: #fff;
|
|
|
|
// box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
|
|
|
|
// position: sticky;
|
|
|
|
// top: 0;
|
|
|
|
// z-index: 999;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// .page-title {
|
|
|
|
// font-size: 32rpx;
|
|
|
|
// font-weight: bold;
|
|
|
|
// color: #333;
|
|
|
|
// flex: 1;
|
|
|
|
// text-align: center;
|
|
|
|
// }
|
|
|
|
|
|
|
|
/* ========== 以下是你原有的全部样式(完全保留) ========== */
|
|
|
|
.plan-page {
|
|
|
|
width: 100%;
|
|
|
|
height: 100vh;
|
|
|
|
background-color: #f5f5f5;
|
|
|
|
box-sizing: border-box;
|
|
|
|
overflow: hidden;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 顶部横幅 */
|
|
|
|
.banner-wrapper {
|
|
|
|
height: 250rpx;
|
|
|
|
width: 100%;
|
|
|
|
margin: 20rpx 0;
|
|
|
|
|
|
|
|
.swiper {
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
background-color: #f5f5f5;
|
|
|
|
box-sizing: border-box;
|
|
|
|
overflow: hidden;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 顶部横幅 */
|
|
|
|
.banner-wrapper {
|
|
|
|
height: 250rpx;
|
|
|
|
width: 100%;
|
|
|
|
margin: 20rpx 0;
|
|
|
|
|
|
|
|
.swiper {
|
|
|
|
.swiper-item {
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
padding: 20rpx;
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
|
|
.swiper-item {
|
|
|
|
.img {
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
padding: 20rpx;
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
|
|
.img {
|
|
|
|
width: 100%;
|
|
|
|
height: 220rpx;
|
|
|
|
border-radius: 20rpx;
|
|
|
|
}
|
|
|
|
height: 220rpx;
|
|
|
|
border-radius: 20rpx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 筛选条 */
|
|
|
|
.filter-bar {
|
|
|
|
margin: 0 20rpx 20rpx;
|
|
|
|
padding: 12rpx 18rpx;
|
|
|
|
border-radius: 40rpx;
|
|
|
|
display: flex;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 筛选条 */
|
|
|
|
.filter-bar {
|
|
|
|
margin: 0 20rpx 20rpx;
|
|
|
|
padding: 12rpx 18rpx;
|
|
|
|
border-radius: 40rpx;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.03);
|
|
|
|
|
|
|
|
.filter-item {
|
|
|
|
flex-direction: row;
|
|
|
|
align-items: center;
|
|
|
|
box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.03);
|
|
|
|
|
|
|
|
.filter-item {
|
|
|
|
flex-direction: row;
|
|
|
|
align-items: center;
|
|
|
|
padding: 8rpx 18rpx;
|
|
|
|
border-radius: 30rpx;
|
|
|
|
border: 1px solid #c5c5c5;
|
|
|
|
margin-right: 10rpx;
|
|
|
|
background-color: #f7f7f7;
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
.text {
|
|
|
|
font-size: 24rpx;
|
|
|
|
color: #666;
|
|
|
|
margin-right: 6rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
&.active {
|
|
|
|
background-color: #e6f7f0;
|
|
|
|
|
|
|
|
.text {
|
|
|
|
color: #26c165;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.filter-search {
|
|
|
|
margin-left: auto;
|
|
|
|
width: 56rpx;
|
|
|
|
height: 56rpx;
|
|
|
|
border-radius: 50%;
|
|
|
|
background-color: #f7f7f7;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
padding: 8rpx 18rpx;
|
|
|
|
border-radius: 30rpx;
|
|
|
|
border: 1px solid #c5c5c5;
|
|
|
|
margin-right: 10rpx;
|
|
|
|
background-color: #f7f7f7;
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
//下拉抽屉
|
|
|
|
.filter-drawer {
|
|
|
|
position: absolute;
|
|
|
|
top: 560rpx;
|
|
|
|
left: 20rpx;
|
|
|
|
right: 20rpx;
|
|
|
|
z-index: 999;
|
|
|
|
border-radius: 0 0 40rpx 40rpx;
|
|
|
|
background-color: #fff;
|
|
|
|
box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.06);
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
|
|
.drawer-content {
|
|
|
|
padding: 10rpx 0;
|
|
|
|
.text {
|
|
|
|
font-size: 24rpx;
|
|
|
|
color: #666;
|
|
|
|
margin-right: 6rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.drawer-item {
|
|
|
|
padding: 20rpx 30rpx;
|
|
|
|
font-size: 26rpx;
|
|
|
|
color: #333;
|
|
|
|
transition: background-color 0.2s ease;
|
|
|
|
&.active {
|
|
|
|
background-color: #e6f7f0;
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
background-color: #f5f5f5;
|
|
|
|
}
|
|
|
|
|
|
|
|
.drawer-item-text {
|
|
|
|
display: block;
|
|
|
|
width: 100%;
|
|
|
|
.text {
|
|
|
|
color: #26c165;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 主体布局 */
|
|
|
|
.content-layout {
|
|
|
|
flex: 1;
|
|
|
|
.filter-search {
|
|
|
|
margin-left: auto;
|
|
|
|
width: 56rpx;
|
|
|
|
height: 56rpx;
|
|
|
|
border-radius: 50%;
|
|
|
|
background-color: #f7f7f7;
|
|
|
|
display: flex;
|
|
|
|
box-sizing: border-box;
|
|
|
|
overflow: hidden;
|
|
|
|
min-height: 0;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//下拉抽屉
|
|
|
|
.filter-drawer {
|
|
|
|
position: absolute;
|
|
|
|
top: 560rpx;
|
|
|
|
|
|
|
|
/* #ifdef H5 */
|
|
|
|
top: 247px;
|
|
|
|
/* #endif */
|
|
|
|
|
|
|
|
left: 20rpx;
|
|
|
|
right: 20rpx;
|
|
|
|
z-index: 999;
|
|
|
|
border-radius: 0 0 40rpx 40rpx;
|
|
|
|
background-color: #fff;
|
|
|
|
box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.06);
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
|
|
.drawer-content {
|
|
|
|
padding: 10rpx 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 左侧分类 */
|
|
|
|
.sidebar {
|
|
|
|
width: 180rpx;
|
|
|
|
background-color: #ffffff;
|
|
|
|
border-radius: 16rpx;
|
|
|
|
height: 100%;
|
|
|
|
box-sizing: border-box;
|
|
|
|
overflow: hidden;
|
|
|
|
.drawer-item {
|
|
|
|
padding: 20rpx 30rpx;
|
|
|
|
font-size: 26rpx;
|
|
|
|
color: #333;
|
|
|
|
transition: background-color 0.2s ease;
|
|
|
|
|
|
|
|
.category-item {
|
|
|
|
padding: 22rpx 24rpx;
|
|
|
|
font-size: 24rpx;
|
|
|
|
color: #666;
|
|
|
|
position: relative;
|
|
|
|
&:active {
|
|
|
|
background-color: #f5f5f5;
|
|
|
|
}
|
|
|
|
|
|
|
|
&.active {
|
|
|
|
background-color: #e8f8f0;
|
|
|
|
color: #26c165;
|
|
|
|
font-weight: 600;
|
|
|
|
.drawer-item-text {
|
|
|
|
display: block;
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 主体布局 */
|
|
|
|
.content-layout {
|
|
|
|
flex: 1;
|
|
|
|
display: flex;
|
|
|
|
box-sizing: border-box;
|
|
|
|
overflow: hidden;
|
|
|
|
min-height: 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 左侧分类 */
|
|
|
|
.sidebar {
|
|
|
|
width: 180rpx;
|
|
|
|
background-color: #ffffff;
|
|
|
|
border-radius: 16rpx;
|
|
|
|
height: 72%;
|
|
|
|
/* #ifdef H5 */
|
|
|
|
height: 86%;
|
|
|
|
/* #endif */
|
|
|
|
box-sizing: border-box;
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
|
|
.category-item {
|
|
|
|
padding: 22rpx 24rpx;
|
|
|
|
font-size: 24rpx;
|
|
|
|
color: #666;
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
&::before {
|
|
|
|
content: '';
|
|
|
|
position: absolute;
|
|
|
|
right: 0;
|
|
|
|
top: 16rpx;
|
|
|
|
bottom: 16rpx;
|
|
|
|
width: 6rpx;
|
|
|
|
border-radius: 0 4rpx 4rpx 0;
|
|
|
|
background-color: #26c165;
|
|
|
|
}
|
|
|
|
&.active {
|
|
|
|
background-color: #e8f8f0;
|
|
|
|
color: #26c165;
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
|
|
&::before {
|
|
|
|
content: '';
|
|
|
|
position: absolute;
|
|
|
|
right: 0;
|
|
|
|
top: 16rpx;
|
|
|
|
bottom: 16rpx;
|
|
|
|
width: 6rpx;
|
|
|
|
border-radius: 0 4rpx 4rpx 0;
|
|
|
|
background-color: #26c165;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 右侧计划列表 */
|
|
|
|
.plan-list-wrap {
|
|
|
|
flex: 1;
|
|
|
|
padding: 0 20rpx;
|
|
|
|
box-sizing: border-box;
|
|
|
|
height: 100%;
|
|
|
|
overflow: hidden;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 右侧计划列表 */
|
|
|
|
.plan-list-wrap {
|
|
|
|
flex: 1;
|
|
|
|
padding: 0 20rpx;
|
|
|
|
box-sizing: border-box;
|
|
|
|
height: 72%;
|
|
|
|
/* #ifdef H5 */
|
|
|
|
height: 86%;
|
|
|
|
/* #endif */
|
|
|
|
overflow: hidden;
|
|
|
|
}
|
|
|
|
|
|
|
|
.plan-card {
|
|
|
|
position: relative;
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
|
|
|
.plan-cover {
|
|
|
|
width: 100%;
|
|
|
|
height: 230rpx;
|
|
|
|
border-radius: 5rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.plan-card {
|
|
|
|
position: relative;
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
|
|
|
.plan-cover {
|
|
|
|
width: 100%;
|
|
|
|
height: 230rpx;
|
|
|
|
border-radius: 5rpx;
|
|
|
|
}
|
|
|
|
.plan-info {
|
|
|
|
position: absolute;
|
|
|
|
left: 20rpx;
|
|
|
|
right: 20rpx;
|
|
|
|
bottom: 20rpx;
|
|
|
|
color: #fff;
|
|
|
|
|
|
|
|
.plan-info {
|
|
|
|
position: absolute;
|
|
|
|
left: 20rpx;
|
|
|
|
right: 20rpx;
|
|
|
|
bottom: 20rpx;
|
|
|
|
color: #fff;
|
|
|
|
|
|
|
|
.plan-tag-row {
|
|
|
|
margin-bottom: 8rpx;
|
|
|
|
|
|
|
|
.plan-tag {
|
|
|
|
display: inline-flex;
|
|
|
|
padding: 4rpx 10rpx;
|
|
|
|
border-radius: 6rpx;
|
|
|
|
font-size: 20rpx;
|
|
|
|
line-height: 1;
|
|
|
|
|
|
|
|
&.tag-hot {
|
|
|
|
background-color: #ff4d4f;
|
|
|
|
}
|
|
|
|
|
|
|
|
&.tag-new {
|
|
|
|
background-color: #ffbb00;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.plan-tag-row {
|
|
|
|
margin-bottom: 8rpx;
|
|
|
|
|
|
|
|
.plan-text {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
.plan-tag {
|
|
|
|
display: inline-flex;
|
|
|
|
padding: 4rpx 10rpx;
|
|
|
|
border-radius: 6rpx;
|
|
|
|
font-size: 20rpx;
|
|
|
|
line-height: 1;
|
|
|
|
|
|
|
|
.plan-title {
|
|
|
|
font-size: 28rpx;
|
|
|
|
font-weight: 600;
|
|
|
|
margin-bottom: 6rpx;
|
|
|
|
&.tag-hot {
|
|
|
|
background-color: #ff4d4f;
|
|
|
|
}
|
|
|
|
|
|
|
|
.plan-meta {
|
|
|
|
font-size: 22rpx;
|
|
|
|
color: rgba(255, 255, 255, 0.8);
|
|
|
|
&.tag-new {
|
|
|
|
background-color: #ffbb00;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 空状态 */
|
|
|
|
.empty-tip {
|
|
|
|
text-align: center;
|
|
|
|
padding: 100rpx 0;
|
|
|
|
color: #999;
|
|
|
|
font-size: 28rpx;
|
|
|
|
.plan-text {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
.plan-title {
|
|
|
|
font-size: 28rpx;
|
|
|
|
font-weight: 600;
|
|
|
|
margin-bottom: 6rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.plan-meta {
|
|
|
|
font-size: 22rpx;
|
|
|
|
color: rgba(255, 255, 255, 0.8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 空状态 */
|
|
|
|
.empty-tip {
|
|
|
|
text-align: center;
|
|
|
|
padding: 100rpx 0;
|
|
|
|
color: #999;
|
|
|
|
font-size: 28rpx;
|
|
|
|
}
|
|
|
|
</style> |
...
|
...
|
|