feat: 问卷调查
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: "NTRP 评测",
|
||||
// navigationBarTitleText: "NTRP 评测",
|
||||
// navigationBarBackgroundColor: '#FAFAFA',
|
||||
// navigationStyle: 'custom',
|
||||
navigationStyle: 'custom',
|
||||
enableShareAppMessage: true,
|
||||
});
|
||||
|
||||
@@ -62,3 +62,503 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 44px;
|
||||
padding: 46px 42px 0 10px;
|
||||
|
||||
.closeIcon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-right: auto;
|
||||
|
||||
.closeImg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
flex: 1;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin commonAvatarStyle($multiple: 1) {
|
||||
.avatar {
|
||||
flex: 0 0 auto;
|
||||
width: calc(100px * $multiple);
|
||||
height: calc(100px * $multiple);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #fff;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #efefef;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.20), 0 8px 20px 0 rgba(0, 0, 0, 0.12);
|
||||
|
||||
.avatarUrl {
|
||||
width: calc(90px * $multiple);
|
||||
height: calc(90px * $multiple);
|
||||
border-radius: 50%;
|
||||
border: 1px solid #efefef;
|
||||
}
|
||||
}
|
||||
|
||||
.addonImage {
|
||||
flex: 0 0 auto;
|
||||
width: calc(88px * $multiple);
|
||||
height: calc(88px * $multiple);
|
||||
transform: rotate(8deg);
|
||||
flex-shrink: 0;
|
||||
aspect-ratio: 1/1;
|
||||
border-radius: calc(20px * $multiple);
|
||||
border: 4px solid #FFF;
|
||||
background: linear-gradient(0deg, rgba(89, 255, 214, 0.20) 0%, rgba(89, 255, 214, 0.20) 100%), #FFF;
|
||||
box-shadow: 0 4px 36px 0 rgba(0, 0, 0, 0.12);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
margin-left: calc(-1 * 20px * $multiple);
|
||||
|
||||
.docImage {
|
||||
width: calc(48px * $multiple);
|
||||
height: calc(48px * $multiple);
|
||||
transform: rotate(-7deg);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.introContainer {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: radial-gradient(227.15% 100% at 50% 0%, #BFFFEF 0%, #FFF 36.58%), #FAFAFA;
|
||||
|
||||
.result {
|
||||
|
||||
.avatarWrap {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
padding: 30px 0 0 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
@include commonAvatarStyle(1);
|
||||
}
|
||||
|
||||
.tip {
|
||||
padding: 0 30px;
|
||||
|
||||
.tipImage {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.lastResult {
|
||||
margin: 40px 22px;
|
||||
display: flex;
|
||||
padding: 16px 20px 20px 20px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||
background: #FFF;
|
||||
box-shadow: 0 8px 64px 0 rgba(0, 0, 0, 0.10);
|
||||
|
||||
.tipAndTime {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
font-feature-settings: 'liga' off, 'clig' off;
|
||||
font-family: "Noto Sans SC";
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.levelWrap {
|
||||
color: #000;
|
||||
font-feature-settings: 'liga' off, 'clig' off;
|
||||
text-overflow: ellipsis;
|
||||
font-family: "Noto Sans SC";
|
||||
font-size: 32px;
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
line-height: 36px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 10px;
|
||||
|
||||
.level {
|
||||
color: #00E5AD;
|
||||
}
|
||||
}
|
||||
|
||||
.slogan {
|
||||
color: #000;
|
||||
font-family: "Noto Sans SC";
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
margin: 0 22px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
|
||||
.buttonWrap {
|
||||
width: 100%;
|
||||
height: 52px;
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||
overflow: hidden;
|
||||
|
||||
.button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-feature-settings: 'liga' off, 'clig' off;
|
||||
font-family: "PingFang SC";
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
|
||||
&.primary {
|
||||
color: #fff;
|
||||
background: #000;
|
||||
|
||||
.arrowImage {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.guide {
|
||||
.tip {
|
||||
padding: 0 30px;
|
||||
|
||||
.tipImage {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.radar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.radarImage {
|
||||
width: 320px;
|
||||
transform: scale(1.8);
|
||||
}
|
||||
}
|
||||
|
||||
.desc {
|
||||
padding: 0 30px;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
font-family: "PingFang SC";
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
margin: 74px 22px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
|
||||
.buttonWrap {
|
||||
width: 100%;
|
||||
height: 52px;
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||
overflow: hidden;
|
||||
|
||||
.button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-feature-settings: 'liga' off, 'clig' off;
|
||||
font-family: "PingFang SC";
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
|
||||
&.primary {
|
||||
color: #fff;
|
||||
background: #000;
|
||||
|
||||
.arrowImage {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.testContainer {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: radial-gradient(227.15% 100% at 50% 0%, #BFFFEF 0%, #FFF 36.58%), #FAFAFA;
|
||||
|
||||
.bar {
|
||||
margin: 12px 20px 36px;
|
||||
height: 8px;
|
||||
border-radius: 999px;
|
||||
background: rgba(0, 0, 0, 0.06);
|
||||
position: relative;
|
||||
|
||||
.progressBar {
|
||||
height: 8px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-radius: 999px;
|
||||
background-color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
.notice {
|
||||
padding: 0 20px 20px;
|
||||
color: #000;
|
||||
font-family: "PingFang SC";
|
||||
font-size: 18px;
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.question {
|
||||
padding: 0 20px 48px;
|
||||
box-sizing: border-box;
|
||||
height: 502px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
|
||||
.content {
|
||||
color: #000;
|
||||
font-family: "PingFang SC";
|
||||
font-size: 36px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.options {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
|
||||
.optionItem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
display: flex;
|
||||
padding: 14px 20px;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
border-radius: 16px;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.12);
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.optionText {
|
||||
color: #000;
|
||||
font-feature-settings: 'liga' off, 'clig' off;
|
||||
font-family: "PingFang SC";
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.optionIcon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 22px;
|
||||
gap: 24px;
|
||||
|
||||
.next {
|
||||
width: 100%;
|
||||
height: 52px;
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||
background: rgba(0, 0, 0, 0.20);
|
||||
box-shadow: 0 8px 64px 0 rgba(0, 0, 0, 0.10);
|
||||
overflow: hidden;
|
||||
|
||||
.nextBtn {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
border-radius: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||
background: rgba(0, 0, 0, 0.20);
|
||||
box-shadow: 0 8px 64px 0 rgba(0, 0, 0, 0.10);
|
||||
|
||||
.nextBtn {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.20);
|
||||
color: #fff;
|
||||
border-radius: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.prev {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
color: #000;
|
||||
font-family: "PingFang SC";
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
|
||||
.backIcon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.resultContainer {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: radial-gradient(227.15% 100% at 50% 0%, #BFFFEF 0%, #FFF 36.58%), #FAFAFA;
|
||||
|
||||
.card {
|
||||
margin: 10px 20px 0;
|
||||
|
||||
padding: 24px 28px 0;
|
||||
position: relative;
|
||||
display: flex;
|
||||
// height: px;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
align-self: stretch;
|
||||
border-radius: 26px;
|
||||
border: 4px solid #FFF;
|
||||
background: linear-gradient(180deg, #BFFFEF 0%, #F2FFFC 100%), #FFF;
|
||||
box-shadow: 0 8px 64px 0 rgba(0, 0, 0, 0.10);
|
||||
|
||||
.avatarWrap {
|
||||
padding-bottom: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
@include commonAvatarStyle(0.5);
|
||||
}
|
||||
|
||||
.desc {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
|
||||
.tip {
|
||||
color: #000;
|
||||
font-family: "PingFang SC";
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.levelWrap {
|
||||
color: #000;
|
||||
font-feature-settings: 'liga' off, 'clig' off;
|
||||
text-overflow: ellipsis;
|
||||
font-family: "Noto Sans SC";
|
||||
font-size: 36px;
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
line-height: 44px;
|
||||
|
||||
.level {
|
||||
color: #00E5AD;
|
||||
}
|
||||
}
|
||||
|
||||
.slogan {
|
||||
color: #000;
|
||||
font-family: "PingFang SC";
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,388 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import { View, Text, Image, Button } from "@tarojs/components";
|
||||
import Taro, { useRouter } from "@tarojs/taro";
|
||||
import { withAuth } from "@/components";
|
||||
import evaluateService from "@/services/evaluateService";
|
||||
import { useUserActions } from "@/store/userStore";
|
||||
import dayjs from "dayjs";
|
||||
import classnames from "classnames";
|
||||
import { withAuth, RadarChart } from "@/components";
|
||||
import evaluateService, {
|
||||
LastTimeTestResult,
|
||||
Question,
|
||||
} from "@/services/evaluateService";
|
||||
import { useUserInfo, useUserActions } from "@/store/userStore";
|
||||
import { delay } from "@/utils";
|
||||
import CloseIcon from "@/static/ntrp/ntrp_close_icon.svg";
|
||||
import DocCopy from "@/static/ntrp/ntrp_doc_copy.svg";
|
||||
import ArrowRight from "@/static/ntrp/ntrp_arrow_right.svg";
|
||||
import ArrowBack from "@/static/ntrp/ntrp_arrow_back.svg";
|
||||
import CircleChecked from "@/static/ntrp/ntrp_circle_checked.svg";
|
||||
import CircleUnChecked from "@/static/ntrp/ntrp_circle_unchecked.svg";
|
||||
import styles from "./index.module.scss";
|
||||
|
||||
enum StageType {
|
||||
INTRO = "intro",
|
||||
TEST = "test",
|
||||
RESULT = "result",
|
||||
}
|
||||
|
||||
function CommonGuideBar(props) {
|
||||
const { title, confirm } = props;
|
||||
const { params } = useRouter();
|
||||
const { redirect } = params;
|
||||
|
||||
function handleClose() {
|
||||
//TODO: 二次确认
|
||||
if (confirm) {
|
||||
}
|
||||
Taro.redirectTo({
|
||||
url: redirect ? redirect : "/game_pages/list/index",
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<View className={styles.header}>
|
||||
<View className={styles.closeIcon} onClick={handleClose}>
|
||||
<Image className={styles.closeImg} src={CloseIcon} />
|
||||
</View>
|
||||
<View className={styles.title}>
|
||||
<Text>{title}</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
function Intro(props) {
|
||||
const { redirect } = props;
|
||||
const [ntrpData, setNtrpData] = useState<LastTimeTestResult>();
|
||||
const userInfo = useUserInfo();
|
||||
const { fetchUserInfo } = useUserActions();
|
||||
const [ready, setReady] = useState(false);
|
||||
|
||||
const { last_test_result: { ntrp_level, create_time, id } = {} } =
|
||||
ntrpData || {};
|
||||
const lastTestTime = dayjs(create_time).format("YYYY年M月D日");
|
||||
|
||||
useEffect(() => {
|
||||
getLastResult();
|
||||
}, []);
|
||||
|
||||
async function getLastResult() {
|
||||
const res = await evaluateService.getLastResult();
|
||||
if (res.code === 0) {
|
||||
setNtrpData(res.data);
|
||||
if (res.data.has_ntrp_level) {
|
||||
fetchUserInfo();
|
||||
}
|
||||
setReady(true);
|
||||
}
|
||||
}
|
||||
if (!ready) {
|
||||
return "";
|
||||
}
|
||||
|
||||
function handleNext(type) {
|
||||
Taro.redirectTo({
|
||||
url: `/other_pages/ntrp-evaluate/index?stage=${type}${
|
||||
type === StageType.RESULT ? `&id=${id}` : ""
|
||||
}${redirect ? `&redirect=${redirect}` : ""}`,
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<View className={styles.introContainer}>
|
||||
<CommonGuideBar />
|
||||
{ntrpData?.has_ntrp_level ? (
|
||||
<View className={styles.result}>
|
||||
<View className={styles.avatarWrap}>
|
||||
<View className={styles.avatar}>
|
||||
<Image
|
||||
className={styles.avatarUrl}
|
||||
src={userInfo.avatar_url}
|
||||
mode="aspectFit"
|
||||
/>
|
||||
</View>
|
||||
{/* avatar side */}
|
||||
<View className={styles.addonImage}>
|
||||
<Image
|
||||
className={styles.docImage}
|
||||
src={DocCopy}
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
{/* tip */}
|
||||
<View className={styles.tip}>
|
||||
<Image
|
||||
className={styles.tipImage}
|
||||
src="http://bimwe.oss-cn-shanghai.aliyuncs.com/front/ball/images/b7cb47aa-b609-4112-899f-3fde02ed2431.png"
|
||||
mode="aspectFit"
|
||||
/>
|
||||
</View>
|
||||
<View className={styles.lastResult}>
|
||||
<View className={styles.tipAndTime}>
|
||||
<Text>上次测试结果</Text>
|
||||
<Text>{lastTestTime}</Text>
|
||||
</View>
|
||||
<View className={styles.levelWrap}>
|
||||
<Text>NTRP</Text>
|
||||
<Text className={styles.level}>{ntrp_level}</Text>
|
||||
</View>
|
||||
<View className={styles.slogan}>
|
||||
<Text>变线+网前,下一步就是赢比赛!</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View className={styles.actions}>
|
||||
<View className={styles.buttonWrap}>
|
||||
<Button
|
||||
className={classnames(styles.button, styles.primary)}
|
||||
type="primary"
|
||||
onClick={() => handleNext(StageType.TEST)}
|
||||
>
|
||||
<Text>再次测试</Text>
|
||||
<Image className={styles.arrowImage} src={ArrowRight} />
|
||||
</Button>
|
||||
</View>
|
||||
<View className={styles.buttonWrap}>
|
||||
<Button
|
||||
className={styles.button}
|
||||
onClick={() => handleNext(StageType.RESULT)}
|
||||
>
|
||||
<Text>继续使用上次测试结果</Text>
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
) : (
|
||||
<View className={styles.guide}>
|
||||
{/* tip */}
|
||||
<View className={styles.tip}>
|
||||
<Image
|
||||
className={styles.tipImage}
|
||||
src="http://bimwe.oss-cn-shanghai.aliyuncs.com/front/ball/images/b7cb47aa-b609-4112-899f-3fde02ed2431.png"
|
||||
mode="aspectFit"
|
||||
/>
|
||||
</View>
|
||||
{/* radar */}
|
||||
<View className={styles.radar}>
|
||||
<Image
|
||||
className={styles.radarImage}
|
||||
src="http://bimwe.oss-cn-shanghai.aliyuncs.com/front/ball/images/a2e1b639-82a9-4ab8-b767-8605556eafcb.png"
|
||||
mode="aspectFit"
|
||||
/>
|
||||
</View>
|
||||
<View className={styles.desc}>
|
||||
<Text>
|
||||
NTRP(National Tennis Rating
|
||||
Program)是一种常用的网球水平分级系统,这不是绝对精准的“分数”,而是一个参考标准,能够帮助你更清晰地了解自己的网球水平,从而在训练、比赛或娱乐活动中找到「难度合适」的球友,避免过度碾压或被碾压。
|
||||
</Text>
|
||||
</View>
|
||||
<View className={styles.actions}>
|
||||
<View className={styles.buttonWrap}>
|
||||
<Button
|
||||
className={classnames(styles.button, styles.primary)}
|
||||
type="primary"
|
||||
onClick={() => handleNext(StageType.TEST)}
|
||||
>
|
||||
<Text>开始测试</Text>
|
||||
<Image className={styles.arrowImage} src={ArrowRight} />
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
function Test(props) {
|
||||
const { redirect } = props;
|
||||
const [disabled, setDisabled] = useState(false);
|
||||
const [index, setIndex] = useState(9);
|
||||
const [questions, setQuestions] = useState<
|
||||
(Question & { choosen: number })[]
|
||||
>([]);
|
||||
const startTimeRef = useRef<number>(0);
|
||||
|
||||
useEffect(() => {
|
||||
startTimeRef.current = Date.now();
|
||||
getQUestions();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setDisabled(questions[index]?.choosen === -1);
|
||||
}, [index, questions]);
|
||||
|
||||
async function getQUestions() {
|
||||
const res = await evaluateService.getQuestions();
|
||||
if (res.code === 0) {
|
||||
setQuestions(res.data.map((item) => ({ ...item, choosen: 3 })));
|
||||
}
|
||||
}
|
||||
|
||||
function handleSelect(i) {
|
||||
setQuestions((prev) =>
|
||||
prev.map((item, pIndex) => ({
|
||||
...item,
|
||||
...(pIndex === index ? { choosen: i } : {}),
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
setDisabled(true);
|
||||
try {
|
||||
const res = await evaluateService.submit({
|
||||
answers: questions.map((item) => ({
|
||||
question_id: item.id,
|
||||
answer_index: item.choosen,
|
||||
})),
|
||||
test_duration: (Date.now() - startTimeRef.current) / 1000,
|
||||
});
|
||||
if (res.code === 0) {
|
||||
Taro.redirectTo({
|
||||
url: `/other_pages/ntrp-evaluate/index?stage=${StageType.RESULT}&id=${
|
||||
res.data.record_id
|
||||
}${redirect ? `&redirect=${redirect}` : ""}`,
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
Taro.showToast({ title: e.message, icon: "error" });
|
||||
} finally {
|
||||
setDisabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
function handIndexChange(direction) {
|
||||
console.log(disabled, direction);
|
||||
if (disabled && direction > 0) {
|
||||
return;
|
||||
}
|
||||
if (index === questions.length - 1 && direction > 0) {
|
||||
handleSubmit();
|
||||
return;
|
||||
}
|
||||
setIndex((prev) => prev + direction);
|
||||
}
|
||||
|
||||
const question = questions[index];
|
||||
if (!question) {
|
||||
return "";
|
||||
}
|
||||
return (
|
||||
<View className={styles.testContainer}>
|
||||
<CommonGuideBar confirm title={`${index + 1} / ${questions.length}`} />
|
||||
<View className={styles.bar}>
|
||||
<View
|
||||
className={styles.progressBar}
|
||||
style={{ width: `${100 * ((index + 1) / questions.length)}%` }}
|
||||
/>
|
||||
</View>
|
||||
<View className={styles.notice}>
|
||||
<Text>根据近3个月实际表现勾选最符合项</Text>
|
||||
</View>
|
||||
<View className={styles.question}>
|
||||
<View className={styles.content}>{question.question_content}</View>
|
||||
<View className={styles.options}>
|
||||
{question.options.map((item, i) => {
|
||||
const checked = question.choosen === i;
|
||||
return (
|
||||
<View
|
||||
key={i}
|
||||
className={styles.optionItem}
|
||||
onClick={() => handleSelect(i)}
|
||||
>
|
||||
<View className={styles.optionText}>{item.text}</View>
|
||||
<View className={styles.optionIcon}>
|
||||
<Image
|
||||
className={styles.icon}
|
||||
src={checked ? CircleChecked : CircleUnChecked}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</View>
|
||||
<View className={styles.actions}>
|
||||
<View
|
||||
className={classnames(styles.next, disabled ? styles.disabled : "")}
|
||||
onClick={() => handIndexChange(1)}
|
||||
>
|
||||
<Button className={styles.nextBtn} type="primary">
|
||||
{index === questions.length - 1 ? "完成测试" : "继续"}
|
||||
</Button>
|
||||
</View>
|
||||
{index !== 0 && (
|
||||
<View className={styles.prev} onClick={() => handIndexChange(-1)}>
|
||||
<Image className={styles.backIcon} src={ArrowBack} />
|
||||
<Text>返回</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
function Result() {
|
||||
const userInfo = useUserInfo();
|
||||
const { fetchUserInfo } = useUserActions();
|
||||
|
||||
useEffect(() => {
|
||||
fetchUserInfo()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<View className={styles.resultContainer}>
|
||||
<CommonGuideBar />
|
||||
<View className={styles.card}>
|
||||
<View className={styles.avatarWrap}>
|
||||
<View className={styles.avatar}>
|
||||
<Image
|
||||
className={styles.avatarUrl}
|
||||
src={userInfo.avatar_url}
|
||||
mode="aspectFit"
|
||||
/>
|
||||
</View>
|
||||
{/* avatar side */}
|
||||
<View className={styles.addonImage}>
|
||||
<Image
|
||||
className={styles.docImage}
|
||||
src={DocCopy}
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<View className={styles.desc}>
|
||||
<View className={styles.tip}>
|
||||
<Text>你的 NTRP 测试结果为</Text>
|
||||
</View>
|
||||
<View className={styles.levelWrap}>
|
||||
<Text>NTRP</Text>
|
||||
<Text className={styles.level}>{1.1}</Text>
|
||||
</View>
|
||||
<View className={styles.slogan}>
|
||||
<Text>变线+网前,下一步就是赢比赛!</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View>
|
||||
<RadarChart />
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const ComponentsMap = {
|
||||
[StageType.INTRO]: Intro,
|
||||
[StageType.TEST]: Test,
|
||||
[StageType.RESULT]: Result,
|
||||
};
|
||||
|
||||
function NtrpEvaluate() {
|
||||
const { updateUserInfo } = useUserActions();
|
||||
const { params } = useRouter();
|
||||
const { redirect } = params;
|
||||
|
||||
useEffect(() => {
|
||||
evaluateService.getEvaluateQuestions().then((data) => {
|
||||
console.log(data);
|
||||
});
|
||||
}, []);
|
||||
const stage = params.stage as StageType;
|
||||
|
||||
async function handleUpdateNtrp() {
|
||||
await updateUserInfo({
|
||||
@@ -33,21 +399,9 @@ function NtrpEvaluate() {
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<View className={styles.container}>
|
||||
<View className={styles.title}>NTRP评分</View>
|
||||
<View className={styles.content}>
|
||||
<Image
|
||||
className={styles.image}
|
||||
src="https://img.yzcdn.cn/vant/cat.jpeg"
|
||||
/>
|
||||
<Text className={styles.description}>您的NTRP评分是 4.0 分。</Text>
|
||||
</View>
|
||||
<Button className={styles.button} onClick={handleUpdateNtrp}>
|
||||
评测通过
|
||||
</Button>
|
||||
</View>
|
||||
);
|
||||
const Component = ComponentsMap[stage];
|
||||
|
||||
return <Component redirect={redirect} />;
|
||||
}
|
||||
|
||||
export default withAuth(NtrpEvaluate);
|
||||
|
||||
Reference in New Issue
Block a user