新增图片默认加载类型 和 我的页面header动画

v2
king 1 year ago
parent a43fc7498c
commit 70e61e187e
  1. 4
      .env
  2. 16
      src/api/brand.ts
  3. 29
      src/components/image/image.tsx
  4. 1
      src/components/learningRecord/learningRecord.tsx
  5. 5
      src/pages/my/components/header/header.tsx
  6. 10
      src/pages/my/my.module.scss
  7. 8
      src/pages/my/my.tsx
  8. 11
      src/pages/preview/brand/list/list.tsx

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

@ -8,7 +8,9 @@ export type BrandRecord = {
brand_album: string brand_album: string
graphic_introduction: string graphic_introduction: string
disabled: number disabled: number
introductory_video_resource:any introductory_video_resource: any
article_count: number
created_at: string
} }
export type ArticleRecord = { export type ArticleRecord = {
title: string title: string
@ -19,24 +21,24 @@ export type ArticleRecord = {
export const brandApi = { export const brandApi = {
/** 品牌列表 */ /** 品牌列表 */
list(page: number , page_size: number) { list(page: number, page_size: number) {
return request<{ return request<{
list: BrandRecord[], list: BrandRecord[],
total: number total: number
}>(`/home/v1/brand/list?page=${page}&page_size=${page_size}` , "GET") }>(`/home/v1/brand/list?page=${page}&page_size=${page_size}`, "GET")
}, },
/** 品牌详情 */ /** 品牌详情 */
info(id: number) { info(id: number) {
return request<BrandRecord>(`/home/v1/brand/${id}`, "GET") return request<BrandRecord>(`/home/v1/brand/${id}`, "GET")
}, },
/** 文章列表 */ /** 文章列表 */
articleList(owner_id: number,page:number) { articleList(owner_id: number, page: number) {
return request<{ return request<{
list: ArticleRecord[], list: ArticleRecord[],
total: number total: number
}>(`/home/v1/article/list?owner_id=${owner_id}&page=${page}&page_size=10` , "GET") }>(`/home/v1/article/list?owner_id=${owner_id}&page=${page}&page_size=10`, "GET")
}, },
articleInfo(id: number ) { articleInfo(id: number) {
return request<ArticleRecord>(`/home/v1/article/${id}` , "GET") return request<ArticleRecord>(`/home/v1/article/${id}`, "GET")
}, },
} }

@ -3,16 +3,19 @@ import {Image, ImageProps, View} from "@tarojs/components";
import shard from '@/static/img/shard.png' import shard from '@/static/img/shard.png'
import styles from './image.module.scss' import styles from './image.module.scss'
import Taro from "@tarojs/taro"; import Taro from "@tarojs/taro";
import avatar from '@/static/img/avatar.png'
interface Props extends ImageProps { interface Props extends ImageProps {
width?: number | string width?: number | string
height?: number | string height?: number | string
fallback?: string fallback?: string
errorType?: "acquiesce" | 'avatar'
} }
const Img: FC<Props> = ({src, mode = 'aspectFill', width, height, fallback = shard, ...props}) => { const Img: FC<Props> = ({src, mode = 'aspectFill', width, height, fallback = shard, ...props}) => {
const [isError, setIsError] = useState(false) const [isError, setIsError] = useState(false)
const [loading, setLoading] = useState(true) const [loading, setLoading] = useState(true)
const [errorUrl, setErrorUrl] = useState(fallback)
const imgAnimation = Taro.createAnimation({duration: 0}).opacity(0).step() const imgAnimation = Taro.createAnimation({duration: 0}).opacity(0).step()
const [animationData, setAnimationData] = useState<TaroGeneral.IAnyObject>(imgAnimation.export()) const [animationData, setAnimationData] = useState<TaroGeneral.IAnyObject>(imgAnimation.export())
@ -22,6 +25,18 @@ const Img: FC<Props> = ({src, mode = 'aspectFill', width, height, fallback = sha
setLoading(!!src) setLoading(!!src)
}, [src]) }, [src])
useEffect(() => {
switch (props.errorType) {
case undefined:
case "acquiesce":
setErrorUrl(fallback)
break
case "avatar":
setErrorUrl(avatar)
break
}
}, [props.errorType])
// 图片加载失败 // 图片加载失败
function onErrorHandler() { function onErrorHandler() {
setLoading(false) setLoading(false)
@ -40,8 +55,8 @@ const Img: FC<Props> = ({src, mode = 'aspectFill', width, height, fallback = sha
style={{ style={{
width: `${width}rpx`, width: `${width}rpx`,
height: `${height}rpx`, height: `${height}rpx`,
backgroundColor: '#F8F8F8' backgroundColor: (isError || !loading) ? 'transparent' : '#F8F8F8'
}} }}
className={`${props?.className} ${styles.imgBox}`}> className={`${props?.className} ${styles.imgBox}`}>
{!isError && {!isError &&
<View animation={animationData}> <View animation={animationData}>
@ -51,8 +66,12 @@ const Img: FC<Props> = ({src, mode = 'aspectFill', width, height, fallback = sha
mode={mode} mode={mode}
lazyLoad lazyLoad
fadeIn fadeIn
defaultSource={fallback} defaultSource={errorUrl}
style={{width: width ? `${width}rpx` : "100%", height: height ? `${height}rpx` : "100%"}} style={{
width: width ? `${width}rpx` : "100%",
height: height ? `${height}rpx` : "100%",
verticalAlign: 'middle'
}}
onError={onErrorHandler} onError={onErrorHandler}
onLoad={onLoadHandler}/> onLoad={onLoadHandler}/>
</View> </View>
@ -62,7 +81,7 @@ const Img: FC<Props> = ({src, mode = 'aspectFill', width, height, fallback = sha
<Image <Image
className={styles.imgError} className={styles.imgError}
mode='aspectFill' mode='aspectFill'
src={fallback} src={errorUrl}
lazyLoad lazyLoad
fadeIn fadeIn
style={{ style={{

@ -59,7 +59,6 @@ const LearningRecord: FC<Props> = ({userId}) => {
}, [userId]) }, [userId])
return (<View className={styles.box} style={{display: 'block'}}> return (<View className={styles.box} style={{display: 'block'}}>
<View className='font-weight font-32 mb-4'></View>
<Tabs tabList={tabList} onChange={tabChange} backMode/> <Tabs tabList={tabList} onChange={tabChange} backMode/>
<View className={styles.total}> <View className={styles.total}>

@ -4,6 +4,7 @@ import styles from "@/pages/my/my.module.scss";
import avatar from "@/static/img/avatar.png" import avatar from "@/static/img/avatar.png"
import blacktriang from "@/static/img/blacktriangle.png" import blacktriang from "@/static/img/blacktriangle.png"
import {FC} from "react"; import {FC} from "react";
import Img from "@/components/image/image";
interface Props { interface Props {
companyList: Company[] companyList: Company[]
@ -16,13 +17,13 @@ const Header: FC<Props> = ({companyList, showCompany}) => {
return ( return (
<View className={styles.header}> <View className={styles.header}>
<View className='flex'> <View className='flex'>
<Image src={user?.avatar || avatar} className={styles.avatar}/> <Img width={100} height={100} src={user?.avatar || avatar} className={styles.avatar} errorType='avatar'/>
{ {
token ? <View className='flex-1 mt-1'> token ? <View className='flex-1 mt-1'>
<View className='font-32'>{user?.name}</View> <View className='font-32'>{user?.name}</View>
<View className='flex align-center mt-2' onClick={showCompany}> <View className='flex align-center mt-2' onClick={showCompany}>
<Text style={{fontSize: '24rpx', fontWeight: '500', color: '#323635'}}>{company?.name}</Text> <Text style={{fontSize: '24rpx', fontWeight: '500', color: '#323635'}}>{company?.name}</Text>
{companyList.length > 2 && <Image src={blacktriang} style={{width: '20rpx', height: '20rpx'}}></Image>} {companyList.length > 2 && <Image src={blacktriang} style={{width: '20rpx', height: '20rpx'}}/>}
</View> </View>
</View> </View>
: <View className='flex-1'> : <View className='flex-1'>

@ -4,6 +4,12 @@ page {
overflow-x: hidden; overflow-x: hidden;
} }
.navigation {
transition: all 300ms;
display: flex;
align-items: center;
}
.page { .page {
background: linear-gradient(180deg, #45D4A8 0%, rgba(69, 212, 168, 0) 100%) no-repeat; background: linear-gradient(180deg, #45D4A8 0%, rgba(69, 212, 168, 0) 100%) no-repeat;
background-size: 100% 458rpx; background-size: 100% 458rpx;
@ -47,8 +53,6 @@ page {
font-size: 10rpx; font-size: 10rpx;
.avatar { .avatar {
width: 100px;
height: 100px;
margin-right: 30px; margin-right: 30px;
} }
} }
@ -59,7 +63,7 @@ page {
box-sizing: border-box; box-sizing: border-box;
height: 136rpx; height: 136rpx;
&:nth-child(n) { &:nth-child(odd) {
padding-right: 11rpx; padding-right: 11rpx;
} }

@ -69,9 +69,10 @@ const My: FC = () => {
backgroundColor={`rgba(255,255,255,${navbarOpacity})`} backgroundColor={`rgba(255,255,255,${navbarOpacity})`}
cancelBack> cancelBack>
{ {
Number(navbarOpacity) > .5 && <View className='flex align-center'> <View className={styles.navigation}
<Img src={user?.avatar || avatar} mode='heightFix' width={60} height={60}/> style={{transform: `translate(0,${Number(navbarOpacity) > .5 ? "0%" : '-300%'})`}}>
<Text className='pl-1'>{user?.name}</Text> <Img src={user?.avatar || avatar} mode='heightFix' width={50} height={50} errorType='avatar'/>
<Text className='pl-2'>{user?.name}</Text>
</View> </View>
} }
</NavigationBar> </NavigationBar>
@ -139,7 +140,6 @@ const My: FC = () => {
</PageContainer> </PageContainer>
</View> </View>
</ScrollView> </ScrollView>
</View> </View>
) )
} }

@ -5,6 +5,7 @@ import Taro, {useReachBottom} from "@tarojs/taro";
import Empty from "@/components/empty/empty"; import Empty from "@/components/empty/empty";
import Spinner from "@/components/spinner"; import Spinner from "@/components/spinner";
import Img from "@/components/image/image"; import Img from "@/components/image/image";
import {formatDate} from "@/utils/time";
const BrandItem: FC<{ data: BrandRecord; onClick: VoidFunction }> = ({data, onClick}) => { const BrandItem: FC<{ data: BrandRecord; onClick: VoidFunction }> = ({data, onClick}) => {
let media: ReactNode let media: ReactNode
@ -41,14 +42,14 @@ const BrandItem: FC<{ data: BrandRecord; onClick: VoidFunction }> = ({data, onCl
<View className="text-row1 font-28">{data.name}</View> <View className="text-row1 font-28">{data.name}</View>
</View> </View>
</View> </View>
<View className="font-24 text-muted mb-4 text-row3" style={{lineHeight:1.4}}> <View className="font-24 text-muted mb-4 text-row3" style={{lineHeight: 1.4}}>
{data.graphic_introduction} {data.graphic_introduction}
</View> </View>
<View className="flex gap20rpx font-24 text-muted"> <View className="flex gap20rpx font-24 text-muted">
<View>2023/03.29 12:22:01</View> <View>{formatDate(new Date(data.created_at), "YY-MM-dd hh:mm:ss")}</View>
<View className="flex-1"></View> <View className="flex-1"></View>
<View>123</View> <View>{data.article_count}</View>
<View>234</View> <View>{(Math.random() * 100).toFixed(0)}</View>
</View> </View>
</View> </View>
</View> </View>
@ -108,7 +109,7 @@ const BrandList: FC = () => {
</> </>
) )
} else { } else {
content = <Empty name='空空如也'/> content = <Empty name='暂无品牌入驻'/>
} }
return ( return (

Loading…
Cancel
Save