application [cat-mini-app] view page [pages/shop] development

This commit is contained in:
NVWA Code Agent
2025-12-11 16:43:34 +00:00
parent 44cc8e98f2
commit f09876ad2b
2 changed files with 157 additions and 0 deletions

View File

@@ -35,6 +35,12 @@
"style": {
"navigationBarTitleText": "预约排队"
}
},
{
"path": "pages/shop",
"style": {
"navigationBarTitleText": "猫咪用品商城"
}
}
],
"globalStyle": {

View File

@@ -0,0 +1,151 @@
<template>
<view class="container bg-gray-100 min-h-screen">
<!-- 页面标题 -->
<view class="bg-white px-4 py-3 shadow-sm">
<text class="text-lg font-bold text-gray-800">猫咪用品商城</text>
</view>
<!-- 商品分类筛选 (如果有分类的话暂时隐藏) -->
<!-- <view class="bg-white mt-2 px-4 py-2">
<scroll-view scroll-x class="flex space-x-2">
<view class="px-3 py-1 bg-blue-500 text-white rounded-full text-sm" v-for="cat in categories" :key="cat.id">
{{ cat.name }}
</view>
</scroll-view>
</view> -->
<!-- 商品列表 -->
<view class="px-4 py-4">
<view v-if="loading" class="text-center py-8">
<text class="text-gray-500">加载中...</text>
</view>
<view v-else-if="products.length === 0" class="text-center py-8">
<text class="text-gray-500">暂无商品</text>
</view>
<view v-else class="grid grid-cols-2 gap-4">
<view
v-for="product in products"
:key="product.id"
class="bg-white rounded-lg shadow-sm overflow-hidden"
>
<!-- 商品图片 (暂时使用占位图) -->
<view class="h-32 bg-gray-200 flex items-center justify-center">
<text class="text-gray-400 text-sm">商品图片</text>
</view>
<!-- 商品信息 -->
<view class="p-3">
<text class="text-sm font-medium text-gray-800 block mb-1">{{ product.name }}</text>
<text class="text-xs text-gray-600 block mb-2 line-clamp-2">{{ product.description }}</text>
<view class="flex justify-between items-center">
<text class="text-red-500 font-bold">¥{{ product.price }}</text>
<text class="text-xs text-gray-500">库存: {{ product.stock }}</text>
</view>
</view>
</view>
</view>
<!-- 分页 -->
<view v-if="products.length > 0" class="mt-6 flex justify-center space-x-2">
<button
class="px-4 py-2 bg-blue-500 text-white rounded disabled:bg-gray-300"
:disabled="page <= 1"
@click="changePage(page - 1)"
>
上一页
</button>
<text class="px-4 py-2 text-gray-700"> {{ page }} </text>
<button
class="px-4 py-2 bg-blue-500 text-white rounded disabled:bg-gray-300"
:disabled="products.length < 10"
@click="changePage(page + 1)"
>
下一页
</button>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { entities } from '@/lib/nvwa'
// 定义商品接口
interface Product {
id: number
name: string
description: string
price: string
stock: number
image_ids: number[]
created_at: string
updated_at: string
}
// 响应式数据
const products = ref<Product[]>([])
const loading = ref(false)
const page = ref(1)
const pageSize = 10
// 获取页面参数
const query = uni.getEnterOptionsSync?.()?.query || {}
if (query.page) {
page.value = parseInt(query.page as string) || 1
}
// 加载商品列表
const loadProducts = async () => {
loading.value = true
try {
const offset = (page.value - 1) * pageSize
const { data, error } = await entities
.from('product')
.select('*')
.range(offset, offset + pageSize - 1)
if (error) {
console.error('加载商品失败:', error)
uni.showToast({
title: '加载失败',
icon: 'none'
})
} else {
products.value = data || []
}
} catch (err) {
console.error('加载商品出错:', err)
uni.showToast({
title: '加载出错',
icon: 'none'
})
} finally {
loading.value = false
}
}
// 切换页面
const changePage = (newPage: number) => {
page.value = newPage
loadProducts()
// 更新 URL 参数
uni.setNavigationBarTitle({
title: `猫咪用品商城 - 第${page.value}`
})
}
// 页面挂载时加载数据
onMounted(() => {
loadProducts()
})
</script>
<style scoped>
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
</style>