基于Taro.js开发的H5应用
This commit is contained in:
@@ -8,9 +8,7 @@ import type { CmsNavigation, CmsNavigationParam } from './model';
|
||||
export async function pageCmsNavigation(params: CmsNavigationParam) {
|
||||
const res = await request.get<ApiResult<PageResult<CmsNavigation>>>(
|
||||
'/cms/cms-navigation/page',
|
||||
{
|
||||
params
|
||||
}
|
||||
);
|
||||
if (res.code === 0) {
|
||||
return res.data;
|
||||
|
||||
@@ -30,6 +30,8 @@ export interface CmsNavigation {
|
||||
banner?: string;
|
||||
// 图标颜色
|
||||
color?: string;
|
||||
// 栅格宽度
|
||||
span?: string;
|
||||
// 是否隐藏, 0否, 1是(仅注册路由不显示在左侧菜单)
|
||||
hide?: number;
|
||||
// 可见类型 0所有人 1登录可见 2密码可见
|
||||
|
||||
@@ -3,7 +3,6 @@ export default defineAppConfig({
|
||||
'pages/index/index',
|
||||
'pages/kefu/kefu',
|
||||
'pages/user/user',
|
||||
'pages/article/article',
|
||||
'pages/study/study'
|
||||
],
|
||||
"subpackages": [
|
||||
@@ -27,6 +26,20 @@ export default defineAppConfig({
|
||||
"userVerify/index",
|
||||
"userVerify/admin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "article",
|
||||
"pages": [
|
||||
"index",
|
||||
"detail"
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "photo",
|
||||
"pages": [
|
||||
"index",
|
||||
"detail"
|
||||
]
|
||||
}
|
||||
],
|
||||
window: {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// 引入手机版容器样式
|
||||
//@use './styles/mobile-container.scss';
|
||||
|
||||
/* ./src/index.css */
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@@ -10,6 +13,8 @@ page{
|
||||
background-position: bottom;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 在全局样式文件中添加
|
||||
button {
|
||||
&::after {
|
||||
|
||||
4
src/article/detail.config.ts
Normal file
4
src/article/detail.config.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '详情',
|
||||
navigationBarBackgroundColor: '#ffe0e0'
|
||||
})
|
||||
128
src/article/detail.scss
Normal file
128
src/article/detail.scss
Normal 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
52
src/article/detail.tsx
Normal 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
|
||||
3
src/article/index.config.ts
Normal file
3
src/article/index.config.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '红色资源'
|
||||
})
|
||||
109
src/article/index.tsx
Normal file
109
src/article/index.tsx
Normal 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
|
||||
3
src/custom/article/article.config.ts
Normal file
3
src/custom/article/article.config.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '红色资源'
|
||||
})
|
||||
72
src/custom/article/article.tsx
Normal file
72
src/custom/article/article.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
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} from "@/api/cms/cmsNavigation";
|
||||
import {CmsNavigation} from "@/api/cms/cmsNavigation/model";
|
||||
|
||||
/**
|
||||
* 文章终极列表
|
||||
* @constructor
|
||||
*/
|
||||
const Article = () => {
|
||||
const {params} = useRouter();
|
||||
const [navigation, setNavigation] = useState<CmsNavigation>()
|
||||
const [list, setList] = useState<CmsArticle[]>([])
|
||||
|
||||
const reload = async () => {
|
||||
const categoryId = Number(params.id);
|
||||
const nav = await getCmsNavigation(categoryId);
|
||||
const articles = await pageCmsArticle({categoryId});
|
||||
|
||||
if(nav){
|
||||
setNavigation(nav);
|
||||
}
|
||||
if(articles){
|
||||
setList(articles?.list)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
reload()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="mobile-container">
|
||||
<Image src={navigation?.style} width={'100%'}
|
||||
height={'auto'}/>
|
||||
<div className={'bg-white rounded-lg py-3 px-2'}>
|
||||
{/* 宫格布局容器 */}
|
||||
<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: `/pages/article/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>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default Article
|
||||
@@ -1,50 +0,0 @@
|
||||
import {useEffect, useState} from "react";
|
||||
import {ArrowRight} from '@nutui/icons-react-taro'
|
||||
import {pageCmsArticle} from "@/api/cms/cmsArticle";
|
||||
import {CmsArticle} from "@/api/cms/cmsArticle/model";
|
||||
import Taro from '@tarojs/taro'
|
||||
|
||||
/**
|
||||
* 文章终极列表
|
||||
* @constructor
|
||||
*/
|
||||
const Article = () => {
|
||||
// const {params} = useRouter();
|
||||
// const [categoryId, setCategoryId] = useState<number>(3494)
|
||||
const [list, setList] = useState<CmsArticle[]>([])
|
||||
|
||||
const reload = () => {
|
||||
// if (params.id) {
|
||||
// setCategoryId(Number(params.id))
|
||||
// }
|
||||
pageCmsArticle({}).then(res => {
|
||||
if (res?.list) {
|
||||
setList(res?.list)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
reload()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className={'px-3 mt-4 mb-10'}>
|
||||
<div className={'flex flex-col justify-between items-center bg-white rounded-lg p-4'}>
|
||||
<div className={'bg-white w-full'}>
|
||||
{
|
||||
list.map((item, index) => {
|
||||
return (
|
||||
<div key={index} className={'flex justify-between items-center py-2'} onClick={() => Taro.navigateTo({url: `/cms/help?id=${item.articleId}`}) }>
|
||||
<div className={'text-sm'}>{item.title}</div>
|
||||
<ArrowRight color={'#cccccc'} size={18} />
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default Article
|
||||
54
src/pages/article/detail.tsx
Normal file
54
src/pages/article/detail.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
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="mobile-container">
|
||||
<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>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Detail
|
||||
@@ -6,6 +6,7 @@ import {pageCmsAd} from "@/api/cms/cmsAd";
|
||||
const MyPage = () => {
|
||||
const [item, setItem] = useState<CmsAd>()
|
||||
const [height, setHeight] = useState<string>()
|
||||
const [width, setWidth] = useState<string>()
|
||||
|
||||
const reload = () => {
|
||||
pageCmsAd({keywords: '幻灯片'}).then(data => {
|
||||
@@ -13,6 +14,7 @@ const MyPage = () => {
|
||||
if(data && data?.count > 0){
|
||||
const cmsAd = data.list[0];
|
||||
setHeight(cmsAd.height)
|
||||
setWidth(cmsAd.width)
|
||||
setItem(data.list[0])
|
||||
}
|
||||
})
|
||||
@@ -23,15 +25,15 @@ const MyPage = () => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Swiper defaultValue={0} height={height} indicator style={{ height: height + 'px' }}>
|
||||
<div style={{width: width, height: height}} className={'px-3'}>
|
||||
<Swiper defaultValue={0} height={height} indicator style={{ height: height + 'px', margin: '0 auto' }}>
|
||||
{item?.imageList?.map((item) => (
|
||||
<Swiper.Item key={item}>
|
||||
<img width="100%" height="100%" src={item.url} alt="" style={{ height: height + 'px' }} />
|
||||
</Swiper.Item>
|
||||
))}
|
||||
</Swiper>
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default MyPage
|
||||
|
||||
36
src/pages/index/Image.tsx
Normal file
36
src/pages/index/Image.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import {useEffect, useState} from 'react'
|
||||
import {CmsAd} from "@/api/cms/cmsAd/model";
|
||||
import {pageCmsAd} from "@/api/cms/cmsAd";
|
||||
|
||||
const MyPage = () => {
|
||||
const [item, setItem] = useState<CmsAd>()
|
||||
const [image, setImage] = useState()
|
||||
const [height, setHeight] = useState<string>()
|
||||
const [width, setWidth] = useState<string>()
|
||||
|
||||
const reload = () => {
|
||||
pageCmsAd({keywords: 'TopBanner'}).then(data => {
|
||||
if (data && data?.count > 0) {
|
||||
const cmsAd = data.list[0];
|
||||
setItem(cmsAd)
|
||||
console.log(item,'ad')
|
||||
setHeight(cmsAd.height)
|
||||
setWidth(cmsAd.width)
|
||||
if (cmsAd.imageList && cmsAd.imageList.length > 0) {
|
||||
setImage(cmsAd.imageList[0].url)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
reload()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<img src={image} alt="" style={{width: width + 'px', height: height + 'px'}}/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
export default MyPage
|
||||
@@ -1,113 +1,39 @@
|
||||
import {useEffect, useState} from 'react'
|
||||
import {navigateTo} from '@tarojs/taro'
|
||||
import Taro from '@tarojs/taro'
|
||||
import {Button} from '@tarojs/components';
|
||||
import {Image} from '@nutui/nutui-react-taro'
|
||||
import {getSiteInfo} from "@/api/layout";
|
||||
import {TenantId} from "@/utils/config";
|
||||
import {CmsNavigation} from "@/api/cms/cmsNavigation/model";
|
||||
|
||||
const Page = () => {
|
||||
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [isLogin, setIsLogin] = useState<boolean>(false)
|
||||
const [navItems, setNavItems] = useState<CmsNavigation[]>([])
|
||||
const [navItems, setNavItems] = useState<CmsNavigation[]>([])
|
||||
|
||||
/* 获取用户手机号 */
|
||||
const handleGetPhoneNumber = ({detail}) => {
|
||||
const {code, encryptedData, iv} = detail
|
||||
Taro.login({
|
||||
success: function () {
|
||||
if (code) {
|
||||
Taro.request({
|
||||
url: 'https://server.gxwebsoft.com/api/wx-login/loginByMpWxPhone',
|
||||
method: 'POST',
|
||||
data: {
|
||||
code,
|
||||
encryptedData,
|
||||
iv,
|
||||
notVerifyPhone: true,
|
||||
refereeId: 0,
|
||||
sceneType: 'save_referee',
|
||||
tenantId: TenantId
|
||||
},
|
||||
header: {
|
||||
'content-type': 'application/json',
|
||||
TenantId
|
||||
},
|
||||
success: function (res) {
|
||||
Taro.setStorageSync('access_token', res.data.data.access_token)
|
||||
Taro.setStorageSync('UserId', res.data.data.user.userId)
|
||||
Taro.setStorageSync('Phone', res.data.data.user.phone)
|
||||
setIsLogin(true)
|
||||
Taro.showToast({
|
||||
title: '登录成功',
|
||||
icon: 'success'
|
||||
});
|
||||
}
|
||||
})
|
||||
} else {
|
||||
console.log('登录失败!')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
const reload = () => {
|
||||
getSiteInfo().then(res => {
|
||||
console.log(res);
|
||||
console.log(res.topNavs, 'top');
|
||||
setNavItems(res.topNavs || []);
|
||||
})
|
||||
};
|
||||
|
||||
const onLogin = (item: any) => {
|
||||
if(!isLogin){
|
||||
return navigateTo({url: `/pages/category/category?id=${item.navigationId}`})
|
||||
}else {
|
||||
// 善款明细
|
||||
if(item.navigationId == 4119){
|
||||
return navigateTo({url: `/bszx/pay-record/pay-record`})
|
||||
}
|
||||
return navigateTo({url: `/pages/category/category?id=${item.navigationId}`})
|
||||
}
|
||||
}
|
||||
useEffect(() => {
|
||||
reload();
|
||||
}, [])
|
||||
|
||||
const reload = () => {
|
||||
getSiteInfo().then(res => {
|
||||
console.log(res);
|
||||
console.log(res.topNavs,'top');
|
||||
setNavItems(res.topNavs || []);
|
||||
})
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
reload();
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className={'my-3'}>
|
||||
<div>
|
||||
<div className={'flex justify-between pb-2 px-1'}>
|
||||
{
|
||||
navItems.map((item, index) => (
|
||||
<div key={index} className={'text-center'}>
|
||||
return (
|
||||
<div className={'py-2 my-3 mx-2'}>
|
||||
<div className={'bg-white grid grid-cols-1 md:grid-cols-3 lg:grid-cols-3 gap-2'}>
|
||||
{
|
||||
isLogin && !loading ?
|
||||
<div className={'flex flex-col justify-center items-center'} onClick={() => {
|
||||
onLogin(item)
|
||||
}}>
|
||||
<Image src={item.icon} height={28} width={28}/>
|
||||
<div className={'mt-2'} style={{fontSize: '15px'}}>{item?.title}</div>
|
||||
</div>
|
||||
:
|
||||
<Button className={'text-white'} open-type="getPhoneNumber" onGetPhoneNumber={handleGetPhoneNumber}>
|
||||
<div className={'flex flex-col justify-center items-center'}>
|
||||
<Image src={item.icon} height={28} width={28}/>
|
||||
<div className={'mt-2 text-gray-700'} style={{fontSize: '15px'}}>{item?.title}</div>
|
||||
</div>
|
||||
</Button>
|
||||
navItems.map((item) => (
|
||||
<div className={'flex flex-col justify-center items-center'} onClick={() => Taro.navigateTo({url: `/${item.model}/index?id=${item.navigationId}`})}>
|
||||
<Image className={'shadow-xl rounded-lg'} style={{borderRadius: '8px'}} src={item.icon}
|
||||
height={90} width={90}/>
|
||||
<div className={'mt-2 text-gray-700'} style={{fontSize: '15px'}}>{item?.title}</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
export default Page
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Swiper } from '@nutui/nutui-react-taro'
|
||||
import {CmsAd} from "@/api/cms/cmsAd/model";
|
||||
import {pageCmsAd} from "@/api/cms/cmsAd";
|
||||
|
||||
const MyPage = () => {
|
||||
const [item, setItem] = useState<CmsAd>()
|
||||
const reload = () => {
|
||||
pageCmsAd({keywords: 'TopBanner'}).then(data => {
|
||||
console.log(data,'幻灯片')
|
||||
if(data && data?.count > 0){
|
||||
setItem(data.list[0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
reload()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Swiper defaultValue={0} height={279} indicator style={{ height: '280px' }}>
|
||||
{item?.imageList?.map((item) => (
|
||||
<Swiper.Item key={item}>
|
||||
<img width="100%" height="100%" src={item.url} alt="" style={{ height: '280px' }} />
|
||||
</Swiper.Item>
|
||||
))}
|
||||
</Swiper>
|
||||
</>
|
||||
)
|
||||
}
|
||||
export default MyPage
|
||||
@@ -1,2 +1,16 @@
|
||||
page {
|
||||
}
|
||||
|
||||
.mobile-container {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
|
||||
// PC端样式
|
||||
//@media screen and (min-width: 768px) {
|
||||
// max-width: 414px;
|
||||
// margin: 0 auto;
|
||||
// min-height: auto;
|
||||
// background-color: #fff;
|
||||
// position: relative;
|
||||
//}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import './index.scss'
|
||||
import Taro from '@tarojs/taro';
|
||||
// import {useShareAppMessage, useShareTimeline} from "@tarojs/taro"
|
||||
import {useEffect, useState} from "react";
|
||||
import {getSiteInfo} from "@/api/layout";
|
||||
import Login from "./Login";
|
||||
import Banner from "./Banner";
|
||||
import Menu from "./Menu";
|
||||
import TopBanner from "./TopBanner";
|
||||
import TabBar from "@/components/TabBar";
|
||||
import Image from "./Image";
|
||||
|
||||
export interface Market {
|
||||
// 自增ID
|
||||
@@ -123,14 +122,14 @@ function Home() {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mobile-container">
|
||||
{!IsLogin && search ? (<Login done={handleLogin}/>) : (<>
|
||||
<TopBanner/>
|
||||
<Image/>
|
||||
<Menu/>
|
||||
<Banner/>
|
||||
<TabBar/>
|
||||
</>)}
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,13 +8,13 @@ function User() {
|
||||
useEffect(() => {
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
<div className="mobile-container">
|
||||
<div className={'fixed w-full'}>
|
||||
<UserCard />
|
||||
<UserCell />
|
||||
<TabBar/>
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
4
src/photo/detail.config.ts
Normal file
4
src/photo/detail.config.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '详情',
|
||||
navigationBarBackgroundColor: '#ffe0e0'
|
||||
})
|
||||
128
src/photo/detail.scss
Normal file
128
src/photo/detail.scss
Normal 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/photo/detail.tsx
Normal file
52
src/photo/detail.tsx
Normal 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
|
||||
3
src/photo/index.config.ts
Normal file
3
src/photo/index.config.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '图文列表'
|
||||
})
|
||||
109
src/photo/index.tsx
Normal file
109
src/photo/index.tsx
Normal 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
|
||||
93
src/styles/mobile-container.scss
Normal file
93
src/styles/mobile-container.scss
Normal file
@@ -0,0 +1,93 @@
|
||||
// 手机版容器样式 - 用于PC端显示手机版效果
|
||||
.mobile-container {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
position: relative;
|
||||
|
||||
// PC端样式 - 768px以上显示手机版效果
|
||||
@media screen and (min-width: 768px) {
|
||||
max-width: 414px;
|
||||
width: 414px !important;
|
||||
margin: 0 auto;
|
||||
min-height: auto;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
// 确保内容不超出容器
|
||||
* {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// 大屏幕设备 - 1024px以上
|
||||
@media screen and (min-width: 1024px) {
|
||||
max-width: 375px;
|
||||
width: 375px !important;
|
||||
}
|
||||
|
||||
// 超大屏幕设备 - 1440px以上
|
||||
@media screen and (min-width: 1440px) {
|
||||
max-width: 414px;
|
||||
width: 414px !important;
|
||||
}
|
||||
}
|
||||
|
||||
// PC端页面背景
|
||||
@media screen and (min-width: 768px) {
|
||||
body {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
padding: 40px 20px;
|
||||
}
|
||||
|
||||
// 主应用容器
|
||||
#app {
|
||||
max-width: 414px !important;
|
||||
width: 414px !important;
|
||||
margin: 0 auto;
|
||||
background-color: transparent;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
// 页面容器
|
||||
page {
|
||||
max-width: 414px !important;
|
||||
width: 414px !important;
|
||||
margin: 0 auto;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 0 30px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
// Taro页面容器
|
||||
.taro_page {
|
||||
max-width: 414px !important;
|
||||
width: 414px !important;
|
||||
margin: 0 auto;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// 底部导航栏在PC端的样式调整
|
||||
.nut-tabbar {
|
||||
max-width: 414px !important;
|
||||
width: 414px !important;
|
||||
margin: 0 auto;
|
||||
border-radius: 0 0 12px 12px;
|
||||
}
|
||||
}
|
||||
|
||||
// 移动端保持原有样式
|
||||
@media screen and (max-width: 767px) {
|
||||
.mobile-container {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user