提交学习笔记专用
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

434 lines
8.9 KiB

3 weeks ago
  1. <template>
  2. <div class="exam-system">
  3. <!-- 头部标题 -->
  4. <header class="header">
  5. <div class="logo">
  6. <span class="icon">📋</span>
  7. <span class="title">股票知识评测系统</span>
  8. </div>
  9. <div class="subtitle">全方面评估您股票知识水平还能个性化学习建议</div>
  10. </header>
  11. <div class="main-content">
  12. <!-- 左侧题目区域 -->
  13. <div class="left-panel">
  14. <!-- 题目显示区 -->
  15. <div class="question-area">
  16. <div class="question-header">
  17. <input type="text" v-model="searchText" placeholder="搜索题目..." class="search-input" />
  18. </div>
  19. <div class="question-content">
  20. <h3 class="question-title">{{ currentQuestion.title }}</h3>
  21. <div class="options">
  22. <div
  23. v-for="option in currentQuestion.options"
  24. :key="option.key"
  25. class="option-item"
  26. :class="{ 'selected': selectedAnswer === option.key }"
  27. @click="selectAnswer(option.key)"
  28. >
  29. <span class="radio-btn" :class="{ 'checked': selectedAnswer === option.key }"></span>
  30. <span class="option-label">{{ option.key }}. {{ option.text }}</span>
  31. </div>
  32. </div>
  33. </div>
  34. </div>
  35. <!-- 答题卡预览区 -->
  36. <div class="answer-preview">
  37. <div class="preview-content">
  38. <!-- 可以显示答题进度或其他信息 -->
  39. </div>
  40. </div>
  41. <!-- 底部按钮 -->
  42. <div class="bottom-actions">
  43. <button class="btn btn-secondary" @click="submitExam">提交</button>
  44. <button class="btn btn-primary" @click="previousQuestion"> 上一题</button>
  45. <button class="btn btn-primary" @click="nextQuestion">下一题 </button>
  46. </div>
  47. </div>
  48. <!-- 右侧答题卡 -->
  49. <div class="right-panel">
  50. <div class="answer-card">
  51. <div class="card-header">
  52. <span class="folder-icon">📁</span>
  53. <span class="card-title">试题导航</span>
  54. </div>
  55. <div class="card-grid">
  56. <div
  57. v-for="(item, index) in totalQuestions"
  58. :key="index"
  59. class="grid-item"
  60. :class="getQuestionStatus(index)"
  61. @click="jumpToQuestion(index)"
  62. >
  63. {{ index + 1 }}
  64. </div>
  65. </div>
  66. </div>
  67. </div>
  68. </div>
  69. </div>
  70. </template>
  71. <script setup>
  72. import { ref, computed } from 'vue'
  73. // 搜索文本
  74. const searchText = ref('')
  75. // 当前题目索引
  76. const currentQuestionIndex = ref(0)
  77. // 用户答案记录
  78. const userAnswers = ref({})
  79. // 选中的答案
  80. const selectedAnswer = ref('')
  81. // 总题目数
  82. const totalQuestions = ref(25)
  83. // 题目数据(示例)
  84. const questions = ref([
  85. {
  86. id: 1,
  87. title: '以下哪个不属于股票的基本特征?',
  88. options: [
  89. { key: 'A', text: '收益性' },
  90. { key: 'B', text: '风险性' },
  91. { key: 'C', text: '流动性' },
  92. { key: 'D', text: '确定性' }
  93. ]
  94. },
  95. {
  96. id: 2,
  97. title: '股票市场的主要功能是什么?',
  98. options: [
  99. { key: 'A', text: '资金融通' },
  100. { key: 'B', text: '价格发现' },
  101. { key: 'C', text: '资源配置' },
  102. { key: 'D', text: '以上都是' }
  103. ]
  104. }
  105. // 可以添加更多题目...
  106. ])
  107. // 当前题目
  108. const currentQuestion = computed(() => {
  109. return questions.value[currentQuestionIndex.value] || questions.value[0]
  110. })
  111. // 选择答案
  112. const selectAnswer = (answer) => {
  113. selectedAnswer.value = answer
  114. userAnswers.value[currentQuestionIndex.value] = answer
  115. }
  116. // 上一题
  117. const previousQuestion = () => {
  118. if (currentQuestionIndex.value > 0) {
  119. currentQuestionIndex.value--
  120. selectedAnswer.value = userAnswers.value[currentQuestionIndex.value] || ''
  121. }
  122. }
  123. // 下一题
  124. const nextQuestion = () => {
  125. if (currentQuestionIndex.value < questions.value.length - 1) {
  126. currentQuestionIndex.value++
  127. selectedAnswer.value = userAnswers.value[currentQuestionIndex.value] || ''
  128. }
  129. }
  130. // 跳转到指定题目
  131. const jumpToQuestion = (index) => {
  132. currentQuestionIndex.value = index
  133. selectedAnswer.value = userAnswers.value[index] || ''
  134. }
  135. // 获取题目状态
  136. const getQuestionStatus = (index) => {
  137. if (index === currentQuestionIndex.value) {
  138. return 'current'
  139. }
  140. if (userAnswers.value[index]) {
  141. return 'answered'
  142. }
  143. return ''
  144. }
  145. // 提交考试
  146. const submitExam = () => {
  147. const answeredCount = Object.keys(userAnswers.value).length
  148. if (answeredCount < questions.value.length) {
  149. if (confirm(`您还有 ${questions.value.length - answeredCount} 道题未作答,确定要提交吗?`)) {
  150. // 提交逻辑
  151. console.log('提交答案:', userAnswers.value)
  152. }
  153. } else {
  154. // 提交逻辑
  155. console.log('提交答案:', userAnswers.value)
  156. }
  157. }
  158. </script>
  159. <style scoped>
  160. .exam-system {
  161. min-height: 100vh;
  162. background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
  163. color: #fff;
  164. font-family: 'Microsoft YaHei', Arial, sans-serif;
  165. }
  166. .header {
  167. padding: 20px 40px;
  168. background: rgba(0, 0, 0, 0.2);
  169. }
  170. .logo {
  171. display: flex;
  172. align-items: center;
  173. gap: 10px;
  174. font-size: 24px;
  175. font-weight: bold;
  176. margin-bottom: 8px;
  177. }
  178. .icon {
  179. font-size: 28px;
  180. }
  181. .subtitle {
  182. color: rgba(255, 255, 255, 0.8);
  183. font-size: 14px;
  184. margin-left: 38px;
  185. }
  186. .main-content {
  187. display: flex;
  188. gap: 20px;
  189. padding: 20px 40px;
  190. max-width: 1400px;
  191. margin: 0 auto;
  192. }
  193. .left-panel {
  194. flex: 1;
  195. display: flex;
  196. flex-direction: column;
  197. gap: 20px;
  198. }
  199. .question-area {
  200. background: rgba(20, 40, 80, 0.6);
  201. border: 1px solid rgba(100, 150, 200, 0.3);
  202. border-radius: 8px;
  203. padding: 20px;
  204. }
  205. .question-header {
  206. margin-bottom: 20px;
  207. }
  208. .search-input {
  209. width: 100%;
  210. padding: 10px 15px;
  211. background: rgba(0, 0, 0, 0.3);
  212. border: 1px solid rgba(100, 150, 200, 0.3);
  213. border-radius: 4px;
  214. color: #fff;
  215. font-size: 14px;
  216. }
  217. .search-input::placeholder {
  218. color: rgba(255, 255, 255, 0.4);
  219. }
  220. .question-content {
  221. padding: 20px 0;
  222. }
  223. .question-title {
  224. color: rgba(255, 255, 255, 0.6);
  225. font-size: 14px;
  226. margin-bottom: 20px;
  227. font-weight: normal;
  228. }
  229. .options {
  230. display: flex;
  231. flex-direction: column;
  232. gap: 15px;
  233. }
  234. .option-item {
  235. display: flex;
  236. align-items: center;
  237. gap: 12px;
  238. padding: 12px 15px;
  239. background: rgba(0, 0, 0, 0.2);
  240. border: 1px solid rgba(100, 150, 200, 0.3);
  241. border-radius: 4px;
  242. cursor: pointer;
  243. transition: all 0.3s;
  244. }
  245. .option-item:hover {
  246. background: rgba(100, 150, 200, 0.2);
  247. border-color: rgba(100, 150, 200, 0.5);
  248. }
  249. .option-item.selected {
  250. background: rgba(220, 80, 80, 0.3);
  251. border-color: rgba(220, 80, 80, 0.6);
  252. }
  253. .radio-btn {
  254. width: 18px;
  255. height: 18px;
  256. border: 2px solid rgba(255, 255, 255, 0.5);
  257. border-radius: 50%;
  258. display: inline-block;
  259. position: relative;
  260. flex-shrink: 0;
  261. }
  262. .radio-btn.checked {
  263. border-color: #e74c3c;
  264. background: #e74c3c;
  265. }
  266. .radio-btn.checked::after {
  267. content: '';
  268. position: absolute;
  269. top: 50%;
  270. left: 50%;
  271. transform: translate(-50%, -50%);
  272. width: 8px;
  273. height: 8px;
  274. background: #fff;
  275. border-radius: 50%;
  276. }
  277. .option-label {
  278. font-size: 15px;
  279. }
  280. .answer-preview {
  281. background: rgba(20, 40, 80, 0.6);
  282. border: 1px solid rgba(100, 150, 200, 0.3);
  283. border-radius: 8px;
  284. padding: 20px;
  285. min-height: 150px;
  286. }
  287. .bottom-actions {
  288. display: flex;
  289. gap: 15px;
  290. justify-content: flex-start;
  291. }
  292. .btn {
  293. padding: 12px 30px;
  294. border: none;
  295. border-radius: 4px;
  296. font-size: 14px;
  297. cursor: pointer;
  298. transition: all 0.3s;
  299. font-weight: 500;
  300. }
  301. .btn-primary {
  302. background: rgba(60, 120, 180, 0.8);
  303. color: #fff;
  304. }
  305. .btn-primary:hover {
  306. background: rgba(60, 120, 180, 1);
  307. }
  308. .btn-secondary {
  309. background: rgba(60, 120, 180, 0.8);
  310. color: #fff;
  311. }
  312. .btn-secondary:hover {
  313. background: rgba(70, 130, 190, 1);
  314. }
  315. .right-panel {
  316. width: 280px;
  317. flex-shrink: 0;
  318. }
  319. .answer-card {
  320. background: rgba(20, 40, 80, 0.6);
  321. border: 1px solid rgba(100, 150, 200, 0.3);
  322. border-radius: 8px;
  323. padding: 20px;
  324. }
  325. .card-header {
  326. display: flex;
  327. align-items: center;
  328. gap: 8px;
  329. margin-bottom: 20px;
  330. padding-bottom: 15px;
  331. border-bottom: 1px solid rgba(100, 150, 200, 0.2);
  332. }
  333. .folder-icon {
  334. font-size: 20px;
  335. }
  336. .card-title {
  337. color: #6db3f2;
  338. font-size: 16px;
  339. }
  340. .card-grid {
  341. display: grid;
  342. grid-template-columns: repeat(5, 1fr);
  343. gap: 10px;
  344. }
  345. .grid-item {
  346. aspect-ratio: 1;
  347. display: flex;
  348. align-items: center;
  349. justify-content: center;
  350. background: rgba(60, 120, 180, 0.6);
  351. border-radius: 4px;
  352. cursor: pointer;
  353. transition: all 0.3s;
  354. font-size: 14px;
  355. }
  356. .grid-item:hover {
  357. background: rgba(60, 120, 180, 0.8);
  358. transform: scale(1.05);
  359. }
  360. .grid-item.current {
  361. background: #3498db;
  362. box-shadow: 0 0 10px rgba(52, 152, 219, 0.5);
  363. }
  364. .grid-item.answered {
  365. background: rgba(60, 120, 180, 0.8);
  366. }
  367. .grid-item:nth-child(1) {
  368. background: #e74c3c;
  369. }
  370. .grid-item:nth-child(2) {
  371. background: #27ae60;
  372. }
  373. </style>