f62ae880be
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1113 lines
26 KiB
Vue
1113 lines
26 KiB
Vue
<template>
|
|
<view class="detail-page">
|
|
<view class="space-bg"></view>
|
|
<view class="status-safe" :style="{ height: safeAreaTop + 'px' }"></view>
|
|
|
|
<view class="top-bar">
|
|
<text class="clock-text">{{ currentTime }}</text>
|
|
<view class="route-pill">
|
|
<view class="shield-icon"></view>
|
|
<text class="route-text">行程中</text>
|
|
<text class="score-text">{{ eventScore }}分</text>
|
|
</view>
|
|
<view class="signal-group">
|
|
<view class="signal-bars">
|
|
<view></view>
|
|
<view></view>
|
|
<view></view>
|
|
<view></view>
|
|
</view>
|
|
<text class="network-text">5GA</text>
|
|
<view class="battery-box"><text>{{ batteryLevel }}</text></view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="floating-nav">
|
|
<view class="circle-btn" @click="goBack">
|
|
<view class="back-icon"></view>
|
|
</view>
|
|
<view class="circle-btn" @click="openMore">
|
|
<view class="more-dot"></view>
|
|
<view class="more-dot"></view>
|
|
<view class="more-dot"></view>
|
|
</view>
|
|
</view>
|
|
|
|
<scroll-view class="content" scroll-y :show-scrollbar="false">
|
|
<view class="hero-card glass-card">
|
|
<view class="hero-timeline">
|
|
<view class="timeline-glow"></view>
|
|
<view class="timeline-node"></view>
|
|
<view class="timeline-line"></view>
|
|
</view>
|
|
|
|
<view class="hero-copy">
|
|
<text class="year">{{ eventYear }}</text>
|
|
<view class="date-row">
|
|
<text class="date-range">{{ dateRange }}</text>
|
|
<text class="type-chip">{{ primaryTag }}</text>
|
|
</view>
|
|
<text class="event-title">{{ displayEvent.title || '决定全职做自己热爱的AI产品' }}</text>
|
|
<view class="location-row">
|
|
<view class="pin-icon"></view>
|
|
<text>{{ locationText }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="memory-cover">
|
|
<view class="cover-sky"></view>
|
|
<view class="cover-window"></view>
|
|
<view class="cover-desk"></view>
|
|
<view class="cover-screen main"></view>
|
|
<view class="cover-screen small left"></view>
|
|
<view class="cover-screen small right"></view>
|
|
</view>
|
|
<view class="hero-star">★</view>
|
|
</view>
|
|
|
|
<view class="description-card glass-card">
|
|
<view class="section-title-row">
|
|
<view class="orbit-icon"></view>
|
|
<text>事件描述</text>
|
|
</view>
|
|
<text class="description-text" :class="{ collapsed: isDescriptionCollapsed }">{{ eventDescription }}</text>
|
|
<text class="collapse-action" @click="isDescriptionCollapsed = !isDescriptionCollapsed">
|
|
{{ isDescriptionCollapsed ? '展开' : '收起' }} ^
|
|
</text>
|
|
</view>
|
|
|
|
<view class="analysis-panel">
|
|
<view class="section-title-row analysis-head">
|
|
<text class="sparkle">✦</text>
|
|
<text>AI 分析</text>
|
|
</view>
|
|
|
|
<view v-if="hasMarkdownAnalysis" class="markdown-analysis-card">
|
|
<Markdown :content="markdownAnalysis" />
|
|
</view>
|
|
|
|
<view v-for="block in analysisBlocks" v-else :key="block.title" class="analysis-card">
|
|
<view class="analysis-icon" :class="block.iconClass">{{ block.icon }}</view>
|
|
<view class="analysis-body">
|
|
<text class="analysis-title">{{ block.title }}</text>
|
|
<text class="analysis-text">{{ block.text }}</text>
|
|
<view class="analysis-tags" :class="{ quote: block.quote }">
|
|
<text v-for="tag in block.tags" :key="tag">{{ tag }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="tags-card glass-card">
|
|
<view class="section-title-row">
|
|
<view class="diamond-icon"></view>
|
|
<text>相关标签</text>
|
|
</view>
|
|
<view class="tag-list">
|
|
<text v-for="tag in relatedTags" :key="tag">{{ tag }}</text>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
|
|
<view class="bottom-actions" :style="{ paddingBottom: bottomInset + 'px' }">
|
|
<view class="bottom-action" @click="editEvent">
|
|
<view class="edit-icon"></view>
|
|
<text>编辑</text>
|
|
</view>
|
|
<view class="bottom-action" @click="toggleFavorite">
|
|
<view class="bookmark-icon" :class="{ active: isFavorite }"></view>
|
|
<text>{{ isFavorite ? '已收藏' : '收藏' }}</text>
|
|
</view>
|
|
<view class="chat-action" @click="chatEvent">
|
|
<view class="chat-badge">AI</view>
|
|
<text>和开开聊聊这段经历</text>
|
|
</view>
|
|
<view class="bottom-action" @click="shareCurrent">
|
|
<view class="share-icon">
|
|
<view></view>
|
|
<view></view>
|
|
<view></view>
|
|
</view>
|
|
<text>分享</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed, onMounted, ref } from 'vue'
|
|
import { useAppStore } from '../../stores/app.js'
|
|
import Markdown from '../../components/Markdown.vue'
|
|
|
|
const store = useAppStore()
|
|
const safeAreaTop = ref(16)
|
|
const safeAreaBottom = ref(0)
|
|
const currentTime = ref('21:10')
|
|
const batteryLevel = ref('41')
|
|
const eventId = ref('')
|
|
const cachedEvent = ref(null)
|
|
const isFavorite = ref(false)
|
|
const isDescriptionCollapsed = ref(false)
|
|
|
|
onMounted(async () => {
|
|
const info = uni.getWindowInfo()
|
|
safeAreaTop.value = info.safeAreaInsets?.top || info.statusBarHeight || 16
|
|
safeAreaBottom.value = info.safeAreaInsets?.bottom || 0
|
|
const now = new Date()
|
|
currentTime.value = `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`
|
|
const pages = getCurrentPages()
|
|
eventId.value = pages[pages.length - 1]?.options?.id || ''
|
|
cachedEvent.value = uni.getStorageSync('current_life_event') || null
|
|
if (!store.events?.length) await store.fetchEvents()
|
|
isFavorite.value = Boolean(uni.getStorageSync(`event_favorite_${eventId.value}`))
|
|
})
|
|
|
|
const displayEvent = computed(() => store.getEventById(eventId.value) || cachedEvent.value || {})
|
|
const profile = computed(() => store.userProfile || store.registrationData || {})
|
|
const bottomInset = computed(() => Math.max(0, safeAreaBottom.value))
|
|
|
|
const eventYear = computed(() => {
|
|
const event = displayEvent.value
|
|
const date = event.time || event.date || event.eventDate
|
|
if (date) return String(date).slice(0, 4)
|
|
if (!isInvalidDateText(event.eventDateText)) return String(event.eventDateText).slice(0, 4)
|
|
return '2025'
|
|
})
|
|
|
|
const dateRange = computed(() => {
|
|
return formatEventTime(displayEvent.value)
|
|
})
|
|
|
|
const isInvalidDateText = (value) => {
|
|
return !value || String(value).includes('%')
|
|
}
|
|
|
|
const toDatePart = (value) => {
|
|
return value ? String(value).split('T')[0] : ''
|
|
}
|
|
|
|
const formatMonthDay = (value) => {
|
|
const date = toDatePart(value)
|
|
if (!date) return ''
|
|
const [, month = '', day = ''] = date.split('-')
|
|
return month && day ? `${month}/${day}` : ''
|
|
}
|
|
|
|
const formatEventTime = (event = {}) => {
|
|
const timeMode = event.timeMode || 'date'
|
|
const start = toDatePart(event.time || event.date || event.eventDate)
|
|
const end = toDatePart(event.endTime || event.eventEndDate)
|
|
const text = isInvalidDateText(event.eventDateText) ? '' : String(event.eventDateText || '')
|
|
|
|
if (timeMode === 'range') {
|
|
if (start && end) return `${formatMonthDay(start)} - ${formatMonthDay(end)}`
|
|
if (text) {
|
|
const normalized = text.replace(/\s*(至|到|~|—|-)\s*/g, ' - ')
|
|
const [rawStart, rawEnd] = normalized.split(' - ')
|
|
if (rawStart && rawEnd) return `${formatMonthDay(rawStart)} - ${formatMonthDay(rawEnd)}`
|
|
return text
|
|
}
|
|
}
|
|
|
|
if (timeMode === 'month') {
|
|
const value = text || start
|
|
return value ? String(value).slice(0, 7).replace('-', '.') : '2025.05'
|
|
}
|
|
|
|
if (timeMode === 'season') {
|
|
const value = text || `${String(start || '2025').slice(0, 4)}-spring`
|
|
const [year, season = 'spring'] = String(value).split('-')
|
|
const seasonMap = { spring: '春季', summer: '夏季', autumn: '秋季', winter: '冬季' }
|
|
return `${year} ${seasonMap[season] || '春季'}`
|
|
}
|
|
|
|
if (!start) return '05/20 - 05/28'
|
|
const first = formatMonthDay(start)
|
|
return first || '05/20'
|
|
}
|
|
|
|
const primaryTag = computed(() => {
|
|
if (Array.isArray(displayEvent.value.tags) && displayEvent.value.tags.length) return displayEvent.value.tags[0]
|
|
const map = { childhood: '童年', highlight: '高光', valley: '低谷', daily_log: '瞬间' }
|
|
return map[displayEvent.value.eventType] || '高光'
|
|
})
|
|
|
|
const locationText = computed(() => {
|
|
return profile.value.city ? `中国 · ${profile.value.city}` : '中国 · 深圳'
|
|
})
|
|
|
|
const eventScore = computed(() => {
|
|
const raw = Number(displayEvent.value.emotionScore || 18)
|
|
return Math.max(1, Math.min(99, Math.round(raw)))
|
|
})
|
|
|
|
const eventDescription = computed(() => {
|
|
return displayEvent.value.content || displayEvent.value.description || '经过了长时间的纠结和准备,我终于辞去了稳定的工作,全职投入到自己热爱的AI产品创业中。这是我人生中最大的一次冒险,也是我第一次真正为自己而活。'
|
|
})
|
|
|
|
const relatedTags = computed(() => {
|
|
const base = Array.isArray(displayEvent.value.tags) ? displayEvent.value.tags.filter(Boolean) : []
|
|
const fallback = ['创业', 'AI产品', '自我实现', '职业转型', '勇气']
|
|
return [...new Set([...base, ...fallback])].slice(0, 5)
|
|
})
|
|
|
|
const markdownAnalysis = computed(() => String(displayEvent.value.aiFeedback || '').trim())
|
|
|
|
const hasMarkdownAnalysis = computed(() => {
|
|
const content = markdownAnalysis.value
|
|
if (!content) return false
|
|
return /(^|\n)\s{0,3}#{1,6}\s+\S/.test(content)
|
|
|| /(^|\n)\s{0,3}(-{3,}|\*{3,}|_{3,})\s*($|\n)/.test(content)
|
|
|| /(^|\n)\s{0,3}[-*+]\s+\S/.test(content)
|
|
|| /(^|\n)\s{0,3}\d+\.\s+\S/.test(content)
|
|
|| /\*\*[^*]+\*\*/.test(content)
|
|
|| /(^|\n)>\s+\S/.test(content)
|
|
})
|
|
|
|
const analysisBlocks = computed(() => {
|
|
const aiText = displayEvent.value.aiFeedback || ''
|
|
return [
|
|
{
|
|
icon: '♣',
|
|
iconClass: 'mind',
|
|
title: '心理状态解读',
|
|
text: aiText ? aiText.slice(0, 72) : '你正处于「自我实现驱动期」,内心充满了对未来的憧憬和掌控感。',
|
|
tags: ['勇气', '自主性', '目标感', '掌控欲']
|
|
},
|
|
{
|
|
icon: '◆',
|
|
iconClass: 'growth',
|
|
title: '成长意义',
|
|
text: '这次选择标志着你从“安全区”走向“成长区”,是自我身份重塑的关键转折点。',
|
|
tags: ['突破舒适区', '价值对齐', '自我认同', '长期主义']
|
|
},
|
|
{
|
|
icon: '!',
|
|
iconClass: 'challenge',
|
|
title: '可能面临的挑战',
|
|
text: '未来可能会遇到不确定性、经济压力和自我怀疑的时刻,需要建立稳定的内在支持系统来应对。',
|
|
tags: ['不确定性', '经济压力', '孤独感', '自我怀疑']
|
|
},
|
|
{
|
|
icon: '★',
|
|
iconClass: 'advice',
|
|
title: '给你的建议',
|
|
text: '保持对初心的连接,记录每一次小的进展,你会在时间的复利中收获巨大成长。',
|
|
tags: ['「你选择的不是一条容易的路,而是一条属于你的路。」'],
|
|
quote: true
|
|
}
|
|
]
|
|
})
|
|
|
|
const editEvent = () => {
|
|
if (!eventId.value) return
|
|
uni.navigateTo({ url: `/pages/life-event/form?id=${eventId.value}` })
|
|
}
|
|
|
|
const toggleFavorite = async () => {
|
|
if (!eventId.value) return
|
|
const next = !isFavorite.value
|
|
const result = await store.favoriteEvent({ id: eventId.value, favorite: next })
|
|
if (!result.success) {
|
|
uni.showToast({ title: result.error || '收藏失败', icon: 'none' })
|
|
return
|
|
}
|
|
isFavorite.value = next
|
|
if (next) uni.setStorageSync(`event_favorite_${eventId.value}`, '1')
|
|
else uni.removeStorageSync(`event_favorite_${eventId.value}`)
|
|
uni.showToast({ title: next ? '已收藏' : '已取消收藏', icon: 'success' })
|
|
}
|
|
|
|
const chatEvent = async () => {
|
|
const result = await store.chatAboutEvent({
|
|
id: eventId.value,
|
|
title: displayEvent.value.title,
|
|
content: displayEvent.value.content
|
|
})
|
|
uni.showModal({
|
|
title: '和开开聊聊',
|
|
content: result.success ? result.data?.reply || '聊天能力已准备' : result.error || '聊天服务暂不可用',
|
|
showCancel: false
|
|
})
|
|
}
|
|
|
|
const shareCurrent = async () => {
|
|
const result = await store.shareEvent({
|
|
id: eventId.value,
|
|
title: displayEvent.value.title,
|
|
content: displayEvent.value.content
|
|
})
|
|
if (!result.success) {
|
|
uni.showToast({ title: result.error || '分享失败', icon: 'none' })
|
|
return
|
|
}
|
|
uni.setClipboardData({
|
|
data: result.data?.shareText || `分享我的人生轨迹:${displayEvent.value.title || ''}`,
|
|
success: () => uni.showToast({ title: '分享文案已复制', icon: 'success' })
|
|
})
|
|
}
|
|
|
|
const openMore = () => {
|
|
uni.showActionSheet({
|
|
itemList: ['编辑经历', isFavorite.value ? '取消收藏' : '收藏经历', '复制分享文案'],
|
|
success: ({ tapIndex }) => {
|
|
if (tapIndex === 0) editEvent()
|
|
if (tapIndex === 1) toggleFavorite()
|
|
if (tapIndex === 2) shareCurrent()
|
|
}
|
|
})
|
|
}
|
|
|
|
const goBack = () => {
|
|
uni.navigateBack()
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.detail-page {
|
|
position: relative;
|
|
height: 100vh;
|
|
min-height: 0;
|
|
overflow: hidden;
|
|
display: flex;
|
|
flex-direction: column;
|
|
color: #f7f2ff;
|
|
background: #050717;
|
|
}
|
|
|
|
.space-bg {
|
|
position: absolute;
|
|
inset: 0;
|
|
background:
|
|
radial-gradient(circle at 22% 4%, rgba(55, 74, 190, 0.22), transparent 30%),
|
|
radial-gradient(circle at 90% 16%, rgba(87, 48, 168, 0.22), transparent 34%),
|
|
linear-gradient(180deg, #070c27 0%, #080420 52%, #05020f 100%);
|
|
}
|
|
|
|
.space-bg::after {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 0;
|
|
opacity: 0.32;
|
|
background-image:
|
|
radial-gradient(circle, rgba(255,255,255,0.7) 0 1rpx, transparent 2rpx),
|
|
radial-gradient(circle, rgba(162,109,255,0.55) 0 1rpx, transparent 2rpx);
|
|
background-size: 160rpx 190rpx, 250rpx 220rpx;
|
|
background-position: 44rpx 44rpx, 10rpx 112rpx;
|
|
}
|
|
|
|
.status-safe,
|
|
.top-bar,
|
|
.floating-nav,
|
|
.content,
|
|
.bottom-actions {
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
|
|
.status-safe {
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.top-bar {
|
|
height: 74rpx;
|
|
flex-shrink: 0;
|
|
display: grid;
|
|
grid-template-columns: 140rpx 1fr 178rpx;
|
|
align-items: center;
|
|
padding: 0 32rpx;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.clock-text {
|
|
color: #fff;
|
|
font-size: 30rpx;
|
|
font-weight: 700;
|
|
letter-spacing: 0;
|
|
}
|
|
|
|
.route-pill {
|
|
justify-self: center;
|
|
width: 356rpx;
|
|
height: 62rpx;
|
|
border-radius: 999rpx;
|
|
display: grid;
|
|
grid-template-columns: 30rpx 1fr auto;
|
|
align-items: center;
|
|
gap: 12rpx;
|
|
padding: 0 24rpx;
|
|
box-sizing: border-box;
|
|
color: #fff;
|
|
background: rgba(0, 0, 0, 0.76);
|
|
border: 3rpx solid rgba(255, 255, 255, 0.22);
|
|
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.42);
|
|
}
|
|
|
|
.route-text,
|
|
.score-text {
|
|
font-size: 23rpx;
|
|
line-height: 1;
|
|
}
|
|
|
|
.route-text {
|
|
font-weight: 800;
|
|
}
|
|
|
|
.score-text {
|
|
color: rgba(255, 255, 255, 0.82);
|
|
text-align: right;
|
|
}
|
|
|
|
.shield-icon {
|
|
position: relative;
|
|
width: 25rpx;
|
|
height: 27rpx;
|
|
border: 4rpx solid #fff;
|
|
border-radius: 10rpx 10rpx 13rpx 13rpx;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.shield-icon::after {
|
|
content: '';
|
|
position: absolute;
|
|
left: 6rpx;
|
|
top: 4rpx;
|
|
width: 7rpx;
|
|
height: 10rpx;
|
|
border-right: 3rpx solid #fff;
|
|
border-bottom: 3rpx solid #fff;
|
|
transform: rotate(42deg);
|
|
}
|
|
|
|
.signal-group {
|
|
justify-self: end;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10rpx;
|
|
}
|
|
|
|
.signal-bars {
|
|
height: 31rpx;
|
|
display: flex;
|
|
align-items: flex-end;
|
|
gap: 5rpx;
|
|
}
|
|
|
|
.signal-bars view {
|
|
width: 8rpx;
|
|
border-radius: 6rpx;
|
|
background: #fff;
|
|
}
|
|
|
|
.signal-bars view:nth-child(1) { height: 12rpx; }
|
|
.signal-bars view:nth-child(2) { height: 18rpx; }
|
|
.signal-bars view:nth-child(3) { height: 24rpx; }
|
|
.signal-bars view:nth-child(4) { height: 31rpx; }
|
|
|
|
.network-text {
|
|
color: #fff;
|
|
font-size: 26rpx;
|
|
font-weight: 800;
|
|
}
|
|
|
|
.battery-box {
|
|
min-width: 52rpx;
|
|
height: 35rpx;
|
|
border-radius: 8rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: #171327;
|
|
background: rgba(255, 255, 255, 0.78);
|
|
}
|
|
|
|
.battery-box text {
|
|
font-size: 24rpx;
|
|
font-weight: 900;
|
|
}
|
|
|
|
.floating-nav {
|
|
height: 108rpx;
|
|
flex-shrink: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0 32rpx;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.circle-btn {
|
|
width: 64rpx;
|
|
height: 64rpx;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 5rpx;
|
|
color: #fff;
|
|
border: 1rpx solid rgba(118, 82, 225, 0.35);
|
|
background: rgba(22, 18, 63, 0.72);
|
|
box-shadow: inset 0 0 20rpx rgba(137, 91, 255, 0.1);
|
|
}
|
|
|
|
.back-icon {
|
|
width: 23rpx;
|
|
height: 23rpx;
|
|
border-left: 6rpx solid #fff;
|
|
border-bottom: 6rpx solid #fff;
|
|
transform: rotate(45deg);
|
|
margin-left: 7rpx;
|
|
}
|
|
|
|
.more-dot {
|
|
width: 7rpx;
|
|
height: 7rpx;
|
|
border-radius: 50%;
|
|
background: #fff;
|
|
}
|
|
|
|
.content {
|
|
flex: 1;
|
|
height: 0;
|
|
min-height: 0;
|
|
box-sizing: border-box;
|
|
padding: 0 32rpx 134rpx;
|
|
}
|
|
|
|
.glass-card {
|
|
border: 1rpx solid rgba(113, 78, 223, 0.42);
|
|
background:
|
|
radial-gradient(circle at 90% 4%, rgba(119, 84, 255, 0.12), transparent 32%),
|
|
rgba(13, 16, 52, 0.72);
|
|
box-shadow: inset 0 0 38rpx rgba(124, 79, 255, 0.07), 0 14rpx 42rpx rgba(0, 0, 0, 0.22);
|
|
backdrop-filter: blur(24rpx);
|
|
-webkit-backdrop-filter: blur(24rpx);
|
|
}
|
|
|
|
.hero-card {
|
|
position: relative;
|
|
min-height: 264rpx;
|
|
border-radius: 28rpx;
|
|
display: grid;
|
|
grid-template-columns: 70rpx 1fr 148rpx;
|
|
gap: 20rpx;
|
|
padding: 38rpx 34rpx 32rpx;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.hero-timeline {
|
|
position: relative;
|
|
display: flex;
|
|
justify-content: center;
|
|
}
|
|
|
|
.timeline-glow {
|
|
position: absolute;
|
|
top: -18rpx;
|
|
width: 8rpx;
|
|
height: 8rpx;
|
|
border-radius: 50%;
|
|
background: #9d64ff;
|
|
box-shadow: 0 0 16rpx #a36cff;
|
|
}
|
|
|
|
.timeline-node {
|
|
position: absolute;
|
|
top: 50rpx;
|
|
z-index: 2;
|
|
width: 34rpx;
|
|
height: 34rpx;
|
|
border-radius: 50%;
|
|
border: 4rpx solid #8f4cff;
|
|
background: radial-gradient(circle, #d7b8ff 0 28%, #8b54ff 32% 100%);
|
|
box-shadow: 0 0 24rpx rgba(159, 96, 255, 0.92);
|
|
}
|
|
|
|
.timeline-line {
|
|
position: absolute;
|
|
top: -10rpx;
|
|
bottom: 12rpx;
|
|
width: 3rpx;
|
|
background: linear-gradient(180deg, rgba(165, 98, 255, 0.22), #9757ff 36%, rgba(132, 78, 255, 0.15));
|
|
}
|
|
|
|
.hero-copy {
|
|
min-width: 0;
|
|
}
|
|
|
|
.year {
|
|
display: block;
|
|
color: rgba(221, 209, 244, 0.58);
|
|
font-size: 24rpx;
|
|
line-height: 1;
|
|
}
|
|
|
|
.date-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 18rpx;
|
|
margin-top: 18rpx;
|
|
}
|
|
|
|
.date-range {
|
|
color: #fff;
|
|
font-size: 34rpx;
|
|
line-height: 1;
|
|
font-weight: 900;
|
|
}
|
|
|
|
.type-chip {
|
|
height: 34rpx;
|
|
padding: 0 16rpx;
|
|
border-radius: 999rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
color: #d6b9ff;
|
|
font-size: 22rpx;
|
|
background: rgba(107, 61, 197, 0.58);
|
|
}
|
|
|
|
.event-title {
|
|
display: block;
|
|
margin-top: 28rpx;
|
|
color: #fff;
|
|
font-size: 31rpx;
|
|
line-height: 1.32;
|
|
font-weight: 900;
|
|
}
|
|
|
|
.location-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10rpx;
|
|
margin-top: 22rpx;
|
|
color: rgba(218, 207, 239, 0.72);
|
|
font-size: 23rpx;
|
|
}
|
|
|
|
.pin-icon {
|
|
width: 16rpx;
|
|
height: 16rpx;
|
|
border: 4rpx solid currentColor;
|
|
border-radius: 50% 50% 50% 0;
|
|
transform: rotate(-45deg);
|
|
}
|
|
|
|
.memory-cover {
|
|
position: relative;
|
|
align-self: center;
|
|
width: 148rpx;
|
|
height: 148rpx;
|
|
border-radius: 20rpx;
|
|
overflow: hidden;
|
|
border: 3rpx solid rgba(143, 82, 255, 0.52);
|
|
background: #130f33;
|
|
box-shadow: 0 0 28rpx rgba(127, 72, 255, 0.3);
|
|
}
|
|
|
|
.cover-sky {
|
|
position: absolute;
|
|
inset: 0;
|
|
background:
|
|
radial-gradient(circle at 74% 20%, rgba(255, 174, 83, 0.74), transparent 16%),
|
|
linear-gradient(155deg, #5221a7 0%, #dd6a92 45%, #26317d 100%);
|
|
}
|
|
|
|
.cover-window {
|
|
position: absolute;
|
|
left: 16rpx;
|
|
right: 16rpx;
|
|
bottom: 45rpx;
|
|
height: 58rpx;
|
|
border-radius: 10rpx;
|
|
background: rgba(18, 15, 43, 0.42);
|
|
border: 2rpx solid rgba(255, 255, 255, 0.15);
|
|
}
|
|
|
|
.cover-desk {
|
|
position: absolute;
|
|
left: 10rpx;
|
|
right: 8rpx;
|
|
bottom: 16rpx;
|
|
height: 28rpx;
|
|
border-radius: 8rpx;
|
|
background: rgba(15, 12, 30, 0.8);
|
|
}
|
|
|
|
.cover-screen {
|
|
position: absolute;
|
|
border-radius: 5rpx;
|
|
background: linear-gradient(135deg, #6e4cff, #ff74b4);
|
|
box-shadow: 0 0 12rpx rgba(198, 124, 255, 0.55);
|
|
}
|
|
|
|
.cover-screen.main {
|
|
left: 55rpx;
|
|
bottom: 28rpx;
|
|
width: 42rpx;
|
|
height: 26rpx;
|
|
}
|
|
|
|
.cover-screen.small {
|
|
bottom: 30rpx;
|
|
width: 28rpx;
|
|
height: 18rpx;
|
|
}
|
|
|
|
.cover-screen.left { left: 20rpx; }
|
|
.cover-screen.right { right: 18rpx; }
|
|
|
|
.hero-star {
|
|
position: absolute;
|
|
right: 20rpx;
|
|
top: 30rpx;
|
|
color: #ffd36e;
|
|
font-size: 38rpx;
|
|
line-height: 1;
|
|
text-shadow: 0 0 22rpx rgba(255, 198, 85, 0.9);
|
|
}
|
|
|
|
.description-card,
|
|
.tags-card {
|
|
border-radius: 28rpx;
|
|
margin-top: 18rpx;
|
|
padding: 28rpx 30rpx;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.section-title-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 14rpx;
|
|
color: #dec9ff;
|
|
font-size: 27rpx;
|
|
line-height: 1;
|
|
font-weight: 900;
|
|
}
|
|
|
|
.orbit-icon {
|
|
position: relative;
|
|
width: 26rpx;
|
|
height: 26rpx;
|
|
}
|
|
|
|
.orbit-icon::before,
|
|
.orbit-icon::after {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 3rpx;
|
|
border: 3rpx solid #9b5cff;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.orbit-icon::after {
|
|
transform: rotate(45deg) scaleX(1.4);
|
|
border-color: rgba(176, 112, 255, 0.62);
|
|
}
|
|
|
|
.description-text {
|
|
display: block;
|
|
margin-top: 24rpx;
|
|
color: rgba(227, 218, 246, 0.73);
|
|
font-size: 25rpx;
|
|
line-height: 1.75;
|
|
}
|
|
|
|
.description-text.collapsed {
|
|
display: -webkit-box;
|
|
overflow: hidden;
|
|
-webkit-line-clamp: 3;
|
|
-webkit-box-orient: vertical;
|
|
}
|
|
|
|
.collapse-action {
|
|
display: block;
|
|
margin-top: 14rpx;
|
|
text-align: right;
|
|
color: #a970ff;
|
|
font-size: 24rpx;
|
|
font-weight: 800;
|
|
}
|
|
|
|
.analysis-panel {
|
|
margin-top: 22rpx;
|
|
border-radius: 30rpx;
|
|
padding: 30rpx 34rpx 34rpx;
|
|
box-sizing: border-box;
|
|
border: 2rpx solid rgba(154, 75, 255, 0.76);
|
|
background:
|
|
radial-gradient(circle at 54% 8%, rgba(126, 72, 255, 0.16), transparent 34%),
|
|
rgba(12, 13, 46, 0.72);
|
|
box-shadow: 0 0 30rpx rgba(156, 73, 255, 0.24), inset 0 0 34rpx rgba(143, 92, 255, 0.08);
|
|
}
|
|
|
|
.analysis-head {
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.sparkle {
|
|
color: #d783ff;
|
|
font-size: 30rpx;
|
|
}
|
|
|
|
.analysis-card {
|
|
margin-top: 18rpx;
|
|
border-radius: 22rpx;
|
|
padding: 24rpx 24rpx 22rpx;
|
|
display: grid;
|
|
grid-template-columns: 42rpx 1fr;
|
|
gap: 18rpx;
|
|
background: rgba(255, 255, 255, 0.042);
|
|
border: 1rpx solid rgba(180, 139, 255, 0.18);
|
|
}
|
|
|
|
.markdown-analysis-card {
|
|
margin-top: 18rpx;
|
|
border-radius: 22rpx;
|
|
padding: 24rpx 24rpx 26rpx;
|
|
background: rgba(255, 255, 255, 0.042);
|
|
border: 1rpx solid rgba(180, 139, 255, 0.18);
|
|
}
|
|
|
|
.analysis-icon {
|
|
width: 32rpx;
|
|
height: 32rpx;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: #fff;
|
|
font-size: 20rpx;
|
|
font-weight: 900;
|
|
}
|
|
|
|
.analysis-icon.mind { background: rgba(211, 91, 255, 0.3); color: #f099ff; }
|
|
.analysis-icon.growth { background: rgba(81, 211, 154, 0.22); color: #86f0b0; }
|
|
.analysis-icon.challenge { background: rgba(255, 147, 92, 0.24); color: #ffa26f; }
|
|
.analysis-icon.advice { background: rgba(255, 210, 105, 0.24); color: #ffd66f; }
|
|
|
|
.analysis-title,
|
|
.analysis-text {
|
|
display: block;
|
|
}
|
|
|
|
.analysis-title {
|
|
color: #eadcff;
|
|
font-size: 26rpx;
|
|
font-weight: 900;
|
|
}
|
|
|
|
.analysis-text {
|
|
margin-top: 14rpx;
|
|
color: rgba(226, 216, 246, 0.72);
|
|
font-size: 24rpx;
|
|
line-height: 1.62;
|
|
}
|
|
|
|
.analysis-tags,
|
|
.tag-list {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 12rpx;
|
|
}
|
|
|
|
.analysis-tags {
|
|
margin-top: 18rpx;
|
|
}
|
|
|
|
.analysis-tags text,
|
|
.tag-list text {
|
|
height: 36rpx;
|
|
padding: 0 18rpx;
|
|
border-radius: 999rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
color: rgba(222, 209, 247, 0.78);
|
|
font-size: 21rpx;
|
|
background: rgba(132, 92, 222, 0.28);
|
|
}
|
|
|
|
.analysis-tags.quote text {
|
|
height: auto;
|
|
padding: 0;
|
|
color: #c77dff;
|
|
background: transparent;
|
|
font-size: 24rpx;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.diamond-icon {
|
|
width: 20rpx;
|
|
height: 20rpx;
|
|
border: 3rpx solid #9b5cff;
|
|
border-radius: 5rpx;
|
|
transform: rotate(45deg);
|
|
}
|
|
|
|
.tag-list {
|
|
margin-top: 24rpx;
|
|
}
|
|
|
|
.tag-list text {
|
|
height: 48rpx;
|
|
padding: 0 24rpx;
|
|
color: rgba(232, 224, 250, 0.78);
|
|
font-size: 23rpx;
|
|
background: rgba(101, 68, 186, 0.34);
|
|
border: 1rpx solid rgba(151, 111, 255, 0.18);
|
|
}
|
|
|
|
.bottom-actions {
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
min-height: 108rpx;
|
|
box-sizing: border-box;
|
|
display: grid;
|
|
grid-template-columns: 0.76fr 0.76fr 2fr 0.76fr;
|
|
align-items: center;
|
|
gap: 8rpx;
|
|
padding: 14rpx 32rpx 0;
|
|
border-radius: 36rpx 36rpx 0 0;
|
|
border-top: 1rpx solid rgba(126, 87, 255, 0.32);
|
|
background: rgba(13, 13, 43, 0.94);
|
|
box-shadow: 0 -14rpx 44rpx rgba(0, 0, 0, 0.45), inset 0 0 28rpx rgba(143, 92, 255, 0.1);
|
|
backdrop-filter: blur(28rpx);
|
|
-webkit-backdrop-filter: blur(28rpx);
|
|
}
|
|
|
|
.bottom-action,
|
|
.chat-action {
|
|
height: 72rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 10rpx;
|
|
color: rgba(238, 231, 255, 0.9);
|
|
font-size: 24rpx;
|
|
font-weight: 800;
|
|
}
|
|
|
|
.bottom-action {
|
|
min-width: 0;
|
|
}
|
|
|
|
.chat-action {
|
|
border-radius: 999rpx;
|
|
color: #fff;
|
|
background: linear-gradient(135deg, #b246ff, #742fff 58%, #5126ff);
|
|
box-shadow: 0 0 28rpx rgba(168, 85, 247, 0.58), inset 0 1rpx 0 rgba(255, 255, 255, 0.18);
|
|
}
|
|
|
|
.chat-badge {
|
|
width: 38rpx;
|
|
height: 38rpx;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border: 3rpx solid #fff;
|
|
font-size: 17rpx;
|
|
font-weight: 900;
|
|
}
|
|
|
|
.edit-icon {
|
|
position: relative;
|
|
width: 34rpx;
|
|
height: 34rpx;
|
|
border-left: 4rpx solid currentColor;
|
|
border-bottom: 4rpx solid currentColor;
|
|
transform: skew(-12deg);
|
|
}
|
|
|
|
.edit-icon::after {
|
|
content: '';
|
|
position: absolute;
|
|
left: 4rpx;
|
|
bottom: 7rpx;
|
|
width: 31rpx;
|
|
height: 5rpx;
|
|
border-radius: 999rpx;
|
|
background: currentColor;
|
|
transform: rotate(-45deg);
|
|
}
|
|
|
|
.bookmark-icon {
|
|
width: 26rpx;
|
|
height: 34rpx;
|
|
border: 4rpx solid currentColor;
|
|
border-bottom: 0;
|
|
border-radius: 5rpx 5rpx 0 0;
|
|
position: relative;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.bookmark-icon::after {
|
|
content: '';
|
|
position: absolute;
|
|
left: 3rpx;
|
|
right: 3rpx;
|
|
bottom: -8rpx;
|
|
height: 16rpx;
|
|
background: #0d0d2b;
|
|
transform: rotate(45deg);
|
|
border-right: 4rpx solid currentColor;
|
|
border-bottom: 4rpx solid currentColor;
|
|
}
|
|
|
|
.bookmark-icon.active {
|
|
color: #ffd36e;
|
|
}
|
|
|
|
.share-icon {
|
|
position: relative;
|
|
width: 38rpx;
|
|
height: 34rpx;
|
|
}
|
|
|
|
.share-icon view {
|
|
position: absolute;
|
|
width: 9rpx;
|
|
height: 9rpx;
|
|
border: 4rpx solid currentColor;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.share-icon view:nth-child(1) {
|
|
left: 0;
|
|
top: 12rpx;
|
|
}
|
|
|
|
.share-icon view:nth-child(2) {
|
|
right: 0;
|
|
top: 0;
|
|
}
|
|
|
|
.share-icon view:nth-child(3) {
|
|
right: 0;
|
|
bottom: 0;
|
|
}
|
|
|
|
.share-icon::before,
|
|
.share-icon::after {
|
|
content: '';
|
|
position: absolute;
|
|
left: 12rpx;
|
|
width: 22rpx;
|
|
height: 3rpx;
|
|
background: currentColor;
|
|
transform-origin: left center;
|
|
}
|
|
|
|
.share-icon::before {
|
|
top: 14rpx;
|
|
transform: rotate(-28deg);
|
|
}
|
|
|
|
.share-icon::after {
|
|
bottom: 12rpx;
|
|
transform: rotate(28deg);
|
|
}
|
|
</style>
|