|
|
@@ -0,0 +1,503 @@
|
|
|
+import { View, Text, ScrollView } from "@tarojs/components";
|
|
|
+import './Workout.scss'
|
|
|
+import { useDidShow, useReady } from "@tarojs/taro";
|
|
|
+import { useDispatch, useSelector } from "react-redux";
|
|
|
+import { useEffect, useState } from "react";
|
|
|
+import Taro from "@tarojs/taro";
|
|
|
+import { activityCards, uploadSteps } from "@/services/trackSomething";
|
|
|
+import { TimeFormatter } from "@/utils/time_format";
|
|
|
+import MetricItem from "../trackSomething/components/MetricItem";
|
|
|
+import Layout from '@/components/layout/layout'
|
|
|
+import NoData from "@/components/view/NoData";
|
|
|
+import { ResultType, checkFail, checkRetry, checkStart, checkSuccess, resetStatus, setResult } from "@/store/action_results";
|
|
|
+import RequestType, { thirdPartRequest } from "@/services/thirdPartRequest";
|
|
|
+import { ModalType, NaviBarTitleShowType, TemplateType, WorkoutType } from "@/utils/types";
|
|
|
+import { useTranslation } from "react-i18next";
|
|
|
+import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
|
|
|
+import TitleView from "@/features/trackTimeDuration/components/TitleView";
|
|
|
+import Modal from "@/components/layout/Modal";
|
|
|
+import { ColorType } from "@/context/themes/color";
|
|
|
+import SetGoal from "@/features/workout/SetGoal";
|
|
|
+import Working from "@/features/workout/Working";
|
|
|
+import { startSuccess } from "@/store/workout";
|
|
|
+import { workoutGroups } from "@/services/workout";
|
|
|
+import { setAuth } from "../trackSomething/hooks/werun";
|
|
|
+// import { useNavigation } from "@react-navigation/native";
|
|
|
+
|
|
|
+let useNavigation;
|
|
|
+if (process.env.TARO_ENV == 'rn') {
|
|
|
+ useNavigation = require("@react-navigation/native").useNavigation
|
|
|
+}
|
|
|
+
|
|
|
+//
|
|
|
+
|
|
|
+let timer
|
|
|
+export default function Component(props: any) {
|
|
|
+ const { t } = useTranslation()
|
|
|
+ const user = useSelector((state: any) => state.user);
|
|
|
+ const checkResult = useSelector((state: any) => state.checkResult);
|
|
|
+ const workout = useSelector((state: any) => state.workout);
|
|
|
+ const [allowRun, setAllowRun] = useState(false)
|
|
|
+ const [stepInfo, setStepInfo] = useState(null)
|
|
|
+ const [lastTime, setLastTime] = useState(new Date().getTime())
|
|
|
+ const [list, setList] = useState([])
|
|
|
+ const dispatch = useDispatch();
|
|
|
+ const [showErrorBadge, setShowErrorBadge] = useState(false)
|
|
|
+ const [latestRecord, setLatestRecord] = useState(null)
|
|
|
+ const [triggered, setTriggered] = useState(true)
|
|
|
+ const [showErrorPage, setErrorPage] = useState(false)
|
|
|
+ const [showModal, setShowModal] = useState(false)
|
|
|
+ const [loaded, setLoaded] = useState(false)
|
|
|
+ const [count, setCount] = useState(0)
|
|
|
+ const [isStart, setIsStart] = useState(false)
|
|
|
+ const [targetTime, setTargetTime] = useState(0)
|
|
|
+ let navigation;
|
|
|
+ if (useNavigation) {
|
|
|
+ navigation = useNavigation()
|
|
|
+ }
|
|
|
+
|
|
|
+ // const navigation = useNavigation();
|
|
|
+ // const [title, setTitle] = useState('打卡')
|
|
|
+
|
|
|
+
|
|
|
+ //未登录<->已登录 状态切换时,重新拉取一次列表数据
|
|
|
+ useEffect(() => {
|
|
|
+ if (user.isLogin) {
|
|
|
+ loadWorkoutCache()
|
|
|
+ }
|
|
|
+ dispatch(resetStatus())
|
|
|
+ getCards();
|
|
|
+ const now = new Date();
|
|
|
+ const nextMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1, 0, 0, 0);
|
|
|
+ const timeUntilMidnight = nextMidnight.getTime() - now.getTime();
|
|
|
+
|
|
|
+ setTimeout(() => {
|
|
|
+ setCount(count + 1)
|
|
|
+ }, timeUntilMidnight);
|
|
|
+ }, [user.isLogin])
|
|
|
+
|
|
|
+ // useEffect(() => {
|
|
|
+ // Taro.setStorage({key:'auth',data:allowRun})
|
|
|
+ // },[allowRun])
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ Taro.getStorage({
|
|
|
+ key: 'auth', success: function (res) {
|
|
|
+ setAllowRun(res.data ? res.data : false)
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }, [])
|
|
|
+
|
|
|
+ //页面渲染完成后执行一次授权检查
|
|
|
+ useReady(() => {
|
|
|
+
|
|
|
+ })
|
|
|
+
|
|
|
+ useDidShow(() => {
|
|
|
+ if (list.length > 0) {
|
|
|
+ checkAuth()
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ function loadWorkoutCache() {
|
|
|
+ Taro.getStorage({
|
|
|
+ key: 'lastWorkout', success: function (res) {
|
|
|
+ var workouts = JSON.parse(res.data)
|
|
|
+ if (workouts && workouts.length > 0) {
|
|
|
+ var workoutObj = workouts[0]
|
|
|
+ dispatch(startSuccess({
|
|
|
+ start: workoutObj.time,
|
|
|
+ id: 1
|
|
|
+ }));
|
|
|
+
|
|
|
+ timer = setInterval(() => {
|
|
|
+ setCount(count => count + 1)
|
|
|
+ }, 1000)
|
|
|
+ }
|
|
|
+ }, fail: function (err) {
|
|
|
+ console.log(err, 'no cache')
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ global.refreshActivity = () => {
|
|
|
+ getCards()
|
|
|
+ }
|
|
|
+
|
|
|
+ function getCards() {
|
|
|
+ setTriggered(true)
|
|
|
+ activityCards().then(res => {
|
|
|
+ setErrorPage(false)
|
|
|
+ setTriggered(false)
|
|
|
+ checkAuth()
|
|
|
+ setList((res as any).cards)
|
|
|
+ for (var i = 0; i < (res as any).cards.length; i++) {
|
|
|
+ var obj = (res as any).cards[i];
|
|
|
+ if (obj.code == '_walk') {
|
|
|
+ setLatestRecord(obj.latest_record)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ setLoaded(true)
|
|
|
+ }).catch(e => {
|
|
|
+ setTriggered(false)
|
|
|
+ if (list.length == 0) {
|
|
|
+ setErrorPage(true)
|
|
|
+ }
|
|
|
+ setLoaded(true)
|
|
|
+ })
|
|
|
+
|
|
|
+ workoutGroups().then(res => {
|
|
|
+
|
|
|
+
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ global.activityCardsFunc = getCards
|
|
|
+
|
|
|
+ function checkAuth() {
|
|
|
+ if (user.isLogin) {
|
|
|
+ Taro.getSetting({
|
|
|
+ success: res => {
|
|
|
+ //第一步,检测是否有授权 - 没有授权
|
|
|
+ if (!res.authSetting['scope.werun']) {
|
|
|
+ setAllowRun(false)
|
|
|
+ Taro.setStorage({ key: 'auth', data: false })
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ setAllowRun(true)
|
|
|
+ Taro.setStorage({ key: 'auth', data: true })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ setAllowRun(false)
|
|
|
+ Taro.setStorage({ key: 'auth', data: false })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function tapBtn() {
|
|
|
+ if (user.isLogin) {
|
|
|
+ if (allowRun) {
|
|
|
+ checkout()
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ setAuth(successAuth, refuseAuth, t)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function successAuth() {
|
|
|
+ Taro.setStorage({ key: 'auth', data: true })
|
|
|
+ setAllowRun(true)
|
|
|
+ }
|
|
|
+
|
|
|
+ function refuseAuth() {
|
|
|
+ // setTitle('开启');
|
|
|
+ Taro.setStorage({ key: 'auth', data: false })
|
|
|
+ setAllowRun(false)
|
|
|
+ }
|
|
|
+
|
|
|
+ function checkout() {
|
|
|
+ dispatch(checkStart());
|
|
|
+ getWeRunData(false)
|
|
|
+ }
|
|
|
+
|
|
|
+ function getWeRunData(autoCheck = false) {
|
|
|
+ if (autoCheck) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ dispatch(checkStart());
|
|
|
+ }
|
|
|
+
|
|
|
+ // setTitle('打卡');
|
|
|
+ setAllowRun(true)
|
|
|
+ var date = new Date();
|
|
|
+ var time = date.getTime()
|
|
|
+ var strDate = (date.getFullYear() + '') + (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : (date.getMonth() + 1)) + (date.getDate() < 10 ? '0' + date.getDate() : date.getDate());
|
|
|
+
|
|
|
+
|
|
|
+ thirdPartRequest(RequestType.RequestTypeWXRunData).then(res => {
|
|
|
+ var params = {
|
|
|
+ is_manual: autoCheck ? 0 : 1,
|
|
|
+ timestamp: time,
|
|
|
+ encryptedData: (res as any).encryptedData,
|
|
|
+ iv: (res as any).iv,
|
|
|
+ date: strDate,
|
|
|
+ cloudID: (res as any).cloudID,
|
|
|
+ }
|
|
|
+ uploadSteps(params).then(res => {
|
|
|
+ if ((res as any).error_code == 'WX_STEP_PARSE_FAIL') {
|
|
|
+ retry(params, autoCheck, time)
|
|
|
+ dispatch(checkRetry())
|
|
|
+ }
|
|
|
+ else {
|
|
|
+
|
|
|
+ setShowErrorBadge(false)
|
|
|
+ uploadSuccess(res, autoCheck, time)
|
|
|
+ setTimeout(() => {
|
|
|
+ setCount(count + 1)
|
|
|
+ }, 31000)
|
|
|
+ }
|
|
|
+
|
|
|
+ }).catch(e => {
|
|
|
+ retry(params, autoCheck, time)
|
|
|
+ });
|
|
|
+ }).catch(_ => {
|
|
|
+ dispatch(setResult({ isSuccess: false }) as any)
|
|
|
+ })
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function retry(params, autoCheck, time) {
|
|
|
+ Taro.login().then(res => {
|
|
|
+ Taro.getWeRunData({
|
|
|
+ success: res2 => {
|
|
|
+ params.code = res.code;
|
|
|
+ params.encryptedData = res2.encryptedData
|
|
|
+ params.iv = res2.iv
|
|
|
+ params.cloudID = res2.cloudID
|
|
|
+ uploadSteps(params).then(res => {
|
|
|
+ if ((res as any).error_code == 'WX_STEP_PARSE_FAIL') {
|
|
|
+ if (!autoCheck) {
|
|
|
+ dispatch(setResult({ isSuccess: false }) as any);
|
|
|
+ setShowErrorBadge(true)
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ else {
|
|
|
+
|
|
|
+ setShowErrorBadge(false)
|
|
|
+ uploadSuccess(res, autoCheck, time)
|
|
|
+ setTimeout(() => {
|
|
|
+ setCount(count + 1)
|
|
|
+ }, 31000)
|
|
|
+ }
|
|
|
+
|
|
|
+ }).catch(e => {
|
|
|
+ if (!autoCheck) {
|
|
|
+ dispatch(setResult({ isSuccess: false }) as any);
|
|
|
+ setShowErrorBadge(true)
|
|
|
+ }
|
|
|
+
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ function uploadSuccess(res, autoCheck, time) {
|
|
|
+ Taro.setStorageSync('lastUploadStepsTime', time)
|
|
|
+ if (!autoCheck)
|
|
|
+ dispatch(setResult({ isSuccess: true }) as any)
|
|
|
+ setStepInfo((res as any)[(res as any).length - 1])
|
|
|
+ setLastTime(time)
|
|
|
+
|
|
|
+ for (var i = 0; i < list.length; i++) {
|
|
|
+ var obj = list[i];
|
|
|
+ if ((obj as any).code == '_walk') {
|
|
|
+ (obj as any).latest_record = res.latest_record
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // getCards();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ function goDetail(item) {
|
|
|
+ if (user.isLogin) {
|
|
|
+ if (!allowRun) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ jumpPage('/pages/common/RecordsHistory?type=activity&refreshList=getCards&title=' + item.name + '&themeColor=' + item.theme_color)
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // checkResult.type == 'ing' && setStrBtnTitle('打卡中...')
|
|
|
+ var btnTitle = '';
|
|
|
+ var isEnable = true;
|
|
|
+ if (allowRun) {
|
|
|
+ switch (checkResult.type) {
|
|
|
+ case ResultType.idle:
|
|
|
+ {
|
|
|
+ btnTitle = t('feature.track_something.activity.btn_status.idle')
|
|
|
+ isEnable = true
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ResultType.ing:
|
|
|
+ {
|
|
|
+ btnTitle = t('feature.track_something.activity.btn_status.ing')
|
|
|
+ isEnable = false
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ResultType.retry:
|
|
|
+ {
|
|
|
+ btnTitle = t('feature.track_something.activity.btn_status.retry')
|
|
|
+ isEnable = false
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ResultType.success:
|
|
|
+ {
|
|
|
+ btnTitle = t('feature.track_something.activity.btn_status.success')
|
|
|
+ isEnable = false
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ResultType.fail:
|
|
|
+ {
|
|
|
+ btnTitle = t('feature.track_something.activity.btn_status.fail')
|
|
|
+ isEnable = false
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ResultType.countdown:
|
|
|
+ {
|
|
|
+ btnTitle = checkResult.title + 's'
|
|
|
+ isEnable = false
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ btnTitle = t('feature.track_something.activity.open');
|
|
|
+ isEnable = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ function addBtnClick(){
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function headerView() {
|
|
|
+ return <TitleView title={t('page.activity.title')} showAddBtn={loaded && !showErrorPage ? true : false} onClick={addBtnClick}>
|
|
|
+ </TitleView>
|
|
|
+ }
|
|
|
+
|
|
|
+ function workoutStart() {
|
|
|
+ setShowModal(true)
|
|
|
+ }
|
|
|
+
|
|
|
+ function detail() {
|
|
|
+ return <View className="activity_container">
|
|
|
+ {
|
|
|
+ list.map((item: any, index) => {
|
|
|
+ var value = '0'
|
|
|
+ var desc = ''
|
|
|
+ var unit = ''
|
|
|
+ var showDetail = false;
|
|
|
+ if (item.latest_record) {
|
|
|
+ showDetail = true
|
|
|
+ value = item.latest_record.items[0].value
|
|
|
+ if (item.latest_record.timestamp == 0) {
|
|
|
+ desc = t('feature.track_something.activity.today_un_check')
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ desc = TimeFormatter.datetimeDescription(item.latest_record.timestamp)
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ desc = t('feature.track_something.activity.today_un_check')
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if (!user.isLogin) {
|
|
|
+ value = t('feature.track_something.activity.un_login')
|
|
|
+ desc = t('feature.track_something.activity.login_then_check')//登录后可开启打卡'
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (!allowRun) {
|
|
|
+ value = t('feature.track_something.activity.un_open')
|
|
|
+ desc = t('feature.track_something.activity.open_then_check')
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ // unit = '步'
|
|
|
+ showDetail = true
|
|
|
+ if (item.latest_record) {
|
|
|
+ value = item.latest_record.items[0].value
|
|
|
+ desc = TimeFormatter.datetimeDescription(item.latest_record.timestamp)
|
|
|
+ unit = '步'
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ value = t('feature.track_something.activity.today_un_check')
|
|
|
+ desc = t('feature.track_something.activity.check_history')//'查看历史记录'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return <MetricItem title={item.name}
|
|
|
+ // value={allowRun ? stepInfo ? (stepInfo as any).step : '' : '未开启'}
|
|
|
+ value={value}
|
|
|
+ unit={unit}
|
|
|
+ desc={desc}
|
|
|
+ btnText={btnTitle}
|
|
|
+ isDisabled={!isEnable}
|
|
|
+ themeColor={item.theme_color}
|
|
|
+ onClickDetail={() => { goDetail(item) }}
|
|
|
+ showBadge={showErrorBadge && checkResult.type == 'idle'}
|
|
|
+ showDetail={showDetail}
|
|
|
+ onClick={() => {
|
|
|
+ tapBtn()
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ <MetricItem title='平板支撑'
|
|
|
+ // value={allowRun ? stepInfo ? (stepInfo as any).step : '' : '未开启'}
|
|
|
+ value={10}
|
|
|
+ unit={'分钟'}
|
|
|
+ desc={'昨天'}
|
|
|
+ btnText={'计时训练'}
|
|
|
+ isDisabled={false}
|
|
|
+ themeColor={ColorType.workout}
|
|
|
+ onClickDetail={() => {
|
|
|
+ Taro.navigateTo({
|
|
|
+ url: '/pages/workout/History'
|
|
|
+ })
|
|
|
+ }}
|
|
|
+ showBadge={showErrorBadge && checkResult.type == 'idle'}
|
|
|
+ showDetail={false}
|
|
|
+ onClick={() => {
|
|
|
+ workoutStart()
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </View>
|
|
|
+ }
|
|
|
+
|
|
|
+ return <View style={{ position: 'relative' }}>
|
|
|
+ <Layout type={TemplateType.customHeader} header={headerView()} children={showErrorPage ? <NoData refresh={() => { getCards() }} /> : detail()}
|
|
|
+ title={t('page.activity.title')}
|
|
|
+ // type={process.env.TARO_ENV == 'rn' ? TemplateType.flex : TemplateType.grid}
|
|
|
+ refresh={() => { getCards() }}
|
|
|
+ triggered={triggered}
|
|
|
+ titleShowStyle={NaviBarTitleShowType.scrollToShow}
|
|
|
+ />
|
|
|
+ {
|
|
|
+ showModal && <Modal dismiss={() => {
|
|
|
+ setIsStart(false)
|
|
|
+ setShowModal(false)
|
|
|
+ }} confirm={() => { }} modalType={ModalType.center}>
|
|
|
+ {
|
|
|
+ !isStart && <SetGoal start={(count) => { setTargetTime(count); setShowModal(false); Taro.navigateTo({ url: '/pages/workout/Working?count=' + count }) }} />
|
|
|
+ }
|
|
|
+ {
|
|
|
+ isStart && <Working targetCount={targetTime} type={WorkoutType.multi} end={() => {
|
|
|
+ setIsStart(false)
|
|
|
+ setShowModal(false)
|
|
|
+ }} />
|
|
|
+ }
|
|
|
+ </Modal>
|
|
|
+ }
|
|
|
+ </View>
|
|
|
+}
|