Compare commits
10 Commits
0a10afcea2
...
14c0f29361
Author | SHA1 | Date |
---|---|---|
![]() |
14c0f29361 | 2 weeks ago |
![]() |
d988caa5ed | 2 weeks ago |
![]() |
7431ce39a5 | 2 weeks ago |
![]() |
8539f04e07 | 2 weeks ago |
![]() |
d46533ac52 | 2 weeks ago |
![]() |
dd1559ba56 | 2 weeks ago |
![]() |
27ddb85aed | 2 weeks ago |
![]() |
7985f0a1a4 | 2 weeks ago |
![]() |
020315838b | 2 weeks ago |
![]() |
d762fa56d4 | 2 weeks ago |
20 changed files with 732 additions and 141 deletions
After Width: | Height: | Size: 7.7 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 4.3 KiB |
@ -0,0 +1,25 @@ |
|||
import {Image, Cell} from '@nutui/nutui-react-taro' |
|||
import Taro from '@tarojs/taro' |
|||
|
|||
const ArticleList = (props: any) => { |
|||
|
|||
return ( |
|||
<> |
|||
<div className={'px-3'}> |
|||
{props.data.map((item, index) => { |
|||
return ( |
|||
<Cell |
|||
title={item.title} |
|||
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})} |
|||
/> |
|||
) |
|||
})} |
|||
</div> |
|||
</> |
|||
) |
|||
} |
|||
export default ArticleList |
@ -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 |
@ -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 |
@ -0,0 +1,4 @@ |
|||
export default definePageConfig({ |
|||
navigationBarTitleText: '文章列表', |
|||
navigationBarTextStyle: 'black' |
|||
}) |
@ -0,0 +1,71 @@ |
|||
import Taro from '@tarojs/taro' |
|||
import {useShareAppMessage} from "@tarojs/taro" |
|||
import {Loading} from '@nutui/nutui-react-taro' |
|||
import {useEffect, useState} from "react" |
|||
import {useRouter} from '@tarojs/taro' |
|||
import {getCmsNavigation, listCmsNavigation} from "@/api/cms/cmsNavigation"; |
|||
import {CmsNavigation} from "@/api/cms/cmsNavigation/model"; |
|||
import {pageCmsArticle} from "@/api/cms/cmsArticle"; |
|||
import {CmsArticle} from "@/api/cms/cmsArticle/model"; |
|||
import ArticleList from './components/ArticleList' |
|||
import ArticleTabs from "./components/ArticleTabs"; |
|||
import './index.scss' |
|||
|
|||
function Category() { |
|||
const {params} = useRouter(); |
|||
const [categoryId, setCategoryId] = useState<number>(0) |
|||
const [category, setCategory] = useState<CmsNavigation[]>([]) |
|||
const [loading, setLoading] = useState<boolean>(true) |
|||
const [nav, setNav] = useState<CmsNavigation>() |
|||
const [list, setList] = useState<CmsArticle[]>([]) |
|||
|
|||
const reload = async () => { |
|||
// 1.加载远程数据
|
|||
const id = Number(params.id || 4328) |
|||
const nav = await getCmsNavigation(id) |
|||
const categoryList = await listCmsNavigation({parentId: id}) |
|||
const shopGoods = await pageCmsArticle({categoryId: id}) |
|||
|
|||
// 2.赋值
|
|||
setCategoryId(id) |
|||
setNav(nav) |
|||
setList(shopGoods?.list || []) |
|||
setCategory(categoryList) |
|||
Taro.setNavigationBarTitle({ |
|||
title: `${nav?.categoryName}` |
|||
}) |
|||
}; |
|||
|
|||
useEffect(() => { |
|||
reload().then(() => { |
|||
setLoading(false) |
|||
}) |
|||
}, []); |
|||
|
|||
useShareAppMessage(() => { |
|||
return { |
|||
title: `${nav?.categoryName}_时里院子市集`, |
|||
path: `/shop/category/index?id=${categoryId}`, |
|||
success: function () { |
|||
console.log('分享成功'); |
|||
}, |
|||
fail: function () { |
|||
console.log('分享失败'); |
|||
} |
|||
}; |
|||
}); |
|||
|
|||
if (loading) { |
|||
return ( |
|||
<Loading className={'px-2'}>加载中</Loading> |
|||
) |
|||
} |
|||
|
|||
if(category.length > 0){ |
|||
return <ArticleTabs data={category}/> |
|||
} |
|||
|
|||
return <ArticleList data={list}/> |
|||
} |
|||
|
|||
export default Category |
@ -0,0 +1,3 @@ |
|||
export default definePageConfig({ |
|||
navigationBarTitleText: '文章详情' |
|||
}) |
@ -0,0 +1,53 @@ |
|||
import Taro from '@tarojs/taro' |
|||
import {useEffect, useState} from 'react' |
|||
import {useRouter} from '@tarojs/taro' |
|||
import {Loading} from '@nutui/nutui-react-taro' |
|||
import {View, RichText} from '@tarojs/components' |
|||
import {wxParse} from "@/utils/common"; |
|||
import {getCmsArticle} from "@/api/cms/cmsArticle"; |
|||
import {CmsArticle} from "@/api/cms/cmsArticle/model" |
|||
import Line from "@/components/Gap"; |
|||
import './index.scss' |
|||
|
|||
function Detail() { |
|||
const {params} = useRouter(); |
|||
const [loading, setLoading] = useState<boolean>(true) |
|||
// 文章详情
|
|||
const [item, setItem] = useState<CmsArticle>() |
|||
const reload = async () => { |
|||
const item = await getCmsArticle(Number(params.id)) |
|||
|
|||
if (item) { |
|||
item.content = wxParse(item.content) |
|||
setItem(item) |
|||
Taro.setNavigationBarTitle({ |
|||
title: `${item?.categoryName}` |
|||
}) |
|||
} |
|||
} |
|||
|
|||
useEffect(() => { |
|||
reload().then(() => { |
|||
setLoading(false) |
|||
}); |
|||
}, []); |
|||
|
|||
if (loading) { |
|||
return ( |
|||
<Loading className={'px-2'}>加载中</Loading> |
|||
) |
|||
} |
|||
|
|||
return ( |
|||
<div className={'bg-white'}> |
|||
<div className={'p-4 font-bold text-lg'}>{item?.title}</div> |
|||
<div className={'text-gray-400 text-sm px-4 '}>{item?.createTime}</div> |
|||
<View className={'content p-4'}> |
|||
<RichText nodes={item?.content}/> |
|||
</View> |
|||
<Line height={44}/> |
|||
</div> |
|||
) |
|||
} |
|||
|
|||
export default Detail |
@ -1,4 +1,9 @@ |
|||
.header-bg{ |
|||
background: url('https://oss.wsdns.cn/20250621/edb5d4da976b4d97ba185cb7077d2858.jpg') no-repeat top center; |
|||
//background: url('https://oss.wsdns.cn/20250621/edb5d4da976b4d97ba185cb7077d2858.jpg') no-repeat top center; |
|||
background: linear-gradient(to bottom, #03605c, #18ae4f); |
|||
background-size: 100%; |
|||
} |
|||
|
|||
.my-bg{ |
|||
background: url('https://oss.wsdns.cn/20250913/5ae575a50dbb4ccaab086c3679c5e2c3.png') no-repeat top center; |
|||
} |
|||
|
@ -0,0 +1,4 @@ |
|||
export default definePageConfig({ |
|||
navigationBarTitleText: '企业采购', |
|||
navigationBarTextStyle: 'black' |
|||
}) |
@ -0,0 +1,115 @@ |
|||
import { useEffect, useState, useRef } from 'react' |
|||
import { Image } from '@nutui/nutui-react-taro' |
|||
import { CmsAd } from "@/api/cms/cmsAd/model"; |
|||
import { getCmsAd } from "@/api/cms/cmsAd"; |
|||
import navTo from "@/utils/common"; |
|||
|
|||
const NaturalFullscreenBanner = () => { |
|||
const [bannerData, setBannerData] = useState<CmsAd | null>(null) |
|||
const [isLoading, setIsLoading] = useState(true) |
|||
const containerRef = useRef<HTMLDivElement>(null) |
|||
const imageRef = useRef<HTMLImageElement>(null) |
|||
|
|||
// 加载图片数据
|
|||
const loadBannerData = () => { |
|||
setIsLoading(true) |
|||
getCmsAd(447) |
|||
.then(data => { |
|||
setBannerData(data) |
|||
setIsLoading(false) |
|||
}) |
|||
.catch(error => { |
|||
console.error('图片数据加载失败:', error) |
|||
setIsLoading(false) |
|||
}) |
|||
} |
|||
|
|||
// 处理图片加载完成后调整显示方式
|
|||
const handleImageLoad = () => { |
|||
if (imageRef.current && containerRef.current) { |
|||
// 获取图片原始宽高比
|
|||
const imgRatio = imageRef.current.naturalWidth / imageRef.current.naturalHeight; |
|||
// 获取容器宽高比
|
|||
const containerRatio = containerRef.current.offsetWidth / containerRef.current.offsetHeight; |
|||
|
|||
// 根据比例差异微调显示方式
|
|||
if (imgRatio > containerRatio) { |
|||
// 图片更宽,适当调整以显示更多垂直内容
|
|||
imageRef.current.style.objectPosition = 'center'; |
|||
} else { |
|||
// 图片更高,适当调整以显示更多水平内容
|
|||
imageRef.current.style.objectPosition = 'center'; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// 设置全屏尺寸
|
|||
useEffect(() => { |
|||
const setFullscreenSize = () => { |
|||
if (containerRef.current) { |
|||
// 减去可能存在的导航栏高度,使显示更自然
|
|||
const windowHeight = window.innerHeight - 48; // 假设导航栏高度为48px
|
|||
const windowWidth = window.innerWidth; |
|||
|
|||
containerRef.current.style.height = `${windowHeight}px`; |
|||
containerRef.current.style.width = `${windowWidth}px`; |
|||
} |
|||
}; |
|||
|
|||
// 初始化尺寸
|
|||
setFullscreenSize(); |
|||
|
|||
// 监听窗口大小变化
|
|||
const resizeHandler = () => setFullscreenSize(); |
|||
window.addEventListener('resize', resizeHandler); |
|||
return () => window.removeEventListener('resize', resizeHandler); |
|||
}, []); |
|||
|
|||
useEffect(() => { |
|||
loadBannerData() |
|||
}, []) |
|||
|
|||
if (isLoading) { |
|||
return ( |
|||
<div ref={containerRef} className="flex items-center justify-center bg-gray-100"> |
|||
<span className="text-gray-500 text-sm">加载中...</span> |
|||
</div> |
|||
) |
|||
} |
|||
|
|||
// 获取第一张图片,如果有
|
|||
const firstImage = bannerData?.imageList?.[0]; |
|||
|
|||
if (!firstImage) { |
|||
return ( |
|||
<div ref={containerRef} className="flex items-center justify-center bg-gray-100"> |
|||
<span className="text-gray-500 text-sm">暂无图片数据</span> |
|||
</div> |
|||
) |
|||
} |
|||
|
|||
return ( |
|||
<div ref={containerRef} className="relative overflow-hidden bg-black"> |
|||
<Image |
|||
ref={imageRef} |
|||
className="absolute inset-0" |
|||
src={firstImage.url} |
|||
mode={'scaleToFill'} |
|||
onClick={() => firstImage.path && navTo(firstImage.path)} |
|||
lazyLoad={false} |
|||
alt="全屏 banner 图" |
|||
onLoad={handleImageLoad} |
|||
style={{ |
|||
width: '100%', |
|||
height: '100%', |
|||
// 优先保持比例,只裁剪必要部分
|
|||
objectFit: 'cover', |
|||
// 默认居中显示,保留图片主体内容
|
|||
objectPosition: 'center center' |
|||
}} |
|||
/> |
|||
</div> |
|||
) |
|||
} |
|||
|
|||
export default NaturalFullscreenBanner |
Loading…
Reference in new issue