Compare commits

...

2 Commits

  1. 4
      .env
  2. 7
      src/api/brand.ts
  3. 13
      src/api/illness.ts
  4. 40
      src/components/articlesBox/articlesBox.module.scss
  5. 45
      src/components/articlesBox/articlesBox.tsx
  6. 6
      src/components/collect/collect.module.scss
  7. 4
      src/components/collect/collect.tsx
  8. 2
      src/components/image/image.tsx
  9. 2
      src/components/videoCover/videoCover.tsx
  10. 15
      src/components/videoList/videoList.tsx
  11. 32
      src/pages/home/components/curRecommended.tsx
  12. 2
      src/pages/home/components/search.tsx
  13. 19
      src/pages/index/index.tsx
  14. 2
      src/pages/manage/depAdmin/depAdmin.scss
  15. 2
      src/pages/manage/depAdmin/depAdmin.tsx
  16. 1
      src/pages/manage/selectDep/selectDep.tsx
  17. 6
      src/pages/preview/brand/article/article.module.scss
  18. 48
      src/pages/preview/brand/article/article.tsx
  19. 3
      src/pages/preview/brand/info/info.module.scss
  20. 33
      src/pages/preview/brand/info/info.tsx
  21. 31
      src/pages/preview/illness/list/list.tsx
  22. 9
      src/pages/preview/search/search/components/list.tsx
  23. 11
      types/articles.d.ts

@ -1,5 +1,5 @@
#TARO_APP_API=https://yjx.dev.yaojiankang.top
TARO_APP_API=https://mooc.yaojiankang.top
TARO_APP_API=https://yjx.dev.yaojiankang.top
#TARO_APP_API=https://mooc.yaojiankang.top
#TARO_APP_API=https://shopfix.yaojiankang.top
#TARO_APP_API=https://playedu.yaojiankang.top
TARO_APP_LGOIN=true

@ -1,4 +1,5 @@
import {request} from "@/api/request";
import {Illness} from "@/api/illness";
export type BrandRecord = {
logo: string;
@ -21,8 +22,10 @@ export type ArticleRecord = {
created_at: string
content: string
brands: BrandRecord[]
illness: Illness[]
collect: boolean
cover:string
cover: string
owner_type: 1 | 2 // 疾病
}
export const brandApi = {
@ -40,7 +43,7 @@ export const brandApi = {
/** 文章列表 */
articleList(owner_id: number, page: number) {
return request<{
list: ArticleRecord[],
list: Articles[],
total: number
}>(`/home/v1/article/list?owner_id=${owner_id}&page=${page}&page_size=10`, "GET")
},

@ -1,5 +1,16 @@
import {request} from "@/api/request";
export interface Illness {
name: string;
description: string;
resource: any;
album: string[]
created_at:string
list: {
list: any[],
total: number
}
}
export const illnessApi = {
/** 疾病列表 */
@ -7,7 +18,7 @@ export const illnessApi = {
return request<{ list: any[], total: number }>(`/home/v1/illness/list`, "GET", {page, page_size, id})
},
articleInfo(owner_id: number, page: number, page_size: number) {
return request<{ illness:{name:string;description:string;resource:any;album:string[]};list:{list: any[], total: number} }>
return request<{ illness: Illness }>
(`/home/v1/article/illness_list`, "GET", {page, page_size, owner_id})
},
}

@ -0,0 +1,40 @@
.artcles {
padding: 30rpx 0;
border-bottom: 1px solid #F5F8F7;
}
.outside {
display: flex;
justify-content: space-between;
.title {
font-size: 28rpx;
font-family: PingFang SC-Bold, PingFang SC;
font-weight: bold;
color: #323635;
}
.intro {
font-size: 24rpx;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #909795;
margin-top: 10rpx;
}
}
.img {
overflow: hidden;
border-radius: 10rpx;
}
.pageView {
font-size: 22rpx;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #909795;
margin-top: 20rpx;
}

@ -0,0 +1,45 @@
import {FC, useEffect, useState} from "react";
import {Text, View} from "@tarojs/components";
import Taro from "@tarojs/taro";
import styles from './articlesBox.module.scss'
import Img from "@/components/image/image";
import {beforeTime} from "@/utils/time";
interface Props {
data: Articles
}
const ArticlesBox: FC<Props> = (props) => {
const [data, setData] = useState(props.data)
useEffect(() => {
setData(props.data)
}, [props.data])
const toArticlePage = () => {
Taro.navigateTo({
url: `/pages/preview/brand/article/article?id=${data.id}`
})
}
return (
<View className={styles.artcles} onClick={toArticlePage}>
<View className={styles.outside}>
<View className='flex-1 mr-2'>
<View className={`${styles.title} text-ellipsis-1`}>{data.title}</View>
<View className={`${styles.intro} text-ellipsis-2`}>{data.intro}</View>
<View className={styles.pageView}>
<Text>{beforeTime(data.created_at)}</Text>·
<Text>{data.page_view || 0}</Text>
</View>
</View>
<Img src={data.cover || ''}
errorType={data.owner_type === 1 ? 'brand' : 'health'}
width={148}
height={116}
className={styles.img}/>
</View>
</View>
)
}
export default ArticlesBox

@ -20,14 +20,16 @@
}
.zoom {
top: 0;
left: 0;
//top: 0;
//left: 0;
position: absolute;
content: '';
width: 32rpx;
height: 32rpx;
border-radius: 50%;
border: 1px solid #FF9E5F;
padding: 0 !important;
margin: 0 !important;
animation: Zooms 300ms ease forwards;
opacity: 1;
transform-origin: -100%, -100% 0;

@ -35,11 +35,9 @@ const Collect: FC<Props> = (props) => {
}
if (loading) return;
props.onClick?.()
console.log(select)
await userApi.create({owner_id: props.owner_id, owner_type: props.owner_type})
setSelect(!select)
setLoading(true)
// fixme: 动画逻辑不对,应该是先 loading, 然后只有操作成功之后才是 select 动画
await userApi.create({owner_id: props.owner_id, owner_type: props.owner_type})
props.onUpdate?.(!select)
setTimeout(() => {
setLoading(false)

@ -81,7 +81,7 @@ const Img: FC<Props> = ({src, mode = 'aspectFill', width, fallback = shard, ...p
overflow: 'hidden',
width: width ? `${width}rpx` : "100%",
height: height ? `${height}rpx` : "100%",
backgroundColor: (isError || !loading) ? 'transparent' : '#F8F8F8'
backgroundColor: (isError || !loading) ? 'transparent' : '#F8F8F8',
}}>
{!isError &&
<View animation={animationData} style={{height: '100%', width: '100%'}}>

@ -29,7 +29,7 @@ const VideoCover: FC<VideoCoverProps> = (opt: VideoCoverProps) => {
<View className='videoBox'>
<View className='video' onClick={jump}>
<View className='upper'>
<Img height={180} src={opt.thumb} mode='widthFix'/>
<Img height={180} src={opt.thumb} mode='widthFix' errorType='course'/>
{opt.marker && <View className='marker'>{opt.marker}</View>}
{opt.content && <View className='content'>{opt.content}</View>}
</View>

@ -1,4 +1,4 @@
import {FC, useState} from "react";
import {FC, useEffect, useState} from "react";
import styles from "@/pages/preview/health/health.module.scss";
import {Image, Text, View} from "@tarojs/components";
import Img from "@/components/image/image";
@ -11,25 +11,28 @@ interface Props {
errorType?: ImgErrType
}
const VideoList: FC<Props> = ({data, errorType}) => {
const [frequency, setFrequency] = useState(0)
const VideoList: FC<Props> = (props) => {
const [data, setData] = useState(props.data)
useEffect(() => {
setData(props.data)
}, [props.data])
function jump() {
Taro.preload(data)
setFrequency(frequency + 1)
Taro.navigateTo({url: `/pages/preview/videoFull/videoFull?id=${data.id}`})
}
return (
<View key={data.id} className={styles.health} onClick={jump}>
<Img src={data.url_path} mode='widthFix' errorType={errorType} height={346} fit/>
<Img src={data.url_path} mode='widthFix' errorType={props.errorType} height={346}/>
<Image src={play} className={styles.play} mode='aspectFit'/>
<View className='p-1'>
<View className='text-ellipsis-2 text-dark'>{data.title}</View>
<View className='text-ellipsis-2 mt-1 font-26 text-secondary'>{data.introduction}</View>
<View className='font-24 text-muted my-2 flex justify-between'>
<Text>{formatDate(new Date(data.publish_time), "YY-MM-dd")}</Text>
<Text>{(data.video_view || 1) + frequency}</Text>
<Text>{(data.video_view || 0)}</Text>
</View>
</View>
</View>)

@ -1,24 +1,17 @@
import {FC, ReactNode, useEffect, useState} from "react";
import {Image, View} from "@tarojs/components";
import {HomeApi} from "@/api";
import Taro, {useReachBottom} from "@tarojs/taro";
import {useReachBottom} from "@tarojs/taro";
import styles from "../home.module.scss";
import VideoCover from "@/components/videoCover/videoCover";
import courseTag from '@/static/img/courseTag.png'
import Img from "@/components/image/image";
import {beforeTime} from "@/utils/time";
const toArticlePage = (d: any) => {
Taro.navigateTo({
url: `/pages/preview/brand/article/article?id=${d.id}`
})
}
import ArticlesBox from "@/components/articlesBox/articlesBox";
const CurRecommended: FC = () => {
const [page, setPage] = useState(1)
const [data, setData] = useState<Curriculum[]>([])
const [total, setTotal] = useState(0)
const [articles, setArticles] = useState<any[]>([])
const [articles, setArticles] = useState<Articles[]>([])
async function getData() {
const res = await HomeApi.course(page, 4)
@ -48,20 +41,11 @@ const CurRecommended: FC = () => {
if (articles.length > 0) {
examines = (
<View className="mb-5">
<View className='text-center my-2'></View>
<View className='bg-white rounded-20 clip'>
{articles.map((d, i) => <View className='p-3 relative' onClick={() => toArticlePage(d)}>
{i > 0 && <View className='absolute top left right divided ml-3 mr-3'/>}
<View className="font-34 text-black">{d.title}</View>
{(d.intro || '').length > 40 && (<View className='flex mt-1'>
<View className="flex-1 font-24 lh1_5">{d.intro}</View>
{d.cover && <Img className='ml-l' width={140} height={100} src={d.cover} errorType="acquiesce"/>}
</View>)}
<View className="flex mt-3 justify-between font-24 text-muted">
<View>{beforeTime(d.created_at)}</View>
<View> {d.page_view || 0}</View>
</View>
</View>)}
<View className='bg-white rounded-20 clip px-3'>
<View className='mt-3 mb-3 font-32 bold text-dark'></View>
{
articles.map(d => <ArticlesBox data={d}/>)
}
</View>
</View>
)

@ -13,7 +13,7 @@ export const Search: FC = () => {
return (
<View className={styles.search} onClick={jump}>
<Image src={search} mode='widthFix' style={{width: 16, height: 16, verticalAlign: 'middle',padding:'0 20rpx'}}/>
<Image src={search} mode='widthFix' style={{width: 16, height: 16, verticalAlign: 'middle',paddingRight:'10rpx'}}/>
<View></View>
</View>
)

@ -6,10 +6,8 @@ import Tabs, {OnChangOpt, TabList} from "@/components/tabs/tabs";
import {CoursesKey, publicApi} from "@/api/public";
import NavigationBar from "@/components/navigationBar/navigationBar";
import Spin from "@/components/spinner";
import Img from "@/components/image/image";
import {beforeTime} from "@/utils/time";
import {isBoolean} from "@tarojs/shared";
import Taro from "@tarojs/taro";
import ArticlesBox from "@/components/articlesBox/articlesBox";
const category: TabList[] = [
{title: "企选课程", value: 'is_required'},
@ -56,20 +54,9 @@ const AuditMode: FC = () => {
auditMode ?
<>
<NavigationBar text='文章列表' cancelBack/>
<View className='bg-white rounded-20 clip'>
<View className='bg-white rounded-20 clip m-3 px-3'>
{
articles.map((d, i) => <View className='p-3 relative' onClick={() => Taro.navigateTo({url: "/pages/preview/brand/article/article?id=" + d.id})}>
{i > 0 && <View className='absolute top left right divided ml-3 mr-3'/>}
<View className="font-34 text-black">{d.title}</View>
{(d.intro || '').length > 40 && (<View className='flex mt-1'>
<View className="flex-1 font-24 lh1_5">{d.intro}</View>
{d.cover && <Img className='ml-l' width={140} height={100} src={d.cover} errorType="acquiesce"/>}
</View>)}
<View className="flex mt-3 justify-between font-24 text-muted">
<View>{beforeTime(d.created_at)}</View>
<View> {d.page_view || 0}</View>
</View>
</View>)
articles.map(d => <ArticlesBox data={d}/>)
}
</View>
<View className='text-center font-24 text-dark mt-2'></View>

@ -1,7 +1,7 @@
.content {
margin-top: 20rpx;
background: white;
min-height: calc(100vh - 20rpx);
min-height: calc(100vh - 20rpx - env(safe-area-inset-bottom));
box-sizing: border-box;
padding-bottom: calc(env(safe-area-inset-bottom) + 80rpx);
}

@ -160,8 +160,6 @@ const DepAdmin: FC = () => {
content={['学员', '管理员', '超级管理员'][d.role_type]}
/>)
}
{manages.length > 0 || users.length > 0 && <View className='text-center font-24 text-dark mt-3'></View>}
{!manages.length && !users.length && <Empty name='暂无数据'/>}
<View className='operation'>

@ -59,7 +59,6 @@ const SelectDep: FC = () => {
leftImage={folder}/>
</View>
</View>)}
<View className='text-center font-24 text-dark mt-3'></View>
<View className={'my-3'}>
<MyButton onClick={ok}></MyButton>

@ -54,12 +54,6 @@ page{
align-items: center;
background: #F5F8F7;
color: #909795;
View {
font-size: 26rpx;
padding: 0 10px;
text-align: center;
}
}
.article {

@ -22,7 +22,6 @@ const article: FC = () => {
const [ultra, setUltra] = useState(true)
const [show, setShow] = useState(false)
const globalData = Taro.getApp().globalData
const pageHeight = globalData.windowHeight - globalData.textBarHeight - globalData.statusBarHeight
const {children, headings} = useMemo(() => parse(articleInfo?.content || ''), [articleInfo])
const query = Taro.createSelectorQuery()
const [maoId, setMaoId] = useState('')
@ -33,7 +32,7 @@ const article: FC = () => {
query.select('#childrenNode').boundingClientRect((res) => {
if (!Array.isArray(res)) {
console.log({childrenNode: res})
setUltra(pageHeight * .45 <= res.height)
setUltra(globalData.pageHeight * .45 <= res.height)
}
}).exec()
}, 300)
@ -51,7 +50,6 @@ const article: FC = () => {
Taro.nextTick(() => {
query.select(`#${id}`).boundingClientRect()
query.exec((res) => {
console.log({res})
if (res.length) {
Taro.pageScrollTo({
scrollTop: res[res.length - 1].top,
@ -92,16 +90,17 @@ const article: FC = () => {
<View>
<Collect
select={articleInfo?.collect}
styles={{flexDirection: 'column', justifyContent: 'center', padding: '20rpx'}}
styles={{flexDirection: 'column', justifyContent: 'center'}}
stylesImage={{margin: '0 0 8rpx 0'}}
owner_id={Number(id)}
owner_type={1}
onUpdate={onCollect}
/>
</View>
<View className='flex flex-column justify-center align-center' onClick={() => setShow(true)}>
<Image src={catalogue} mode='widthFix' style={{width: '40rpx', height: '40rpx'}}/>
<View></View>
<View className='flex flex-column justify-center align-center text-center px-10'
onClick={() => setShow(true)}>
<Image src={catalogue} mode='widthFix' style={{width: '36rpx', height: '36rpx', marginBottom: '8rpx'}}/>
<View className='font-26'></View>
</View>
</View>
}
@ -110,13 +109,14 @@ const article: FC = () => {
<View
className={styles.articleBox}
style={{
height: !token ? Taro.getWindowInfo().windowHeight - 60 + 'px' : 'auto',
overflow: !token ? 'hidden' : 'auto'
height: !token ? globalData.pageHeight - 60 + 'px' : 'auto',
overflow: !token ? 'hidden' : 'auto',
boxSizing: 'border-box'
}}>
<View id="childrenNode">
<View className={styles.articleTitle}>{articleInfo?.title}</View>
{
articleInfo?.brands?.map(d => (
articleInfo?.owner_type === 1 && articleInfo?.brands?.map(d => (
<View className='flex align-center mb-4'>
<View className={`${styles.article} flex-1`}>
<Img src={d.logo} width={80} height={80} className={styles.articleImag} errorType='avatar'/>
@ -142,6 +142,34 @@ const article: FC = () => {
</View>
))
}
{
articleInfo?.owner_type === 2 && articleInfo?.illness?.map(d => (
<View className='flex align-center mb-4'>
<View className={`${styles.article} flex-1`}>
<Img src={''} width={80} height={80} className={styles.articleImag} errorType='health'/>
<View className='ml-2'>
<View>{d?.name}</View>
<View className='flex mt-1 text-muted font-24'>
<View className='mr-2'>{beforeTime(articleInfo?.created_at)} . </View>
<View> {articleInfo.page_view || 1}</View>
</View>
</View>
</View>
<View className='ml-2'>
<Collect
select={articleInfo?.collect}
styles={{flexDirection: 'column', justifyContent: 'center', padding: '20rpx'}}
stylesImage={{margin: '0 0 8rpx 0'}}
owner_id={Number(id)}
owner_type={1}
textHidden
onUpdate={onCollect}
/>
</View>
</View>
))
}
{
children.length > 0
? <View>{children}</View>

@ -40,6 +40,9 @@ page{
background-color: #fff;
border-radius: 32rpx 32rpx 0 0;
width: 100%;
padding: 0 30rpx;
width: 100%;
box-sizing: border-box;
.box {
display: flex;
background-color: #fff;

@ -1,14 +1,14 @@
import {FC, useCallback, useEffect, useState} from "react";
import {Swiper, SwiperItem, Text, Video, View} from "@tarojs/components";
import {ArticleRecord, brandApi, BrandRecord} from "@/api";
import { brandApi, BrandRecord} from "@/api";
import styles from './info.module.scss'
import Taro, {useReachBottom, useRouter} from "@tarojs/taro";
import LineEllipsis from "@/components/textCollapse/collapse";
import Empty from "@/components/empty/empty";
import Img from "@/components/image/image";
import {rfc33392time} from "@/utils/day";
import Spin from "@/components/spinner";
import Collect from "@/components/collect/collect";
import ArticlesBox from "@/components/articlesBox/articlesBox";
type Params = {
id: number
@ -16,7 +16,7 @@ type Params = {
const BrandInfo: FC = () => {
const {id} = useRouter().params as unknown as Params
const [brandInfo, setBrandInfo] = useState<BrandRecord>()
const [articleList, setArticleList] = useState<ArticleRecord[]>([])
const [articleList, setArticleList] = useState<Articles[]>([])
const [curIndex, setCurIndex] = useState<number>(1)
const [page, setPage] = useState(1)
const [total, setTotal] = useState(0)
@ -64,15 +64,6 @@ const BrandInfo: FC = () => {
setCurIndex(+e.detail.current + 1)
}
function jump(data: ArticleRecord, index: number) {
Taro.navigateTo({url: `/pages/preview/brand/article/article?id=${data.id}`})
const oldArticle: ArticleRecord[] = JSON.parse(JSON.stringify(articleList))
oldArticle.splice(index, 1, {
...data,
page_view: (data.page_view || 1) + 1
})
setArticleList(oldArticle)
}
return (
<View className='flex flex-column' style={{display: 'flex'}}>
@ -106,7 +97,7 @@ const BrandInfo: FC = () => {
(brandInfo?.brand_album?.length || 0) > 0
&& brandInfo?.brand_album?.split(',').map((d) =>
<SwiperItem>
<Img mode={'aspectFill'} width={750} height={600} src={d}/>
<Img mode={'aspectFill'} width={750} height={600} src={d} errorType='brand'/>
</SwiperItem>)
}
</Swiper>
@ -123,23 +114,13 @@ const BrandInfo: FC = () => {
<Text className={`${styles['title']} flex-1`}>{brandInfo?.name}</Text>
<Collect owner_type={4} owner_id={id} select={brandInfo?.collect}/>
</View>
<LineEllipsis text={brandInfo?.graphic_introduction || '暂无简介'}></LineEllipsis>
<LineEllipsis text={brandInfo?.graphic_introduction || '暂无简介'}/>
</View>
<View className={styles['bottom']}>
{
articleList?.length ? <>{
articleList.map((i, index) => <View className={styles.box} onClick={() => jump(i, index)}>
<View className={styles.inner}>
<View className={styles.leftBox}>
<View className='font-weight mb-2 font-28 lh-40'>{i.title}</View>
<View className={styles.desc}>{rfc33392time(i.created_at)} {i.page_view || 1}</View>
</View>
<View className={styles.image}>
<Img width={172} height={128} src={i.cover} errorType='brand'/>
</View>
</View>
</View>)}
<View className='text-center font-24 text-dark'></View>
articleList.map(d => <ArticlesBox data={d}/>)}
<View className='text-center font-24 text-dark mt-3'></View>
</>
: <Empty name='空空如也'/>
}

@ -4,8 +4,7 @@ import Taro, {useReachBottom, useRouter} from "@tarojs/taro";
import {illnessApi} from "@/api/illness";
import Empty from "@/components/empty/empty";
import Spin from "@/components/spinner";
import Img from "@/components/image/image";
import {beforeTime} from "@/utils/time";
import ArticlesBox from "@/components/articlesBox/articlesBox";
const BrandList: FC = () => {
const params = useRouter().params as unknown as { id: number }
@ -32,17 +31,6 @@ const BrandList: FC = () => {
Taro.hideLoading()
}, [page])
function jump(data: any, index: number) {
Taro.navigateTo({url: '/pages/preview/brand/article/article?id=' + data.id})
const oldArticles: any[] = JSON.parse(JSON.stringify(articles))
oldArticles.splice(index, 1, {
...data,
page_view: data.page_view + 1
})
setArticles(oldArticles)
}
useReachBottom(useCallback(() => {
if (articles?.length < total) {
setPage(page + 1)
@ -51,25 +39,14 @@ const BrandList: FC = () => {
return (
<View style={{display: fetchDone ? 'block' : 'none'}} className='px-2 mt-2'>
<View style={{display: fetchDone ? 'block' : 'none'}} className='px-3 mt-3'>
<Spin enable={enable} overlay/>
{
articles.length > 0 ?
<>
<View className='bg-white rounded-20 clip'>
<View className='bg-white rounded-20 clip px-3'>
{
articles.map((d, i) => <View className='p-3 relative' onClick={() => jump(d, i)}>
{i > 0 && <View className='absolute top left right divided ml-3 mr-3'/>}
<View className="font-34 text-black">{d.title}</View>
{(d.intro || '').length > 40 && (<View className='flex mt-1'>
<View className="flex-1 font-24 lh1_5">{d.intro}</View>
{d.cover && <Img className='ml-l' width={140} height={100} src={d.cover} errorType="acquiesce"/>}
</View>)}
<View className="flex mt-3 justify-between font-24 text-muted">
<View>{beforeTime(d.created_at)}</View>
<View> {d.page_view || 0}</View>
</View>
</View>)
articles.map(d => <ArticlesBox data={d}/>)
}
</View>
<View className='text-center font-24 text-dark mt-3'></View>

@ -5,9 +5,9 @@ import Taro from "@tarojs/taro";
import Empty from "@/components/empty/empty";
import Img from "@/components/image/image";
import {SearchApi} from "@/api/search";
import {AtLoadMore} from 'taro-ui'
import {rfc33392time} from "@/utils/day";
import play from "@/static/img/play-back.png";
import Spin from "@/components/spinner";
type Props = {
name: string
@ -95,10 +95,9 @@ const SearchList: FC<Props> = ({name, clear}) => {
className='scrollview'
scrollY
scrollWithAnimation
style={{height: `${globalData.screenHeight - 140}px`, backgroundColor: `#f5f5f5`}}
onScrollToLower={onScrollToLower}
>
{loading && <AtLoadMore status={'loading'}/>}
style={{height: `${globalData.screenHeight - 140}px`, backgroundColor: `#f5f5f5`, position: 'relative'}}
onScrollToLower={onScrollToLower}>
<Spin enable={loading} block overlay/>
{
brands.length >= 1 && !loading &&
<>

@ -0,0 +1,11 @@
interface Articles {
id: number
title: string
/** 封面 */
cover?: string
created_at: string
page_view: number
/** 描述 */
intro: string
owner_type:number
}
Loading…
Cancel
Save