Initial Commit

This commit is contained in:
yuming
2025-10-26 19:29:30 +08:00
commit 6747ade9c4
33 changed files with 4387 additions and 0 deletions
+188
View File
@@ -0,0 +1,188 @@
// person-detail.js
const storage = require('../../utils/storage')
const dateUtils = require('../../utils/date')
Page({
data: {
personId: null,
person: {},
anniversaries: []
},
onLoad(options) {
if (!options.id) {
wx.showToast({ title: '参数错误', icon: 'none' })
wx.navigateBack()
return
}
this.setData({ personId: options.id })
this.loadPerson()
this.loadAnniversaries()
},
onShow() {
// 重新加载数据
this.loadPerson()
this.loadAnniversaries()
},
/**
* 加载人员信息
*/
loadPerson() {
const person = storage.getPersonById(this.data.personId)
if (person) {
this.setData({ person })
wx.setNavigationBarTitle({ title: person.name })
} else {
wx.showToast({ title: '人员不存在', icon: 'none' })
wx.navigateBack()
}
},
/**
* 加载纪念日
*/
loadAnniversaries() {
const anniversaries = storage.getAnniversariesByPersonId(this.data.personId)
// 格式化纪念日数据
const formatted = anniversaries.map(a => {
const date = new Date(a.solarYear, a.solarMonth - 1, a.solarDay)
const daysUntil = dateUtils.getDaysUntil(date)
return {
...a,
date,
dateText: dateUtils.formatDate(date, 'YYYY年MM月DD日'),
daysUntil,
typeIcon: this.getTypeIcon(a.type),
typeName: a.customTypeName || this.getTypeName(a.type),
importanceText: this.getImportanceText(a.importance)
}
})
// 按日期排序
formatted.sort((a, b) => a.daysUntil - b.daysUntil)
this.setData({ anniversaries: formatted })
},
/**
* 获取类型图标
*/
getTypeIcon(type) {
const icons = {
birthday: '🎂',
lunar_birthday: '🌙',
wedding: '💍',
engagement: '💕',
other: '📅'
}
return icons[type] || '📅'
},
/**
* 获取类型名称
*/
getTypeName(type) {
const names = {
birthday: '公历生日',
lunar_birthday: '农历生日',
wedding: '结婚纪念日',
engagement: '订婚纪念日',
other: '其他纪念日'
}
return names[type] || '其他'
},
/**
* 获取重要程度文本
*/
getImportanceText(importance) {
const texts = {
high: '非常重要',
medium: '重要',
low: '一般'
}
return texts[importance] || '一般'
},
/**
* 编辑人员
*/
onEditPerson() {
wx.navigateTo({
url: `/pages/add-person/add-person?id=${this.data.personId}`
})
},
/**
* 删除人员
*/
onDeletePerson() {
wx.showModal({
title: '确认删除',
content: `确定要删除"${this.data.person.name}"吗?相关纪念日也将被删除。`,
success: (res) => {
if (res.confirm) {
// 先删除相关纪念日
const anniversaries = storage.getAnniversariesByPersonId(this.data.personId)
anniversaries.forEach(a => storage.deleteAnniversary(a.id))
// 再删除人员
const success = storage.deletePerson(this.data.personId)
if (success) {
wx.showToast({ title: '删除成功', icon: 'success' })
setTimeout(() => {
wx.navigateBack()
}, 1500)
}
}
}
})
},
/**
* 添加纪念日
*/
onAddAnniversary() {
wx.navigateTo({
url: `/pages/add-anniversary/add-anniversary?personId=${this.data.personId}`
})
},
/**
* 编辑纪念日
*/
onEditAnniversary(e) {
const id = e.currentTarget.dataset.id
wx.navigateTo({
url: `/pages/add-anniversary/add-anniversary?personId=${this.data.personId}&id=${id}`
})
},
/**
* 删除纪念日
*/
onDeleteAnniversary(e) {
const id = e.currentTarget.dataset.id
const anniversary = this.data.anniversaries.find(a => a.id === id)
wx.showModal({
title: '确认删除',
content: '确定要删除这条纪念日吗?',
success: (res) => {
if (res.confirm) {
const success = storage.deleteAnniversary(id)
if (success) {
wx.showToast({ title: '删除成功', icon: 'success' })
this.loadAnniversaries()
}
}
}
})
}
})
+63
View File
@@ -0,0 +1,63 @@
<!--person-detail.wxml-->
<view class="container">
<!-- 人员信息卡片 -->
<view class="person-card">
<view class="person-header">
<image class="avatar" src="{{person.avatar || '/images/default-avatar.png'}}" mode="aspectFill" />
<view class="person-info">
<text class="person-name">{{person.name}}</text>
<text wx:if="{{person.nickname}}" class="person-nickname">{{person.nickname}}</text>
</view>
</view>
<text wx:if="{{person.remark}}" class="person-remark">{{person.remark}}</text>
<view class="actions">
<button class="action-btn" bindtap="onEditPerson">编辑</button>
<button class="action-btn danger" bindtap="onDeletePerson">删除</button>
</view>
</view>
<!-- 纪念日列表 -->
<view class="section">
<view class="section-header">
<text class="section-title">纪念日列表 ({{anniversaries.length}})</text>
<button class="add-btn" bindtap="onAddAnniversary">+ 添加纪念日</button>
</view>
<view wx:if="{{anniversaries.length === 0}}" class="empty-state">
<text class="icon">📅</text>
<text class="text">还没有添加纪念日</text>
</view>
<view wx:for="{{anniversaries}}" wx:key="id" class="anniversary-card">
<view class="anniversary-header">
<view class="anniversary-type">
<text class="type-icon">{{item.typeIcon}}</text>
<text class="type-text">{{item.typeName}}</text>
</view>
<text class="importance-badge importance-{{item.importance}}">{{item.importanceText}}</text>
</view>
<view class="anniversary-date">
<text class="date-label">日期:</text>
<text class="date-text">{{item.dateText}}</text>
<text wx:if="{{item.isLunar}}" class="lunar-badge">农历</text>
</view>
<view wx:if="{{item.daysUntil !== undefined}}" class="days-info">
<text wx:if="{{item.daysUntil === 0}}" class="days-text urgent">今天</text>
<text wx:else-if="{{item.daysUntil === 1}}" class="days-text warning">明天</text>
<text wx:else-if="{{item.daysUntil > 0}}" class="days-text">{{item.daysUntil}}天后</text>
<text wx:else class="days-text past">已过{{Math.abs(item.daysUntil)}}天</text>
</view>
<view wx:if="{{item.remark}}" class="anniversary-remark">{{item.remark}}</view>
<view class="anniversary-actions">
<button class="edit-btn" bindtap="onEditAnniversary" data-id="{{item.id}}">编辑</button>
<button class="delete-btn" bindtap="onDeleteAnniversary" data-id="{{item.id}}">删除</button>
</view>
</view>
</view>
</view>
+273
View File
@@ -0,0 +1,273 @@
/**person-detail.wxss**/
.container {
min-height: 100vh;
background-color: #f5f5f5;
padding-bottom: 120rpx;
}
.person-card {
background-color: #fff;
margin: 32rpx;
border-radius: 16rpx;
padding: 40rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
}
.person-header {
display: flex;
align-items: center;
margin-bottom: 24rpx;
}
.avatar {
width: 120rpx;
height: 120rpx;
border-radius: 50%;
margin-right: 32rpx;
background-color: #f0f0f0;
}
.person-info {
flex: 1;
}
.person-name {
font-size: 36rpx;
font-weight: 600;
color: #333;
display: block;
margin-bottom: 8rpx;
}
.person-nickname {
font-size: 26rpx;
color: #999;
}
.person-remark {
font-size: 28rpx;
color: #666;
line-height: 1.6;
margin-bottom: 24rpx;
padding: 24rpx;
background-color: #f9f9f9;
border-radius: 8rpx;
}
.actions {
display: flex;
gap: 24rpx;
margin-top: 32rpx;
}
.action-btn {
flex: 1;
height: 72rpx;
line-height: 72rpx;
border-radius: 12rpx;
font-size: 28rpx;
background-color: #f5f5f5;
color: #666;
border: none;
}
.action-btn.danger {
background-color: #fff3f0;
color: #ff5722;
}
.action-btn::after {
border: none;
}
/* 纪念日列表 */
.section {
padding: 0 32rpx;
}
.section-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 24rpx;
}
.section-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.add-btn {
padding: 12rpx 24rpx;
background-color: #07c160;
color: #fff;
border-radius: 40rpx;
font-size: 24rpx;
border: none;
}
.add-btn::after {
border: none;
}
/* 纪念日卡片 */
.anniversary-card {
background-color: #fff;
border-radius: 16rpx;
padding: 32rpx;
margin-bottom: 24rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
}
.anniversary-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20rpx;
}
.anniversary-type {
display: flex;
align-items: center;
}
.type-icon {
font-size: 40rpx;
margin-right: 12rpx;
}
.type-text {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.importance-badge {
padding: 8rpx 20rpx;
border-radius: 40rpx;
font-size: 22rpx;
}
.importance-high {
background-color: #fff3f0;
color: #ff5722;
}
.importance-medium {
background-color: #fff8e6;
color: #ff9800;
}
.importance-low {
background-color: #f5f5f5;
color: #999;
}
.anniversary-date {
margin-bottom: 16rpx;
font-size: 26rpx;
color: #666;
}
.date-label {
color: #999;
}
.date-text {
color: #333;
font-weight: 500;
margin-right: 12rpx;
}
.lunar-badge {
display: inline-block;
padding: 4rpx 12rpx;
background-color: #e3f2fd;
color: #1976d2;
border-radius: 4rpx;
font-size: 20rpx;
}
.days-info {
margin: 16rpx 0;
}
.days-text {
font-size: 28rpx;
font-weight: 500;
color: #07c160;
}
.days-text.urgent {
color: #ff5722;
font-weight: 600;
}
.days-text.warning {
color: #ff9800;
}
.days-text.past {
color: #999;
}
.anniversary-remark {
font-size: 26rpx;
color: #999;
line-height: 1.6;
margin: 16rpx 0;
padding: 16rpx;
background-color: #f9f9f9;
border-radius: 8rpx;
}
.anniversary-actions {
display: flex;
gap: 16rpx;
margin-top: 24rpx;
padding-top: 24rpx;
border-top: 1px solid #f0f0f0;
}
.edit-btn,
.delete-btn {
flex: 1;
height: 64rpx;
line-height: 64rpx;
border-radius: 8rpx;
font-size: 24rpx;
border: none;
}
.edit-btn {
background-color: #f5f5f5;
color: #666;
}
.delete-btn {
background-color: #fff3f0;
color: #ff5722;
}
.edit-btn::after,
.delete-btn::after {
border: none;
}
.empty-state {
text-align: center;
padding: 120rpx 40rpx;
}
.empty-state .icon {
font-size: 120rpx;
display: block;
margin-bottom: 32rpx;
}
.empty-state .text {
font-size: 28rpx;
color: #999;
}