Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 

209 rindas
4.9 KiB

  1. <template>
  2. <view class="page">
  3. <!-- 顶部横幅 -->
  4. <image class="banner" src="https://cdn.csybhelp.com/images/cytx/index-bg.png" mode="widthFix" />
  5. <!-- 正文内容区域 -->
  6. <view class="content-area">
  7. <view v-if="content" class="letter">
  8. <view class="body">
  9. <mp-html :content="content" />
  10. </view>
  11. </view>
  12. <view v-else-if="!loaded" class="loading-text">加载中...</view>
  13. <button class="join-btn" :class="btnClass" @tap="handleJoin">{{ btnText }}</button>
  14. </view>
  15. </view>
  16. </template>
  17. <script setup>
  18. import { ref, computed } from 'vue'
  19. import { onShow } from '@dcloudio/uni-app'
  20. import { get } from '@/utils/request.js'
  21. import { getToken, getUserInfo, setUserInfo } from '@/utils/cache.js'
  22. import mpHtml from '@/uni_modules/mp-html/components/mp-html/mp-html.vue'
  23. const CONTENT_CACHE_KEY = 'cytx-index-content'
  24. const content = ref('')
  25. const loaded = ref(false)
  26. const userInfo = ref(null)
  27. const isLoggedIn = ref(false)
  28. // 患者状态
  29. const patient = computed(() => (userInfo.value && userInfo.value.patient) || null)
  30. const isAuthed = computed(() => patient.value && patient.value.auth_status === 1)
  31. const patientStatus = computed(() => {
  32. if (!patient.value || patient.value.status === undefined || patient.value.status === null) return null
  33. return patient.value.status
  34. })
  35. // 按钮文案和样式
  36. const btnText = computed(() => {
  37. if (!isLoggedIn.value) return '加入项目'
  38. if (!isAuthed.value) return '加入项目'
  39. if (patientStatus.value === null || patientStatus.value === undefined) return '加入项目'
  40. if (patientStatus.value === -1) return '加入项目'
  41. if (patientStatus.value === 1) return '已加入'
  42. if (patientStatus.value === 0) return '已申请,审核中'
  43. if (patientStatus.value === 2) return '已拒绝,重新申请'
  44. return '加入项目'
  45. })
  46. const btnClass = computed(() => {
  47. if (!isLoggedIn.value || !isAuthed.value) return ''
  48. if (patientStatus.value === 1) return 'joined'
  49. if (patientStatus.value === 0) return 'pending'
  50. if (patientStatus.value === 2) return 'rejected'
  51. return ''
  52. })
  53. const loadContent = async () => {
  54. // 先读缓存
  55. try {
  56. const cached = uni.getStorageSync(CONTENT_CACHE_KEY)
  57. if (cached) content.value = cached
  58. } catch (e) {}
  59. // 再请求最新
  60. try {
  61. const res = await get('/api/content', { key: 'index_content' })
  62. if (res.data && res.data.content) {
  63. content.value = res.data.content
  64. uni.setStorageSync(CONTENT_CACHE_KEY, res.data.content)
  65. }
  66. } catch (e) {
  67. console.error('获取首页内容失败', e)
  68. } finally {
  69. loaded.value = true
  70. }
  71. }
  72. const refreshUserState = async () => {
  73. isLoggedIn.value = !!getToken()
  74. userInfo.value = getUserInfo()
  75. if (isLoggedIn.value) {
  76. try {
  77. const res = await get('/api/mp/userinfo')
  78. userInfo.value = res.data
  79. setUserInfo(res.data)
  80. } catch (e) {}
  81. }
  82. }
  83. const handleJoin = () => {
  84. // 未登录 -> 去登录
  85. if (!isLoggedIn.value) {
  86. uni.navigateTo({ url: '/pages/login/index' })
  87. return
  88. }
  89. // 未实名 -> 提示去认证
  90. if (!isAuthed.value) {
  91. uni.showModal({
  92. title: '提示',
  93. content: '请先完成实名认证',
  94. confirmText: '去认证',
  95. success: (res) => {
  96. if (res.confirm) uni.navigateTo({ url: '/pages/verify/verify' })
  97. }
  98. })
  99. return
  100. }
  101. // 审核通过 -> 跳转到个人中心
  102. if (patientStatus.value === 1) {
  103. uni.switchTab({ url: '/pages/profile/profile' })
  104. return
  105. }
  106. // 待审核 -> 跳转到个人中心
  107. if (patientStatus.value === 0) {
  108. uni.switchTab({ url: '/pages/profile/profile' })
  109. return
  110. }
  111. // 已拒绝 -> 跳转资料页重新提交
  112. if (patientStatus.value === 2) {
  113. uni.navigateTo({ url: '/pages/myinfo/myinfo' })
  114. return
  115. }
  116. // 已实名但未提交资料(status=-1)-> 去提交资料
  117. uni.navigateTo({ url: '/pages/myinfo/myinfo' })
  118. }
  119. onShow(() => {
  120. if (!loaded.value) loadContent()
  121. refreshUserState()
  122. })
  123. </script>
  124. <style lang="scss" scoped>
  125. .page {
  126. min-height: 100vh;
  127. background: #f0f0f0;
  128. padding-bottom: 20rpx;
  129. }
  130. .banner {
  131. width: 100%;
  132. display: block;
  133. }
  134. .content-area {
  135. background: #fff;
  136. border-radius: 24rpx;
  137. margin: -40% 24rpx 0;
  138. position: relative;
  139. z-index: 1;
  140. padding: 56rpx 40rpx 32rpx;
  141. }
  142. .letter {
  143. .body {
  144. font-size: 28rpx;
  145. color: #606266;
  146. line-height: 2;
  147. text-align: justify;
  148. }
  149. }
  150. .loading-text {
  151. text-align: center;
  152. color: #909399;
  153. padding: 40rpx 0;
  154. }
  155. .join-btn {
  156. display: block;
  157. width: 100%;
  158. margin: 56rpx 0 0;
  159. height: 88rpx;
  160. line-height: 88rpx;
  161. background: linear-gradient(135deg, #1890ff, #096dd9);
  162. color: #fff;
  163. border: none;
  164. border-radius: 44rpx;
  165. font-size: 32rpx;
  166. font-weight: 500;
  167. letter-spacing: 4rpx;
  168. padding: 0;
  169. &::after {
  170. border: none;
  171. }
  172. &.joined {
  173. background: linear-gradient(135deg, #52c41a, #389e0d);
  174. color: #fff;
  175. letter-spacing: 2rpx;
  176. }
  177. &.pending {
  178. background: linear-gradient(135deg, #faad14, #d48806);
  179. letter-spacing: 2rpx;
  180. }
  181. &.rejected {
  182. background: linear-gradient(135deg, #ff4d4f, #cf1322);
  183. letter-spacing: 2rpx;
  184. }
  185. }
  186. </style>