3965e542fc
部署到群晖 / deploy (push) Failing after 6m22s
- 新增 server/:Node + Express + SQLite + node-cron 实现登录、纪念日 CRUD 和定时订阅消息推送 - 新增 .gitea/workflows/deploy.yml:推送即触发群晖 Docker 部署,监听 15002 - utils/api.js:自动按 envVersion 切换本地/线上 BASE_URL - app.js 与 add-anniversary.js 移除 wx.cloud 调用,改走自建后端 - cloudfunctions/ 暂保留以便回滚 - 一并提交此前未入库的首页 / 设置页 / 日历 / 万年历等改造 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
349 lines
8.0 KiB
JavaScript
349 lines
8.0 KiB
JavaScript
// add-anniversary.js
|
||
const storage = require('../../utils/storage')
|
||
const dateUtils = require('../../utils/date')
|
||
const api = require('../../utils/api')
|
||
|
||
Page({
|
||
data: {
|
||
anniversaryId: null,
|
||
personId: null,
|
||
personList: [],
|
||
personIndex: 0,
|
||
selectedPerson: '',
|
||
typeList: ['公历生日', '农历生日', '结婚纪念日', '订婚纪念日', '其他纪念日'],
|
||
typeIndex: 0,
|
||
showCustomType: false,
|
||
dateValue: '',
|
||
remindDaysList: ['提前3天', '提前7天', '提前14天', '提前30天', '自定义'],
|
||
remindDaysIndex: 0,
|
||
formData: {
|
||
isLunar: false,
|
||
type: 'birthday',
|
||
customTypeName: '',
|
||
solarYear: '',
|
||
solarMonth: '',
|
||
solarDay: '',
|
||
lunarYear: '',
|
||
lunarMonth: '',
|
||
lunarDay: '',
|
||
importance: 'low',
|
||
remindEnabled: true,
|
||
remindDays: 7,
|
||
remark: ''
|
||
}
|
||
},
|
||
|
||
onLoad(options) {
|
||
// 获取人员列表
|
||
const persons = storage.getPersons()
|
||
this.setData({ personList: persons })
|
||
|
||
if (options.personId) {
|
||
// 从人员详情页进入
|
||
const index = persons.findIndex(p => p.id === options.personId)
|
||
if (index !== -1) {
|
||
this.setData({
|
||
personIndex: index,
|
||
personId: options.personId,
|
||
selectedPerson: persons[index].name
|
||
})
|
||
}
|
||
}
|
||
|
||
if (options.id) {
|
||
// 编辑模式
|
||
this.setData({ anniversaryId: options.id })
|
||
this.loadAnniversary(options.id)
|
||
} else {
|
||
// 设置默认日期为今天
|
||
const today = new Date()
|
||
this.setData({
|
||
dateValue: dateUtils.formatDate(today, 'YYYY-MM-DD')
|
||
})
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 加载纪念日信息(编辑模式)
|
||
*/
|
||
loadAnniversary(id) {
|
||
const anniversaries = storage.getAnniversaries()
|
||
const anniversary = anniversaries.find(a => a.id === id)
|
||
|
||
if (anniversary) {
|
||
const date = dateUtils.formatDate(
|
||
new Date(anniversary.solarYear, anniversary.solarMonth - 1, anniversary.solarDay),
|
||
'YYYY-MM-DD'
|
||
)
|
||
|
||
// 设置类型
|
||
const typeIndex = this.getTypeIndex(anniversary.type)
|
||
|
||
this.setData({
|
||
formData: anniversary,
|
||
dateValue: date,
|
||
typeIndex,
|
||
showCustomType: anniversary.type === 'other'
|
||
})
|
||
|
||
wx.setNavigationBarTitle({ title: '编辑纪念日' })
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 获取类型索引
|
||
*/
|
||
getTypeIndex(type) {
|
||
const indexMap = {
|
||
birthday: 0,
|
||
lunar_birthday: 1,
|
||
wedding: 2,
|
||
engagement: 3,
|
||
other: 4
|
||
}
|
||
return indexMap[type] || 0
|
||
},
|
||
|
||
/**
|
||
* 选择人员
|
||
*/
|
||
onPersonChange(e) {
|
||
const index = parseInt(e.detail.value)
|
||
const person = this.data.personList[index]
|
||
this.setData({
|
||
personIndex: index,
|
||
personId: person.id,
|
||
selectedPerson: person.name
|
||
})
|
||
},
|
||
|
||
/**
|
||
* 选择类型
|
||
*/
|
||
onTypeChange(e) {
|
||
const index = parseInt(e.detail.value)
|
||
const types = ['birthday', 'lunar_birthday', 'wedding', 'engagement', 'other']
|
||
const isOther = index === 4
|
||
|
||
this.setData({
|
||
typeIndex: index,
|
||
showCustomType: isOther,
|
||
'formData.type': types[index]
|
||
})
|
||
},
|
||
|
||
/**
|
||
* 自定义类型输入
|
||
*/
|
||
onCustomTypeInput(e) {
|
||
this.setData({
|
||
'formData.customTypeName': e.detail.value
|
||
})
|
||
},
|
||
|
||
/**
|
||
* 日期类型改变
|
||
*/
|
||
onDateTypeChange(e) {
|
||
const isLunar = e.detail.value === 'lunar'
|
||
this.setData({
|
||
'formData.isLunar': isLunar
|
||
})
|
||
},
|
||
|
||
/**
|
||
* 日期改变
|
||
*/
|
||
onDateChange(e) {
|
||
const dateStr = e.detail.value
|
||
const parts = dateStr.split('-')
|
||
|
||
this.setData({
|
||
dateValue: dateStr,
|
||
'formData.solarYear': parseInt(parts[0]),
|
||
'formData.solarMonth': parseInt(parts[1]),
|
||
'formData.solarDay': parseInt(parts[2])
|
||
})
|
||
},
|
||
|
||
/**
|
||
* 重要程度改变
|
||
*/
|
||
onImportanceChange(e) {
|
||
this.setData({
|
||
'formData.importance': e.detail.value
|
||
})
|
||
},
|
||
|
||
/**
|
||
* 提醒开关改变
|
||
*/
|
||
onRemindEnabledChange(e) {
|
||
this.setData({
|
||
'formData.remindEnabled': e.detail.value
|
||
})
|
||
},
|
||
|
||
/**
|
||
* 提醒天数改变
|
||
*/
|
||
onRemindDaysChange(e) {
|
||
const index = parseInt(e.detail.value)
|
||
this.setData({ remindDaysIndex: index })
|
||
if (index === 4) {
|
||
// 自定义天数
|
||
wx.showModal({
|
||
title: '自定义提前天数',
|
||
editable: true,
|
||
placeholderText: '请输入天数(1-365)',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
const days = parseInt(res.content)
|
||
if (!days || days < 1 || days > 365) {
|
||
wx.showToast({ title: '请输入1-365之间的天数', icon: 'none' })
|
||
this.setData({ remindDaysIndex: 1, 'formData.remindDays': 7 })
|
||
return
|
||
}
|
||
this.setData({ 'formData.remindDays': days })
|
||
} else {
|
||
// 取消则回到默认7天
|
||
this.setData({ remindDaysIndex: 1, 'formData.remindDays': 7 })
|
||
}
|
||
}
|
||
})
|
||
} else {
|
||
const days = [3, 7, 14, 30][index]
|
||
this.setData({ 'formData.remindDays': days })
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 备注改变
|
||
*/
|
||
onRemarkChange(e) {
|
||
this.setData({
|
||
'formData.remark': e.detail.value
|
||
})
|
||
},
|
||
|
||
/**
|
||
* 取消
|
||
*/
|
||
onCancel() {
|
||
wx.navigateBack()
|
||
},
|
||
|
||
/**
|
||
* 提交
|
||
*/
|
||
async onSubmit() {
|
||
const { formData, personId, anniversaryId, personList } = this.data
|
||
|
||
// 验证关联人员
|
||
if (!personId) {
|
||
wx.showToast({ title: '请选择关联人员', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
// 验证日期
|
||
if (!formData.solarYear || !formData.solarMonth || !formData.solarDay) {
|
||
wx.showToast({ title: '请选择日期', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
// 验证自定义类型
|
||
if (formData.type === 'other' && !formData.customTypeName) {
|
||
wx.showToast({ title: '请输入自定义类型', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
// 如果开启了提醒,请求订阅消息授权
|
||
if (formData.remindEnabled) {
|
||
try {
|
||
await this.requestSubscribe()
|
||
} catch (err) {
|
||
console.log('用户拒绝订阅消息')
|
||
// 继续保存,即使用户拒绝订阅
|
||
}
|
||
}
|
||
|
||
// 获取人员名称
|
||
const person = personList.find(p => p.id === personId)
|
||
const personName = person ? person.name : ''
|
||
|
||
if (anniversaryId) {
|
||
// 编辑模式
|
||
const success = storage.updateAnniversary(anniversaryId, {
|
||
personId,
|
||
personName,
|
||
...formData
|
||
})
|
||
|
||
if (success) {
|
||
// 同步到云端
|
||
this.syncToCloud(anniversaryId, {
|
||
personId,
|
||
personName,
|
||
...formData
|
||
}, 'update')
|
||
|
||
wx.showToast({ title: '保存成功', icon: 'success' })
|
||
setTimeout(() => wx.navigateBack(), 1500)
|
||
}
|
||
} else {
|
||
// 新增模式
|
||
const newAnniversary = storage.addAnniversary({
|
||
personId,
|
||
personName,
|
||
...formData
|
||
})
|
||
|
||
if (newAnniversary) {
|
||
// 同步到云端
|
||
this.syncToCloud(newAnniversary.id, newAnniversary, 'add')
|
||
|
||
wx.showToast({ title: '添加成功', icon: 'success' })
|
||
setTimeout(() => wx.navigateBack(), 1500)
|
||
}
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 请求订阅消息授权
|
||
*/
|
||
requestSubscribe() {
|
||
return new Promise((resolve, reject) => {
|
||
wx.requestSubscribeMessage({
|
||
tmplIds: ['6J7Stt-lu7DKU6jblJ0nZGq_D81z5glnksf7qWfy5Yw'],
|
||
success: (res) => {
|
||
console.log('订阅消息授权结果:', res)
|
||
resolve(res)
|
||
},
|
||
fail: (err) => {
|
||
console.error('订阅消息授权失败:', err)
|
||
reject(err)
|
||
}
|
||
})
|
||
})
|
||
},
|
||
|
||
/**
|
||
* 同步到自建后端
|
||
*/
|
||
async syncToCloud(id, data, action) {
|
||
try {
|
||
const openid = wx.getStorageSync('openid')
|
||
if (!openid) {
|
||
console.log('未获取到openid,跳过云端同步')
|
||
return
|
||
}
|
||
const res = await api.anniversary(action, { id, ...data })
|
||
console.log('云端同步成功:', res)
|
||
} catch (err) {
|
||
console.error('云端同步失败:', err)
|
||
// 不影响本地保存
|
||
}
|
||
}
|
||
})
|
||
|