Files
ShaFaFanXin/前端/pages/cases/list.uvue

287 lines
6.0 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="page">
<!-- 分类筛选 -->
<view class="category-bar">
<scroll-view class="category-scroll" scroll-x>
<view class="category-list">
<view
class="category-item"
:class="{ 'category-active': currentCategory == item.id }"
v-for="item in categories"
:key="item.id"
@click="selectCategory(item.id)"
>
<text
class="category-text"
:class="{ 'category-text-active': currentCategory == item.id }"
>{{ item.name }}</text>
</view>
</view>
</scroll-view>
</view>
<!-- 案例列表 -->
<scroll-view
class="case-scroll"
scroll-y
@scrolltolower="loadMore"
>
<view class="case-list">
<case-card
v-for="item in caseList"
:key="item.id"
:caseData="item"
@click="goToDetail"
></case-card>
</view>
<!-- 加载状态 -->
<view class="load-status">
<text class="load-text" v-if="loading">加载中...</text>
<text class="load-text" v-else-if="noMore">没有更多了</text>
</view>
<!-- 空状态 -->
<view class="empty-state" v-if="!loading && caseList.length == 0">
<text class="empty-icon">📭</text>
<text class="empty-text">暂无相关案例</text>
</view>
<!-- 底部间距 -->
<view class="bottom-space"></view>
</scroll-view>
</view>
</template>
<script setup lang="uts">
import { getCaseList } from '@/api/index.uts'
import { SOFA_CATEGORIES, PAGE_SIZE, getServiceTypeName } from '@/utils/config.uts'
// 分类类型
type CategoryItem = {
id : string
name : string
}
// 案例类型
type CaseItem = {
id : string
title : string
category : string
categoryName : string
coverImage : string
material : string
duration : string
price : string
views : number
likes : number
}
// 分类列表
const categories = ref<CategoryItem[]>([])
// 当前分类
const currentCategory = ref('all')
// 案例列表
const caseList = ref<CaseItem[]>([])
// 分页
const page = ref(1)
const total = ref(0)
// 加载状态
const loading = ref(false)
const noMore = ref(false)
// 初始化分类
const initCategories = () => {
categories.value = SOFA_CATEGORIES.map((item) : CategoryItem => {
return {
id: item.id,
name: item.name
} as CategoryItem
})
}
// 选择分类
const selectCategory = (id : string) => {
if (currentCategory.value == id) return
currentCategory.value = id
page.value = 1
caseList.value = []
noMore.value = false
console.log(111)
fetchCaseList()
}
// 获取案例列表
const fetchCaseList = async () => {
if (loading.value || noMore.value) return
loading.value = true
try {
const params = {
serviceType: currentCategory.value != 'all' ? currentCategory.value : undefined,
page: page.value,
limit: PAGE_SIZE,
status: 'published'
} as UTSJSONObject
const res = await getCaseList(params)
if (res.code == 0 && res.data != null) {
const data = res.data as UTSJSONObject
// 适应后端返回格式:{ list: [], total: 0, page: 1, pageSize: 10 }
const list = data['list'] as UTSJSONObject[] || []
total.value = data['total'] as number || 0
const newList = list.map((item) : CaseItem => {
// 优先使用images其次afterImages最后beforeImages
const images = item['images'] as string[] || []
const afterImages = item['afterImages'] as string[] || []
const beforeImages = item['beforeImages'] as string[] || []
const coverImage = images.length > 0 ? images[0] : (afterImages.length > 0 ? afterImages[0] : (beforeImages.length > 0 ? beforeImages[0] : ''))
return {
id: String(item['id']),
title: item['title'] as string,
category: item['serviceType'] as string,
categoryName: getServiceTypeName(item['serviceType'] as string),
coverImage: coverImage,
material: item['materials'] as string || '暂无',
duration: (item['duration'] as number || 0) + '天',
price: item['price'] != null ? '¥' + item['price'] : '面议',
views: item['views'] as number || 0,
likes: item['likes'] as number || 0
} as CaseItem
})
if (page.value == 1) {
caseList.value = newList
} else {
caseList.value = [...caseList.value, ...newList]
}
if (caseList.value.length >= total.value) {
noMore.value = true
}
}
} catch (e) {
console.error('获取案例列表失败', e)
uni.showToast({
title: '加载失败',
icon: 'none'
})
}
loading.value = false
}
// 加载更多
const loadMore = () => {
if (!noMore.value && !loading.value) {
page.value++
fetchCaseList()
}
}
// 跳转详情
const goToDetail = (id : string) => {
uni.navigateTo({
url: `/pages/cases/detail?id=${id}`
})
}
onLoad(() => {
initCategories()
fetchCaseList()
})
</script>
<style lang="scss">
.page {
flex: 1;
background-color: #f5f5f5;
}
/* 分类栏 */
.category-bar {
background-color: #ffffff;
padding: 24rpx 0;
border-bottom-width: 1rpx;
border-bottom-style: solid;
border-bottom-color: #EBEEF5;
}
.category-scroll {
flex-direction: row;
}
.category-scroll ::-webkit-scrollbar {
display: none;
}
.category-list {
flex-direction: row;
padding: 0 24rpx;
}
.category-item {
padding: 16rpx 32rpx;
margin-right: 16rpx;
border-radius: 999rpx;
background-color: #f5f5f5;
}
.category-active {
background-color: #D4A574;
}
.category-text {
font-size: 28rpx;
color: #606266;
}
.category-text-active {
color: #ffffff;
}
/* 案例列表 */
.case-scroll {
flex: 1;
}
.case-list {
padding: 24rpx;
}
/* 加载状态 */
.load-status {
padding: 32rpx 0;
align-items: center;
}
.load-text {
font-size: 26rpx;
color: #909399;
}
/* 空状态 */
.empty-state {
padding: 120rpx 0;
align-items: center;
}
.empty-icon {
font-size: 80rpx;
margin-bottom: 24rpx;
}
.empty-text {
font-size: 28rpx;
color: #909399;
}
/* 底部间距 */
.bottom-space {
height: 120rpx;
}
</style>