feat: 优化小程序人生事件详情页、表单页和记录视图页样式

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-12 00:30:37 +08:00
parent 6230e2bc8d
commit f62ae880be
3 changed files with 143 additions and 32 deletions
+54 -7
View File
@@ -167,18 +167,65 @@ const profile = computed(() => store.userProfile || store.registrationData || {}
const bottomInset = computed(() => Math.max(0, safeAreaBottom.value))
const eventYear = computed(() => {
const date = displayEvent.value.time || displayEvent.value.date || displayEvent.value.eventDate
return date ? String(date).slice(0, 4) : '2025'
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(() => {
const date = displayEvent.value.time || displayEvent.value.date || displayEvent.value.eventDate
if (!date) return '05/20 - 05/28'
const month = String(date).slice(5, 7) || '05'
const day = String(date).slice(8, 10) || '20'
return `${month}/${day} - ${month}/${String(Math.min(28, Number(day) + 8)).padStart(2, '0')}`
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: '瞬间' }
+42 -17
View File
@@ -94,13 +94,13 @@
<picker mode="date" :value="form.time" @change="e => setRangeStart(e.detail.value)">
<view class="picker-field compact">
<view class="calendar-icon"></view>
<text>{{ formatDate(form.time) }}</text>
<text class="range-date-text">{{ formatShortDate(form.time) }}</text>
</view>
</picker>
<text class="range-line"></text>
<picker mode="date" :value="form.endTime" @change="e => setRangeEnd(e.detail.value)">
<view class="picker-field compact">
<text>{{ formatDate(form.endTime) }}</text>
<text class="range-date-text">{{ formatShortDate(form.endTime) }}</text>
<text class="chevron"></text>
</view>
</picker>
@@ -301,6 +301,11 @@ const formatDate = (value) => {
return `${year}${month}${day}`
}
const formatShortDate = (value) => {
if (!value) return '选择日期'
return String(value).replaceAll('-', '.')
}
const formatMonth = (value) => {
const [year, month] = (value || form.time.slice(0, 7)).split('-')
return `${year}${month}`
@@ -617,7 +622,7 @@ const goBack = () => {
flex: 1;
height: 0;
min-height: 0;
padding: 0 32rpx 28rpx;
padding: 0 28rpx 28rpx;
box-sizing: border-box;
}
@@ -625,7 +630,7 @@ const goBack = () => {
position: relative;
overflow: hidden;
border-radius: 30rpx;
padding: 38rpx 30rpx 88rpx;
padding: 36rpx 26rpx 84rpx;
border: 2rpx solid rgba(145, 70, 255, 0.76);
background:
radial-gradient(circle at 52% 8%, rgba(126, 72, 255, 0.13), transparent 35%),
@@ -648,9 +653,9 @@ const goBack = () => {
}
.group-title {
gap: 16rpx;
gap: 14rpx;
color: #d7bdff;
font-size: 31rpx;
font-size: 29rpx;
font-weight: 900;
}
@@ -766,7 +771,7 @@ const goBack = () => {
align-items: center;
justify-content: center;
color: rgba(224, 214, 243, 0.78);
font-size: 24rpx;
font-size: 22rpx;
font-weight: 600;
}
@@ -785,25 +790,31 @@ const goBack = () => {
border: 1rpx solid rgba(151, 111, 255, 0.28);
background: rgba(12, 15, 46, 0.74);
color: #fff;
font-size: 27rpx;
font-size: 25rpx;
}
.picker-field {
height: 78rpx;
margin-top: 26rpx;
padding: 0 24rpx;
padding: 0 22rpx;
display: flex;
align-items: center;
gap: 18rpx;
gap: 14rpx;
}
.picker-field text:nth-child(2) {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.picker-field.compact {
margin-top: 0;
min-width: 284rpx;
min-width: 0;
height: 72rpx;
padding: 0 16rpx;
}
.calendar-icon {
@@ -827,20 +838,34 @@ const goBack = () => {
.chevron {
flex: none !important;
color: rgba(224, 214, 243, 0.7);
font-size: 50rpx;
font-size: 42rpx;
line-height: 1;
}
.range-fields {
margin-top: 26rpx;
display: flex;
display: grid;
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
align-items: center;
gap: 12rpx;
gap: 10rpx;
}
.range-fields picker {
min-width: 0;
}
.range-line {
color: rgba(224, 214, 243, 0.7);
font-size: 24rpx;
font-size: 22rpx;
font-weight: 700;
}
.range-date-text {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.divider {
@@ -853,7 +878,7 @@ const goBack = () => {
.optional,
.custom-tag {
color: #b58bff;
font-size: 23rpx;
font-size: 22rpx;
font-weight: 600;
}
@@ -927,7 +952,7 @@ const goBack = () => {
align-items: center;
justify-content: center;
color: rgba(224, 214, 243, 0.74);
font-size: 24rpx;
font-size: 22rpx;
border: 1rpx solid rgba(151, 111, 255, 0.2);
background: rgba(20, 22, 58, 0.58);
}
+47 -8
View File
@@ -95,8 +95,8 @@
</view>
<view class="event-card kos-card">
<view class="date-box">
<text class="date-month">{{ getMonth(event.time) }}</text>
<text class="date-age">{{ getAgeText(event.time) }}</text>
<text class="date-month">{{ getTimelineDate(event) }}</text>
<text class="date-age">{{ getAgeText(event) }}</text>
</view>
<view class="event-divider"></view>
<view class="event-body">
@@ -206,7 +206,33 @@ const getMonth = (date) => {
return String(date).slice(0, 7).replace('-', '.')
}
const getAgeText = (date) => {
const isInvalidDateText = (value) => {
return !value || String(value).includes('%')
}
const getTimelineDate = (event) => {
if (event?.timeMode === 'range') {
const start = event.time || ''
const end = event.endTime || ''
if (start && end) return `${getMonth(start)}-${getMonth(end)}`
if (!isInvalidDateText(event.eventDateText)) return String(event.eventDateText).replace(/\s*至\s*/, '-')
}
if (event?.timeMode === 'month' && !isInvalidDateText(event.eventDateText)) {
return String(event.eventDateText).slice(0, 7).replace('-', '.')
}
if (event?.timeMode === 'season' && !isInvalidDateText(event.eventDateText)) {
const [year, season] = String(event.eventDateText).split('-')
const seasonMap = { spring: '春', summer: '夏', autumn: '秋', winter: '冬' }
return `${year}.${seasonMap[season] || '春'}`
}
return getMonth(event?.time)
}
const getAgeText = (event) => {
const date = event?.time
if (!date) return ''
const year = Number(String(date).slice(0, 4))
if (!year || !profile.value.birthYear) return ''
@@ -261,10 +287,11 @@ const addFilter = () => {
<style scoped>
.record-view {
position: relative;
display: flex;
flex-direction: column;
gap: 24rpx;
padding-bottom: 22rpx;
padding-bottom: 238rpx;
}
.profile-card {
@@ -602,6 +629,7 @@ const addFilter = () => {
.timeline {
display: flex;
flex-direction: column;
padding-bottom: 32rpx;
}
.timeline-item {
@@ -762,18 +790,25 @@ const addFilter = () => {
}
.create-fab {
align-self: center;
position: fixed;
left: 50%;
bottom: calc(124rpx + constant(safe-area-inset-bottom));
bottom: calc(124rpx + env(safe-area-inset-bottom));
z-index: 19;
display: flex;
flex-direction: column;
align-items: center;
gap: 8rpx;
transform: translateX(-50%);
color: #caa6ff;
font-size: 22rpx;
font-weight: 800;
text-shadow: 0 0 20rpx rgba(168, 85, 247, 0.72);
}
.plus-core {
width: 78rpx;
height: 78rpx;
width: 82rpx;
height: 82rpx;
border-radius: 50%;
display: flex;
align-items: center;
@@ -781,6 +816,10 @@ const addFilter = () => {
color: #fff;
font-size: 46rpx;
background: linear-gradient(135deg, #b348ff, #582cff);
box-shadow: 0 0 38rpx rgba(171, 72, 255, 0.62);
border: 2rpx solid rgba(235, 210, 255, 0.46);
box-shadow:
0 0 38rpx rgba(171, 72, 255, 0.68),
0 12rpx 34rpx rgba(0, 0, 0, 0.38),
inset 0 1rpx 0 rgba(255, 255, 255, 0.28);
}
</style>