training.vue 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. <template>
  2. <view class="container">
  3. <PageBanner theme="mind-wisdom"
  4. tagline="能力训练"
  5. :quote="currentQuote" />
  6. <!-- 训练描述卡片 -->
  7. <view class="dimension-card" v-if="currentDim">
  8. <view class="dimension-icon-wrap" :style="{ background: currentDim.lightColor }">
  9. <text class="dimension-icon">{{ currentDim.icon }}</text>
  10. </view>
  11. <text class="dimension-name">{{ currentDim.name }}</text>
  12. <text class="dimension-desc">{{ currentDim.desc }}</text>
  13. </view>
  14. <!-- 开始训练按钮 -->
  15. <view class="action-section">
  16. <button class="start-btn" :style="{ background: currentDim ? currentDim.color : '#8B5CF6' }"
  17. :disabled="isTraining" @click="startTraining">
  18. <text class="btn-text" v-if="!isTraining">开始训练</text>
  19. <text class="btn-text" v-else>训练中...</text>
  20. </button>
  21. </view>
  22. <!-- 底部占位 -->
  23. <view class="bottom-spacer"></view>
  24. </view>
  25. </template>
  26. <script>
  27. import PageBanner from '../../components/PageBanner.vue'
  28. var BASE_URL = 'http://localhost:9082'
  29. var accountInfo = null
  30. try {
  31. accountInfo = uni.getAccountInfoSync()
  32. } catch (_e) {}
  33. var env = accountInfo && accountInfo.miniProgram && accountInfo.miniProgram.envVersion
  34. if (env) {
  35. switch (env) {
  36. case 'develop':
  37. BASE_URL = 'http://localhost:9082'
  38. break
  39. case 'trial':
  40. BASE_URL = 'https://cfc.iwintrue.com'
  41. break
  42. case 'release':
  43. BASE_URL = 'https://cfc.etotem.com.cn'
  44. break
  45. }
  46. }
  47. var DIMENSION_MAP = {
  48. perception: {
  49. key: 'perception',
  50. name: '感知训练',
  51. icon: '\u{1F441}',
  52. color: '#8B5CF6',
  53. lightColor: '#EDE9FE',
  54. desc: '通过图形匹配、颜色分辨等练习提升感知能力',
  55. quote: '观千剑而后识器,操千曲而后晓声'
  56. },
  57. focus: {
  58. key: 'focus',
  59. name: '专注训练',
  60. icon: '\u{1F3AF}',
  61. color: '#F97316',
  62. lightColor: '#FFF7ED',
  63. desc: '通过舒尔特方格、数字追踪等练习提升专注力',
  64. quote: '专心致志,惟弈秋之为听'
  65. },
  66. memory: {
  67. key: 'memory',
  68. name: '记忆训练',
  69. icon: '\u{1F9E0}',
  70. color: '#10B981',
  71. lightColor: '#ECFDF5',
  72. desc: '通过记忆卡片、数字记忆等练习提升记忆力',
  73. quote: '温故而知新,可以为师矣'
  74. },
  75. logic: {
  76. key: 'logic',
  77. name: '逻辑训练',
  78. icon: '\u{1F9E9}',
  79. color: '#3B82F6',
  80. lightColor: '#EFF6FF',
  81. desc: '通过推理题、模式识别等练习提升逻辑思维',
  82. quote: '学而不思则罔,思而不学则殆'
  83. },
  84. spatial: {
  85. key: 'spatial',
  86. name: '空间训练',
  87. icon: '\u{1F9CA}',
  88. color: '#8D6E63',
  89. lightColor: '#EFEBE9',
  90. desc: '通过空间旋转、立体构建等练习提升空间思维能力',
  91. quote: '横看成岭侧成峰,远近高低各不同'
  92. },
  93. processingSpeed: {
  94. key: 'processingSpeed',
  95. name: '加工速度训练',
  96. icon: '\u26A1',
  97. color: '#FFD700',
  98. lightColor: '#FFFBEB',
  99. desc: '通过快速反应、速度测试等练习提升加工速度',
  100. quote: '静如处子,动如脱兔'
  101. }
  102. }
  103. export default {
  104. components: { PageBanner },
  105. data() {
  106. return {
  107. dimension: null,
  108. childId: null,
  109. isTraining: false
  110. }
  111. },
  112. computed: {
  113. currentDim: function() {
  114. var dim = DIMENSION_MAP[this.dimension]
  115. return dim || null
  116. },
  117. currentQuote: function() {
  118. var dim = this.currentDim
  119. return dim ? dim.quote : '知己知彼,百战不殆'
  120. }
  121. },
  122. onLoad: function(options) {
  123. if (options && options.dimension) {
  124. this.dimension = options.dimension
  125. }
  126. if (options && options.childId) {
  127. this.childId = options.childId
  128. } else {
  129. this.childId = uni.getStorageSync('currentChildId') || null
  130. }
  131. uni.setNavigationBarTitle({
  132. title: this.currentDim ? this.currentDim.name : '能力训练'
  133. })
  134. },
  135. methods: {
  136. startTraining: function() {
  137. if (this.isTraining) return
  138. this.isTraining = true
  139. var self = this
  140. setTimeout(function() {
  141. var newScore = Math.floor(Math.random() * 31) + 70
  142. self.updateScore(newScore)
  143. }, 2000)
  144. },
  145. updateScore: function(score) {
  146. var self = this
  147. var token = uni.getStorageSync('token')
  148. var userId = uni.getStorageSync('userId') || ''
  149. uni.request({
  150. url: BASE_URL + '/api/cognitive/update',
  151. method: 'POST',
  152. data: {
  153. childId: self.childId,
  154. dimension: self.dimension + 'Score',
  155. score: score
  156. },
  157. header: {
  158. 'Content-Type': 'application/json',
  159. 'X-User-Id': userId,
  160. 'Authorization': token ? 'Bearer ' + token : ''
  161. },
  162. success: function(res) {
  163. self.isTraining = false
  164. if (res.data && res.data.code === 200) {
  165. uni.showToast({
  166. title: '训练完成!',
  167. icon: 'success'
  168. })
  169. setTimeout(function() {
  170. uni.navigateBack({
  171. delta: 1
  172. })
  173. }, 1500)
  174. } else {
  175. uni.showToast({
  176. title: res.data && res.data.message ? res.data.message : '提交失败',
  177. icon: 'none'
  178. })
  179. }
  180. },
  181. fail: function() {
  182. self.isTraining = false
  183. uni.showToast({
  184. title: '网络请求失败,请重试',
  185. icon: 'none'
  186. })
  187. }
  188. })
  189. }
  190. }
  191. }
  192. </script>
  193. <style scoped>
  194. .container {
  195. min-height: 100vh;
  196. background: #f5f7fa;
  197. padding-bottom: 120rpx;
  198. }
  199. /* ===== 训练描述卡片 ===== */
  200. .dimension-card {
  201. margin: 30rpx;
  202. background: #fff;
  203. border-radius: 20rpx;
  204. padding: 40rpx 32rpx;
  205. display: flex;
  206. flex-direction: column;
  207. align-items: center;
  208. box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
  209. }
  210. .dimension-icon-wrap {
  211. width: 120rpx;
  212. height: 120rpx;
  213. border-radius: 60rpx;
  214. display: flex;
  215. align-items: center;
  216. justify-content: center;
  217. margin-bottom: 20rpx;
  218. }
  219. .dimension-icon {
  220. font-size: 56rpx;
  221. }
  222. .dimension-name {
  223. font-size: 36rpx;
  224. font-weight: bold;
  225. color: #333;
  226. margin-bottom: 16rpx;
  227. }
  228. .dimension-desc {
  229. font-size: 26rpx;
  230. color: #888;
  231. text-align: center;
  232. line-height: 1.6;
  233. }
  234. /* ===== 按钮区域 ===== */
  235. .action-section {
  236. margin: 20rpx 30rpx;
  237. }
  238. .start-btn {
  239. width: 100%;
  240. height: 96rpx;
  241. border-radius: 48rpx;
  242. display: flex;
  243. align-items: center;
  244. justify-content: center;
  245. border: none;
  246. outline: none;
  247. color: #fff;
  248. font-size: 32rpx;
  249. font-weight: 600;
  250. box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.15);
  251. }
  252. .start-btn[disabled] {
  253. opacity: 0.6;
  254. }
  255. .start-btn:active {
  256. opacity: 0.85;
  257. }
  258. .btn-text {
  259. color: #fff;
  260. font-size: 32rpx;
  261. font-weight: 600;
  262. }
  263. /* ===== 底部 ===== */
  264. .bottom-spacer {
  265. height: 120rpx;
  266. }
  267. </style>