feat: 修复 Redis 超时问题、固定小程序端口、新增人生事件模块及优化多个页面
- 修复 Redis 超时:添加 commons-pool2 依赖,启用 Lettuce 连接池,超时提升至 15s - 固定 mini-program H5 端口为 5175,避免与 web 项目端口冲突 - 新增人生事件(life-event)模块:表单和详情页面 - 新增 EpicScript 灵感接口(Controller/Service/DTO) - 优化登录、引导、主页、记录、剧本详情等多个页面 - 优化服务管理脚本和 Nginx 配置 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,310 @@
|
||||
<template>
|
||||
<view class="event-detail-page">
|
||||
<view class="space-bg"></view>
|
||||
<view class="top-safe" :style="{ height: safeAreaTop + 'px' }"></view>
|
||||
|
||||
<view class="header">
|
||||
<text class="back" @click="goBack">‹</text>
|
||||
<text class="title">人生轨迹内容</text>
|
||||
<text class="more">•••</text>
|
||||
</view>
|
||||
|
||||
<scroll-view class="content" scroll-y :show-scrollbar="false">
|
||||
<view class="hero-card kos-card">
|
||||
<view class="cover">{{ (event.title || '轨').slice(0, 1) }}</view>
|
||||
<view class="hero-body">
|
||||
<text class="date">{{ event.time || event.date || '未知日期' }}</text>
|
||||
<text class="event-title">{{ event.title || '未命名经历' }}</text>
|
||||
<text class="tag">{{ primaryTag }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="panel kos-card">
|
||||
<text class="panel-title">经历描述</text>
|
||||
<text class="body-text">{{ event.content || event.description || '暂无内容。' }}</text>
|
||||
</view>
|
||||
|
||||
<view class="panel ai-panel kos-card">
|
||||
<view class="ai-head">
|
||||
<text class="spark">✦</text>
|
||||
<text>AI 人生解读</text>
|
||||
</view>
|
||||
<view v-for="block in analysisBlocks" :key="block.title" class="analysis-block">
|
||||
<text class="analysis-title">{{ block.title }}</text>
|
||||
<text class="analysis-text">{{ block.text }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="related-tags">
|
||||
<text v-for="tag in relatedTags" :key="tag" class="tag-pill kos-pill">{{ tag }}</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="bottom-actions" :style="{ paddingBottom: safeAreaBottom + 14 + 'px' }">
|
||||
<view class="action kos-pill" @click="notReady('编辑')">编辑</view>
|
||||
<view class="action kos-pill" @click="notReady('收藏')">收藏</view>
|
||||
<view class="action primary kos-primary" @click="notReady('聊天')">聊聊这段经历</view>
|
||||
<view class="action kos-pill" @click="notReady('分享')">分享</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, ref, onMounted } from 'vue'
|
||||
import { useAppStore } from '../../stores/app.js'
|
||||
|
||||
const store = useAppStore()
|
||||
const safeAreaTop = ref(20)
|
||||
const safeAreaBottom = ref(0)
|
||||
const eventId = ref('')
|
||||
|
||||
onMounted(async () => {
|
||||
const info = uni.getWindowInfo()
|
||||
safeAreaTop.value = info.safeAreaInsets?.top || info.statusBarHeight || 20
|
||||
safeAreaBottom.value = info.safeAreaInsets?.bottom || 0
|
||||
const pages = getCurrentPages()
|
||||
eventId.value = pages[pages.length - 1]?.options?.id || ''
|
||||
if (!store.events?.length) await store.fetchEvents()
|
||||
})
|
||||
|
||||
const event = computed(() => store.getEventById(eventId.value) || {})
|
||||
const primaryTag = computed(() => Array.isArray(event.value.tags) && event.value.tags.length ? event.value.tags[0] : '人生片段')
|
||||
const relatedTags = computed(() => {
|
||||
if (Array.isArray(event.value.tags) && event.value.tags.length) return event.value.tags
|
||||
return ['理解', '成长', '转折']
|
||||
})
|
||||
|
||||
const analysisBlocks = computed(() => {
|
||||
const ai = event.value.aiFeedback
|
||||
if (!ai) {
|
||||
return [
|
||||
{ title: '情绪整理', text: '这段经历还没有 AI 解读,但它已经是一枚重要的生命坐标。' },
|
||||
{ title: '成长意义', text: '你可以继续补充当时的选择、关系和感受,让它成为后续剧本生成的素材。' }
|
||||
]
|
||||
}
|
||||
return [
|
||||
{ title: '情绪整理', text: ai.slice(0, 90) },
|
||||
{ title: '能力映射', text: '从这段经历里,可以看到你对变化的感知、承受和重新组织能力。' },
|
||||
{ title: '下一步建议', text: '把这段经历与一个目标连接起来,它会更容易转化成行动路径。' }
|
||||
]
|
||||
})
|
||||
|
||||
const notReady = (label) => {
|
||||
uni.showToast({ title: `${label}能力稍后开放`, icon: 'none' })
|
||||
}
|
||||
|
||||
const goBack = () => {
|
||||
uni.navigateBack()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.event-detail-page {
|
||||
position: relative;
|
||||
height: 100vh;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: #fff;
|
||||
background: #050615;
|
||||
}
|
||||
|
||||
.space-bg {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background:
|
||||
radial-gradient(circle at 18% 2%, rgba(124, 58, 237, 0.3), transparent 34%),
|
||||
radial-gradient(circle at 88% 22%, rgba(14, 165, 233, 0.18), transparent 28%),
|
||||
linear-gradient(180deg, #07091d 0%, #07031a 52%, #04020e 100%);
|
||||
}
|
||||
|
||||
.top-safe,
|
||||
.header,
|
||||
.content,
|
||||
.bottom-actions {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.header {
|
||||
height: 92rpx;
|
||||
flex-shrink: 0;
|
||||
display: grid;
|
||||
grid-template-columns: 80rpx 1fr 80rpx;
|
||||
align-items: center;
|
||||
padding: 0 28rpx;
|
||||
}
|
||||
|
||||
.back {
|
||||
font-size: 66rpx;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.title {
|
||||
text-align: center;
|
||||
font-size: 34rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.more {
|
||||
text-align: right;
|
||||
color: rgba(255, 255, 255, 0.68);
|
||||
letter-spacing: 4rpx;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
min-height: 0;
|
||||
box-sizing: border-box;
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.hero-card,
|
||||
.panel {
|
||||
border-radius: 30rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.hero-card {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.cover {
|
||||
height: 256rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-size: 88rpx;
|
||||
font-weight: 900;
|
||||
background:
|
||||
radial-gradient(circle at 30% 20%, rgba(56, 189, 248, 0.3), transparent 30%),
|
||||
linear-gradient(135deg, #7d35ff, #111827);
|
||||
}
|
||||
|
||||
.hero-body,
|
||||
.panel {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.date,
|
||||
.tag,
|
||||
.body-text,
|
||||
.analysis-text {
|
||||
display: block;
|
||||
color: rgba(226, 216, 246, 0.72);
|
||||
}
|
||||
|
||||
.date {
|
||||
font-size: 22rpx;
|
||||
letter-spacing: 3rpx;
|
||||
}
|
||||
|
||||
.event-title {
|
||||
display: block;
|
||||
margin-top: 12rpx;
|
||||
color: #fff;
|
||||
font-size: 40rpx;
|
||||
font-weight: 900;
|
||||
line-height: 1.24;
|
||||
}
|
||||
|
||||
.tag {
|
||||
width: fit-content;
|
||||
margin-top: 18rpx;
|
||||
padding: 9rpx 18rpx;
|
||||
border-radius: 999rpx;
|
||||
color: #caa0ff;
|
||||
background: rgba(124, 58, 237, 0.18);
|
||||
}
|
||||
|
||||
.panel-title {
|
||||
display: block;
|
||||
margin-bottom: 16rpx;
|
||||
color: #fff;
|
||||
font-size: 30rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.body-text {
|
||||
font-size: 26rpx;
|
||||
line-height: 1.75;
|
||||
}
|
||||
|
||||
.ai-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
margin-bottom: 18rpx;
|
||||
color: #fff;
|
||||
font-size: 30rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.spark {
|
||||
color: #d982ff;
|
||||
}
|
||||
|
||||
.analysis-block {
|
||||
padding: 20rpx 0;
|
||||
border-top: 1rpx solid rgba(180, 139, 255, 0.14);
|
||||
}
|
||||
|
||||
.analysis-title {
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
color: #dccbff;
|
||||
font-size: 24rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.analysis-text {
|
||||
font-size: 24rpx;
|
||||
line-height: 1.65;
|
||||
}
|
||||
|
||||
.related-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 14rpx;
|
||||
padding-bottom: 34rpx;
|
||||
}
|
||||
|
||||
.tag-pill {
|
||||
height: 48rpx;
|
||||
padding: 0 18rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: rgba(237, 233, 254, 0.78);
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.bottom-actions {
|
||||
min-height: 124rpx;
|
||||
box-sizing: border-box;
|
||||
display: grid;
|
||||
grid-template-columns: 0.8fr 0.8fr 1.5fr 0.8fr;
|
||||
gap: 12rpx;
|
||||
padding: 14rpx 22rpx;
|
||||
background: rgba(5, 6, 21, 0.72);
|
||||
backdrop-filter: blur(24rpx);
|
||||
}
|
||||
|
||||
.action {
|
||||
height: 72rpx;
|
||||
border-radius: 999rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #caa0ff;
|
||||
font-size: 23rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.action.primary {
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user