application [cat-mini-app] view page [pages/cats] development
This commit is contained in:
@@ -23,6 +23,12 @@
|
||||
"style": {
|
||||
"navigationBarTitleText": "种公种母介绍"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/cats",
|
||||
"style": {
|
||||
"navigationBarTitleText": "猫咪情况"
|
||||
}
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
|
||||
295
apps/cat-mini-app/src/pages/cats.vue
Normal file
295
apps/cat-mini-app/src/pages/cats.vue
Normal file
@@ -0,0 +1,295 @@
|
||||
<template>
|
||||
<view class="cats-page">
|
||||
<!-- 列表模式 -->
|
||||
<view v-if="!detailId" class="cats-list">
|
||||
<uni-list>
|
||||
<uni-list-item v-for="cat in cats" :key="cat.id" :show-arrow="true" @click="goToDetail(cat.id)">
|
||||
<view class="cat-item">
|
||||
<view class="cat-image">
|
||||
<image v-if="cat.images && cat.images.length > 0" :src="cat.images[0].url" mode="aspectFit" />
|
||||
<view v-else class="no-image">暂无图片</view>
|
||||
</view>
|
||||
<view class="cat-info">
|
||||
<view class="cat-name">{{ cat.name }}</view>
|
||||
<view class="cat-details">
|
||||
年龄: {{ getAgeString(cat.age) }} |
|
||||
等级: {{ cat.grade }} |
|
||||
性别: {{ cat.gender === 'male' ? '公' : '母' }} |
|
||||
类型: {{ getTypeString(cat.type) }} |
|
||||
状态: {{ cat.is_available ? '可售卖' : '不可售卖' }}
|
||||
</view>
|
||||
<view v-if="cat.description" class="cat-description">{{ cat.description }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-list-item>
|
||||
</uni-list>
|
||||
<view class="pagination">
|
||||
<uni-pagination
|
||||
v-model="currentPage"
|
||||
:total="totalCats"
|
||||
:page-size="pageSize"
|
||||
@change="onPageChange"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 详情模式 -->
|
||||
<view v-else class="cat-detail">
|
||||
<view v-if="currentCat">
|
||||
<view class="cat-header">
|
||||
<view class="cat-name">{{ currentCat.name }}</view>
|
||||
<view class="cat-status">
|
||||
<uni-tag :text="currentCat.is_available ? '可售卖' : '不可售卖'" :type="currentCat.is_available ? 'success' : 'error'" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="cat-images">
|
||||
<image v-for="image in currentCat.images" :key="image.id" :src="image.url" mode="aspectFit" />
|
||||
</view>
|
||||
<view class="cat-details">
|
||||
<view>年龄: {{ getAgeString(currentCat.age) }}</view>
|
||||
<view>等级: {{ currentCat.grade }}</view>
|
||||
<view>性别: {{ currentCat.gender === 'male' ? '公' : '母' }}</view>
|
||||
<view>类型: {{ getTypeString(currentCat.type) }}</view>
|
||||
<view v-if="currentCat.description">描述: {{ currentCat.description }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else>加载中...</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { entities } from '@/lib/nvwa'
|
||||
import type { Cat } from '@/types/cat' // 假设有类型定义
|
||||
|
||||
const detailId = ref<number | null>(null)
|
||||
const cats = ref<Cat[]>([])
|
||||
const currentCat = ref<Cat | null>(null)
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(10)
|
||||
const totalCats = ref(0)
|
||||
|
||||
const getAgeString = (ageInMonths: number) => {
|
||||
const years = Math.floor(ageInMonths / 12)
|
||||
const months = ageInMonths % 12
|
||||
if (years > 0) {
|
||||
return `${years}岁${months}个月`
|
||||
}
|
||||
return `${months}个月`
|
||||
}
|
||||
|
||||
const getTypeString = (type: string) => {
|
||||
const typeMap = {
|
||||
breeding_male: '种公',
|
||||
breeding_female: '种母',
|
||||
kitten: '幼猫'
|
||||
}
|
||||
return typeMap[type] || type
|
||||
}
|
||||
|
||||
const loadCats = async (page: number) => {
|
||||
try {
|
||||
const offset = (page - 1) * pageSize.value
|
||||
const { data, error } = await entities
|
||||
.from('cat')
|
||||
.select('id, name, age, gender, grade, type, is_available, description, image_ids')
|
||||
.range(offset, offset + pageSize.value - 1)
|
||||
|
||||
if (error) {
|
||||
console.error('Error loading cats:', error)
|
||||
return
|
||||
}
|
||||
|
||||
cats.value = data || []
|
||||
|
||||
// 加载图片信息
|
||||
for (const cat of cats.value) {
|
||||
if (cat.image_ids && cat.image_ids.length > 0) {
|
||||
const { data: images } = await entities
|
||||
.from('nvwa_attribute_file')
|
||||
.select('id, url')
|
||||
.in('id', cat.image_ids)
|
||||
cat.images = images || []
|
||||
} else {
|
||||
cat.images = []
|
||||
}
|
||||
}
|
||||
|
||||
// 获取总数
|
||||
const { count } = await entities
|
||||
.from('cat')
|
||||
.select('*', { count: 'exact', head: true })
|
||||
totalCats.value = count || 0
|
||||
} catch (e) {
|
||||
console.error('Failed to load cats:', e)
|
||||
}
|
||||
}
|
||||
|
||||
const loadCatDetail = async (id: number) => {
|
||||
try {
|
||||
const { data, error } = await entities
|
||||
.from('cat')
|
||||
.select('id, name, age, gender, grade, type, is_available, description, image_ids')
|
||||
.eq('id', id)
|
||||
.single()
|
||||
|
||||
if (error) {
|
||||
console.error('Error loading cat detail:', error)
|
||||
return
|
||||
}
|
||||
|
||||
currentCat.value = data
|
||||
|
||||
// 加载图片
|
||||
if (currentCat.value.image_ids && currentCat.value.image_ids.length > 0) {
|
||||
const { data: images } = await entities
|
||||
.from('nvwa_attribute_file')
|
||||
.select('id, url')
|
||||
.in('id', currentCat.value.image_ids)
|
||||
currentCat.value.images = images || []
|
||||
} else {
|
||||
currentCat.value.images = []
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to load cat detail:', e)
|
||||
}
|
||||
}
|
||||
|
||||
const goToDetail = (id: number) => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/cats?id=${id}`
|
||||
})
|
||||
}
|
||||
|
||||
const onPageChange = (page: number) => {
|
||||
currentPage.value = page
|
||||
loadCats(page)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const pages = getCurrentPages()
|
||||
const currentPageInstance = pages[pages.length - 1]
|
||||
const query = currentPageInstance.$page.options || {}
|
||||
|
||||
if (query.id) {
|
||||
detailId.value = parseInt(query.id as string)
|
||||
loadCatDetail(detailId.value)
|
||||
} else {
|
||||
const page = parseInt(query.page as string) || 1
|
||||
currentPage.value = page
|
||||
loadCats(page)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.cats-page {
|
||||
background-color: #f8f8f8;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.cats-list {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.cat-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
background-color: white;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 10px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.cat-image {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin-right: 10px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
background-color: #eee;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.cat-image image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.no-image {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.cat-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.cat-name {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.cat-details {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.cat-description {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.cat-detail {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.cat-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.cat-name {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.cat-images {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.cat-images image {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.cat-details {
|
||||
background-color: white;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.cat-details view {
|
||||
margin-bottom: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user