application [cat-mini-app] view page [pages/shop] development
This commit is contained in:
@@ -35,6 +35,12 @@
|
|||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "预约排队"
|
"navigationBarTitleText": "预约排队"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/shop",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "猫咪用品商城"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"globalStyle": {
|
"globalStyle": {
|
||||||
|
|||||||
151
apps/cat-mini-app/src/pages/shop.vue
Normal file
151
apps/cat-mini-app/src/pages/shop.vue
Normal 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>
|
||||||
Reference in New Issue
Block a user