基于Taro.js开发的H5应用

This commit is contained in:
2025-07-07 13:24:48 +08:00
parent 3db95dbe9b
commit 59f771d542
26 changed files with 919 additions and 193 deletions

View File

@@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: '详情',
navigationBarBackgroundColor: '#ffe0e0'
})

128
src/article/detail.scss Normal file
View File

@@ -0,0 +1,128 @@
.content {
padding: 32px;
line-height: 2.4rem;
// 富文本内容样式
:global {
// 段落样式
p {
margin: 16px 0;
line-height: 1.8;
text-align: justify;
}
// 标题样式
h1, h2, h3, h4, h5, h6 {
margin: 24px 0 16px 0;
font-weight: bold;
line-height: 1.4;
}
h1 { font-size: 24px; }
h2 { font-size: 22px; }
h3 { font-size: 20px; }
h4 { font-size: 18px; }
h5 { font-size: 16px; }
h6 { font-size: 14px; }
// 图片样式
img {
max-width: 100%;
height: auto;
border-radius: 8px;
margin: 16px 0;
display: block;
}
// 列表样式
ul, ol {
margin: 16px 0;
padding-left: 24px;
li {
margin: 8px 0;
line-height: 1.6;
}
}
// 引用样式
blockquote {
margin: 16px 0;
padding: 16px;
background-color: #f5f5f5;
border-left: 4px solid #ddd;
border-radius: 4px;
p {
margin: 0;
font-style: italic;
}
}
// 代码样式
code {
background-color: #f5f5f5;
padding: 2px 6px;
border-radius: 4px;
font-family: 'Courier New', monospace;
font-size: 14px;
}
pre {
background-color: #f5f5f5;
padding: 16px;
border-radius: 8px;
overflow-x: auto;
margin: 16px 0;
code {
background: none;
padding: 0;
}
}
// 表格样式
table {
width: 100%;
border-collapse: collapse;
margin: 16px 0;
th, td {
border: 1px solid #ddd;
padding: 12px;
text-align: left;
}
th {
background-color: #f5f5f5;
font-weight: bold;
}
}
// 链接样式
a {
color: #1890ff;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
// 分割线样式
hr {
margin: 24px 0;
border: none;
border-top: 1px solid #eee;
}
// 强调样式
strong, b {
font-weight: bold;
}
em, i {
font-style: italic;
}
}
}

52
src/article/detail.tsx Normal file
View File

@@ -0,0 +1,52 @@
import {useEffect, useState} from 'react'
import {Tag} from '@nutui/nutui-react-taro'
import {useRouter} from '@tarojs/taro'
import {Divider} from '@nutui/nutui-react-taro'
import {CmsArticle} from "@/api/cms/cmsArticle/model"
import {Eye} from '@nutui/icons-react-taro'
// 显示html富文本
import {View, RichText} from '@tarojs/components'
import './detail.scss'
import Line from "@/components/Gap";
import {getCmsArticle} from "@/api/cms/cmsArticle";
function Detail() {
const {params} = useRouter();
// 文章详情
const [item, setItem] = useState<CmsArticle>()
// 浏览量
const [views, setViews] = useState<number>()
const reload = () => {
getCmsArticle(Number(params.id)).then(data => {
if (data) {
setItem(data)
setViews(data.actualViews)
}
})
}
useEffect(() => {
reload();
}, []);
return (
<div className={'bg-white'}>
<div className={'p-3 font-bold text-lg'}>{item?.title}</div>
<div className={'flex justify-between px-3'}>
<Tag type={'success'}>{item?.categoryName}</Tag>
<div className={'flex items-center gap-2 text-sm text-gray-400'}><Eye size={14}/>{views}</div>
</div>
<Divider/>
<View className={'content text-gray-700 text-sm'}>
<RichText
nodes={item?.content || '暂无内容'}
space="nbsp"
/>
</View>
<Line height={44}/>
</div>
)
}
export default Detail

View File

@@ -0,0 +1,3 @@
export default definePageConfig({
navigationBarTitleText: '红色资源'
})

109
src/article/index.tsx Normal file
View File

@@ -0,0 +1,109 @@
import {useEffect, useState} from "react";
import {pageCmsArticle} from "@/api/cms/cmsArticle";
import {CmsArticle} from "@/api/cms/cmsArticle/model";
import Taro from '@tarojs/taro'
import {useRouter} from '@tarojs/taro'
import {Image} from '@nutui/nutui-react-taro'
import {getCmsNavigation, pageCmsNavigation} from "@/api/cms/cmsNavigation";
import {CmsNavigation} from "@/api/cms/cmsNavigation/model";
/**
* 文章终极列表
* @constructor
*/
const Index = () => {
const {params} = useRouter();
const [navigation, setNavigation] = useState<CmsNavigation>()
const [childCategory, setChildCategory] = useState<CmsNavigation[]>([])
const [list, setList] = useState<CmsArticle[]>([])
const reload = async () => {
// 获取栏目ID
const categoryId = Number(params.id);
// 当前栏目信息
const navs = await getCmsNavigation(categoryId);
// 二级栏目
const childCateogry = await pageCmsNavigation({parentId: categoryId});
// 终极新闻列表
const articles = await pageCmsArticle({categoryId});
// 当前栏目信息
if (navs) {
setNavigation(navs);
}
// 获取子级栏目
if (childCateogry) {
setChildCategory(childCateogry.list)
}
// 新闻列表
if (articles) {
setList(articles?.list || [])
}
}
useEffect(() => {
reload()
}, [])
return (
<>
<div style={{padding: navigation?.span + 'px'}}>
<Image src={navigation?.style} width={'100%'}
height={'auto'}/>
</div>
<div className={'bg-white rounded-lg py-3 px-3'}>
<div className={'grid grid-cols-2 gap-3'}>
{
// 子级栏目
childCategory.map((item, index) => {
return (
<div
key={index}
className={'flex flex-col justify-center items-center cursor-pointer'}
onClick={() => Taro.navigateTo({url: `./index?id=${item.navigationId}`})}
>
{/* 图片容器 */}
<div className={'w-full mb-2 flex justify-center'}>
<img
className={'object-cover rounded-lg'}
src={item.icon}
alt={item.title || ''}
/>
</div>
</div>
)
})
}
</div>
<div className={'grid grid-cols-3'}>
{
// 终极文章列表
list.map((item, index) => {
return (
<div
key={index}
className={'flex flex-col items-center cursor-pointer my-1'}
onClick={() => Taro.navigateTo({url: `./detail?id=${item.articleId}`})}
>
{/* 图片容器 */}
<div className={'w-full mb-2 flex justify-center'}>
<img
className={'object-cover rounded-lg'}
src={item.image}
alt={item.title || ''}
/>
</div>
{/* 标题 */}
<div className={'text-xs text-center text-gray-800 leading-tight px-1'}>
{item.title}
</div>
</div>
)
})
}
</div>
</div>
</>
)
}
export default Index