testTopic.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. <template>
  2. <!-- 能力测评 -->
  3. <div class="home-container">
  4. <el-row class="test-paper">
  5. <el-col class="answer-sheet" span="12">
  6. <el-card style="min-height: 100%" shadow="hover">
  7. <h4>序号:</h4>
  8. <div class="all-serial-number">
  9. <el-button
  10. @click="handleLeft(index)"
  11. v-for="(item, index) in state.examDetails"
  12. :key="index"
  13. class="serial-number"
  14. size="mini"
  15. :class="{ 'yi-zuo-da': item.da.length != 0 }"
  16. >
  17. {{ index + 1 }}
  18. </el-button>
  19. </div>
  20. <div>
  21. <el-button @click="getSubmit" type="primary" plain>提 交</el-button>
  22. </div>
  23. </el-card>
  24. </el-col>
  25. <el-col class="test-questions" span="12">
  26. <el-card shadow="hover">
  27. <div
  28. @click="getChenge"
  29. v-for="(shiTi, index) in state.examDetails"
  30. :key="index"
  31. :id="'id' + index"
  32. class="exam-details"
  33. :class="{ 'skip-style': index === state.navgatorIndex }"
  34. >
  35. <!-- 试题 -->
  36. <div class="shi-ti-style">
  37. <!-- 题目 -->
  38. <div>{{ index + 1 }}、{{ shiTi.timu }}</div>
  39. <!-- 选项 -->
  40. <div class="xuan-xiang-style">
  41. <!-- 单选 -->
  42. <el-radio-group
  43. @input="gegegegeg(shiTi, index)"
  44. v-if="shiTi.type == '单选'"
  45. v-model="shiTi.da"
  46. >
  47. <el-radio
  48. v-for="(dan, danIdnex) in shiTi.xuanxiang"
  49. :label="danIdnex"
  50. :key="danIdnex"
  51. >
  52. {{ dan }}
  53. </el-radio>
  54. </el-radio-group>
  55. <!-- 多选 -->
  56. <el-checkbox-group
  57. @change="gegegegeg(shiTi, index)"
  58. v-else-if="shiTi.type == '多选'"
  59. v-model="shiTi.da"
  60. >
  61. <el-checkbox
  62. v-for="(duo, duoIndex) in shiTi.xuanxiang"
  63. :label="duoIndex"
  64. :key="duoIndex"
  65. >
  66. {{ duo }}
  67. </el-checkbox>
  68. </el-checkbox-group>
  69. <!-- 问答 -->
  70. <div v-else>
  71. <el-input
  72. type="textarea"
  73. :rows="2"
  74. placeholder="请输入内容"
  75. v-model="shiTi.da"
  76. />
  77. </div>
  78. </div>
  79. </div>
  80. <!-- 标记 @click="getChangMark(index)"-->
  81. <div class="mark-style">
  82. <el-tooltip
  83. :content="shiTi.mark ? '已标记' : '可标记'"
  84. placement="right"
  85. effect="light"
  86. >
  87. <a
  88. @click="getChangMark(index)"
  89. class="el-icon-star-on"
  90. :class="{ mark: shiTi.mark }"
  91. />
  92. </el-tooltip>
  93. </div>
  94. </div>
  95. </el-card>
  96. </el-col>
  97. </el-row>
  98. </div>
  99. </template>
  100. <script setup>
  101. import { reactive, onMounted, onUnmounted, ref } from 'vue'
  102. import { ElMessage } from 'element-plus'
  103. // 定义响应式数据
  104. const state = reactive({
  105. examDetails: [
  106. {
  107. timu: '《山行》是描绘了( C )的景色。',
  108. type: '单选',
  109. xuanxiang: ['A、春天', 'B、夏天', 'C、秋天', ' D、冬天'],
  110. // 答案存放字符串
  111. da: '',
  112. mark: false
  113. },
  114. {
  115. timu: '劝君更尽一杯酒,西出阳关无故人。”出自( B )的名句。',
  116. type: '单选',
  117. xuanxiang: ['A、李白', 'B、王维', 'C、王昌龄', 'D、杜牧'],
  118. // 答案存放字符串
  119. da: '',
  120. mark: false
  121. },
  122. {
  123. timu: '把“春风”比作“剪刀”的是哪首诗?( C )',
  124. type: '单选',
  125. xuanxiang: [
  126. 'A、《忆江南》',
  127. 'B、《滁州西涧》',
  128. 'C、《咏柳》',
  129. 'D、《游园不值》'
  130. ],
  131. // 答案存放字符串
  132. da: '',
  133. mark: false
  134. },
  135. {
  136. timu: '横看成岭侧成峰,远近高低各不一样。”诗中写的名胜是( D )。',
  137. type: '单选',
  138. xuanxiang: ['A、泰山', 'B、华山', 'C、黄山', 'D、庐山'],
  139. // 答案存放字符串
  140. da: '',
  141. mark: false
  142. },
  143. {
  144. timu: '解落三秋叶,能开二月花。过江千尺浪,入竹万竿斜。”这首诗写的是( B )。',
  145. type: '单选',
  146. xuanxiang: ['A、花', 'B、风', 'C、竹', 'D、水'],
  147. // 答案存放字符串
  148. da: '',
  149. mark: false
  150. },
  151. {
  152. timu: '以下哪些诗句出自白居易的作品?( A、C、E )',
  153. type: '多选',
  154. xuanxiang: [
  155. 'A、春风又绿江南岸',
  156. 'B、白日依山尽',
  157. 'C、人生自古谁无死',
  158. 'D、大漠孤烟直',
  159. 'E、举杯邀明月',
  160. 'F、月落乌啼霜满天'
  161. ],
  162. // 答案存放数组
  163. da: [0, 2, 4],
  164. mark: false
  165. },
  166. {
  167. timu: '以下哪些是唐代诗人?( A、B、C、E、F )',
  168. type: '多选',
  169. xuanxiang: [
  170. 'A、杜甫',
  171. 'B、苏轼',
  172. 'C、白居易',
  173. 'D、李清照',
  174. 'E、辛弃疾',
  175. 'F、陆游'
  176. ],
  177. // 答案存放数组
  178. da: [],
  179. mark: false
  180. },
  181. {
  182. timu: '以下哪些诗人被称为“唐三百首”?( A、B、C )',
  183. type: '多选',
  184. xuanxiang: ['A、李白', 'B、杜甫', 'C、白居易', 'D、苏轼', 'E、王之涣'],
  185. // 答案存放数组
  186. da: [],
  187. mark: false
  188. },
  189. {
  190. timu: '以下哪些诗人被称为“宋词四大家”?( A、B、C、D )',
  191. type: '多选',
  192. xuanxiang: ['A、李清照', 'B、辛弃疾', 'C、苏轼', 'D、杜牧', 'E、杨万里'],
  193. // 答案存放数组
  194. da: [],
  195. mark: false
  196. },
  197. // {
  198. // timu: '具有诗仙、诗圣、诗鬼称号的的诗人分别是谁?',
  199. // type: '问答',
  200. // xuanxiang: ['李白 杜甫 李贺'],
  201. // // 答案存放字符串
  202. // da: '',
  203. // mark: false
  204. // },
  205. // {
  206. // timu: '在苏轼写的《惠崇春江晚景》这首中,让我们明白了有一种味美但内脏有毒的鱼叫什么?',
  207. // type: '问答',
  208. // xuanxiang: ['河豚'],
  209. // // 答案存放字符串
  210. // da: '',
  211. // mark: false
  212. // }
  213. ],
  214. navgatorIndex: null,
  215. listBoxState: true,
  216. isSkip: true,
  217. isShiTi: false,
  218. listBox: null
  219. })
  220. // DOM引用
  221. const scrollContainer = ref(null)
  222. let timeId = null
  223. // 页面滚动处理函数
  224. const handleScroll = () => {
  225. clearTimeout(timeId)
  226. timeId = setTimeout(() => {
  227. scrollToTop()
  228. console.log('执行完成')
  229. }, 100)
  230. }
  231. // 点击导航菜单滚动到指定位置
  232. const handleLeft = index => {
  233. state.navgatorIndex = index
  234. const element = document.getElementById(`id${index}`)
  235. if (element) {
  236. element.scrollIntoView({
  237. top: '100px',
  238. behavior: 'smooth',
  239. block: 'center'
  240. })
  241. }
  242. state.listBoxState = false
  243. clearTimeout(timeId)
  244. timeId = setTimeout(() => {
  245. state.listBoxState = true
  246. }, 200)
  247. }
  248. // 监听页面滚动改变导航选中状态
  249. const scrollToTop = () => {
  250. const scrollTop =
  251. window.pageYOffset ||
  252. document.documentElement.scrollTop ||
  253. document.body.scrollTop
  254. if (state.listBoxState && state.listBox) {
  255. state.listBox.forEach((_, i) => {
  256. const element = document.getElementById(`id${i}`)
  257. if (element) {
  258. const offsetTop = element.offsetTop
  259. const scrollHeight = element.scrollHeight
  260. if (scrollTop >= offsetTop && scrollTop <= offsetTop + scrollHeight) {
  261. state.navgatorIndex = i
  262. }
  263. }
  264. })
  265. }
  266. }
  267. // 标记或收藏题目
  268. // const getChangMark = num => {
  269. // state.examDetails[num].mark = !state.examDetails[num].mark
  270. // }
  271. const gegegegeg = (val, num) => {
  272. console.log(val)
  273. }
  274. // 取消跳转样式
  275. const getChenge = () => {
  276. state.navgatorIndex = null
  277. }
  278. // 提交答案
  279. const getSubmit = () => {
  280. console.log(state.examDetails)
  281. const list = state.examDetails.map(item => item.da)
  282. console.log(list)
  283. ElMessage({
  284. message: JSON.stringify(list),
  285. type: 'success'
  286. })
  287. }
  288. // 生命周期钩子
  289. onMounted(() => {
  290. window.addEventListener('scroll', handleScroll, true)
  291. })
  292. onUnmounted(() => {
  293. window.removeEventListener('scroll', handleScroll, true)
  294. clearTimeout(timeId)
  295. })
  296. </script>
  297. <style scoped lang="scss">
  298. @use 'sass:math';
  299. // 定义rpx转换函数
  300. @function rpx($px) {
  301. @return math.div($px, 750) * 100vw;
  302. }
  303. .home-container {
  304. position: fixed;
  305. top: 0;
  306. left: 0;
  307. right: 0;
  308. bottom: 0;
  309. background: linear-gradient(to bottom, #001169, #8a78d0);
  310. display: flex;
  311. flex-direction: column;
  312. gap: rpx(0);
  313. font-size: rpx(8);
  314. }
  315. .test-paper {
  316. width: 100%;
  317. height: 100%;
  318. }
  319. :deep(.el-card__body) {
  320. min-height: 100%;
  321. }
  322. .el-card {
  323. border: none;
  324. // background: linear-gradient(to bottom, #e2ddfc, #f1effd);
  325. }
  326. .answer-sheet {
  327. width: rpx(140);
  328. display: inline-block;
  329. margin-right: rpx(5);
  330. text-align: left;
  331. }
  332. .test-questions {
  333. flex: 1;
  334. height: 100%;
  335. display: inline-block;
  336. text-align: left;
  337. overflow-y: auto; /* 启用垂直滚动 */
  338. }
  339. .test-questions .el-card::-webkit-scrollbar {
  340. width: rpx(2);
  341. }
  342. .test-questions .el-card::-webkit-scrollbar-thumb {
  343. background-color: #ddd;
  344. border-radius: 3px;
  345. }
  346. </style>
  347. <style scoped lang="scss">
  348. @use 'sass:math';
  349. // 定义rpx转换函数
  350. @function rpx($px) {
  351. @return math.div($px, 750) * 100vw;
  352. }
  353. /* 具体样式:答题卡样式 */
  354. .all-serial-number {
  355. }
  356. .serial-number {
  357. margin: rpx(5);
  358. width: rpx(15);
  359. height: rpx(15);
  360. font-size: rpx(8);
  361. }
  362. /* 具体样式:试题样式 */
  363. .exam-details {
  364. margin-bottom: rpx(5);
  365. padding: rpx(5);
  366. border: 1px solid #001169;
  367. border-radius: rpx(5);
  368. height: rpx(55);
  369. }
  370. /* 指定跳转题目样式 */
  371. .skip-style {
  372. border: 1px solid rgb(255, 0, 0);
  373. }
  374. .shi-ti-style {
  375. display: inline-block;
  376. // width: calc(100% - 30px);
  377. }
  378. /* 选项样式 */
  379. .xuan-xiang-style {
  380. margin-top: rpx(10);
  381. }
  382. /* 标记样式 */
  383. // .mark-style {
  384. // float: right;
  385. // text-align: center;
  386. // width: 30px;
  387. // }
  388. // .el-icon-star-on {
  389. // font-size: 25px;
  390. // }
  391. // .mark {
  392. // color: #f7ba2a;
  393. // }
  394. </style>
  395. <style scoped lang="scss">
  396. @use 'sass:math';
  397. // 定义rpx转换函数
  398. @function rpx($px) {
  399. @return math.div($px, 750) * 100vw;
  400. }
  401. /* 联动样式 */
  402. .yi-zuo-da {
  403. color: #fff;
  404. background: dodgerblue;
  405. }
  406. </style>