shapeIntuition_random.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. <template>
  2. <div class="txt-center">
  3. <div v-show="testResultStrShow" style="width: 650px; margin: 20px auto; line-height: 2">
  4. <p style="margin-top: 20%; font-size: 30px">
  5. {{ testResultStr }}
  6. </p>
  7. </div>
  8. <div v-if="testFlag" :class="{ testMainDiv: !testState, activeTask: testState }" @contextmenu.prevent=""
  9. @click.left="userClick('L')" @click.right="userClick('R')">
  10. <div class="taskHead">
  11. <!-- <div class="scale" @click.stop="screen">
  12. <img src="../../assets/small-big.png" alt="" />
  13. </div> -->
  14. <!-- <el-button @click="messageFun">弹出留言框</el-button> -->
  15. <el-progress class="main_progress" color="linear-gradient(to right, #ffd650, #ff8431)" :stroke-width="48"
  16. :text-inside="true" :format="format" :percentage="(imgIndex * 100) / 120" v-if="testTypeCode == 1"
  17. style="width:50%;margin-top:10px"></el-progress>
  18. </div>
  19. <div class="glass">
  20. <p v-show="countDownShow" class="countdownStr">
  21. {{ countDownStr }}
  22. </p>
  23. <img v-show="showDuckEgg" :src="examImgUrl" alt="" class="shapeImg" />
  24. </div>
  25. <!-- <img v-show="showWhiteFlag" src='../../assets/congnitiveAblitity/whiteFlag.png' alt="" style="width: 50px; height: 50px; margin-top: 20%"> -->
  26. <!-- 演示使用 -->
  27. <!-- <div class="steering">
  28. <el-button type="primary" icon="el-icon-arrow-left" @click="userClick('L')"></el-button>
  29. <el-button type="primary" @click="userClick('R')"><i class="el-icon-arrow-right el-icon--right"></i></el-button>
  30. </div> -->
  31. </div>
  32. </div>
  33. <CpdmMessage ref="cpdmMe" />
  34. </template>
  35. <script>
  36. // import cognitiveAbilityTaskList from "@/assets/data/cognitiveAbilityData.js";
  37. // import { preloader, requireImg } from "@/utils/utils";
  38. import { preloader } from "@/utils/utils";
  39. // import { preloader } from "@/utils/utils";
  40. // import screenfull from "screenfull";
  41. import { userInfoStore } from '@/stores';
  42. import { saveEggRecordApi } from '@/api/record'
  43. import { format as myFormat } from 'date-fns';
  44. import { userPlanDetailApi } from '@/api/home';
  45. import CpdmMessage from '@/components/CpdmMessage.vue';
  46. const userInfo = userInfoStore()
  47. export default {
  48. components: { CpdmMessage },
  49. data() {
  50. return {
  51. userId: "",
  52. userTestResult: {},
  53. imgUrl: "",
  54. examImgUrl: "",
  55. taskId: "", // 认知任务id
  56. testFlag: false,
  57. testState: false,
  58. saveFlag: false, //结果保存按钮显示标志
  59. subjectInfo: "", //认知任务详情
  60. button0Show: true, // 控制按钮显示隐藏
  61. button1Show: false, // 控制按钮显示隐藏
  62. buttonName: "开始测试", // 正式测试 // 重新练习
  63. testTypeCode: 0, // 0-练习测试 1-正式测试 2-重新测试
  64. imgIndex: 0,
  65. userTestPicList: [], //用户点击图片列表
  66. showImage: true,
  67. difficultList: [0], // [0,10,30,45,60,90,120,180,360]
  68. testPicCount: 10, //测试数目
  69. userRightClickDirection: "", //测试者应该点击的方向
  70. userRightResponseCount: 0, //测试者反应正确的次数
  71. showDuckEgg: false,
  72. countDownTime: 6, //开始前的倒计时
  73. countDownStr: "练习马上开始!",
  74. countDownShow: true,
  75. testTunrnCount: 0, //正式测试轮数
  76. testEndFlag: false, //测试结束标志
  77. testResultStrShow: false, //测试结果展示
  78. testResultStr: "", //测试成绩
  79. userCanClick: true, //用户标识用户单次刺激只能点击一次
  80. myInterval: "",
  81. timeOne: "",
  82. timeTwo: "",
  83. startMilliSeconds: 0, //反应时
  84. userResponseRecords: [], //用户测试反应记录
  85. saveFalg: true,
  86. // requireImg: requireImg,
  87. planId: '',
  88. planName: '',
  89. flag: '',
  90. flagName: '',
  91. formalTest: '',
  92. beginTime: '',
  93. userPlanDetailApi: userPlanDetailApi
  94. };
  95. },
  96. // 页面初始化函数
  97. created() {
  98. // this.taskId = this.$route.query.taskId;
  99. //获取测试计划ID
  100. this.planId = this.$route.params.planId;
  101. //测试名称
  102. this.planName = this.$route.params.planName;
  103. //认知任务 flag
  104. this.flag = this.$route.params.flag;
  105. //认知任务 flag名称
  106. this.flagName = this.$route.params.flagName;
  107. //
  108. this.formalTest = this.$route.params.formalTest;
  109. this.beginTime = myFormat(new Date().getTime(), "yyyy-MM-dd HH:mm:ss")
  110. //拿到是练习测试还是正式测试
  111. this.init(this.formalTest);
  112. },
  113. destroyed() {
  114. clearInterval(this.myInterval);
  115. clearTimeout(this.timeOne);
  116. clearTimeout(this.timeTwo);
  117. },
  118. methods: {
  119. // messageFun() {
  120. // this.$refs.cpdmMe.open()
  121. // },
  122. requireImg(name) {
  123. return new URL(`../assets/cognize/shapeIntuition/${name}.jpg`, import.meta.url).href
  124. },
  125. init(val) {
  126. this.startTest(val);
  127. },
  128. userClick(clickFlag) {
  129. if (this.countDownShow || !this.userCanClick) {
  130. return;
  131. }
  132. this.userCanClick = false;
  133. let milliSecondsCount = new Date().getTime() - this.startMilliSeconds;
  134. let userResponseStr = "Wrong";
  135. clearTimeout(this.timeOne);
  136. //用户反应正确性判断
  137. if (this.userRightClickDirection == clickFlag) {
  138. this.userRightResponseCount++;
  139. userResponseStr = "Right";
  140. }
  141. //判断是否测试结束
  142. if (this.imgIndex == this.userTestPicList.length) {
  143. this.testEndFlag = true;
  144. }
  145. //记录用户反应
  146. if (this.testTypeCode == 1) {
  147. this.userResponseRecords.push({
  148. index: this.imgIndex,
  149. rightOrWrong: userResponseStr,
  150. responseTime: milliSecondsCount,
  151. diff: this.userTestPicList[this.imgIndex - 1].diff,
  152. });
  153. }
  154. this.showDuckEgg = false;
  155. this.timeTwo = setTimeout(() => {
  156. this.showTargetNow();
  157. }, 500);
  158. },
  159. format(percentage) {
  160. return percentage === 100 ? "测试已完成" : "任务进度";
  161. },
  162. screen() {
  163. // screenfull.toggle();
  164. },
  165. startTest(testType) {
  166. // if (
  167. // sessionStorage.getItem("b80bb7740288fda1f201890375a60c8f") == "" ||
  168. // sessionStorage.getItem("b80bb7740288fda1f201890375a60c8f") == null
  169. // ) {
  170. // this.$message.error("请先登录!");
  171. // return;
  172. // }
  173. // this.screen();
  174. if (testType == 0) {
  175. this.testTypeCode = 0;
  176. } else {
  177. this.saveFalg = true;
  178. this.testTypeCode = 1;
  179. }
  180. this.userId = sessionStorage.getItem("b80bb7740288fda1f201890375a60c8f");
  181. if (this.testTypeCode == 1) {
  182. this.difficultList = [360, 180, 90, 60, 30, 0]; // [360,180,90,60,30,0]
  183. this.imgIndex = 0;
  184. this.countDownStr = "马上开始!";
  185. this.countDownTime = 6;
  186. this.testEndFlag = false;
  187. this.showDuckEgg = false;
  188. this.userTestPicList = [];
  189. }
  190. this.countDownShow = true;
  191. this.userTestPicListCreate();
  192. // 预加载图片后开始测试
  193. preloader(this.userTestPicList, () => {
  194. this.testFlag = true;
  195. this.testState = true;
  196. this.countDown();
  197. });
  198. },
  199. showTargetNow() {
  200. // 练习间隔2~4,正式测试2~12;
  201. this.showDuckEgg = false;
  202. if (this.testEndFlag) {
  203. this.computeScore();
  204. } else {
  205. this.userRightClickDirection = this.userTestPicList[this.imgIndex].imgDirection;
  206. this.examImgUrl = this.userTestPicList[this.imgIndex].imgUrl;
  207. this.showDuckEgg = true;
  208. this.imgIndex++;
  209. this.startMilliSeconds = new Date().getTime();
  210. this.userCanClick = true;
  211. if (this.imgIndex == this.userTestPicList.length) {
  212. this.testEndFlag = true;
  213. }
  214. this.timeOne = setTimeout(this.ifShowNextOne, 10 * 1000, this.imgIndex);
  215. }
  216. },
  217. ifShowNextOne(needClickIndex) {
  218. if (needClickIndex == this.imgIndex) {
  219. this.userClick("NULL");
  220. }
  221. },
  222. async computeScore() {
  223. // screenfull.exit();
  224. if (this.testTypeCode == 0) {
  225. this.testFlag = false;
  226. this.testState = false;
  227. //this.testTypeCode =1
  228. this.countDownStr = "练习马上开始!";
  229. this.userRightResponseCount = 0;
  230. this.imgIndex = 0;
  231. this.countDownTime = 6;
  232. this.testEndFlag = false;
  233. this.showDuckEgg = false;
  234. this.userTestPicList = [];
  235. this.button1Show = true;
  236. this.$message({
  237. message: "练习测试结束!",
  238. type: "success",
  239. });
  240. //跳转到上一页
  241. this.$router.go(-1)
  242. } else {
  243. let userScore = (
  244. (this.userRightResponseCount / this.userResponseRecords.length) *
  245. 100
  246. ).toFixed(2);
  247. this.testFlag = false;
  248. this.testState = false;
  249. this.button0Show = false;
  250. this.button1Show = false;
  251. if (this.saveFalg) {
  252. let result = {
  253. beginTime: this.beginTime,
  254. // "id": "string",
  255. orgName: userInfo.userInfo.orgName,
  256. orgNo: userInfo.userInfo.orgNo,
  257. planId: this.planId,
  258. planName: this.planName,
  259. taskFlag: this.flag,
  260. taskName: this.flagName,
  261. testRecord: JSON.stringify(this.userResponseRecords),
  262. testResult: JSON.stringify({ 'userScore': userScore }),
  263. type: 1,
  264. userName: userInfo.userInfo.userName,
  265. userNo: userInfo.userInfo.userNo
  266. }
  267. const res = await saveEggRecordApi(result);
  268. this.$message({
  269. message: "测试结束!",
  270. type: "success",
  271. });
  272. //调用接口---查看此计划后边是不是还有--需要测试的认知任务---如果有的话
  273. //跳转到--- 计划页
  274. //判断该计划下是否还有 需要显示且需要测试记的计划//如果还有的话需要跳转到plan界面
  275. //如果该计划下没有需要测试的话--需要跳转到 测试记录里边
  276. //根据planId查询计划列表
  277. let params = {
  278. planId: this.planId,
  279. userNo: userInfo.userInfo.userNo
  280. }
  281. let temp = await userPlanDetailApi(params)
  282. let listT = temp.data;
  283. let listP = []
  284. listP = listT.filter((item) => {
  285. return item.isCompleted == '0' && item.contentType == '1'
  286. })
  287. this.saveFalg = false;
  288. //等--认知任务如果有未测试的话--需要跳转到测试计划页面
  289. //否则--跳转到测试计划页面
  290. if (listP.length > 0) {
  291. this.$router.push({ name: 'plan' })
  292. } else {
  293. //当测试完了以后--需要弹出确认的弹出框
  294. //把弹出框的内容 及用户信息 进行处理 进行发布
  295. this.$refs.cpdmMe.open()
  296. // this.$router.push({ name: 'testRecord' })
  297. }
  298. //如果后边没有--则测试跳转到报告页
  299. //需要跳转到
  300. }
  301. }
  302. },
  303. userTestPicListCreate() {
  304. let imgObj = {
  305. // imgUrl:'',
  306. // imgDirection:'',
  307. // userClickDirection:''
  308. };
  309. if (this.testTypeCode == 0) {
  310. //随机呈现最简单的10张图片
  311. let imgIndexList = this.getRandomNumber(10, 20);
  312. for (let j = 0; j < this.difficultList.length; j++) {
  313. for (let i = 0; i < imgIndexList.length; i++) {
  314. imgObj = {};
  315. if (i % 2 == 0) {
  316. imgObj.imgUrl = this.requireImg("R_ELP_test_jitter" +
  317. this.difficultList[j] +
  318. "_s" +
  319. imgIndexList[i]);
  320. imgObj.imgDirection = "R";
  321. imgObj.userClickDirection = "";
  322. } else {
  323. imgObj.imgUrl = this.requireImg("ELP_test_jitter" +
  324. this.difficultList[j] +
  325. "_s" +
  326. imgIndexList[i]);
  327. imgObj.imgDirection = "L";
  328. imgObj.userClickDirection = "";
  329. }
  330. this.userTestPicList.push(imgObj);
  331. }
  332. }
  333. this.shuffle(this.userTestPicList);
  334. } else {
  335. //展示所有图片
  336. for (let j = 0; j < this.difficultList.length; j++) {
  337. var tempList = [];
  338. for (let i = 1; i < 11; i++) {
  339. imgObj = {};
  340. imgObj.imgUrl = this.requireImg("R_ELP_test_jitter" +
  341. this.difficultList[j] +
  342. "_s" +
  343. i);
  344. imgObj.imgDirection = "R";
  345. imgObj.userClickDirection = "";
  346. imgObj.diff = this.difficultList[j];
  347. tempList.push(imgObj);
  348. imgObj = {};
  349. imgObj.imgUrl = this.requireImg("ELP_test_jitter" +
  350. this.difficultList[j] +
  351. "_s" +
  352. i);
  353. imgObj.imgDirection = "L";
  354. imgObj.userClickDirection = "";
  355. imgObj.diff = this.difficultList[j];
  356. tempList.push(imgObj);
  357. }
  358. //this.shuffle(tempList);
  359. this.userTestPicList = this.userTestPicList.concat(tempList);
  360. this.testPicCount = this.userTestPicList.length;
  361. }
  362. this.shuffle(this.userTestPicList);
  363. }
  364. },
  365. getRandomNumber(size, maxNumber) {
  366. let numberList = [];
  367. for (var i = 0; i < size; i++) {
  368. numberList.push(Math.floor(Math.random() * maxNumber) + 1);
  369. }
  370. return numberList;
  371. },
  372. countDown() {
  373. // 测试时间倒计时
  374. this.myInterval = setInterval(() => {
  375. this.countDownTime--;
  376. this.countDownStr = this.countDownTime;
  377. if (this.countDownTime == 0) {
  378. this.countDownShow = false;
  379. //显示鸭蛋
  380. this.showTargetNow();
  381. // 清除定时器
  382. clearInterval(this.myInterval);
  383. //this.countDownTime = 5;
  384. }
  385. }, 1000);
  386. },
  387. shuffle(arr) {
  388. var i = arr.length,
  389. t,
  390. j;
  391. while (i) {
  392. j = Math.floor(Math.random() * i--);
  393. t = arr[i];
  394. arr[i] = arr[j];
  395. arr[j] = t;
  396. }
  397. },
  398. },
  399. };
  400. </script>
  401. <style scoped>
  402. .testMainDiv {
  403. margin: 0 auto;
  404. margin-top: 10px;
  405. background: gray;
  406. background-size: cover;
  407. /* text-align:center; */
  408. width: 500px;
  409. height: 300px;
  410. /* object-fit:fill; */
  411. }
  412. .activeTask {
  413. background: url(../assets/cognize/shapeIntuition.png) no-repeat center;
  414. background-size: cover;
  415. position: fixed;
  416. top: 0;
  417. left: 0;
  418. right: 0;
  419. bottom: 0;
  420. }
  421. .scaleName {
  422. margin-top: 70px;
  423. background-size: cover;
  424. }
  425. .scaleButton {
  426. margin-top: 20px;
  427. margin-bottom: 20px;
  428. background-size: cover;
  429. }
  430. .steering {
  431. width: 50%;
  432. position: absolute;
  433. bottom: 20%;
  434. left: 50%;
  435. transform: translateX(-50%);
  436. display: flex;
  437. justify-content: space-between;
  438. }
  439. .steering .left {
  440. width: 60px;
  441. height: 60px;
  442. background: url(../../assets/left.png) no-repeat center;
  443. }
  444. .steering .right {
  445. width: 60px;
  446. height: 60px;
  447. background: url(../../assets/right.png) no-repeat center;
  448. margin-left: 15px;
  449. }
  450. .imgBox {
  451. font-size: 50px;
  452. color: black;
  453. position: absolute;
  454. top: 50%;
  455. left: 50%;
  456. transform: translate(-50%, -50%);
  457. }
  458. .shapeImg {
  459. width: 20vw;
  460. min-width: 200px;
  461. position: absolute;
  462. top: 50%;
  463. left: 50%;
  464. transform: translate(-50%, -50%);
  465. }
  466. .addImg {
  467. width: 71px;
  468. width: 71px;
  469. position: absolute;
  470. top: 50%;
  471. left: 50%;
  472. transform: translate(-50%, -50%);
  473. }
  474. .countdownStr {
  475. width: 70%;
  476. position: absolute;
  477. top: 40%;
  478. left: 50%;
  479. transform: translate(-50%, -50%);
  480. color: black;
  481. font-size: 70px;
  482. text-align: center;
  483. line-height: 100px;
  484. }
  485. .main_progress .el-progress-bar__inner {
  486. position: absolute;
  487. left: 0;
  488. top: 0;
  489. height: 100%;
  490. background-color: #ff3c3c !important;
  491. text-align: right;
  492. border-radius: 100px;
  493. line-height: 1;
  494. white-space: nowrap;
  495. transition: width 0.6s ease;
  496. background-image: linear-gradient(to right, #ffd650, #ff8431) !important;
  497. }
  498. .main_progress {
  499. width: 50%;
  500. margin-left: 10%;
  501. }
  502. </style>