|
- <template>
- <view class="page">
- <!-- 顶部横幅 -->
- <image class="banner" src="/static/img/index-bg.png" mode="widthFix" />
-
- <!-- 正文内容区域 -->
- <view class="content-area">
- <view v-if="content" class="letter">
- <view class="body">
- <mp-html :content="content" />
- </view>
- </view>
- <view v-else-if="!loaded" class="loading-text">加载中...</view>
-
- <button class="join-btn" :class="btnClass" @tap="handleJoin">{{ btnText }}</button>
- </view>
- </view>
- </template>
-
- <script setup>
- import { ref, computed } from 'vue'
- import { onShow } from '@dcloudio/uni-app'
- import { get } from '@/utils/request.js'
- import { getToken, getUserInfo, setUserInfo } from '@/utils/cache.js'
- import mpHtml from '@/uni_modules/mp-html/components/mp-html/mp-html.vue'
-
- const CONTENT_CACHE_KEY = 'cytx-index-content'
-
- const content = ref('')
- const loaded = ref(false)
- const userInfo = ref(null)
- const isLoggedIn = ref(false)
-
- // 患者状态
- const patient = computed(() => userInfo.value?.patient || null)
- const isAuthed = computed(() => patient.value?.auth_status === 1)
- const patientStatus = computed(() => patient.value?.status ?? null)
-
- // 按钮文案和样式
- const btnText = computed(() => {
- if (!isLoggedIn.value) return '加入项目'
- if (!isAuthed.value) return '加入项目'
- if (patientStatus.value === null || patientStatus.value === undefined) return '加入项目'
- if (patientStatus.value === -1) return '加入项目'
- if (patientStatus.value === 1) return '已加入'
- if (patientStatus.value === 0) return '已申请,审核中'
- if (patientStatus.value === 2) return '已拒绝,重新申请'
- return '加入项目'
- })
-
- const btnClass = computed(() => {
- if (!isLoggedIn.value || !isAuthed.value) return ''
- if (patientStatus.value === 1) return 'joined'
- if (patientStatus.value === 0) return 'pending'
- if (patientStatus.value === 2) return 'rejected'
- return ''
- })
-
- const loadContent = async () => {
- // 先读缓存
- try {
- const cached = uni.getStorageSync(CONTENT_CACHE_KEY)
- if (cached) content.value = cached
- } catch (e) {}
- // 再请求最新
- try {
- const res = await get('/api/content', { key: 'index_content' })
- if (res.data && res.data.content) {
- content.value = res.data.content
- uni.setStorageSync(CONTENT_CACHE_KEY, res.data.content)
- }
- } catch (e) {
- console.error('获取首页内容失败', e)
- } finally {
- loaded.value = true
- }
- }
-
- const refreshUserState = async () => {
- isLoggedIn.value = !!getToken()
- userInfo.value = getUserInfo()
- if (isLoggedIn.value) {
- try {
- const res = await get('/api/mp/userinfo')
- userInfo.value = res.data
- setUserInfo(res.data)
- } catch (e) {}
- }
- }
-
- const handleJoin = () => {
- // 未登录 -> 去登录
- if (!isLoggedIn.value) {
- uni.navigateTo({ url: '/pages/login/index' })
- return
- }
- // 未实名 -> 提示去认证
- if (!isAuthed.value) {
- uni.showModal({
- title: '提示',
- content: '请先完成实名认证',
- confirmText: '去认证',
- success: (res) => {
- if (res.confirm) uni.navigateTo({ url: '/pages/verify/verify' })
- }
- })
- return
- }
- // 审核通过 -> 不可点击
- if (patientStatus.value === 1) return
- // 待审核 -> 不可点击
- if (patientStatus.value === 0) return
- // 已拒绝 -> 跳转资料页重新提交
- if (patientStatus.value === 2) {
- uni.navigateTo({ url: '/pages/myinfo/myinfo' })
- return
- }
- // 已实名但未提交资料(status=-1)-> 去提交资料
- uni.navigateTo({ url: '/pages/myinfo/myinfo' })
- }
-
- onShow(() => {
- if (!loaded.value) loadContent()
- refreshUserState()
- })
- </script>
-
- <style lang="scss" scoped>
- .page {
- min-height: 100vh;
- background: #f0f0f0;
- padding-bottom: 20rpx;
- }
-
- .banner {
- width: 100%;
- display: block;
- }
-
- .content-area {
- background: #fff;
- border-radius: 24rpx;
- margin: -30% 24rpx 0;
- position: relative;
- z-index: 1;
- padding: 56rpx 40rpx 32rpx;
- }
-
- .letter {
- .body {
- font-size: 28rpx;
- color: #606266;
- line-height: 2;
- text-align: justify;
- }
- }
-
- .loading-text {
- text-align: center;
- color: #909399;
- padding: 40rpx 0;
- }
-
- .join-btn {
- display: block;
- width: 100%;
- margin: 56rpx 0 0;
- height: 88rpx;
- line-height: 88rpx;
- background: linear-gradient(135deg, #1890ff, #096dd9);
- color: #fff;
- border: none;
- border-radius: 44rpx;
- font-size: 32rpx;
- font-weight: 500;
- letter-spacing: 4rpx;
- padding: 0;
-
- &::after {
- border: none;
- }
-
- &.joined {
- background: #d9d9d9;
- color: #999;
- letter-spacing: 2rpx;
- }
-
- &.pending {
- background: linear-gradient(135deg, #faad14, #d48806);
- letter-spacing: 2rpx;
- }
-
- &.rejected {
- background: linear-gradient(135deg, #ff4d4f, #cf1322);
- letter-spacing: 2rpx;
- }
- }
- </style>
|