feat(pages): 实现商品分类页面及优化轮播图功能

- 新增商品分类页面,包含左侧导航和右侧商品列表
- 实现分类切换和商品展示功能
- 添加骨架屏加载效果和空状态处理
- 优化首页轮播图组件,支持自动播放和触摸滑动
- 调整轮播图高度默认值为300px- 移除旧的热卖商品逻辑,改为获取推荐文章
- 修复医生申请页面用户类型选择功能
- 更新页面标题文本内容
- 添加网站配置获取hook
This commit is contained in:
2025-10-05 09:45:18 +08:00
parent 0a517b1247
commit 7b7bf80bc5
21 changed files with 1153 additions and 123 deletions

View File

@@ -0,0 +1,3 @@
export default definePageConfig({
navigationBarTitleText: '分类'
})

View File

@@ -0,0 +1,425 @@
.category-container {
display: flex;
height: calc(100vh - 1rpx);
background-color: #f5f5f5;
}
/* 左侧分类导航 */
.category-left {
width: 200rpx;
background-color: #fff;
border-right: 2rpx solid #f0f0f0;
position: relative;
z-index: 10;
.category-scroll {
height: calc(100vh - 1rpx);
}
.category-item {
padding: 30rpx 20rpx;
background-color: #fff;
transition: all 0.3s ease;
position: relative;
cursor: pointer;
&:hover {
background-color: #f8f8f8;
}
&.active {
background-color: #fff;
color: #ff6b35;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 8rpx;
height: 50rpx;
background: linear-gradient(180deg, #ff6b35 0%, #ff8f6b 100%);
border-radius: 0 8rpx 8rpx 0;
box-shadow: 0 2rpx 8rpx rgba(255, 107, 53, 0.3);
}
&::after {
content: '';
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 2rpx;
background-color: #fff;
z-index: 1;
}
}
.category-name {
font-size: 28rpx;
color: #333;
font-weight: 500;
display: block;
text-align: center;
line-height: 1.2;
transition: color 0.3s ease;
}
.category-count {
font-size: 20rpx;
color: #999;
margin-top: 8rpx;
display: block;
text-align: center;
}
&.active .category-name {
color: #ff6b35;
font-weight: 600;
}
&.active .category-count {
color: #ff6b35;
}
}
}
/* 右侧商品列表 */
.category-right {
flex: 1;
background-color: #fff;
position: relative;
.goods-scroll {
height: calc(100vh - 1rpx);
}
.goods-section {
.section-title {
position: sticky;
top: 0;
background: linear-gradient(135deg, #f8f8f8 0%, #f0f0f0 100%);
padding: 24rpx 30rpx;
border-bottom: 2rpx solid #f0f0f0;
z-index: 10;
text {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
}
.goods-list {
padding: 20rpx 30rpx;
}
.goods-item {
display: flex;
padding: 24rpx 0;
border-bottom: 2rpx solid #f8f8f8;
transition: all 0.3s ease;
border-radius: 12rpx;
margin-bottom: 8rpx;
cursor: pointer;
&:last-child {
border-bottom: none;
margin-bottom: 0;
}
&:hover {
background-color: #fafafa;
transform: translateY(-2rpx);
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
}
.goods-image {
width: 160rpx;
height: 160rpx;
border-radius: 16rpx;
margin-right: 24rpx;
flex-shrink: 0;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease;
&:hover {
transform: scale(1.05);
}
}
.goods-info {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
.goods-name {
font-size: 30rpx;
color: #333;
font-weight: 600;
line-height: 1.4;
margin-bottom: 8rpx;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
.goods-desc {
font-size: 24rpx;
color: #666;
line-height: 1.3;
margin-bottom: 12rpx;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
.goods-price-row {
display: flex;
align-items: center;
margin-bottom: 8rpx;
.goods-price {
font-size: 36rpx;
color: #ff6b35;
font-weight: 700;
margin-right: 16rpx;
position: relative;
&::before {
content: '¥';
font-size: 24rpx;
position: relative;
top: -2rpx;
}
}
.goods-original-price {
font-size: 24rpx;
color: #999;
text-decoration: line-through;
position: relative;
&::before {
content: '¥';
font-size: 20rpx;
}
}
}
.goods-stock {
font-size: 22rpx;
color: #999;
background-color: #f8f8f8;
padding: 4rpx 8rpx;
border-radius: 4rpx;
display: inline-block;
width: fit-content;
}
}
}
.empty-section {
padding: 120rpx 30rpx;
text-align: center;
text {
font-size: 28rpx;
color: #999;
position: relative;
&::before {
content: '📋';
display: block;
font-size: 80rpx;
margin-bottom: 20rpx;
}
}
}
}
}
/* 骨架屏样式 */
.category-skeleton {
display: flex;
height: calc(100vh - 1rpx);
.category-left {
width: 200rpx;
background-color: #fff;
border-right: 2rpx solid #f0f0f0;
padding: 20rpx 0;
.skeleton-category-item {
padding: 30rpx 20rpx;
.skeleton-text {
height: 32rpx;
background-color: #f0f0f0;
border-radius: 4rpx;
animation: skeleton-loading 1.5s ease-in-out infinite;
}
}
}
.category-right {
flex: 1;
background-color: #fff;
padding: 30rpx;
.skeleton-goods-item {
display: flex;
padding: 24rpx 0;
border-bottom: 2rpx solid #f8f8f8;
.skeleton-image {
width: 160rpx;
height: 160rpx;
background-color: #f0f0f0;
border-radius: 16rpx;
margin-right: 24rpx;
animation: skeleton-loading 1.5s ease-in-out infinite;
}
.skeleton-info {
flex: 1;
.skeleton-text {
height: 32rpx;
background-color: #f0f0f0;
border-radius: 4rpx;
animation: skeleton-loading 1.5s ease-in-out infinite;
}
}
}
}
}
@keyframes skeleton-loading {
0% {
opacity: 1;
}
50% {
opacity: 0.6;
}
100% {
opacity: 1;
}
}
/* 响应式设计 */
@media (max-width: 750rpx) {
.category-left {
width: 160rpx;
.category-item {
padding: 24rpx 16rpx;
.category-name {
font-size: 26rpx;
}
.category-count {
font-size: 18rpx;
}
}
}
.category-right {
.goods-section {
.goods-list {
padding: 16rpx 20rpx;
}
.goods-item {
padding: 20rpx 0;
.goods-image {
width: 140rpx;
height: 140rpx;
margin-right: 20rpx;
}
.goods-info {
.goods-name {
font-size: 28rpx;
}
.goods-desc {
font-size: 22rpx;
}
.goods-price-row {
.goods-price {
font-size: 32rpx;
}
}
}
}
}
}
}
/* 空状态样式 */
.empty-container {
height: calc(100vh - 1rpx);
display: flex;
align-items: center;
justify-content: center;
background-color: #f5f5f5;
.empty-content {
text-align: center;
padding: 60rpx 40rpx;
.empty-icon {
font-size: 120rpx;
display: block;
margin-bottom: 30rpx;
}
.empty-title {
font-size: 32rpx;
color: #333;
font-weight: 600;
display: block;
margin-bottom: 16rpx;
}
.empty-desc {
font-size: 28rpx;
color: #666;
display: block;
margin-bottom: 40rpx;
line-height: 1.4;
}
.empty-action {
background: linear-gradient(135deg, #ff6b35 0%, #ff8f6b 100%);
color: #fff;
padding: 20rpx 40rpx;
border-radius: 50rpx;
font-size: 28rpx;
font-weight: 600;
box-shadow: 0 4rpx 12rpx rgba(255, 107, 53, 0.3);
transition: all 0.3s ease;
cursor: pointer;
&:hover {
transform: translateY(-2rpx);
box-shadow: 0 6rpx 16rpx rgba(255, 107, 53, 0.4);
}
&:active {
transform: translateY(0);
box-shadow: 0 2rpx 8rpx rgba(255, 107, 53, 0.3);
}
}
}
}

View File

@@ -0,0 +1,270 @@
import Taro from '@tarojs/taro'
import { useShareAppMessage } from "@tarojs/taro"
import { useEffect, useState, useRef, useCallback } from "react"
import { View, Text, ScrollView } from '@tarojs/components'
import { Image } from '@nutui/nutui-react-taro'
import { listCmsNavigation } from "@/api/cms/cmsNavigation"
import { CmsNavigation } from "@/api/cms/cmsNavigation/model"
import { pageShopGoods } from "@/api/shop/shopGoods"
import { ShopGoods } from "@/api/shop/shopGoods/model"
import './category.scss'
function Category() {
const [loading, setLoading] = useState<boolean>(true)
const [categories, setCategories] = useState<CmsNavigation[]>([])
const [selectedCategoryId, setSelectedCategoryId] = useState<number>(0)
const [goods, setGoods] = useState<{ [key: number]: ShopGoods[] }>({})
const [allGoods, setAllGoods] = useState<ShopGoods[]>([])
const rightScrollRef = useRef<any>(null)
const [scrollIntoView, setScrollIntoView] = useState('')
const [isScrollingByClick, setIsScrollingByClick] = useState(false)
// 初始化数据
const initData = async () => {
try {
setLoading(true)
// 获取商品分类
const categoryList = await listCmsNavigation({ model: 'goods' })
if (!categoryList || categoryList.length === 0) {
Taro.showToast({
title: '暂无商品分类',
icon: 'none'
})
setLoading(false)
return
}
setCategories(categoryList)
const firstCategory = categoryList[0]
setSelectedCategoryId(firstCategory.navigationId!)
// 并行获取所有分类的商品数据
const goodsPromises = categoryList.map((category: CmsNavigation) =>
pageShopGoods({ categoryId: category.navigationId }).catch(err => {
console.error(`分类 ${category.title} 商品加载失败:`, err)
return { list: [] }
})
)
const goodsResults = await Promise.all(goodsPromises)
// 组织商品数据
const goodsByCategory: { [key: number]: ShopGoods[] } = {}
categoryList.forEach((category: CmsNavigation, index: number) => {
goodsByCategory[category.navigationId!] = goodsResults[index]?.list || []
})
setGoods(goodsByCategory)
// 获取所有商品用于搜索等功能
try {
const allGoodsRes = await pageShopGoods({})
setAllGoods(allGoodsRes?.list || [])
} catch (err) {
console.error('获取所有商品失败:', err)
}
Taro.setNavigationBarTitle({
title: '商品分类'
})
} catch (error) {
console.error('分类数据加载失败:', error)
Taro.showToast({
title: '加载失败,请重试',
icon: 'none'
})
} finally {
setLoading(false)
}
}
useEffect(() => {
initData().then()
console.log(allGoods,'allGoods')
}, [])
// 点击左侧分类
const handleCategoryClick = (categoryId: number) => {
setIsScrollingByClick(true)
setSelectedCategoryId(categoryId)
setScrollIntoView(`category-${categoryId}`)
// 延迟重置滚动标志
setTimeout(() => {
setIsScrollingByClick(false)
}, 1000)
}
// 右侧滚动时处理分类切换
const handleRightScroll = useCallback((e: any) => {
console.log(e,'右侧滚动时处理分类切换')
if (isScrollingByClick) return
// 这里可以添加逻辑来检测当前滚动到哪个分类
// 由于小程序限制,暂时简化处理
}, [isScrollingByClick])
// 跳转商品详情
const goToGoodsDetail = (goodsId: number) => {
Taro.navigateTo({ url: `/shop/goodsDetail/index?id=${goodsId}` })
}
useShareAppMessage(() => {
return {
title: '商品分类',
path: '/pages/category/category',
success: function () {
console.log('分享成功')
},
fail: function () {
console.log('分享失败')
}
}
})
// 骨架屏组件
const CategorySkeleton = () => (
<View className="category-skeleton" style={{
marginTop: '1rpx',
}}>
<View className="category-left">
{[1, 2, 3, 4, 5].map(i => (
<View key={i} className="skeleton-category-item">
<View className="skeleton-text" />
</View>
))}
</View>
<View className="category-right">
{[1, 2, 3, 4].map(i => (
<View key={i} className="skeleton-goods-item">
<View className="skeleton-image" />
<View className="skeleton-info">
<View className="skeleton-text" style={{ width: '80%', marginBottom: '8px' }} />
<View className="skeleton-text" style={{ width: '60%' }} />
</View>
</View>
))}
</View>
</View>
)
if (loading) {
return <CategorySkeleton />
}
// 空状态处理
if (!categories || categories.length === 0) {
return (
<View className="empty-container">
<View className="empty-content">
<Text className="empty-icon">📋</Text>
<Text className="empty-title"></Text>
<Text className="empty-desc"></Text>
<View className="empty-action" onClick={initData}>
<Text></Text>
</View>
</View>
</View>
)
}
return (
<View className="category-container" style={{
marginTop: '1rpx',
}}>
{/* 左侧分类导航 */}
<View className="category-left">
<ScrollView
className="category-scroll"
scrollY
enhanced
showScrollbar={false}
> {categories.map((category) => (
<View
key={category.navigationId}
className={`category-item ${
selectedCategoryId === category.navigationId ? 'active' : ''
}`}
onClick={() => handleCategoryClick(category.navigationId!)}
>
<Text className="category-name">{category.title}</Text>
</View>
))}
</ScrollView>
</View>
{/* 右侧商品列表 */}
<View className="category-right">
<ScrollView
ref={rightScrollRef}
className="goods-scroll"
scrollY
enhanced
showScrollbar={false}
scrollIntoView={scrollIntoView}
onScroll={handleRightScroll}
>
{categories.map((category) => {
const categoryGoods = goods[category.navigationId!] || []
return (
<View
key={category.navigationId}
id={`category-${category.navigationId}`}
className="goods-section"
>
<View className="section-title">
<Text>{category.title}</Text>
</View>
{categoryGoods.length > 0 ? (
<View className="goods-list">
{categoryGoods.map((item) => (
<View
key={item.goodsId}
className="goods-item"
onClick={() => goToGoodsDetail(item.goodsId!)}
>
<Image
className="goods-image"
src={item.image || ''}
mode="aspectFill"
lazyLoad
width={80}
height={80}
/>
<View className="goods-info">
<Text className="goods-name">{item.name}</Text>
{item.comments && (
<Text className="goods-desc">{item.comments}</Text>
)}
<View className="goods-price-row">
<Text className="goods-price">¥{item.price}</Text>
{item.salePrice && Number(item.salePrice) !== Number(item.price) && (
<Text className="goods-original-price">¥{item.salePrice}</Text>
)}
</View>
{item.stock !== undefined && (
<Text className="goods-stock">
: {item.stock > 0 ? item.stock : '缺货'}
</Text>
)}
</View>
</View>
))}
</View>
) : (
<View className="empty-section">
<Text></Text>
</View>
)}
</View>
)
})}
</ScrollView>
</View>
</View>
)
}
export default Category

View File

@@ -0,0 +1,35 @@
import {Image, Cell} from '@nutui/nutui-react-taro'
import {View, Text} from '@tarojs/components'
import Taro from '@tarojs/taro'
const ArticleList = (props: any) => {
return (
<>
<View className={'px-3'}>
{props.data.map((item: any, index: number) => {
return (
<Cell
title={
<View>
<View className="text-base font-medium mb-1">{item.title}</View>
{item.comments && (
<Text className="text-sm text-gray-500 leading-relaxed">
{item.comments}
</Text>
)}
</View>
}
extra={
<Image src={item.image} mode={'aspectFit'} lazyLoad={false} width={100} height="100"/>
}
key={index}
onClick={() => Taro.navigateTo({url: '/cms/detail/index?id=' + item.articleId})}
/>
)
})}
</View>
</>
)
}
export default ArticleList

View File

@@ -0,0 +1,59 @@
import {useEffect, useState} from "react";
import {Tabs, Loading} from '@nutui/nutui-react-taro'
import {pageCmsArticle} from "@/api/cms/cmsArticle";
import {CmsArticle} from "@/api/cms/cmsArticle/model";
import ArticleList from "./ArticleList";
const ArticleTabs = (props: any) => {
const [loading, setLoading] = useState<boolean>(true)
const [tab1value, setTab1value] = useState<string | number>('0')
const [list, setList] = useState<CmsArticle[]>([])
const reload = async (value) => {
const {data} = props
pageCmsArticle({
categoryId: data[value].navigationId,
page: 1,
status: 0,
limit: 10
}).then((res) => {
res && setList(res?.list || [])
})
.catch(err => {
console.log(err)
})
.finally(() => {
setTab1value(value)
setLoading(false)
})
}
useEffect(() => {
reload(0).then()
}, []);
if (loading) {
return (
<Loading className={'px-2'}></Loading>
)
}
return (
<>
<Tabs
value={tab1value}
onChange={(value) => {
reload(value).then()
}}
>
{props.data?.map((item, index) => {
return (
<Tabs.TabPane title={item.categoryName} key={index}/>
)
})}
</Tabs>
<ArticleList data={list}/>
</>
)
}
export default ArticleTabs

View File

@@ -0,0 +1,31 @@
import { useEffect, useState } from 'react'
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";
const MyPage = () => {
const [item, setItem] = useState<CmsAd>()
const reload = () => {
getCmsAd(439).then(data => {
setItem(data)
})
}
useEffect(() => {
reload()
}, [])
return (
<>
<Swiper defaultValue={0} height={item?.height} indicator style={{ height: item?.height + 'px', display: 'none' }}>
{item?.imageList?.map((item) => (
<Swiper.Item key={item}>
<Image width="100%" height="100%" src={item.url} mode={'scaleToFill'} lazyLoad={false} style={{ height: item.height + 'px' }} />
</Swiper.Item>
))}
</Swiper>
</>
)
}
export default MyPage

View File

@@ -5,55 +5,123 @@ import {CmsAd} from "@/api/cms/cmsAd/model";
import {Image} from '@nutui/nutui-react-taro'
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 [loading, setLoading] = useState(true)
// const [disableSwiper, setDisableSwiper] = useState(false)
// 用于记录触摸开始位置
// const touchStartRef = useRef({x: 0, y: 0})
// 加载数据
const loadData = () => {
// 轮播图
getCmsAdByCode('flash').then(data => {
setCarouselData(data)
})
// 今日热卖素材(上层图片)
// getCmsAd(444).then(data => {
// setHotToday(data)
// })
// 社区拼团素材(下层图片)
// getCmsAd(445).then(data => {
// setGroupBuy(data)
// })
// 今日热卖
listShopGoods({categoryId: 4424, limit: 2}).then(data => {
setHotGoods(data)
})
const loadData = async () => {
try {
setLoading(true)
// 轮播图
const flash = await getCmsAdByCode('flash')
// 今日热卖
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])
}
} catch (error) {
console.error('Banner数据加载失败:', error)
} finally {
setLoading(false)
}
}
useEffect(() => {
loadData()
}, [])
// 轮播图高度,默认200px
const carouselHeight = carouselData?.height || 200;
// 轮播图高度,默认300px
const carouselHeight = carouselData?.height || 300;
// 骨架屏组件
const BannerSkeleton = () => (
<View className="flex p-2 justify-between" style={{height: `${carouselHeight}px`}}>
{/* 左侧轮播图骨架屏 */}
<View style={{width: '50%', height: '100%'}}>
<View
className="bg-gray-200 rounded animate-pulse"
style={{height: `${carouselHeight}px`}}
/>
</View>
{/* 右侧骨架屏 */}
<View className="flex flex-col" style={{width: '50%', height: '100%'}}>
{/* 上层骨架屏 */}
<View className="ml-2 bg-white rounded-lg">
<View className="px-3 my-2">
<View className="bg-gray-200 h-4 w-16 rounded animate-pulse"/>
</View>
<View className="px-3 flex" style={{height: '110px'}}>
{[1, 2].map(i => (
<View key={i} className="item flex flex-col mr-4">
<View className="bg-gray-200 rounded animate-pulse" style={{width: 70, height: 70}}/>
<View className="bg-gray-200 h-3 w-16 rounded mt-2 animate-pulse"/>
</View>
))}
</View>
</View>
{/* 下层骨架屏 */}
<View className="ml-2 bg-white rounded-lg mt-3">
<View className="px-3 my-2">
<View className="bg-gray-200 h-4 w-20 rounded animate-pulse"/>
</View>
<View className="rounded-lg px-3 pb-3">
<View className="bg-gray-200 rounded animate-pulse" style={{width: '100%', height: 106}}/>
</View>
</View>
</View>
</View>
)
// 如果正在加载,显示骨架屏
if (loading) {
return <BannerSkeleton />
}
return (
<View className="flex p-2 justify-between" style={{height: `${carouselHeight}px`}}>
{/* 左侧轮播图区域 */}
<View style={{width: '50%', height: '100%'}}>
<View
style={{width: '50%', height: '100%'}}
className="banner-swiper-container"
>
<Swiper
defaultValue={0}
height={carouselHeight}
indicator
style={{height: `${carouselHeight}px`}}
autoPlay
duration={3000}
style={{
height: `${carouselHeight}px`,
touchAction: 'pan-y' // 关键修改:允许垂直滑动
}}
disableTouch={false}
direction="horizontal"
className="custom-swiper"
>
{carouselData?.imageList?.map((img, index) => (
<Swiper.Item key={index}>
{carouselData && carouselData?.imageList?.map((img, index) => (
<Swiper.Item key={index} style={{ touchAction: 'pan-x pan-y' }}>
<Image
width="100%"
height="100%"
@@ -61,7 +129,11 @@ const MyPage = () => {
mode={'scaleToFill'}
onClick={() => navTo(`${img.path}`)}
lazyLoad={false}
style={{height: `${carouselHeight}px`, borderRadius: '4px'}}
style={{
height: `${carouselHeight}px`,
borderRadius: '4px',
touchAction: 'manipulation' // 关键修改:优化触摸操作
}}
/>
</Swiper.Item>
))}
@@ -71,26 +143,26 @@ const MyPage = () => {
{/* 右侧上下图片区域 - 从API获取数据 */}
<View className="flex flex-col" style={{width: '50%', height: '100%'}}>
{/* 上层图片 - 使用今日热卖素材 */}
<View className={'ml-2 bg-white rounded-lg'}>
<View className={'ml-2 bg-white rounded-lg shadow-sm'}>
<View className={'px-3 my-2 font-bold text-sm'}></View>
<View className={'px-3 flex'} style={{
<View className={'px-3 flex justify-between'} style={{
height: '110px'
}}>
{
hotGoods.map(item => (
<View className={'item flex flex-col mr-4'}>
hotToday?.imageList?.map(item => (
<View className={'item flex flex-col mr-1'} key={item.url}>
<Image
width={70}
height={70}
src={item.image}
src={item.url}
mode={'scaleToFill'}
lazyLoad={false}
style={{
borderRadius: '4px'
}}
onClick={() => navTo('/shop/category/index?id=4424')}
onClick={() => navTo(item.path)}
/>
<View className={'text-xs py-2'}>¥{item.price}</View>
<View className={'text-xs py-2 text-orange-600 whitespace-nowrap text-center'}>{item.title || '到手价¥9.9'}</View>
</View>
))
}
@@ -98,19 +170,19 @@ const MyPage = () => {
</View>
{/* 下层图片 - 使用社区拼团素材 */}
<View className={'ml-2 bg-white rounded-lg mt-3'}>
<View className={'px-3 my-2 font-bold text-sm'}></View>
<View className={'ml-2 bg-white rounded-lg mt-3 shadow-sm'}>
<View className={'px-3 my-2 font-bold text-sm'}>{item?.overview || item?.categoryName || '推荐文章'}</View>
<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={94}
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>
@@ -120,4 +192,3 @@ const MyPage = () => {
}
export default MyPage

View File

@@ -1,4 +0,0 @@
// 订单页面样式
.order-page {
// 订单相关样式
}

View File

@@ -3,18 +3,28 @@ import navTo from "@/utils/common";
import {View, Text} from '@tarojs/components'
import {ArrowRight, Reward, Setting} from '@nutui/icons-react-taro'
import {useUser} from '@/hooks/useUser'
import {useEffect} from "react";
import {useDealerUser} from "@/hooks/useDealerUser";
import {useThemeStyles} from "@/hooks/useTheme";
import { useConfig } from "@/hooks/useConfig";
import {useEffect, useState} from "react";
import {getCmsAdByCode} from "@/api/cms/cmsAd";
import {CmsAd} from "@/api/cms/cmsAd/model"; // 使用新的自定义Hook
const IsDealer = () => {
const themeStyles = useThemeStyles();
const { config } = useConfig(); // 使用新的Hook
const {isSuperAdmin} = useUser();
const {dealerUser} = useDealerUser()
const [register, setRegister] = useState<CmsAd>()
const reload = async () => {
const item = await getCmsAdByCode('register')
setRegister(item)
}
useEffect(() => {
}, [])
reload().then()
}, []);
/**
* 管理中心
@@ -54,7 +64,7 @@ const IsDealer = () => {
<View style={{display: 'inline-flex', alignItems: 'center'}}>
<Reward className={'text-orange-100 '} size={16}/>
<Text style={{fontSize: '16px'}}
className={'pl-3 text-orange-100 font-medium'}>VIP申请</Text>
className={'pl-3 text-orange-100 font-medium'}>{config?.vipText || '入驻申请'}</Text>
{/*<Text className={'text-white opacity-80 pl-3'}>门店核销</Text>*/}
</View>
}
@@ -78,12 +88,12 @@ const IsDealer = () => {
title={
<View style={{display: 'inline-flex', alignItems: 'center'}}>
<Reward className={'text-orange-100 '} size={16}/>
<Text style={{fontSize: '16px'}} className={'pl-3 text-orange-100 font-medium'}>VIP</Text>
<Text className={'text-white opacity-80 pl-3'}></Text>
<Text style={{fontSize: '16px'}} className={'pl-3 text-orange-100 font-medium'}>{register?.name || '注册会员'}</Text>
<Text className={'text-white opacity-80 pl-3'}></Text>
</View>
}
extra={<ArrowRight color="#cccccc" size={18}/>}
onClick={() => navTo('/doctor/apply/add', true)}
onClick={() => navTo(`${register?.path}`, true)}
/>
</View>
</>