7 changed files with 2176 additions and 1614 deletions
@ -0,0 +1,389 @@ |
|||
<template> |
|||
<view class="daily-page"> |
|||
<view class="top-safe" :style="{ height: menuButtonInfo.top + 'px' }"></view> |
|||
<view class="nav"> |
|||
<view class="back" @tap="back">‹</view> |
|||
<view class="title">每日同频一题</view> |
|||
<view class="ghost"></view> |
|||
</view> |
|||
|
|||
<view class="question-card" v-if="question.exists"> |
|||
<view class="q-deco">✦ 今日全校同题 ✦</view> |
|||
<view class="q-text">{{ question.content }}</view> |
|||
<view class="q-count">已有 {{ question.answerCount }} 人回答</view> |
|||
</view> |
|||
<view class="question-card" v-else> |
|||
<view class="q-text">{{ loading ? '正在取今天的题目...' : '今天还没有题目,明天再来吧' }}</view> |
|||
</view> |
|||
|
|||
<view class="answer-box" v-if="question.exists && !question.answered"> |
|||
<textarea class="answer-input" v-model="draft" maxlength="200" |
|||
placeholder="写下你的回答,答完就能看到大家的答案(200字以内)"></textarea> |
|||
<view class="answer-submit" :class="{ disabled: !draft.trim() || submitting }" @tap="submit"> |
|||
提交回答,解锁大家的答案 ✨ |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="my-answer" v-if="question.exists && question.answered"> |
|||
<view class="my-answer-label">我的回答</view> |
|||
<view class="my-answer-text">{{ question.myAnswer }}</view> |
|||
</view> |
|||
|
|||
<view class="feed" v-if="question.answered"> |
|||
<view class="feed-title">大家的回答</view> |
|||
<view class="answer-card" v-for="item in answers" :key="item.id"> |
|||
<view class="card-head"> |
|||
<image class="card-avatar-img" v-if="item.avatarUrl" :src="item.avatarUrl" mode="aspectFill"></image> |
|||
<view class="card-avatar" v-else>{{ item.avatarText || '◌' }}</view> |
|||
<view class="card-user"> |
|||
<view class="card-name"> |
|||
{{ item.anonymousName || '半匿名漂流者' }} |
|||
<text class="school-badge" v-if="item.sameSchool">同校</text> |
|||
<text class="mine-badge" v-if="item.mine">我</text> |
|||
</view> |
|||
<view class="card-mode">{{ item.currentMode === 'e' ? 'e 人 · 轻轻热闹' : 'i 人 · 安静陪伴' }}</view> |
|||
</view> |
|||
<view class="card-chat" v-if="!item.mine" @tap="chatWith(item)">和TA聊聊</view> |
|||
</view> |
|||
<view class="card-content">{{ item.content }}</view> |
|||
</view> |
|||
<view class="feed-status">{{ loadingAnswers ? '正在加载...' : (hasMore ? '上滑加载更多' : (answers.length ? '今天先到这里' : '还没有人回答,抢个沙发')) }}</view> |
|||
</view> |
|||
<view class="locked-tip" v-else-if="question.exists"> |
|||
<view class="locked-icon">🔒</view> |
|||
<view class="locked-text">回答之后才能看到大家的答案</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { getIeDailyQuestion, answerIeDailyQuestion, pageIeDailyAnswers, matchIeByAnswer } from '@/common/ieApi.js' |
|||
|
|||
export default { |
|||
data() { |
|||
return { |
|||
menuButtonInfo: { top: 44 }, |
|||
loading: true, |
|||
question: { exists: false }, |
|||
draft: '', |
|||
submitting: false, |
|||
answers: [], |
|||
pageNumber: 1, |
|||
hasMore: true, |
|||
loadingAnswers: false, |
|||
matchingAnswerId: null |
|||
} |
|||
}, |
|||
onLoad() { |
|||
if (uni.getMenuButtonBoundingClientRect) { |
|||
this.menuButtonInfo = uni.getMenuButtonBoundingClientRect() |
|||
} |
|||
this.loadQuestion() |
|||
}, |
|||
onReachBottom() { |
|||
if (this.question.answered && this.hasMore && !this.loadingAnswers) { |
|||
this.loadAnswers() |
|||
} |
|||
}, |
|||
methods: { |
|||
back() { |
|||
uni.navigateBack({ fail: () => uni.redirectTo({ url: '/package1/ieBrowser/index' }) }) |
|||
}, |
|||
async loadQuestion() { |
|||
this.loading = true |
|||
const res = await getIeDailyQuestion().catch(() => null) |
|||
this.loading = false |
|||
if (!res) return |
|||
this.question = res |
|||
if (res.answered) { |
|||
this.pageNumber = 1 |
|||
this.answers = [] |
|||
this.hasMore = true |
|||
this.loadAnswers() |
|||
} |
|||
}, |
|||
async submit() { |
|||
const content = this.draft.trim() |
|||
if (!content || this.submitting) return |
|||
this.submitting = true |
|||
try { |
|||
const res = await answerIeDailyQuestion(content) |
|||
if (!res) return |
|||
this.draft = '' |
|||
uni.showToast({ title: '已提交,去看看大家的回答', icon: 'none' }) |
|||
this.loadQuestion() |
|||
} finally { |
|||
this.submitting = false |
|||
} |
|||
}, |
|||
async loadAnswers() { |
|||
if (this.loadingAnswers) return |
|||
this.loadingAnswers = true |
|||
try { |
|||
const res = await pageIeDailyAnswers(this.pageNumber, 10) |
|||
if (!res) return |
|||
const records = res.records || [] |
|||
this.answers = this.pageNumber === 1 ? records : this.answers.concat(records) |
|||
this.hasMore = this.answers.length < (res.total || 0) |
|||
this.pageNumber += 1 |
|||
} finally { |
|||
this.loadingAnswers = false |
|||
} |
|||
}, |
|||
async chatWith(item) { |
|||
if (this.matchingAnswerId) return |
|||
this.matchingAnswerId = item.id |
|||
try { |
|||
const match = await matchIeByAnswer(item.id) |
|||
if (!match || !match.roomId) return |
|||
uni.navigateTo({ |
|||
url: '/package1/ieBrowser/chat?mode=' + (match.mode || 'i') + |
|||
'&roomId=' + match.roomId + |
|||
'&targetUserId=' + match.targetUserId + |
|||
'&name=' + encodeURIComponent(match.anonymousName || item.anonymousName || '') + |
|||
'&avatar=' + encodeURIComponent(match.avatarText || item.avatarText || '') + |
|||
'&avatarUrl=' + encodeURIComponent(match.avatarUrl || item.avatarUrl || '') + |
|||
'"e=' + encodeURIComponent(match.quoteText || '') |
|||
}) |
|||
} finally { |
|||
this.matchingAnswerId = null |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.daily-page { |
|||
min-height: 100vh; |
|||
padding: 0 32rpx 60rpx; |
|||
box-sizing: border-box; |
|||
color: #161b2e; |
|||
background: radial-gradient(circle at 18% 10%, rgba(167, 139, 250, .26), transparent 320rpx), |
|||
radial-gradient(circle at 86% 24%, rgba(255, 184, 209, .26), transparent 320rpx), |
|||
linear-gradient(180deg, #fbfdff, #eef4ff 62%, #fff4e8); |
|||
} |
|||
|
|||
.nav { |
|||
display: flex; |
|||
align-items: center; |
|||
height: 88rpx; |
|||
} |
|||
|
|||
.back { |
|||
width: 62rpx; |
|||
font-size: 52rpx; |
|||
color: rgba(22, 27, 46, .62); |
|||
} |
|||
|
|||
.title { |
|||
flex: 1; |
|||
text-align: center; |
|||
font-size: 31rpx; |
|||
font-weight: 800; |
|||
} |
|||
|
|||
.ghost { |
|||
width: 62rpx; |
|||
} |
|||
|
|||
.question-card { |
|||
margin-top: 18rpx; |
|||
padding: 36rpx 30rpx; |
|||
border-radius: 34rpx; |
|||
background: rgba(255, 255, 255, .8); |
|||
border: 1rpx solid rgba(255, 255, 255, .9); |
|||
box-shadow: 0 18rpx 44rpx rgba(96, 112, 160, .14); |
|||
text-align: center; |
|||
} |
|||
|
|||
.q-deco { |
|||
font-size: 22rpx; |
|||
font-weight: 800; |
|||
color: #7a4dff; |
|||
letter-spacing: 4rpx; |
|||
} |
|||
|
|||
.q-text { |
|||
margin-top: 16rpx; |
|||
font-size: 36rpx; |
|||
font-weight: 800; |
|||
line-height: 1.5; |
|||
} |
|||
|
|||
.q-count { |
|||
margin-top: 14rpx; |
|||
font-size: 23rpx; |
|||
color: rgba(22, 27, 46, .5); |
|||
} |
|||
|
|||
.answer-box { |
|||
margin-top: 24rpx; |
|||
} |
|||
|
|||
.answer-input { |
|||
width: 100%; |
|||
height: 220rpx; |
|||
padding: 24rpx; |
|||
box-sizing: border-box; |
|||
border-radius: 28rpx; |
|||
background: rgba(255, 255, 255, .85); |
|||
border: 1rpx solid rgba(255, 255, 255, .9); |
|||
font-size: 26rpx; |
|||
} |
|||
|
|||
.answer-submit { |
|||
margin-top: 20rpx; |
|||
height: 92rpx; |
|||
line-height: 92rpx; |
|||
text-align: center; |
|||
border-radius: 999rpx; |
|||
font-size: 28rpx; |
|||
font-weight: 800; |
|||
color: #fff; |
|||
background: linear-gradient(135deg, #7a4dff, #ff7eb3); |
|||
box-shadow: 0 16rpx 36rpx rgba(122, 77, 255, .3); |
|||
} |
|||
|
|||
.answer-submit.disabled { |
|||
opacity: .5; |
|||
box-shadow: none; |
|||
} |
|||
|
|||
.my-answer { |
|||
margin-top: 24rpx; |
|||
padding: 24rpx 26rpx; |
|||
border-radius: 26rpx; |
|||
background: rgba(122, 77, 255, .08); |
|||
border: 1rpx solid rgba(122, 77, 255, .16); |
|||
} |
|||
|
|||
.my-answer-label { |
|||
font-size: 22rpx; |
|||
font-weight: 800; |
|||
color: #7a4dff; |
|||
} |
|||
|
|||
.my-answer-text { |
|||
margin-top: 8rpx; |
|||
font-size: 26rpx; |
|||
line-height: 1.5; |
|||
} |
|||
|
|||
.feed { |
|||
margin-top: 28rpx; |
|||
} |
|||
|
|||
.feed-title { |
|||
font-size: 28rpx; |
|||
font-weight: 800; |
|||
margin-bottom: 16rpx; |
|||
} |
|||
|
|||
.answer-card { |
|||
margin-bottom: 18rpx; |
|||
padding: 24rpx; |
|||
border-radius: 28rpx; |
|||
background: rgba(255, 255, 255, .82); |
|||
border: 1rpx solid rgba(255, 255, 255, .9); |
|||
box-shadow: 0 12rpx 30rpx rgba(96, 112, 160, .1); |
|||
} |
|||
|
|||
.card-head { |
|||
display: flex; |
|||
align-items: center; |
|||
} |
|||
|
|||
.card-avatar, |
|||
.card-avatar-img { |
|||
width: 76rpx; |
|||
height: 76rpx; |
|||
border-radius: 50%; |
|||
flex-shrink: 0; |
|||
} |
|||
|
|||
.card-avatar { |
|||
line-height: 76rpx; |
|||
text-align: center; |
|||
font-size: 30rpx; |
|||
font-weight: 800; |
|||
color: #5a4632; |
|||
background: linear-gradient(135deg, #ffe9c9, #ffd6a5); |
|||
} |
|||
|
|||
.card-user { |
|||
flex: 1; |
|||
margin-left: 16rpx; |
|||
min-width: 0; |
|||
} |
|||
|
|||
.card-name { |
|||
font-size: 27rpx; |
|||
font-weight: 800; |
|||
} |
|||
|
|||
.school-badge, |
|||
.mine-badge { |
|||
margin-left: 10rpx; |
|||
padding: 2rpx 12rpx; |
|||
border-radius: 999rpx; |
|||
font-size: 18rpx; |
|||
font-weight: 800; |
|||
vertical-align: 4rpx; |
|||
} |
|||
|
|||
.school-badge { |
|||
color: #1d7a4f; |
|||
background: rgba(61, 220, 151, .16); |
|||
} |
|||
|
|||
.mine-badge { |
|||
color: #7a4dff; |
|||
background: rgba(122, 77, 255, .12); |
|||
} |
|||
|
|||
.card-mode { |
|||
margin-top: 4rpx; |
|||
font-size: 21rpx; |
|||
color: rgba(22, 27, 46, .48); |
|||
} |
|||
|
|||
.card-chat { |
|||
flex-shrink: 0; |
|||
padding: 12rpx 24rpx; |
|||
border-radius: 999rpx; |
|||
font-size: 22rpx; |
|||
font-weight: 800; |
|||
color: #fff; |
|||
background: linear-gradient(135deg, #7a4dff, #ff7eb3); |
|||
} |
|||
|
|||
.card-content { |
|||
margin-top: 16rpx; |
|||
font-size: 26rpx; |
|||
line-height: 1.55; |
|||
color: rgba(22, 27, 46, .82); |
|||
} |
|||
|
|||
.feed-status { |
|||
padding: 24rpx 0 10rpx; |
|||
text-align: center; |
|||
font-size: 23rpx; |
|||
color: rgba(22, 27, 46, .42); |
|||
} |
|||
|
|||
.locked-tip { |
|||
margin-top: 60rpx; |
|||
text-align: center; |
|||
} |
|||
|
|||
.locked-icon { |
|||
font-size: 64rpx; |
|||
} |
|||
|
|||
.locked-text { |
|||
margin-top: 14rpx; |
|||
font-size: 25rpx; |
|||
color: rgba(22, 27, 46, .5); |
|||
} |
|||
</style> |
|||
File diff suppressed because it is too large
Loading…
Reference in new issue