shapeIntuition2.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. <template>
  2. <div class="app-container">
  3. <Header />
  4. <!--<div class="desc_wrap" v-if="!testResultStr">-->
  5. <!--<div-->
  6. <!--style="-->
  7. <!--width: 70%;-->
  8. <!--height: 100%;-->
  9. <!--background: rgb(248, 248, 248);-->
  10. <!--opacity: 1;-->
  11. <!--border-radius: 12px;-->
  12. <!--margin: 0 auto;-->
  13. <!--"-->
  14. <!--&gt;-->
  15. <!--<div style="float: left; width: 50%; height: 100%; overflow-y: auto">-->
  16. <!--<div id="left_top">-->
  17. <!--<div>-->
  18. <!--<div id="setting">-->
  19. <!--<img src="../../assets/9551.png" alt="" />-->
  20. <!--</div>-->
  21. <!--<div id="text">-->
  22. <!--<span>操作提示:</span>-->
  23. <!--</div>-->
  24. <!--</div>-->
  25. <!--</div>-->
  26. <!--<div style="margin: 100px auto; width: 80%; text-align: left">-->
  27. <!--<p v-html="subjectInfo.testDescription"></p>-->
  28. <!--&lt;!&ndash; <p>{{subjectInfo.description}}</p> &ndash;&gt;-->
  29. <!--</div>-->
  30. <!--</div>-->
  31. <!--<div-->
  32. <!--class="right_part"-->
  33. <!--:style="{-->
  34. <!--background:-->
  35. <!--'url(' + require('../../assets/page' + taskId + '.png') + ')',-->
  36. <!--'background-size': '100% 100%',-->
  37. <!--}"-->
  38. <!--&gt;-->
  39. <!--<div id="title">-->
  40. <!--<span>{{ subjectInfo.name }}</span>-->
  41. <!--</div>-->
  42. <!--<div-->
  43. <!--style="-->
  44. <!--position: absolute;-->
  45. <!--bottom: 30px;-->
  46. <!--left: 50%;-->
  47. <!--transform: translateX(-50%);-->
  48. <!--"-->
  49. <!--&gt;-->
  50. <!--<el-button-->
  51. <!--class="start"-->
  52. <!--type="primary"-->
  53. <!--v-if="button0Show"-->
  54. <!--@click="startTest(0)"-->
  55. <!--&gt;练习测试</el-button-->
  56. <!--&gt;-->
  57. <!--<el-button-->
  58. <!--class="start"-->
  59. <!--type="primary"-->
  60. <!--v-if="button1Show"-->
  61. <!--@click="startTest(1)"-->
  62. <!--&gt;正式测试</el-button-->
  63. <!--&gt;-->
  64. <!--</div>-->
  65. <!--</div>-->
  66. <!--</div>-->
  67. <!--</div>-->
  68. <div class="main-container">
  69. <van-nav-bar
  70. :title="subjectInfo.name"
  71. left-arrow
  72. left-text=""
  73. @click-left="goBack"
  74. />
  75. <div v-if="!testResultStr" class="explan">
  76. <!-- LOGO -->
  77. <!--<h1>{{ subjectInfo.name }}</h1>-->
  78. <div class="main-text-div">
  79. <!--<p v-html="subjectInfo.testDescription">{{ subjectInfo.testDescription }}</p>-->
  80. <p>{{ subjectInfo.mobileTestDescription }}</p>
  81. </div>
  82. <div class="btnArea">
  83. <van-button
  84. v-if="button0Show"
  85. block
  86. round
  87. type="primary"
  88. @click="startTest(0)"
  89. >练习测试
  90. </van-button>
  91. <van-button
  92. v-if="button1Show"
  93. block
  94. round
  95. style="margin-top: 15px"
  96. type="primary"
  97. @click="startTest(1)"
  98. >
  99. 正式测试
  100. </van-button>
  101. </div>
  102. </div>
  103. <!-- LOGO -->
  104. <div
  105. v-show="testResultStrShow"
  106. style="width: 650px; margin: 20px auto; line-height: 2"
  107. >
  108. <p style="margin-top: 20%; font-size: 30px">
  109. {{ testResultStr }}
  110. </p>
  111. </div>
  112. <div v-if="testFlag" class="activeTask">
  113. <div v-if="testTypeCode == 1" class="progress-content">
  114. <van-progress
  115. :percentage="(imgIndex * 100) / 120"
  116. color="#f2826a"
  117. pivot-text="任务进度"
  118. />
  119. </div>
  120. <div class="glass">
  121. <p v-show="countDownShow" class="timingBox">{{ countDownStr }}</p>
  122. <img v-show="showDuckEgg" :src="examImgUrl" alt="" class="shapeImg" />
  123. <div v-show="showDuckEgg" class="btn-content">
  124. <div class="btn-item">
  125. <van-button
  126. block
  127. round
  128. size="small"
  129. type="info"
  130. @click="userClick('L')"
  131. >
  132. <van-icon name="arrow-left" />
  133. </van-button>
  134. </div>
  135. <div class="btn-item">
  136. <van-button
  137. block
  138. round
  139. size="small"
  140. type="info"
  141. @click="userClick('R')"
  142. >
  143. <van-icon name="arrow" />
  144. </van-button>
  145. </div>
  146. </div>
  147. </div>
  148. <!-- <img v-show="showWhiteFlag" src='../../assets/congnitiveAblitity/whiteFlag.png' alt="" style="width: 50px; height: 50px; margin-top: 20%"> -->
  149. <!-- 演示使用 -->
  150. <!-- <div class="steering">
  151. <el-button type="primary" icon="el-icon-arrow-left" @click="userClick('L')"></el-button>
  152. <el-button type="primary" @click="userClick('R')"><i class="el-icon-arrow-right el-icon--right"></i></el-button>
  153. </div> -->
  154. </div>
  155. </div>
  156. </div>
  157. </template>
  158. <script>
  159. import { preloader } from "@/utils/utils";
  160. import Header from "@/components/header/index.vue";
  161. export default {
  162. name: "shapeIntuition2",
  163. components: { Header },
  164. data() {
  165. return {
  166. userId: "",
  167. userTestResult: {},
  168. imgUrl: "",
  169. examImgUrl: "",
  170. taskId: "", // 认知任务id
  171. testFlag: false,
  172. testState: false,
  173. saveFlag: false, //结果保存按钮显示标志
  174. subjectInfo: "", //认知任务详情
  175. button0Show: true, // 控制按钮显示隐藏
  176. button1Show: false, // 控制按钮显示隐藏
  177. buttonName: "开始测试", // 正式测试 // 重新练习
  178. testTypeCode: 0, // 0-练习测试 1-正式测试 2-重新测试
  179. imgIndex: 0,
  180. userTestPicList: [], //用户点击图片列表
  181. showImage: true,
  182. difficultList: [0], // [0,10,30,45,60,90,120,180,360]
  183. testPicCount: 10, //测试数目
  184. userRightClickDirection: "", //测试者应该点击的方向
  185. userRightResponseCount: 0, //测试者反应正确的次数
  186. showDuckEgg: false,
  187. countDownTime: 6, //开始前的倒计时
  188. countDownStr: "练习马上开始!",
  189. countDownShow: true,
  190. testTunrnCount: 0, //正式测试轮数
  191. testEndFlag: false, //测试结束标志
  192. testResultStrShow: false, //测试结果展示
  193. testResultStr: "", //测试成绩
  194. userCanClick: true, //用户标识用户单次刺激只能点击一次
  195. myInterval: "",
  196. timeOne: "",
  197. timeTwo: "",
  198. startMilliSeconds: 0, //反应时
  199. userResponseRecords: [], //用户测试反应记录
  200. saveFalg: true,
  201. testPlanId: ""
  202. };
  203. },
  204. // 页面初始化函数
  205. created() {
  206. // this.taskId = this.$route.query.taskId;
  207. this.init();
  208. },
  209. destroyed() {
  210. clearInterval(this.myInterval);
  211. clearTimeout(this.timeOne);
  212. clearTimeout(this.timeTwo);
  213. },
  214. methods: {
  215. goBack() {
  216. if (this.testPlanId) {
  217. //来自测试计划列表
  218. this.$router.push({
  219. name: "testPlanClassify",
  220. params: {
  221. testPlanId: this.testPlanId
  222. }
  223. });
  224. } else {
  225. this.$router.push("/index/cognitionTask");
  226. }
  227. },
  228. init() {
  229. this.testPlanId = this.$route.query.testPlanId || "";
  230. this.userId = JSON.parse(sessionStorage.getItem("userInfo")).id;
  231. this.subjectInfo = JSON.parse(sessionStorage.getItem("subjectInfo"));
  232. },
  233. userClick(clickFlag) {
  234. if (this.countDownShow || !this.userCanClick) {
  235. return;
  236. }
  237. this.userCanClick = false;
  238. let milliSecondsCount = new Date().getTime() - this.startMilliSeconds;
  239. let userResponseStr = "Wrong";
  240. clearTimeout(this.timeOne);
  241. //用户反应正确性判断
  242. if (this.userRightClickDirection == clickFlag) {
  243. this.userRightResponseCount++;
  244. userResponseStr = "Right";
  245. }
  246. //判断是否测试结束
  247. if (this.imgIndex == this.userTestPicList.length) {
  248. this.testEndFlag = true;
  249. clearTimeout(this.timeOne);
  250. }
  251. //记录用户反应
  252. // console.log(this.imgIndex);
  253. if (this.testTypeCode == 1) {
  254. this.userResponseRecords.push({
  255. index: this.imgIndex,
  256. rightOrWrong: userResponseStr,
  257. responseTime: milliSecondsCount,
  258. diff: this.userTestPicList[this.imgIndex - 1].diff
  259. });
  260. }
  261. // console.log(this.userResponseRecords);
  262. this.showDuckEgg = false;
  263. this.timeTwo = setTimeout(() => {
  264. this.showTargetNow();
  265. }, 500);
  266. },
  267. startTest(testType) {
  268. if (!sessionStorage.getItem("userInfo")) {
  269. this.$toast("请先登录!");
  270. this.$router.push("/login");
  271. return;
  272. }
  273. if (testType == 0) {
  274. this.testTypeCode = 0;
  275. } else {
  276. this.saveFalg = true;
  277. this.testTypeCode = 1;
  278. }
  279. if (this.testTypeCode == 1) {
  280. this.difficultList = [360, 180, 90, 60, 30, 0]; // [360,180,90,60,30,0]
  281. this.imgIndex = 0;
  282. this.countDownStr = "马上开始!";
  283. this.countDownTime = 6;
  284. this.testEndFlag = false;
  285. this.showDuckEgg = false;
  286. this.userTestPicList = [];
  287. }
  288. this.countDownShow = true;
  289. this.userTestPicListCreate();
  290. // 预加载图片后开始测试
  291. preloader(this.userTestPicList, () => {
  292. this.testFlag = true;
  293. this.testState = true;
  294. this.countDown();
  295. });
  296. },
  297. showTargetNow() {
  298. // 练习间隔2~4,正式测试2~12;
  299. this.showDuckEgg = false;
  300. if (this.testEndFlag) {
  301. this.computeScore();
  302. } else {
  303. this.userRightClickDirection = this.userTestPicList[
  304. this.imgIndex
  305. ].imgDirection;
  306. this.examImgUrl = this.userTestPicList[this.imgIndex].imgUrl;
  307. this.showDuckEgg = true;
  308. this.imgIndex++;
  309. this.startMilliSeconds = new Date().getTime();
  310. this.userCanClick = true;
  311. if (this.imgIndex == this.userTestPicList.length) {
  312. this.testEndFlag = true;
  313. }
  314. this.timeOne = setTimeout(this.ifShowNextOne, 10 * 1000, this.imgIndex);
  315. // this.timeOne = setTimeout(() => {
  316. // this.userClick('NULL')
  317. // },10*1000);
  318. }
  319. },
  320. ifShowNextOne(needClickIndex) {
  321. if (needClickIndex == this.imgIndex) {
  322. this.userClick("NULL");
  323. }
  324. },
  325. computeScore() {
  326. if (this.testTypeCode == 0) {
  327. this.testFlag = false;
  328. this.testState = false;
  329. //this.testTypeCode =1
  330. this.countDownStr = "练习马上开始!";
  331. this.userRightResponseCount = 0;
  332. this.imgIndex = 0;
  333. this.countDownTime = 6;
  334. this.testEndFlag = false;
  335. this.showDuckEgg = false;
  336. this.userTestPicList = [];
  337. this.button1Show = true;
  338. // this.$message({
  339. // message: "测试结束!",
  340. // type: "success",
  341. // });
  342. this.$toast.success({
  343. message: "测试结束!",
  344. position: "top"
  345. });
  346. } else {
  347. let userScore = (
  348. (this.userRightResponseCount / this.userResponseRecords.length) *
  349. 100
  350. ).toFixed(2);
  351. this.testFlag = false;
  352. this.testState = false;
  353. this.button0Show = false;
  354. this.button1Show = false;
  355. //console.log(this.userResponseRecords)
  356. if (this.saveFalg) {
  357. this.$http.post(
  358. `/cognize/SHAPE2`,
  359. {
  360. userId: this.userId,
  361. userScore: userScore + "%",
  362. userResponseRecords: this.userResponseRecords,
  363. testPlanId: this.testPlanId
  364. },
  365. response => {
  366. if (response?.code == 200) {
  367. // sessionStorage.setItem("resultInfo", JSON.stringify({"测试准确率":response.data.userScore}));
  368. // this.$router.push(`/cognitiveTestResult?from=1&testPlanId=${this.testPlanId}`);
  369. //跳转新测试结果页面
  370. this.goTestResult(response.data);
  371. } else {
  372. this.$toast.fail(response?.msg);
  373. }
  374. },
  375. err => {
  376. this.$toast.fail(err.msg);
  377. }
  378. );
  379. this.$toast.success("测试结束!");
  380. this.saveFalg = false;
  381. }
  382. }
  383. },
  384. // goTestResult(id){
  385. // this.$http.get(`getRecordById?id=${id}`, {}, (res) => {
  386. // if (res.code == 2001) {
  387. // this.$toast.fail(res.msg);
  388. // return;
  389. // }
  390. // if (res && res.code == 200) {
  391. // if (JSON.parse(res.data?.userRecordEntity?.testResult).versionNo == "2.0.1") {
  392. // //跳转新测试结果模版数据暂存本地
  393. // // sessionStorage.setItem("testResult", res.data?.userRecordEntity?.testResult);
  394. // // this.$store.dispatch('setTestResult',JSON.parse(res.data?.userRecordEntity?.testResult));
  395. // this.$store.dispatch('setTestResult',res?.data);
  396. // this.$router.push({
  397. // name: "testResultNew",
  398. // query: {
  399. // id: res.data?.userRecordEntity?.id,
  400. // title: res.data?.userRecordEntity?.name,
  401. // testPlanId: this.testPlanId || '',
  402. // come: 1, //1-来自认知任务列表,2-测试记录列表
  403. // },
  404. // });
  405. // } else {
  406. // //跳转旧测试结果模版
  407. //
  408. // let testResult= JSON.parse(res.data?.userRecordEntity?.testResult)[0].version;
  409. //
  410. // if( testResult == 2 ) {
  411. // this.$router.push("/testRecordsSCl?id=" + id);
  412. // }else {
  413. // this.$router.push("/testResult?flag=" + res.data?.userRecordEntity?.flag + "&id=" + id);
  414. // }
  415. // }
  416. //
  417. // } else {
  418. // this.$toast.fail("获取数据失败!服务器异常");
  419. // }
  420. // });
  421. // },
  422. userTestPicListCreate() {
  423. let imgObj = {
  424. // imgUrl:'',
  425. // imgDirection:'',
  426. // userClickDirection:''
  427. };
  428. if (this.testTypeCode == 0) {
  429. //随机呈现最简单的10张图片
  430. let imgIndexList = this.getRandomNumber(10, 20);
  431. for (let j = 0; j < this.difficultList.length; j++) {
  432. for (let i = 0; i < imgIndexList.length; i++) {
  433. imgObj = {};
  434. if (i % 2 == 0) {
  435. imgObj.imgUrl = require("../../assets/congnitiveAblitity/shapeIntuition/R_ELP_test_jitter" +
  436. this.difficultList[j] +
  437. "_s" +
  438. imgIndexList[i] +
  439. ".jpg");
  440. imgObj.imgDirection = "R";
  441. imgObj.userClickDirection = "";
  442. } else {
  443. imgObj.imgUrl = require("../../assets/congnitiveAblitity/shapeIntuition/ELP_test_jitter" +
  444. this.difficultList[j] +
  445. "_s" +
  446. imgIndexList[i] +
  447. ".jpg");
  448. imgObj.imgDirection = "L";
  449. imgObj.userClickDirection = "";
  450. }
  451. this.userTestPicList.push(imgObj);
  452. }
  453. }
  454. this.shuffle(this.userTestPicList);
  455. } else {
  456. //展示所有图片
  457. for (let j = 0; j < this.difficultList.length; j++) {
  458. var tempList = [];
  459. for (let i = 1; i < 11; i++) {
  460. imgObj = {};
  461. imgObj.imgUrl = require("../../assets/congnitiveAblitity/shapeIntuition/R_ELP_test_jitter" +
  462. this.difficultList[j] +
  463. "_s" +
  464. i +
  465. ".jpg");
  466. imgObj.imgDirection = "R";
  467. imgObj.userClickDirection = "";
  468. imgObj.diff = this.difficultList[j];
  469. tempList.push(imgObj);
  470. imgObj = {};
  471. imgObj.imgUrl = require("../../assets/congnitiveAblitity/shapeIntuition/ELP_test_jitter" +
  472. this.difficultList[j] +
  473. "_s" +
  474. i +
  475. ".jpg");
  476. imgObj.imgDirection = "L";
  477. imgObj.userClickDirection = "";
  478. imgObj.diff = this.difficultList[j];
  479. tempList.push(imgObj);
  480. //console.log(tempList)
  481. }
  482. this.shuffle(tempList);
  483. this.userTestPicList = this.userTestPicList.concat(tempList);
  484. console.log(this.userTestPicList);
  485. this.testPicCount = this.userTestPicList.length;
  486. }
  487. }
  488. },
  489. getRandomNumber(size, maxNumber) {
  490. let numberList = [];
  491. for (var i = 0; i < size; i++) {
  492. numberList.push(Math.floor(Math.random() * maxNumber) + 1);
  493. }
  494. return numberList;
  495. },
  496. countDown() {
  497. // 测试时间倒计时
  498. this.myInterval = setInterval(() => {
  499. this.countDownTime--;
  500. this.countDownStr = this.countDownTime;
  501. if (this.countDownTime == 0) {
  502. this.countDownShow = false;
  503. //显示鸭蛋
  504. this.showTargetNow();
  505. // 清除定时器
  506. clearInterval(this.myInterval);
  507. //this.countDownTime = 5;
  508. }
  509. }, 1000);
  510. },
  511. shuffle(arr) {
  512. var i = arr.length,
  513. t,
  514. j;
  515. while (i) {
  516. j = Math.floor(Math.random() * i--);
  517. t = arr[i];
  518. arr[i] = arr[j];
  519. arr[j] = t;
  520. }
  521. }
  522. }
  523. };
  524. </script>
  525. <style scoped>
  526. .explan {
  527. box-sizing: border-box;
  528. padding: 15px 15px 0;
  529. }
  530. .explan h1 {
  531. font-size: 16px;
  532. color: #222222;
  533. text-align: center;
  534. }
  535. .explan p {
  536. font-size: 14px;
  537. color: #666666;
  538. line-height: 26px;
  539. text-indent: 15px;
  540. margin-bottom: 20px;
  541. }
  542. .activeTask {
  543. box-sizing: border-box;
  544. padding-top: 46px;
  545. background: url(../../assets/congnitiveAblitity/shapeIntuition.png) no-repeat
  546. center;
  547. background-size: cover;
  548. position: fixed;
  549. top: 0;
  550. left: 0;
  551. right: 0;
  552. bottom: 0;
  553. }
  554. .scaleName {
  555. margin-top: 70px;
  556. background-size: cover;
  557. }
  558. .scaleButton {
  559. margin-top: 20px;
  560. margin-bottom: 20px;
  561. background-size: cover;
  562. }
  563. .steering {
  564. width: 50%;
  565. position: absolute;
  566. bottom: 20%;
  567. left: 50%;
  568. transform: translateX(-50%);
  569. display: flex;
  570. justify-content: space-between;
  571. }
  572. .steering .left {
  573. width: 60px;
  574. height: 60px;
  575. background: url(../../assets/left.png) no-repeat center;
  576. }
  577. .steering .right {
  578. width: 60px;
  579. height: 60px;
  580. background: url(../../assets/right.png) no-repeat center;
  581. margin-left: 15px;
  582. }
  583. .progress-content {
  584. position: absolute;
  585. width: 100%;
  586. height: 20px;
  587. left: 0;
  588. top: 60px;
  589. box-sizing: border-box;
  590. padding: 4px 10px;
  591. }
  592. .timingBox {
  593. position: absolute;
  594. top: 50%;
  595. left: 50%;
  596. transform: translate(-50%, -50%);
  597. color: black;
  598. font-size: 18px;
  599. text-align: center;
  600. line-height: 50px;
  601. margin: 0 auto;
  602. z-index: 10;
  603. }
  604. .btn-content {
  605. position: absolute;
  606. width: 100%;
  607. left: 50%;
  608. bottom: 10%;
  609. transform: translate(-50%, 0);
  610. text-align: center;
  611. z-index: 10;
  612. display: flex;
  613. flex-direction: row;
  614. justify-content: space-around;
  615. align-items: center;
  616. box-sizing: border-box;
  617. padding: 0 5px;
  618. }
  619. .btn-content .btn-item {
  620. width: 30%;
  621. display: flex;
  622. flex-direction: column;
  623. justify-content: space-around;
  624. }
  625. .btn-content .btn-item /deep/ .van-button {
  626. margin: 35px 0;
  627. }
  628. .imgBox {
  629. font-size: 50px;
  630. color: black;
  631. position: absolute;
  632. top: 50%;
  633. left: 50%;
  634. transform: translate(-50%, -50%);
  635. }
  636. .shapeImg {
  637. width: 90%;
  638. position: absolute;
  639. top: 50%;
  640. left: 50%;
  641. transform: translate(-50%, -50%);
  642. }
  643. .addImg {
  644. width: 71px;
  645. width: 71px;
  646. position: absolute;
  647. top: 50%;
  648. left: 50%;
  649. transform: translate(-50%, -50%);
  650. }
  651. </style>