修改我的header 和 学习记录

v2
king 1 year ago
parent 451828b70c
commit dfe30478ea
  1. 2
      src/components/learningRecord/learningRecord.module.scss
  2. 5
      src/components/learningRecord/learningRecord.tsx
  3. 3
      src/components/navigationBar/navigationBar.module.scss
  4. 14
      src/components/navigationBar/navigationBar.tsx
  5. 12
      src/pages/home/components/search.tsx
  6. 8
      src/pages/home/home.module.scss
  7. 12
      src/pages/home/home.tsx
  8. 2
      src/pages/my/components/header/header.tsx
  9. 20
      src/pages/my/components/header/time.tsx
  10. 66
      src/pages/my/my.module.scss
  11. 169
      src/pages/my/my.tsx
  12. BIN
      src/static/img/search.png

@ -1,7 +1,7 @@
.box { .box {
background: #fff; background: #fff;
border-radius: 20rpx; border-radius: 20rpx;
padding: 40rpx 20rpx; padding: 40rpx;
display: flex; display: flex;
align-items: center; align-items: center;
box-sizing: border-box; box-sizing: border-box;

@ -32,12 +32,14 @@ interface Props {
userId: string | number userId: string | number
} }
/** /**
* 线 * 线
*/ */
const LearningRecord: FC<Props> = ({userId}) => { const LearningRecord: FC<Props> = ({userId}) => {
const [lineData, setLineData] = useState<any[]>([]) const [lineData, setLineData] = useState<any[]>([])
async function getStatistics(data: StatisticsParam) { async function getStatistics(data: StatisticsParam) {
try { try {
const res = await userApi.statistics(userId, data) const res = await userApi.statistics(userId, data)
@ -56,7 +58,8 @@ const LearningRecord: FC<Props> = ({userId}) => {
userId && getStatistics(tabList[0].value) userId && getStatistics(tabList[0].value)
}, [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}>

@ -2,7 +2,7 @@
position: sticky; position: sticky;
top: 0; top: 0;
left: 0; left: 0;
width: 730rpx; width: 100%;
padding-left: 20rpx; padding-left: 20rpx;
z-index: 10; z-index: 10;
overflow: hidden; overflow: hidden;
@ -26,6 +26,7 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
font-size: 28rpx;
} }
.arrow { .arrow {

@ -40,12 +40,14 @@ const NavigationBar: FC<Props> = (props) => {
return ( return (
<View className={`${props.className} ${styles.navigation}`} style={navigationBarStyle}> <View className={`${props.className} ${styles.navigation}`} style={navigationBarStyle}>
<View style={navigationTextStyle} className={styles.leftNode}> <View style={navigationTextStyle} className={styles.leftNode}>
{!props.cancelBack && <View className="flex flex-column justify-center align-center" style={{ {
width: globalData.textBarHeight + 'px', !props.cancelBack && <View className="flex flex-column justify-center align-center" style={{
height: globalData.textBarHeight + 'px', width: globalData.textBarHeight + 'px',
}} onClick={() => Taro.navigateBack()}> height: globalData.textBarHeight + 'px',
<Image src={leftArrow} mode='aspectFill' className={styles.arrow}/> }} onClick={() => Taro.navigateBack()}>
</View>} <Image src={leftArrow} mode='aspectFill' className={styles.arrow}/>
</View>
}
{props.leftNode} {props.leftNode}
</View> </View>
<View style={navigationTextStyle} className={styles.text}>{props.children || props.text}</View> <View style={navigationTextStyle} className={styles.text}>{props.children || props.text}</View>

@ -1,18 +1,20 @@
import {FC} from "react"; import {FC} from "react";
import {View} from "@tarojs/components"; import {Image, View} from "@tarojs/components";
import styles from "../home.module.scss"; import styles from "../home.module.scss";
import Icon from "@/components/icon";
import Taro from "@tarojs/taro"; import Taro from "@tarojs/taro";
import search from "@/static/img/search.png"
export const Search: FC = () => { export const Search: FC = () => {
function jump(){ function jump() {
Taro.navigateTo({url:'/pages/preview/search/search/index'}) Taro.navigateTo({url: '/pages/preview/search/search/index'})
} }
return ( return (
<View className={styles.search} onClick={jump}> <View className={styles.search} onClick={jump}>
<Icon name='search' size={18} color='#808080'/> <Image src={search} mode='widthFix' style={{width: 18,verticalAlign:'middle'}}/>
{/*<Icon name='search' size={18} color='#808080'/>*/}
<View className='ml-1'></View> <View className='ml-1'></View>
</View> </View>
) )

@ -51,7 +51,7 @@
} }
.content { .content {
padding: 0 20px; padding: 0 30rpx;
box-sizing: border-box; box-sizing: border-box;
&:after { &:after {
@ -78,7 +78,11 @@
justify-content: center; justify-content: center;
height: 68rpx; height: 68rpx;
margin-bottom: 40rpx; margin-bottom: 40rpx;
font-size: 28rpx;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #909795; color: #909795;
line-height: 1;
} }
.adware { .adware {
@ -97,7 +101,7 @@
font-family: PingFang SC-Bold, PingFang SC; font-family: PingFang SC-Bold, PingFang SC;
font-weight: bold; font-weight: bold;
color: #323635; color: #323635;
margin-top: 10px; margin-top: 20px;
} }

@ -20,7 +20,7 @@ const Home: FC = () => {
const [data, setData] = useState<null | HomeData>(null) const [data, setData] = useState<null | HomeData>(null)
const [enable, setEnable] = useState(true) const [enable, setEnable] = useState(true)
const [navbarOpacity, setNavbarOpacity] = useState('0') const [navbarOpacity, setNavbarOpacity] = useState('0')
const navbarHeight = globalData.statusBarHeight + globalData.textBarHeight; const navbarHeight = globalData.statusBarHeight + globalData.textBarHeight;
function unLogin() { function unLogin() {
Taro.clearStorage() Taro.clearStorage()
@ -48,16 +48,16 @@ const Home: FC = () => {
<NavigationBar <NavigationBar
className={styles.header} className={styles.header}
backgroundColor={`rgba(255,255,255,${navbarOpacity})`} backgroundColor={`rgba(255,255,255,${navbarOpacity})`}
// backgroundColor={`rgba(255,255,255,0.89)`} cancelBack
leftNode={ leftNode={
<> <>
<Image src={logo} style={{height: "80%"}} mode='heightFix'/> <Image src={logo} style={{height: "100%"}} mode='heightFix'/>
<Text style={{color: '#45d4a8', fontWeight: 'bold'}}></Text> <Text style={{fontWeight: 'bold'}} className='ml-2'></Text>
</> </>
} }
cancelBack
> >
<View className={styles.headerDivider} style={{borderBottom: `1px solid rgba(200,200,200,${navbarOpacity})`}}></View> <View className={styles.headerDivider}
style={{borderBottom: `1px solid rgba(200,200,200,${navbarOpacity})`}}></View>
</NavigationBar> </NavigationBar>
<Spin enable={enable} overlay/> <Spin enable={enable} overlay/>
<View className={styles.content} style={{paddingBottom: token ? 0 : '100rpx'}}> <View className={styles.content} style={{paddingBottom: token ? 0 : '100rpx'}}>

@ -18,7 +18,7 @@ const Header: FC<Props> = ({companyList, showCompany}) => {
<View className='flex'> <View className='flex'>
<Image src={user?.avatar || avatar} className={styles.avatar}/> <Image src={user?.avatar || avatar} className={styles.avatar}/>
{ {
token ? <View className='flex-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>

@ -1,7 +1,5 @@
import {Image, View} from "@tarojs/components"; import {Image, View} from "@tarojs/components";
import styles from '../../my.module.scss' import styles from '../../my.module.scss'
import curriculum1 from '@/static/img/curriculum1.png'
import curriculum2 from '@/static/img/curriculum2.png'
import Taro from "@tarojs/taro"; import Taro from "@tarojs/taro";
import {curriculum} from "@/api"; import {curriculum} from "@/api";
import {FC, useState} from "react"; import {FC, useState} from "react";
@ -24,10 +22,10 @@ const Time: FC = () => {
const [list, setList] = useState<List[]>([ const [list, setList] = useState<List[]>([
{title: '今日时长', time: '00:00', src: time1}, {title: '今日时长', time: '00:00', src: time1},
{title: '累计时长', time: '00:00', src: time2}, {title: '累计时长', time: '00:00', src: time2},
{title: '必修课', time: '0', src: curriculum1, type: 1}, // {title: '必修课', time: '0', src: curriculum1, type: 1},
{title: '选修课', time: '0', src: curriculum2, type: 2}, // {title: '选修课', time: '0', src: curriculum2, type: 2},
{title: '已完成', time: '0', src: over, type: 3}, {title: '已完成', time: '0', src: over, type: 3},
{title: '未完成', time: '0', src: incomplete, type: 4}, {title: '未完成(必修)', time: '0', src: incomplete, type: 4},
]) ])
@ -37,10 +35,10 @@ const Time: FC = () => {
const oldList: List[] = JSON.parse(JSON.stringify(list)) const oldList: List[] = JSON.parse(JSON.stringify(list))
oldList[0].time = formatMinute(res.today_learn_time) oldList[0].time = formatMinute(res.today_learn_time)
oldList[1].time = formatMinute(res.total_learn_time) oldList[1].time = formatMinute(res.total_learn_time)
oldList[2].time = res.required_count // oldList[2].time = res.required_count
oldList[3].time = res.not_required_count // oldList[3].time = res.not_required_count
oldList[4].time = res.finished_count oldList[2].time = res.finished_count
oldList[5].time = res.not_finished_count oldList[3].time = res.not_finished_count
setList(oldList) setList(oldList)
} catch (e) { } catch (e) {
} }
@ -57,7 +55,7 @@ const Time: FC = () => {
return ( return (
<View className='flex mt-3 mb-1 justify-between flex-wrap'> <View className='flex mt-3 justify-between flex-wrap'>
{ {
list.map(d => { list.map(d => {
return ( return (
@ -65,7 +63,7 @@ const Time: FC = () => {
<View className={styles.timeBoxFlex}> <View className={styles.timeBoxFlex}>
<View> <View>
<View className='mb-2 font-28 font-weight'>{d.title}</View> <View className='mb-2 font-28 font-weight'>{d.title}</View>
{token && <View className='text-muted font-26'>{d.time}</View>} {token && <View className='text-muted font-26 mt-1'>{d.time}</View>}
</View> </View>
<Image src={d.src} mode='aspectFit' className={styles.timeImag}/> <Image src={d.src} mode='aspectFit' className={styles.timeImag}/>
</View> </View>

@ -4,68 +4,80 @@ page {
overflow-x: hidden; overflow-x: hidden;
} }
.content { .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;
position: relative; width: 100%;
padding: 0 10rpx;
width: 750rpx;
box-sizing: border-box;
overflow: hidden;
&:after { &:before {
content: ''; content: '';
display: block; display: block;
position: absolute; position: absolute;
top: 106rpx; top: -80rpx;
right: -100rpx; left: -80rpx;
width: 290rpx; width: 230rpx;
height: 290rpx; height: 230rpx;
background: #FFFF; background: #FFFF;
opacity: 0.2; opacity: 0.2;
border-radius: 290rpx; border-radius: 230rpx;
} }
}
&:before { .content {
box-sizing: border-box;
padding: 0 30rpx;
width: 100%;
&:after {
content: ''; content: '';
display: block; display: block;
position: absolute; position: absolute;
top: -80rpx; top: 0rpx;
left: -80rpx; right: -100rpx;
width: 230rpx; width: 290rpx;
height: 230rpx; height: 290rpx;
background: #FFFF; background: #FFFF;
opacity: 0.2; opacity: 0.2;
border-radius: 230rpx; border-radius: 290rpx;
} }
} }
.header { .header {
padding: 130px 10rpx 0;
font-size: 10rpx; font-size: 10rpx;
.avatar { .avatar {
width: 100px; width: 100px;
height: 100px; height: 100px;
margin-right: 30px; margin-right: 30px;
margin-top: -10px;
} }
} }
.timeBox { .timeBox {
width: 50%; width: 50%;
height: 124rpx; margin-bottom: 22rpx;
margin-bottom: 15rpx;
padding: 12rpx 10rpx;
box-sizing: border-box; box-sizing: border-box;
height: 136rpx;
&:nth-child(n) {
padding-right: 11rpx;
}
&:nth-child(2n) {
padding-left: 11rpx;
}
} }
.timeBoxFlex { .timeBoxFlex {
padding: 20px; padding: 28px 30rpx;
box-sizing: border-box;
border-radius: 20px; border-radius: 20px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
background: #fff; background: #fff;
height: 100%;
} }
.timeImag { .timeImag {
@ -75,10 +87,10 @@ page {
} }
.service { .service {
margin-top: 44rpx; margin-top: 48rpx;
display: grid; display: grid;
grid-template-columns:1fr 1fr 1fr 1fr; grid-template-columns:1fr 1fr 1fr 1fr;
grid-auto-rows: 80px 80px 80px 80px; grid-auto-rows: 100px 100px 100px 100px;
grid-gap: 60px; grid-gap: 60px;
font-size: 28px; font-size: 28px;
text-align: center; text-align: center;
@ -92,7 +104,7 @@ page {
.tool { .tool {
background: #fff; background: #fff;
border-radius: 20rpx; border-radius: 20rpx;
padding: 30rpx 20px 46rpx; padding: 30rpx;
margin-top: 30rpx; margin-top: 30rpx;
} }

@ -1,4 +1,4 @@
import {PageContainer, View, Image} from "@tarojs/components"; import {PageContainer, View, Image, ScrollView, Text} from "@tarojs/components";
import Taro from "@tarojs/taro"; import Taro from "@tarojs/taro";
import styles from './my.module.scss' import styles from './my.module.scss'
import Header from "./components/header/header"; import Header from "./components/header/header";
@ -8,79 +8,138 @@ import Service from "@/pages/my/components/header/service";
import {Profile} from "@/store"; import {Profile} from "@/store";
import Img from "@/components/image/image"; import Img from "@/components/image/image";
import GreenNike from "@/static/img/greenNike.png" import GreenNike from "@/static/img/greenNike.png"
import {userApi} from "@/api"; import {curriculum, userApi} from "@/api";
import LearningRecord from "@/components/learningRecord/learningRecord"; import LearningRecord from "@/components/learningRecord/learningRecord";
import NavigationBar from "@/components/navigationBar/navigationBar";
import over from "@/static/img/over.png";
import incomplete from "@/static/img/incomplete.png";
import avatar from "@/static/img/avatar.png";
interface List {
title: string
time: string | number
src: string,
type?: number
}
const My: FC = () => { const My: FC = () => {
const globalData = Taro.getApp().globalData const globalData = Taro.getApp().globalData
const {token, company, setCompany, user} = Profile.useContainer() const {token, company, setCompany, user} = Profile.useContainer()
const [companyShow, setCompanyShow] = useState(false) const [companyShow, setCompanyShow] = useState(false)
const [companyList, setCompanyList] = useState<Company[]>([]) const [companyList, setCompanyList] = useState<Company[]>([])
const [navbarOpacity, setNavbarOpacity] = useState('0')
const navbarHeight = globalData.statusBarHeight + globalData.textBarHeight;
const pageHeight = globalData.windowHeight - globalData.textBarHeight - globalData.statusBarHeight
Taro.useDidShow(() => { Taro.useDidShow(() => {
token && userApi.companyList().then(res => { token && userApi.companyList().then(res => {
setCompanyList(res as Company[]) setCompanyList(res as Company[])
}) })
}) })
return ( function onScroll(e) {
<View className={styles.content} style={`paddingTop:${globalData.statusBarHeight}px`}> const v = (Math.min(e.detail.scrollTop / navbarHeight, 1) * 0.9).toFixed(6)
if (v != navbarOpacity) {
setNavbarOpacity(v)
}
}
<Header companyList={companyList} showCompany={() => companyList.length >= 2 && setCompanyShow(true)}/> const [list, setList] = useState<List[]>([
<Time/> {title: '已完成', time: '0', src: over, type: 3},
{ {title: '未完成', time: '0', src: incomplete, type: 4},
token && user && <View className='px-1'> ])
<LearningRecord userId={user.id}/>
<Service/>
</View>
}
<PageContainer Taro.useDidShow(async () => {
overlayStyle={'background:rgba(0,0,0,0.3)'} try {
position='bottom' const res = await curriculum.course()
round const oldList: List[] = JSON.parse(JSON.stringify(list))
show={companyShow} oldList[1].time = res.finished_count
onClickOverlay={() => setCompanyShow(false)}> oldList[2].time = res.not_finished_count
<View className="px-3 py-5"> setList(oldList)
<View className="font-32 pb-3" } catch (e) {
style={{display: 'flex', justifyContent: 'center', borderBottom: '2rpx solid #f5f8f7'}}></View> }
})
return (
<View className={styles.page}>
<NavigationBar
backgroundColor={`rgba(255,255,255,${navbarOpacity})`}
cancelBack>
{
Number(navbarOpacity) > .5 && <View className='flex align-center'>
<Img src={user?.avatar || avatar} mode='heightFix' width={60} height={60}/>
<Text className='pl-1'>{user?.name}</Text>
</View>
}
</NavigationBar>
<ScrollView scrollY enhanced showScrollbar={false} style={{height: pageHeight}} onScroll={onScroll}>
<View className={styles.content}>
<View style={{opacity: 1 - Number(navbarOpacity)}}>
<Header companyList={companyList} showCompany={() => companyList.length >= 2 && setCompanyShow(true)}/>
</View>
<Time/>
{ {
companyList.length >= 1 && token && user && <View>
companyList.map((d, idx) => <LearningRecord userId={user.id}/>
<View className={`${styles.box} ${companyList.length - 1 === idx && styles.noBorder} `} <Service/>
onClick={async () => { </View>
if (company?.id === d.id) return;
Taro.showLoading({
title: '切换公司中',
mask: true,
})
const data = await userApi.companyReplace(d.id)
Taro.hideLoading()
!data && setCompany(d)
!data && Taro.showModal({
title: '友情提示',
content: '切换公司成功,需要重新进入',
showCancel: false,
success: function (res) {
if (res.confirm) {
Taro.reLaunch({url: '/pages/my/my'})
}
}
})
setCompanyShow(false)
}}>
<View className={styles.image}>
<Img width={68} height={68} src={d.logo}/>
</View>
<View className={styles.innerBox}>
<View className={styles.title}>{d.name}</View>
<Image src={company?.id === d.id ? GreenNike : ''} className={styles.icon}></Image>
</View>
</View>
)
} }
<PageContainer
overlayStyle={'background:rgba(0,0,0,0.3)'}
position='bottom'
round
show={companyShow}
onClickOverlay={() => setCompanyShow(false)}>
<View className="px-3 py-5">
<View className="font-32 pb-3"
style={{
display: 'flex',
justifyContent: 'center',
borderBottom: '2rpx solid #f5f8f7'
}}></View>
{
companyList.length >= 1 &&
companyList.map((d, idx) =>
<View className={`${styles.box} ${companyList.length - 1 === idx && styles.noBorder} `}
onClick={async () => {
if (company?.id === d.id) return;
Taro.showLoading({
title: '切换公司中',
mask: true,
})
const data = await userApi.companyReplace(d.id)
Taro.hideLoading()
!data && setCompany(d)
!data && Taro.showModal({
title: '友情提示',
content: '切换公司成功,需要重新进入',
showCancel: false,
success: function (res) {
res.confirm && Taro.reLaunch({url: '/pages/my/my'})
}
})
setCompanyShow(false)
}}>
<View className={styles.image}>
<Img width={68} height={68} src={d.logo}/>
</View>
<View className={styles.innerBox}>
<View className={styles.title}>{d.name}</View>
<Image src={company?.id === d.id ? GreenNike : ''} className={styles.icon}></Image>
</View>
</View>
)
}
</View>
</PageContainer>
</View> </View>
</PageContainer> </ScrollView>
</View> </View>
) )
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Loading…
Cancel
Save