// 云数据库操作工具库 /** * 延迟获取 db 实例,确保 cloud.init 已完成 */ function getDb() { return wx.cloud.database() } function getCmd() { return getDb().command } /** * 格式化云数据库时间字段 * @param {object} record - 含 createTime 的记录 * @returns {object} 格式化后的记录 */ function formatRecord(record) { if (!record) return record const date = record.createTime let createTimeStr = '' if (date) { if (typeof date === 'string') { // 后端API返回的时间字符串,直接格式化 createTimeStr = new Date(date).toLocaleString('zh-CN') } else if (typeof date === 'object' && date.$date) { createTimeStr = new Date(date.$date).toLocaleString('zh-CN') } else if (typeof date === 'number') { createTimeStr = new Date(date).toLocaleString('zh-CN') } else { createTimeStr = new Date(date).toLocaleString('zh-CN') } } return { ...record, createTime: createTimeStr } } /** * 用户相关操作 */ const userDB = { /** * 通过 openId 查找用户,不存在则创建 * @param {string} openid * @returns {Promise} 用户记录 */ async loginOrCreate(openid) { const db = getDb() const res = await db.collection('users').where({ _openid: openid }).get() if (res.data.length > 0) { const existing = res.data[0] await db.collection('users').doc(existing._id).update({ data: { lastLoginTime: db.serverDate() } }) return existing } else { const addRes = await db.collection('users').add({ data: { _openid: openid, createTime: db.serverDate(), lastLoginTime: db.serverDate() } }) return { _id: addRes._id, _openid: openid } } } } /** * 预约相关操作 */ const appointmentDB = { /** * 创建预约 * @param {object} data - 预约表单数据 * @returns {Promise} 新记录 _id */ async create(data) { const db = getDb() const res = await db.collection('appointments').add({ data: { ...data, status: 'pending', statusText: '待审核', createTime: db.serverDate() } }) return res._id }, /** * 获取当前用户的预约列表(按创建时间倒序,自动分页取全部) * @param {string} openid * @returns {Promise} */ async getList(openid) { const db = getDb() const MAX_LIMIT = 100 let allData = [] let countResult = await db.collection('appointments').where({ _openid: openid }).count() const total = countResult.total const batchTimes = Math.ceil(total / MAX_LIMIT) for (let i = 0; i < batchTimes; i++) { const res = await db.collection('appointments') .where({ _openid: openid }) .orderBy('createTime', 'desc') .skip(i * MAX_LIMIT) .limit(MAX_LIMIT) .get() allData = allData.concat(res.data) } return allData }, /** * 将后端API返回的预约记录映射为前端模板兼容的字段 * 后端字段: id, visitDate, visitTime, createTime, ... * 前端字段: _id, date, time, createTime(格式化后), ... */ _mapApiRecord(record) { if (!record) return null return { ...record, _id: record.id, date: record.visitDate, time: record.visitTime } }, /** * 获取当前用户最新一条预约(通过后端API) * @param {string} openid * @returns {Promise} */ getLatest(openid) { return new Promise((resolve, reject) => { wx.request({ url: 'https://xcx.yun.588580.xyz/api/wx-mini/appointment/latest', method: 'GET', data: { openid }, success: (res) => { const result = res.data if (result && result.code === 0) { resolve(this._mapApiRecord(result.data) || null) } else { console.error('获取最新预约失败', result) reject(new Error(result ? result.message : '请求失败')) } }, fail: (err) => { console.error('请求后端获取最新预约失败', err) reject(err) } }) }) }, /** * 取消预约 * @param {string} id - 预约记录 _id * @param {string} openid - 当前用户 openid,用于权限校验 * @returns {Promise} 是否成功 */ async cancel(id, openid) { const db = getDb() const res = await db.collection('appointments').doc(id).get() if (res.data._openid !== openid) { return false } if (res.data.status !== 'pending') { return false } await db.collection('appointments').doc(id).update({ data: { status: 'cancelled', statusText: '已取消' } }) return true } } module.exports = { getDb, getCmd, formatRecord, userDB, appointmentDB }