fix(api): 替换所有接口请求的域名为 guilixu-api.websoft.top

- 将获取 STS Token 的接口地址由 paopao-api 改为 guilixu-api
- 更新图片上传接口地址为新的 guilixu-api 域名
- 修改用户推广页面中邀请码链接和二维码接口的域名
- 更改注册页微信登录接口请求的域名为 guilixu-api
This commit is contained in:
2026-06-16 17:15:59 +08:00
commit f3886664f7
617 changed files with 77059 additions and 0 deletions

231
src/pages/shop/cart.tsx Normal file
View File

@@ -0,0 +1,231 @@
import React, { useEffect, useState } from 'react'
import { View, Text, Image, ScrollView } from '@tarojs/components'
import Taro from '@tarojs/taro'
import { useCartContext } from '@/contexts/CartContext'
import { useUserContext } from '@/contexts/UserContext'
import { pageShopGoods } from '@/api/shop/shopGoods'
import type { ShopGoods } from '@/api/shop/shopGoods/model'
import EmptyState from '@/components/common/EmptyState'
import Loading from '@/components/common/Loading'
definePageConfig({
navigationBarTitleText: '购物车',
})
const CartPage: React.FC = () => {
const { items, selectedCount, selectedPrice, updateQuantity, toggleSelect, selectAll, removeItem, refresh, loading, removeSelected, addItem } = useCartContext()
const { isLoggedIn } = useUserContext()
const [recommendPage, setRecommendPage] = useState(1)
const [refreshingRecommend, setRefreshingRecommend] = useState(false)
useEffect(() => {
if (isLoggedIn) {
refresh()
fetchRecommendGoods(1)
}
}, [isLoggedIn])
const fetchRecommendGoods = async (page?: number) => {
const targetPage = page || recommendPage
try {
setRefreshingRecommend(true)
const res = await pageShopGoods({ page: targetPage, limit: 6 })
if (res && res.list && res.list.length > 0) {
setRecommendGoods(res.list || [])
setRecommendPage(targetPage + 1)
} else {
// 没有更多数据时回到第一页重新请求
if (targetPage > 1) {
const firstRes = await pageShopGoods({ page: 1, limit: 6 })
setRecommendGoods(firstRes?.list || [])
setRecommendPage(2)
} else {
setRecommendGoods([])
}
}
} catch (err) {
console.error('获取推荐商品失败', err)
} finally {
setRefreshingRecommend(false)
}
}
// 换一批
const handleRefreshRecommend = () => {
if (!refreshingRecommend) {
fetchRecommendGoods()
}
}
const handleCheckout = () => {
if (selectedCount === 0) {
Taro.showToast({ title: '请选择商品', icon: 'none' })
return
}
Taro.navigateTo({ url: '/pages/shop/checkout' })
}
// 未登录状态
if (!isLoggedIn) {
return (
<View className="min-h-screen bg-gray-50 flex flex-col">
<View className="flex-1 flex items-center justify-center">
<EmptyState
text="请先登录"
actionText="去登录"
onAction={() => Taro.navigateTo({ url: '/pages/passport/login' })}
/>
</View>
</View>
)
}
return (
<View className="flex flex-col min-h-screen">
{/* 主要内容区域 - 使用ScrollView实现滚动 */}
<ScrollView scrollY className="flex-1 bg-gray-50">
{items.length === 0 && !loading ? (
<View className="flex items-center justify-center py-20">
<EmptyState text="购物车是空的" actionText="去逛逛" onAction={() => Taro.switchTab({ url: '/pages/index/index' })} />
</View>
) : (
<View className="p-3">
{/* 全选 */}
<View className="flex items-center justify-between mb-3">
<View className="flex items-center gap-2">
<View
className="w-5 h-5 rounded-full border border-gray-300 flex items-center justify-center"
onClick={() => selectAll(!items.every(i => i.checked))}
style={{ backgroundColor: items.length > 0 && items.every(i => i.checked) ? '#0e932e' : 'transparent' }}
>
{items.length > 0 && items.every(i => i.checked) && <Text className="text-white text-xs"></Text>}
</View>
<Text className="text-sm text-gray-600"></Text>
</View>
{selectedCount > 0 && (
<View onClick={removeSelected}>
<Text className="text-xs text-gray-400"></Text>
</View>
)}
</View>
{/* 商品列表 */}
{loading ? (
<Loading />
) : (
items.map((item) => (
<View key={`${item.goodsId}-${item.skuId}`} className="bg-white rounded-lg p-3 mb-2 flex gap-3">
<View
className="w-5 h-5 rounded-full border border-gray-300 flex items-center justify-center mt-2 flex-shrink-0"
onClick={() => toggleSelect(item.goodsId, item.skuId)}
style={{ backgroundColor: item.checked ? '#0e932e' : 'transparent' }}
>
{item.checked && <Text className="text-white text-xs"></Text>}
</View>
<Image
className="w-20 h-20 rounded-md bg-gray-100 flex-shrink-0"
src={item.goodsImage || item.product?.image || ''}
mode="aspectFill"
/>
<View className="flex-1 flex flex-col justify-between">
<Text className="text-sm text-gray-700 flex-1 line-clamp-2">
{item.goodsName || item.product?.name || item.product?.goodsName || '商品名称'}
</Text>
{item.skuSpec && (
<Text className="text-xs text-gray-400 mb-1">{item.skuSpec}</Text>
)}
<View className="flex justify-between items-center">
<Text className="text-sm font-bold text-red-500">
¥{item.skuPrice || item.sku?.price || item.product?.salePrice || item.product?.price || '0'}
</Text>
<View className="flex items-center gap-3">
<View className="w-6 h-6 rounded bg-gray-100 flex items-center justify-center" onClick={() => updateQuantity(item.goodsId, item.skuId, item.quantity - 1)}>
<Text className="text-gray-500 text-sm">-</Text>
</View>
<Text className="text-sm w-6 text-center">{item.quantity}</Text>
<View className="w-6 h-6 rounded bg-gray-100 flex items-center justify-center" onClick={() => updateQuantity(item.goodsId, item.skuId, item.quantity + 1)}>
<Text className="text-gray-500 text-sm">+</Text>
</View>
</View>
</View>
</View>
<View className="flex items-center ml-1 flex-shrink-0" onClick={() => removeItem(item.goodsId, item.skuId)}>
<Text className="text-gray-300 text-sm"></Text>
</View>
</View>
))
)}
{/* 推荐商品 */}
{recommendGoods.length > 0 && (
<View className="mt-3">
<View className="flex items-center justify-between mb-2">
<Text className="text-sm font-medium text-gray-700"></Text>
<Text className="text-xs text-gray-400" onClick={handleRefreshRecommend}>
{refreshingRecommend ? '加载中...' : '换一批'}
</Text>
</View>
<ScrollView scrollX className="whitespace-nowrap" style={{ width: '100%', height: '180px' }}>
<View className="flex gap-2" style={{ display: 'inline-flex' }}>
{recommendGoods.map(goods => (
<View
key={goods.id}
className="bg-white rounded-lg p-2 inline-block"
style={{ width: '110px', flexShrink: 0 }}
onClick={() => Taro.navigateTo({ url: `/pages/shop/product-detail?id=${goods.goodsId}` })}
>
<Image
className="w-full rounded-md bg-gray-100"
src={goods.image || ''}
mode="aspectFill"
style={{ height: '90px' }}
/>
<Text className="text-xs text-gray-700 mt-1 block" style={{ width: '100px' }} ellipsizeMode="tail" numberOfLines={1}>
{goods.name || goods.title || '商品名称'}
</Text>
<View className="flex items-center justify-between mt-1">
<Text className="text-xs font-bold text-red-500">
¥{goods.salePrice || goods.price || '0'}
</Text>
<View
className="w-5 h-5 rounded-full flex items-center justify-center"
style={{ backgroundColor: '#0e932e' }}
onClick={(e) => {
e.stopPropagation()
addItem(goods, undefined, 1)
}}
>
<Text className="text-white text-xs">+</Text>
</View>
</View>
</View>
))}
</View>
</ScrollView>
</View>
)}
</View>
)}
</ScrollView>
{/* 底部结算栏 */}
{items.length > 0 && (
<View className="flex items-center justify-between bg-white border-t border-gray-100 px-3 py-3">
<View className="flex items-center gap-2">
<Text className="text-sm text-gray-500">:</Text>
<Text className="text-lg font-bold text-red-500">¥{selectedPrice}</Text>
</View>
<View
className="px-6 py-2 rounded-full text-white text-sm font-medium"
style={{ backgroundColor: selectedCount > 0 ? '#0e932e' : '#ccc' }}
onClick={handleCheckout}
>
<Text>({selectedCount})</Text>
</View>
</View>
)}
</View>
)
}
export default CartPage