| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- <template>
- <view class="container">
- <!-- 搜索/分类 -->
- <view class="filter-bar">
- <view class="search-box">
- <input class="search-input" v-model="keyword" placeholder="搜索任务模板" @confirm="search" />
- </view>
- <view class="categories">
- <text
- class="cat-item"
- :class="{ active: !currentCategory }"
- @click="selectCategory('')"
- >全部</text>
- <text
- class="cat-item"
- v-for="cat in categories"
- :key="cat"
- :class="{ active: currentCategory === cat }"
- @click="selectCategory(cat)"
- >{{ cat }}</text>
- </view>
- </view>
- <!-- 任务模板列表 -->
- <view class="package-list">
- <view
- class="package-card"
- v-for="pkg in packages"
- :key="pkg.id"
- @click="goToDetail(pkg.id)"
- >
- <image class="package-cover" :src="getImageUrl(pkg.coverImage) || '/static/default-cover.png'" mode="aspectFill" />
- <view class="package-content">
- <text class="package-name">{{ pkg.name }}</text>
- <text class="package-desc">{{ pkg.description }}</text>
- <view class="package-meta">
- <text class="meta-item">{{ pkg.cycleDays }}天</text>
- <text class="meta-item">{{ pkg.category }}</text>
- <text class="price">{{ formatPriceWithSymbol(pkg.price) }}</text>
- </view>
- </view>
- </view>
- </view>
- <!-- 空状态 -->
- <view class="empty" v-if="packages.length === 0">
- <text>暂无任务模板</text>
- </view>
- </view>
- </template>
- <script>
- import { getPublicPackages } from '@/utils/api.js'
- import config from '@/config.js'
- export default {
- data() {
- return {
- packages: [],
- keyword: '',
- currentCategory: '',
- categories: ['学习', '习惯', '健康', '情绪', '其他']
- }
- },
- onShow() {
- this.loadPackages()
- },
- methods: {
- async loadPackages() {
- try {
- const res = await getPublicPackages(this.currentCategory)
- this.packages = res.data || []
- } catch (e) {
- console.error(e)
- }
- },
- selectCategory(cat) {
- this.currentCategory = cat
- this.loadPackages()
- },
- search() {
- // 简单筛选
- if (this.keyword) {
- this.packages = this.packages.filter(p => p.name.includes(this.keyword))
- } else {
- this.loadPackages()
- }
- },
- goToDetail(id) {
- uni.navigateTo({
- url: `/pages/parent/market/detail?id=${id}`
- })
- },
- getImageUrl: function(path) {
- return config.API_BASE_URL + path
- }
- }
- }
- </script>
- <style scoped>
- .container { min-height: 100vh; background: #f5f5f5; }
- .filter-bar { background: #fff; padding: 20rpx; margin-bottom: 10rpx; }
- .search-box { margin-bottom: 20rpx; }
- .search-input { padding: 16rpx 20rpx; background: #f5f5f5; border-radius: 30rpx; font-size: 28rpx; }
- .categories { display: flex; gap: 20rpx; overflow-x: auto; }
- .cat-item { font-size: 26rpx; color: #666; padding: 10rpx 20rpx; white-space: nowrap; }
- .cat-item.active { color: #4CAF50; font-weight: bold; }
- .package-list { padding: 20rpx; display: flex; flex-direction: column; gap: 20rpx; }
- .package-card { background: #fff; border-radius: 16rpx; overflow: hidden; box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.05); }
- .package-cover { width: 100%; height: 300rpx; }
- .package-content { padding: 20rpx; }
- .package-name { font-size: 32rpx; font-weight: bold; color: #333; display: block; margin-bottom: 10rpx; }
- .package-desc { font-size: 26rpx; color: #999; display: block; margin-bottom: 16rpx; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
- .package-meta { display: flex; align-items: center; gap: 20rpx; }
- .meta-item { font-size: 24rpx; color: #666; }
- .price { font-size: 32rpx; color: #f44336; font-weight: bold; margin-left: auto; }
- .empty { display: flex; justify-content: center; padding: 100rpx; color: #999; }
- </style>
|