feat(user): 更新用户界面和功能实现- 默认 修改 UnifiedQRButton类型为 danger- 更新 Banner 组件使用 getCmsAdByCode 获取广告数据

- 新增 CMS 文章查询接口 getCmsArticleByCode
- 调整 UserCard 组件界面样式和逻辑-优化 BestSellers 商品展示组件
- 更新 IsDealer 组件支持网站字段配置
- 移除用户页面部分冗余代码和样式
- 增加主题样式支持和背景装饰元素
- 调整用户相关组件层级和定位样式
This commit is contained in:
2025-09-26 11:22:09 +08:00
parent 6505b48d3a
commit 915c06ecab
30 changed files with 1190 additions and 294 deletions

View File

@@ -3,36 +3,35 @@ import {View} from '@tarojs/components'
import {Swiper} from '@nutui/nutui-react-taro'
import {CmsAd} from "@/api/cms/cmsAd/model";
import {Image} from '@nutui/nutui-react-taro'
import {getCmsAd} from "@/api/cms/cmsAd";
import {getCmsAdByCode} from "@/api/cms/cmsAd";
import navTo from "@/utils/common";
import {ShopGoods} from "@/api/shop/shopGoods/model";
import {listShopGoods} from "@/api/shop/shopGoods";
import {pageCmsArticle} from "@/api/cms/cmsArticle";
import {CmsArticle} from "@/api/cms/cmsArticle/model";
const MyPage = () => {
const [carouselData, setCarouselData] = useState<CmsAd>()
// const [hotToday, setHotToday] = useState<CmsAd>()
// const [groupBuy, setGroupBuy] = useState<CmsAd>()
const [hotGoods, setHotGoods] = useState<ShopGoods[]>([])
const [hotToday, setHotToday] = useState<CmsAd>()
const [item, setItem] = useState<CmsArticle>()
// 加载数据
const loadData = () => {
const loadData = async () => {
// 轮播图
getCmsAd(439).then(data => {
setCarouselData(data)
})
// 今日热卖素材(上层图片)
// getCmsAd(444).then(data => {
// setHotToday(data)
// })
// 社区拼团素材(下层图片)
// getCmsAd(445).then(data => {
// setGroupBuy(data)
// })
const flash = await getCmsAdByCode('flash')
// 今日热卖
listShopGoods({categoryId: 4424, limit: 2}).then(data => {
setHotGoods(data)
})
const hotToday = await getCmsAdByCode('hot_today')
// 时里动态
const news = await pageCmsArticle({limit:1,recommend:1})
// 赋值
if(flash){
setCarouselData(flash)
}
if(hotToday){
setHotToday(hotToday)
}
if(news && news.list.length > 0){
setItem(news.list[0])
}
}
useEffect(() => {
@@ -77,12 +76,12 @@ const MyPage = () => {
height: '110px'
}}>
{
hotGoods.map(item => (
hotToday?.imageList?.map(item => (
<View className={'item flex flex-col mr-4'}>
<Image
width={70}
height={70}
src={item.image}
src={item.url}
mode={'scaleToFill'}
lazyLoad={false}
style={{
@@ -90,7 +89,7 @@ const MyPage = () => {
}}
onClick={() => navTo('/shop/category/index?id=4424')}
/>
<View className={'text-xs py-2'}>¥{item.price}</View>
<View className={'text-xs py-2 text-orange-600 whitespace-nowrap'}>{item.title || '到手价¥9.9'}</View>
</View>
))
}
@@ -103,14 +102,14 @@ const MyPage = () => {
<View className={'rounded-lg px-3 pb-3'}>
<Image
width={'100%'}
height={100}
src={'https://oss.wsdns.cn/20250919/941c99899e694a7798cab3bb28f1f238.png?x-oss-process=image/resize,m_fixed,w_750/quality,Q_90'}
height={106}
src={item?.image}
mode={'scaleToFill'}
lazyLoad={false}
style={{
borderRadius: '4px'
}}
onClick={() => navTo('cms/detail/index?id=10109')}
onClick={() => navTo('cms/detail/index?id=' + item?.articleId)}
/>
</View>
</View>

View File

@@ -1,70 +1,37 @@
import {useEffect, useState} from "react";
import {Image, Swiper, SwiperItem, Empty} from '@nutui/nutui-react-taro'
import {Image} from '@nutui/nutui-react-taro'
import {Share} from '@nutui/icons-react-taro'
import {View, Text} from '@tarojs/components';
import Taro from "@tarojs/taro";
import {Tabs} from '@nutui/nutui-react-taro'
import {ShopGoods} from "@/api/shop/shopGoods/model";
import {pageShopGoods} from "@/api/shop/shopGoods";
const BestSellers = () => {
const [tab1value, setTab1value] = useState<string | number>('0')
const [list, setList] = useState<ShopGoods[]>([])
const [goods, setGoods] = useState<ShopGoods | null>(null)
// 轮播图固定高度,可根据需求调整
const SWIPER_HEIGHT = 180;
const [goods, setGoods] = useState<ShopGoods>()
const reload = () => {
pageShopGoods({}).then(res => {
const processGoodsItem = (item: ShopGoods) => {
const pics: string[] = [];
// 添加主图
if (item.image) {
pics.push(item.image);
}
// 处理附加图片
if (item.files) {
try {
// 解析文件字符串为对象
const files = typeof item.files === "string"
? JSON.parse(item.files)
: item.files;
// 收集所有图片URL
Object.values(files).forEach(file => {
if (file?.url) {
pics.push(file.url);
}
});
} catch (error) {
console.error('解析文件失败:', error);
}
}
// 返回新对象,避免直接修改原对象
return {...item, pics};
};
// 处理商品列表
const goods = (res?.list || []).map(processGoodsItem);
setList(goods);
}).catch(err => {
console.error('获取商品列表失败:', err);
});
setList(res?.list || []);
})
}
// 处理分享点击
const handleShare = (item: ShopGoods) => {
setGoods(item);
console.log(goods)
// 显示分享选项菜单
Taro.showActionSheet({
itemList: ['分享给好友'],
success: (res) => {
if (res.tapIndex === 0) {
// 分享给好友 - 触发转发
Taro.showShareMenu({
withShareTicket: true,
success: () => {
// 提示用户点击右上角分享
Taro.showToast({
title: '请点击右上角分享给好友',
icon: 'none',
@@ -81,135 +48,56 @@ const BestSellers = () => {
}
useEffect(() => {
reload();
}, []);
reload()
}, [])
// 配置分享内容
Taro.useShareAppMessage(() => {
if (goods) {
return {
title: goods.name,
path: `/shop/goodsDetail/index?id=${goods.goodsId}`,
imageUrl: goods.image || ''
};
}
return {
title: '热销商品',
path: '/pages/index/index'
};
});
// 注意:不在这里配置分享,避免与首页分享冲突
// 商品分享应该在商品详情页处理,首页分享应该分享首页本身
return (
<View className={'py-3'}>
<View className={'flex flex-col justify-between items-center rounded-lg px-2'}>
<Tabs
value={tab1value}
className={'w-full'}
onChange={(value) => {
setTab1value(value)
}}
style={{
backgroundColor: '#fff',
}}
activeType="smile"
>
<Tabs.TabPane title="今日主推">
</Tabs.TabPane>
<Tabs.TabPane title="即将到期">
</Tabs.TabPane>
<Tabs.TabPane title="活动预告">
</Tabs.TabPane>
</Tabs>
{tab1value == '0' && list?.map((item) => (
<View
key={item.goodsId || item.id} // 使用商品唯一ID作为key
className={'flex flex-col rounded-lg bg-white shadow-sm w-full mb-5'}
>
{/* 轮播图组件 */}
{item.pics && item.pics.length > 0 ? (
<Swiper
defaultValue={0}
height={SWIPER_HEIGHT}
indicator
className="swiper-container"
autoPlay
interval={3000}
>
{item.pics.map((pic, picIndex) => (
<SwiperItem key={picIndex}>
<Image
radius="12px 12px 0 0"
height={SWIPER_HEIGHT}
src={pic}
mode={'aspectFill'} // 使用aspectFill保持比例并填充容器
lazyLoad
onClick={() => Taro.navigateTo({
url: `/shop/goodsDetail/index?id=${item.goodsId}`
})}
className="swiper-image"
/>
</SwiperItem>
))}
</Swiper>
) : (
// 没有图片时显示占位图
<View className="no-image-placeholder" style={{height: `${SWIPER_HEIGHT}px`}}>
<Text className="placeholder-text"></Text>
</View>
)}
<View className={'flex flex-col p-2 rounded-lg'}>
<View>
<View className={'car-no text-sm'}>{item.name}</View>
<View className={'flex justify-between text-xs py-1'}>
<Text className={'text-orange-500'}>{item.comments}</Text>
<Text className={'text-gray-400'}> {item.sales}</Text>
</View>
<View className={'flex justify-between items-center py-2'}>
<View className={'flex text-red-500 text-xl items-baseline'}>
<Text className={'text-xs'}></Text>
<Text className={'font-bold text-2xl'}>{item.price}</Text>
</View>
<View className={'buy-btn'}>
<View className={'cart-icon flex items-center hidden'}>
<View
className={'flex flex-col justify-center items-center text-white px-3 gap-1 text-nowrap whitespace-nowrap cursor-pointer'}
onClick={() => handleShare(item)}
>
<Share size={20}/>
<>
<View className={'py-3'}>
<View className={'flex flex-col justify-between items-center rounded-lg px-2'}>
{list?.map((item, index) => {
return (
<View key={index} className={'flex flex-col rounded-lg bg-white shadow-sm w-full mb-5'}>
<Image src={item.image} mode={'aspectFit'} lazyLoad={false}
radius="10px 10px 0 0" height="180"
onClick={() => Taro.navigateTo({url: '/shop/goodsDetail/index?id=' + item.goodsId})}/>
<View className={'flex flex-col p-2 rounded-lg'}>
<View>
<View className={'car-no text-sm'}>{item.name}</View>
<View className={'flex justify-between text-xs py-1'}>
<Text className={'text-orange-500'}>{item.comments}</Text>
<Text className={'text-gray-400'}> {item.sales}</Text>
</View>
<View className={'flex justify-between items-center py-2'}>
<View className={'flex text-red-500 text-xl items-baseline'}>
<Text className={'text-xs'}></Text>
<Text className={'font-bold text-2xl'}>{item.price}</Text>
</View>
<View className={'buy-btn'}>
<View className={'cart-icon items-center hidden'}>
<View
className={'flex flex-col justify-center items-center text-white px-3 gap-1 text-nowrap whitespace-nowrap cursor-pointer'}
onClick={() => handleShare(item)}
>
<Share size={20}/>
</View>
</View>
<Text className={'text-white pl-4 pr-5'}
onClick={() => Taro.navigateTo({url: '/shop/goodsDetail/index?id=' + item.goodsId})}>
</Text>
</View>
</View>
<Text
className={'text-white pl-5 pr-5'}
onClick={() => Taro.navigateTo({
url: `/shop/goodsDetail/index?id=${item.goodsId}`
})}
>
</Text>
</View>
</View>
</View>
</View>
</View>
))}
{
tab1value == '1' && <Empty description="暂无相关商品" style={{
background: 'transparent',
}}/>
}
{
tab1value == '2' && <Empty description="暂无相关商品" style={{
background: 'transparent',
}}/>
}
)
})}
</View>
</View>
</View>
</>
)
}
export default BestSellers