Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 

245 righe
5.7 KiB

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