self-check-result.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. <template>
  2. <view class="scr-page">
  3. <!-- Loading -->
  4. <view class="scr-loading" v-if="loading">
  5. <text class="scr-loading-text">加载中...</text>
  6. </view>
  7. <template v-else>
  8. <!-- 总分横幅 -->
  9. <view class="scr-hero">
  10. <view class="scr-hero-badge">
  11. <text class="scr-hero-title">五维幸福总分</text>
  12. <view class="scr-hero-score-row">
  13. <text class="scr-hero-score">{{ result.totalScore }}</text>
  14. <text class="scr-hero-total">/45</text>
  15. </view>
  16. <view class="scr-hero-level" :class="'level-' + overallLevel">
  17. <text>{{ overallLevelName }}</text>
  18. </view>
  19. </view>
  20. <text class="scr-hero-date" v-if="result.createdAt">自检时间:{{ formatDate(result.createdAt) }}</text>
  21. </view>
  22. <!-- 雷达图 -->
  23. <view class="scr-card">
  24. <view class="scr-card-title">
  25. <text class="scr-card-title-text">五维能量雷达</text>
  26. <text class="scr-card-sub">身·智·富·行·心</text>
  27. </view>
  28. <view class="scr-canvas-wrap">
  29. <canvas
  30. type="2d"
  31. id="selfCheckRadar"
  32. class="scr-canvas"
  33. @ready="onCanvasReady"
  34. ></canvas>
  35. </view>
  36. </view>
  37. <!-- 维度得分 -->
  38. <view class="scr-card">
  39. <view class="scr-card-title">
  40. <text class="scr-card-title-text">维度得分</text>
  41. <text class="scr-card-sub">满分9分/维</text>
  42. </view>
  43. <view class="scr-dim-list">
  44. <view class="scr-dim-item" v-for="dim in result.dimensions" :key="dim.dimension">
  45. <view class="scr-dim-head">
  46. <view class="scr-dim-label">
  47. <view class="scr-dim-dot" :style="{ background: dim.color }"></view>
  48. <text class="scr-dim-name">{{ dim.name }}</text>
  49. <text class="scr-dim-element">{{ dim.element }}</text>
  50. </view>
  51. <view class="scr-dim-score-wrap">
  52. <text class="scr-dim-score" :style="{ color: dim.color }">{{ dim.score }}</text>
  53. <text class="scr-dim-score-max">/9</text>
  54. </view>
  55. </view>
  56. <view class="scr-dim-bar">
  57. <view class="scr-dim-bar-fill" :style="{ width: (dim.score / 9 * 100) + '%', background: dim.color }"></view>
  58. </view>
  59. <view class="scr-dim-foot">
  60. <text class="scr-dim-level" :class="'lvl-' + dim.level">{{ dim.levelName }}</text>
  61. <text class="scr-dim-summary">{{ dim.summary }}</text>
  62. </view>
  63. </view>
  64. </view>
  65. </view>
  66. <!-- 五行相生寻源建议(P0-2) -->
  67. <view class="scr-card" v-if="result.advices && result.advices.length > 0">
  68. <view class="scr-card-title">
  69. <text class="scr-card-title-text">五行相生 · 寻源建议</text>
  70. <text class="scr-card-sub">低分维度 {{ result.advices.length }} 项</text>
  71. </view>
  72. <view class="scr-advice-intro">低于6分的维度,先别硬补——从"生"它的上游借力,同时避开"克"它的压制源:</view>
  73. <view class="scr-advice-item" v-for="adv in result.advices" :key="adv.dimension">
  74. <!-- 低分维度 -->
  75. <view class="scr-advice-dim-row">
  76. <view class="scr-advice-dim-badge" :style="{ background: adv.color }">
  77. <text class="scr-advice-dim-name">{{ adv.dimensionName }}</text>
  78. <text class="scr-advice-dim-elem">{{ adv.element }}</text>
  79. </view>
  80. <text class="scr-advice-dim-score">{{ adv.score }}分</text>
  81. </view>
  82. <!-- 相生寻源 -->
  83. <view class="scr-advice-flow">
  84. <view class="scr-flow-node">
  85. <view class="scr-flow-dot" :style="{ background: adv.upstreamColor }"></view>
  86. <text class="scr-flow-label">上游 · {{ adv.upstreamName }}({{ adv.upstreamElement }})</text>
  87. </view>
  88. <text class="scr-flow-arrow">⟶</text>
  89. <text class="scr-flow-action">{{ adv.upstreamReason }}</text>
  90. </view>
  91. <!-- 相克寻源 -->
  92. <view class="scr-advice-flow">
  93. <view class="scr-flow-node">
  94. <view class="scr-flow-dot" :style="{ background: adv.restrainerColor }"></view>
  95. <text class="scr-flow-label">压制 · {{ adv.restrainerName }}({{ adv.restrainerElement }})</text>
  96. </view>
  97. <text class="scr-flow-arrow">⛔</text>
  98. <text class="scr-flow-action">{{ adv.restrainerReason }}</text>
  99. </view>
  100. <!-- 行动建议 -->
  101. <view class="scr-advice-action">
  102. <text class="scr-advice-action-label">本周行动</text>
  103. <text class="scr-advice-action-text">{{ adv.action }}</text>
  104. </view>
  105. </view>
  106. </view>
  107. <!-- 全部健康提示 -->
  108. <view class="scr-card" v-else>
  109. <view class="scr-all-healthy">
  110. <text class="scr-all-healthy-icon">🌿</text>
  111. <text class="scr-all-healthy-text">五维状态均健康,请继续保持这份平衡!</text>
  112. </view>
  113. </view>
  114. <!-- 历史与重测 -->
  115. <view class="scr-footer">
  116. <button class="scr-btn scr-btn-primary" @click="goHistory">历史记录</button>
  117. <button class="scr-btn scr-btn-outline" @click="retake">重新自检</button>
  118. </view>
  119. </template>
  120. </view>
  121. </template>
  122. <script>
  123. import { getSelfCheckLatest, getSelfCheckHistory } from '@/utils/api'
  124. import { parseDate } from '@/utils/format.js'
  125. export default {
  126. data() {
  127. return {
  128. loading: true,
  129. result: null,
  130. selfCheckId: '',
  131. canvasContext: null,
  132. canvasWidth: 340,
  133. canvasHeight: 340,
  134. // 雷达图轴序(对应 tianpan 木火土金水,顺时针)
  135. axes: ['木', '火', '土', '金', '水'],
  136. elementKeys: ['action', 'mind', 'body', 'wisdom', 'wealth'],
  137. elementColors: ['#10B981', '#FF6B9D', '#FF8C42', '#6366F1', '#F59E0B'],
  138. levelMap: {
  139. healthy: '健康',
  140. attention: '留意',
  141. tense: '紧绷'
  142. }
  143. }
  144. },
  145. computed: {
  146. overallLevel: function() {
  147. var total = this.result ? (this.result.totalScore || 0) : 0
  148. if (total >= 35) return 'healthy'
  149. if (total >= 20) return 'attention'
  150. return 'tense'
  151. },
  152. overallLevelName: function() {
  153. return this.levelMap[this.overallLevel] || '留意'
  154. }
  155. },
  156. onLoad: function(options) {
  157. this.selfCheckId = options && options.id ? options.id : ''
  158. this.loadResult()
  159. },
  160. methods: {
  161. loadResult: function() {
  162. var self = this
  163. // 优先使用刚提交时缓存的结果,避免多一次请求
  164. var cached = uni.getStorageSync('lastSelfCheckResult')
  165. if (cached && cached.id) {
  166. this.result = cached
  167. this.loading = false
  168. this.drawRadar()
  169. return
  170. }
  171. getSelfCheckLatest().then(function(res) {
  172. self.loading = false
  173. if (res.code === 200 && res.data) {
  174. self.result = res.data
  175. self.drawRadar()
  176. } else {
  177. uni.showToast({ title: (res && res.message) || '暂无自检记录', icon: 'none' })
  178. }
  179. }).catch(function() {
  180. self.loading = false
  181. uni.showToast({ title: '加载失败', icon: 'none' })
  182. })
  183. },
  184. onCanvasReady: function(res) {
  185. if (!res || !res[0] || !res[0].node) {
  186. return
  187. }
  188. var ctx = res[0].node.getContext('2d')
  189. var dpr = uni.getWindowInfo().pixelRatio
  190. this.canvasContext = ctx
  191. this.canvasContext.scale(dpr, dpr)
  192. this.drawRadar()
  193. },
  194. drawRadar: function() {
  195. if (!this.canvasContext || !this.result) {
  196. return
  197. }
  198. var ctx = this.canvasContext
  199. var w = this.canvasWidth
  200. var h = this.canvasHeight
  201. var cx = w / 2
  202. var cy = h / 2
  203. var r = w * 0.34
  204. var angleStep = (Math.PI * 2) / 5
  205. // 清空画布
  206. ctx.clearRect(0, 0, w, h)
  207. ctx.fillStyle = '#FFF8F0'
  208. ctx.fillRect(0, 0, w, h)
  209. // 维度分数映射
  210. var scores = {}
  211. var dims = this.result.dimensions || []
  212. for (var i = 0; i < dims.length; i++) {
  213. scores[dims[i].dimension] = dims[i].score || 0
  214. }
  215. // 背景五边形(三层网格)
  216. for (var layer = 1; layer <= 3; layer++) {
  217. ctx.beginPath()
  218. for (var g = 0; g < 5; g++) {
  219. var gAngle = g * angleStep - Math.PI / 2
  220. var gx = cx + r * (layer / 3) * Math.cos(gAngle)
  221. var gy = cy + r * (layer / 3) * Math.sin(gAngle)
  222. if (g === 0) {
  223. ctx.moveTo(gx, gy)
  224. } else {
  225. ctx.lineTo(gx, gy)
  226. }
  227. }
  228. ctx.closePath()
  229. ctx.strokeStyle = 'rgba(249, 114, 22, 0.15)'
  230. ctx.lineWidth = 1
  231. ctx.stroke()
  232. }
  233. // 轴线 + 标签
  234. for (var j = 0; j < 5; j++) {
  235. var a2 = j * angleStep - Math.PI / 2
  236. var lx = cx + r * Math.cos(a2)
  237. var ly = cy + r * Math.sin(a2)
  238. ctx.beginPath()
  239. ctx.moveTo(cx, cy)
  240. ctx.lineTo(lx, ly)
  241. ctx.strokeStyle = this.elementColors[j] + '44'
  242. ctx.lineWidth = 1
  243. ctx.stroke()
  244. var labelX = cx + (r + 18) * Math.cos(a2)
  245. var labelY = cy + (r + 18) * Math.sin(a2)
  246. ctx.fillStyle = this.elementColors[j]
  247. ctx.font = 'bold 13px sans-serif'
  248. ctx.textAlign = 'center'
  249. ctx.textBaseline = 'middle'
  250. ctx.fillText(this.axes[j], labelX, labelY)
  251. }
  252. // 数据驱动多边形
  253. ctx.beginPath()
  254. for (var m = 0; m < 5; m++) {
  255. var ang = m * angleStep - Math.PI / 2
  256. var key = this.elementKeys[m]
  257. var ratio = (scores[key] || 0) / 9
  258. var dataR = r * ratio
  259. var dx = cx + dataR * Math.cos(ang)
  260. var dy = cy + dataR * Math.sin(ang)
  261. if (m === 0) {
  262. ctx.moveTo(dx, dy)
  263. } else {
  264. ctx.lineTo(dx, dy)
  265. }
  266. }
  267. ctx.closePath()
  268. ctx.fillStyle = 'rgba(249, 114, 22, 0.2)'
  269. ctx.fill()
  270. ctx.strokeStyle = '#F97316'
  271. ctx.lineWidth = 2
  272. ctx.stroke()
  273. // 数据节点圆点 + 分数标签
  274. for (var n = 0; n < 5; n++) {
  275. var ang2 = n * angleStep - Math.PI / 2
  276. var key2 = this.elementKeys[n]
  277. var ratio2 = (scores[key2] || 0) / 9
  278. var dataR2 = r * ratio2
  279. var px = cx + dataR2 * Math.cos(ang2)
  280. var py = cy + dataR2 * Math.sin(ang2)
  281. ctx.beginPath()
  282. ctx.arc(px, py, 4, 0, Math.PI * 2)
  283. ctx.fillStyle = this.elementColors[n]
  284. ctx.fill()
  285. var pctLabelR = dataR2 + (ratio2 > 0.35 ? -16 : 18)
  286. var pLabelX = cx + pctLabelR * Math.cos(ang2)
  287. var pLabelY = cy + pctLabelR * Math.sin(ang2)
  288. ctx.fillStyle = this.elementColors[n]
  289. ctx.font = 'bold 11px sans-serif'
  290. ctx.textAlign = 'center'
  291. ctx.textBaseline = 'middle'
  292. ctx.fillText(String(scores[key2] || 0), pLabelX, pLabelY)
  293. }
  294. },
  295. formatDate: function(dateStr) {
  296. if (!dateStr) {
  297. return ''
  298. }
  299. var d = parseDate(dateStr)
  300. if (!d) return ''
  301. var pad = function(n) { return n < 10 ? '0' + n : '' + n }
  302. return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) + ' ' + pad(d.getHours()) + ':' + pad(d.getMinutes())
  303. },
  304. goHistory: function() {
  305. getSelfCheckHistory().then(function(res) {
  306. if (res.code === 200 && res.data && res.data.length > 0) {
  307. uni.showToast({ title: '已生成 ' + res.data.length + ' 条记录', icon: 'none' })
  308. } else {
  309. uni.showToast({ title: '暂无历史记录', icon: 'none' })
  310. }
  311. }).catch(function() {
  312. uni.showToast({ title: '暂无历史记录', icon: 'none' })
  313. })
  314. },
  315. retake: function() {
  316. uni.redirectTo({ url: '/pages/family/self-check' })
  317. }
  318. }
  319. }
  320. </script>
  321. <style scoped>
  322. .scr-page {
  323. min-height: 100vh;
  324. background: #F5FAFE;
  325. padding: 24rpx 30rpx 120rpx;
  326. box-sizing: border-box;
  327. }
  328. .scr-loading {
  329. display: flex;
  330. justify-content: center;
  331. align-items: center;
  332. height: 60vh;
  333. }
  334. .scr-loading-text {
  335. font-size: 28rpx;
  336. color: #999;
  337. }
  338. /* 总分横幅 */
  339. .scr-hero {
  340. background: linear-gradient(135deg, #F97316, #FF8C42);
  341. border-radius: 24rpx;
  342. padding: 40rpx 30rpx;
  343. margin-bottom: 24rpx;
  344. box-shadow: 0 6rpx 20rpx rgba(249, 114, 22, 0.25);
  345. }
  346. .scr-hero-badge {
  347. display: flex;
  348. flex-direction: column;
  349. align-items: center;
  350. }
  351. .scr-hero-title {
  352. font-size: 26rpx;
  353. color: rgba(255, 255, 255, 0.9);
  354. }
  355. .scr-hero-score-row {
  356. display: flex;
  357. align-items: baseline;
  358. margin-top: 10rpx;
  359. }
  360. .scr-hero-score {
  361. font-size: 88rpx;
  362. font-weight: 700;
  363. color: #fff;
  364. }
  365. .scr-hero-total {
  366. font-size: 30rpx;
  367. color: rgba(255, 255, 255, 0.7);
  368. margin-left: 6rpx;
  369. }
  370. .scr-hero-level {
  371. margin-top: 14rpx;
  372. padding: 8rpx 28rpx;
  373. border-radius: 24rpx;
  374. font-size: 26rpx;
  375. font-weight: 600;
  376. background: rgba(255, 255, 255, 0.92);
  377. }
  378. .scr-hero-level.level-healthy { color: #2E7D32; }
  379. .scr-hero-level.level-attention { color: #E65100; }
  380. .scr-hero-level.level-tense { color: #C62828; }
  381. .scr-hero-date {
  382. display: block;
  383. text-align: center;
  384. font-size: 22rpx;
  385. color: rgba(255, 255, 255, 0.8);
  386. margin-top: 16rpx;
  387. }
  388. /* 通用卡片 */
  389. .scr-card {
  390. background: #fff;
  391. border-radius: 24rpx;
  392. padding: 30rpx 26rpx;
  393. margin-bottom: 24rpx;
  394. box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
  395. }
  396. .scr-card-title {
  397. display: flex;
  398. align-items: baseline;
  399. justify-content: space-between;
  400. margin-bottom: 24rpx;
  401. }
  402. .scr-card-title-text {
  403. font-size: 32rpx;
  404. font-weight: 600;
  405. color: #333;
  406. }
  407. .scr-card-sub {
  408. font-size: 22rpx;
  409. color: #999;
  410. }
  411. /* 雷达图 */
  412. .scr-canvas-wrap {
  413. display: flex;
  414. justify-content: center;
  415. }
  416. .scr-canvas {
  417. width: 340px;
  418. height: 340px;
  419. }
  420. /* 维度得分 */
  421. .scr-dim-list {
  422. display: flex;
  423. flex-direction: column;
  424. }
  425. .scr-dim-item {
  426. margin-bottom: 28rpx;
  427. }
  428. .scr-dim-item:last-child {
  429. margin-bottom: 0;
  430. }
  431. .scr-dim-head {
  432. display: flex;
  433. align-items: center;
  434. justify-content: space-between;
  435. }
  436. .scr-dim-label {
  437. display: flex;
  438. align-items: center;
  439. }
  440. .scr-dim-dot {
  441. width: 28rpx;
  442. height: 28rpx;
  443. border-radius: 50%;
  444. margin-right: 12rpx;
  445. }
  446. .scr-dim-name {
  447. font-size: 30rpx;
  448. font-weight: 600;
  449. color: #333;
  450. }
  451. .scr-dim-element {
  452. font-size: 22rpx;
  453. color: #999;
  454. margin-left: 10rpx;
  455. }
  456. .scr-dim-score-wrap {
  457. display: flex;
  458. align-items: baseline;
  459. }
  460. .scr-dim-score {
  461. font-size: 40rpx;
  462. font-weight: 700;
  463. }
  464. .scr-dim-score-max {
  465. font-size: 22rpx;
  466. color: #BBB;
  467. }
  468. .scr-dim-bar {
  469. height: 12rpx;
  470. background: #F0F0F0;
  471. border-radius: 6rpx;
  472. margin-top: 14rpx;
  473. overflow: hidden;
  474. }
  475. .scr-dim-bar-fill {
  476. height: 100%;
  477. border-radius: 6rpx;
  478. transition: width 0.5s ease;
  479. }
  480. .scr-dim-foot {
  481. display: flex;
  482. align-items: center;
  483. margin-top: 12rpx;
  484. }
  485. .scr-dim-level {
  486. font-size: 22rpx;
  487. padding: 4rpx 16rpx;
  488. border-radius: 16rpx;
  489. margin-right: 14rpx;
  490. flex-shrink: 0;
  491. }
  492. .scr-dim-level.lvl-healthy { background: #E8F5E9; color: #2E7D32; }
  493. .scr-dim-level.lvl-attention { background: #FFF8E1; color: #F57F17; }
  494. .scr-dim-level.lvl-tense { background: #FFEBEE; color: #C62828; }
  495. .scr-dim-summary {
  496. flex: 1;
  497. font-size: 24rpx;
  498. color: #888;
  499. line-height: 1.4;
  500. }
  501. /* 寻源建议 */
  502. .scr-advice-intro {
  503. font-size: 24rpx;
  504. color: #666;
  505. line-height: 1.6;
  506. background: #FFF7ED;
  507. border-radius: 12rpx;
  508. padding: 16rpx 20rpx;
  509. margin-bottom: 24rpx;
  510. }
  511. .scr-advice-item {
  512. border: 2rpx solid #F0E6DC;
  513. border-radius: 16rpx;
  514. padding: 24rpx;
  515. margin-bottom: 20rpx;
  516. }
  517. .scr-advice-item:last-child {
  518. margin-bottom: 0;
  519. }
  520. .scr-advice-dim-row {
  521. display: flex;
  522. align-items: center;
  523. justify-content: space-between;
  524. margin-bottom: 18rpx;
  525. }
  526. .scr-advice-dim-badge {
  527. display: flex;
  528. align-items: center;
  529. padding: 8rpx 20rpx;
  530. border-radius: 20rpx;
  531. }
  532. .scr-advice-dim-name {
  533. font-size: 28rpx;
  534. font-weight: 700;
  535. color: #fff;
  536. margin-right: 8rpx;
  537. }
  538. .scr-advice-dim-elem {
  539. font-size: 22rpx;
  540. color: rgba(255, 255, 255, 0.9);
  541. }
  542. .scr-advice-dim-score {
  543. font-size: 26rpx;
  544. font-weight: 600;
  545. color: #C62828;
  546. }
  547. .scr-advice-flow {
  548. display: flex;
  549. align-items: flex-start;
  550. margin-bottom: 12rpx;
  551. }
  552. .scr-flow-node {
  553. display: flex;
  554. align-items: center;
  555. flex-shrink: 0;
  556. width: 200rpx;
  557. }
  558. .scr-flow-dot {
  559. width: 20rpx;
  560. height: 20rpx;
  561. border-radius: 50%;
  562. margin-right: 8rpx;
  563. flex-shrink: 0;
  564. }
  565. .scr-flow-label {
  566. font-size: 24rpx;
  567. font-weight: 600;
  568. color: #333;
  569. }
  570. .scr-flow-arrow {
  571. flex-shrink: 0;
  572. font-size: 24rpx;
  573. color: #F97316;
  574. margin: 0 10rpx;
  575. }
  576. .scr-flow-action {
  577. flex: 1;
  578. font-size: 24rpx;
  579. color: #666;
  580. line-height: 1.5;
  581. }
  582. .scr-advice-action {
  583. display: flex;
  584. align-items: flex-start;
  585. background: #F5FAFE;
  586. border-radius: 12rpx;
  587. padding: 16rpx 20rpx;
  588. margin-top: 10rpx;
  589. }
  590. .scr-advice-action-label {
  591. flex-shrink: 0;
  592. font-size: 22rpx;
  593. font-weight: 600;
  594. color: #F97316;
  595. margin-right: 12rpx;
  596. padding: 2rpx 0;
  597. }
  598. .scr-advice-action-text {
  599. flex: 1;
  600. font-size: 24rpx;
  601. color: #333;
  602. line-height: 1.5;
  603. }
  604. /* 全部健康 */
  605. .scr-all-healthy {
  606. display: flex;
  607. flex-direction: column;
  608. align-items: center;
  609. padding: 30rpx 0;
  610. }
  611. .scr-all-healthy-icon {
  612. font-size: 72rpx;
  613. margin-bottom: 16rpx;
  614. }
  615. .scr-all-healthy-text {
  616. font-size: 28rpx;
  617. color: #666;
  618. }
  619. /* 底部按钮 */
  620. .scr-footer {
  621. display: flex;
  622. gap: 20rpx;
  623. margin-top: 20rpx;
  624. }
  625. .scr-btn {
  626. flex: 1;
  627. height: 88rpx;
  628. line-height: 88rpx;
  629. font-size: 30rpx;
  630. border-radius: 44rpx;
  631. text-align: center;
  632. border: none;
  633. }
  634. .scr-btn-primary {
  635. background: linear-gradient(135deg, #F97316, #FF8C42);
  636. color: #fff;
  637. font-weight: 600;
  638. }
  639. .scr-btn-outline {
  640. background: #fff;
  641. color: #F97316;
  642. border: 2rpx solid #F97316;
  643. }
  644. </style>