From 055549f1981ef92dbcd9cd5c0488516a86c4d621 Mon Sep 17 00:00:00 2001 From: ws Date: Tue, 21 Apr 2026 17:30:53 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E5=B0=8F=E7=A8=8B=E5=BA=8F=E4=BB=8E=E4=BA=91=E5=BC=80?= =?UTF-8?q?=E5=8F=91=E8=BF=81=E7=A7=BB=E8=87=B3=E5=90=8E=E7=AB=AFAPI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将云数据库操作改为调用后端API接口 提取登录失败处理逻辑到单独方法 添加环境配置和API请求工具类 移除云开发相关配置 --- app.js | 51 +++----- cloudfunctions/login/index.js | 54 -------- cloudfunctions/login/package.json | 9 -- pages/appointment/appointment.js | 7 +- pages/index/index.js | 2 +- pages/records/records.js | 2 +- project.config.json | 3 +- project.private.config.json | 5 +- utils/api.js | 131 ++++++++++++++++++++ utils/cloud.js | 196 ------------------------------ utils/config.js | 35 ++++++ 11 files changed, 192 insertions(+), 303 deletions(-) delete mode 100644 cloudfunctions/login/index.js delete mode 100644 cloudfunctions/login/package.json create mode 100644 utils/api.js delete mode 100644 utils/cloud.js create mode 100644 utils/config.js diff --git a/app.js b/app.js index dc71f5f..9c0bfea 100644 --- a/app.js +++ b/app.js @@ -1,16 +1,8 @@ // app.js +const { BASE_URL, API } = require('./utils/config') + App({ onLaunch() { - if (!wx.cloud) { - console.error('请使用 2.2.3 或以上的基础库以使用云能力') - } else { - wx.cloud.init({ - traceUser: true - }) - } - - - // 自动静默登录:wx.login 获取 code,再请求后端接口换取 openid this.silentLogin() }, @@ -22,66 +14,55 @@ App({ this.loginWithCode(loginRes.code) } else { console.error('wx.login 失败', loginRes.errMsg) - this.globalData.isLoggedIn = false - this.globalData.loginFailed = true - if (this.loginReadyCallback) { - this.loginReadyCallback(null) - } + this.handleLoginFail() } }, fail: (err) => { console.error('wx.login 调用失败', err) - this.globalData.isLoggedIn = false - this.globalData.loginFailed = true - if (this.loginReadyCallback) { - this.loginReadyCallback(null) - } + this.handleLoginFail() } }) }, loginWithCode(code) { wx.request({ - url: 'https://xcx.yun.588580.xyz/api/wx-mini/login', + url: BASE_URL + API.LOGIN, method: 'GET', data: { code }, success: (res) => { const result = res.data if (result && result.code === 0 && result.data) { - const openid = result.data.openid const userInfo = { - openid, + openid: result.data.openid, sessionKey: result.data.session_key, unionid: result.data.unionid || '' } - this.globalData.userInfo = userInfo this.globalData.isLoggedIn = true wx.setStorageSync('userInfo', userInfo) - if (this.loginReadyCallback) { this.loginReadyCallback(userInfo) } } else { console.error('后端登录失败', result) - this.globalData.isLoggedIn = false - this.globalData.loginFailed = true - if (this.loginReadyCallback) { - this.loginReadyCallback(null) - } + this.handleLoginFail() } }, fail: (err) => { console.error('请求后端登录接口失败', err) - this.globalData.isLoggedIn = false - this.globalData.loginFailed = true - if (this.loginReadyCallback) { - this.loginReadyCallback(null) - } + this.handleLoginFail() } }) }, + handleLoginFail() { + this.globalData.isLoggedIn = false + this.globalData.loginFailed = true + if (this.loginReadyCallback) { + this.loginReadyCallback(null) + } + }, + globalData: { userInfo: null, isLoggedIn: false, diff --git a/cloudfunctions/login/index.js b/cloudfunctions/login/index.js deleted file mode 100644 index 13c64ab..0000000 --- a/cloudfunctions/login/index.js +++ /dev/null @@ -1,54 +0,0 @@ -// 云函数入口文件 -const cloud = require('wx-server-sdk') - -cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) - -const db = cloud.database() - -// 云函数入口函数 -exports.main = async (event, context) => { - const wxContext = cloud.getWXContext() - const openid = wxContext.OPENID - - // 查找是否已存在用户 - const userRes = await db.collection('users').where({ _openid: openid }).get() - - let user - if (userRes.data.length > 0) { - // 已存在,更新登录时间(如果传了头像昵称也一并更新) - user = userRes.data[0] - const updateData = { - lastLoginTime: db.serverDate() - } - if (event.avatarUrl) updateData.avatarUrl = event.avatarUrl - if (event.nickName) updateData.nickName = event.nickName - await db.collection('users').doc(user._id).update({ data: updateData }) - // 合并最新数据返回 - if (event.avatarUrl) user.avatarUrl = event.avatarUrl - if (event.nickName) user.nickName = event.nickName - } else { - // 新用户,创建记录 - const addRes = await db.collection('users').add({ - data: { - _openid: openid, - avatarUrl: event.avatarUrl || '', - nickName: event.nickName || '', - createTime: db.serverDate(), - lastLoginTime: db.serverDate() - } - }) - user = { - _id: addRes._id, - _openid: openid, - avatarUrl: event.avatarUrl || '', - nickName: event.nickName || '' - } - } - - return { - openid: openid, - appid: wxContext.APPID, - unionid: wxContext.UNIONID, - userInfo: user - } -} diff --git a/cloudfunctions/login/package.json b/cloudfunctions/login/package.json deleted file mode 100644 index e610802..0000000 --- a/cloudfunctions/login/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "login", - "version": "1.0.0", - "description": "登录云函数", - "main": "index.js", - "dependencies": { - "wx-server-sdk": "~2.6.3" - } -} diff --git a/pages/appointment/appointment.js b/pages/appointment/appointment.js index 86ed315..4a37071 100644 --- a/pages/appointment/appointment.js +++ b/pages/appointment/appointment.js @@ -1,6 +1,6 @@ // appointment.js const { formatDate } = require('../../utils/util') -const { appointmentDB } = require('../../utils/cloud') +const { appointmentDB } = require('../../utils/api') const app = getApp() Page({ @@ -109,8 +109,9 @@ Page({ this.setData({ submitting: true }) try { - // 写入云数据库 - await appointmentDB.create(this.data.form) + // 通过后端API创建预约 + const openid = app.globalData.userInfo.openid + await appointmentDB.create({ ...this.data.form, openid }) this.setData({ submitting: false }) diff --git a/pages/index/index.js b/pages/index/index.js index fefdc04..6a68aa2 100644 --- a/pages/index/index.js +++ b/pages/index/index.js @@ -1,5 +1,5 @@ // index.js -const { appointmentDB, formatRecord } = require('../../utils/cloud') +const { appointmentDB, formatRecord } = require('../../utils/api') const app = getApp() Page({ diff --git a/pages/records/records.js b/pages/records/records.js index e4bfe7a..a72e451 100644 --- a/pages/records/records.js +++ b/pages/records/records.js @@ -1,5 +1,5 @@ // records.js -const { appointmentDB, formatRecord } = require('../../utils/cloud') +const { appointmentDB, formatRecord } = require('../../utils/api') const app = getApp() Page({ diff --git a/project.config.json b/project.config.json index 5209e1e..a017510 100644 --- a/project.config.json +++ b/project.config.json @@ -1,6 +1,6 @@ { "compileType": "miniprogram", - "libVersion": "trial", + "libVersion": "3.15.2", "packOptions": { "ignore": [], "include": [] @@ -37,6 +37,5 @@ "tabSize": 2 }, "appid": "wx50fe0c5c28dd3060", - "cloudfunctionRoot": "cloudfunctions/", "simulatorPluginLibVersion": {} } \ No newline at end of file diff --git a/project.private.config.json b/project.private.config.json index 3698571..60ebd34 100644 --- a/project.private.config.json +++ b/project.private.config.json @@ -1,6 +1,6 @@ { "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", - "projectname": "p1", + "projectname": "miniwx", "setting": { "compileHotReLoad": true, "urlCheck": true, @@ -18,5 +18,6 @@ "checkInvalidKey": true, "ignoreDevUnusedFiles": true }, - "libVersion": "3.15.2" + "libVersion": "3.15.2", + "condition": {} } \ No newline at end of file diff --git a/utils/api.js b/utils/api.js new file mode 100644 index 0000000..72abaa9 --- /dev/null +++ b/utils/api.js @@ -0,0 +1,131 @@ +// 后端 API 请求工具库 +const { BASE_URL, API } = require('./config') + +/** + * 封装 wx.request 为 Promise + * @param {object} options - wx.request 参数 + * @returns {Promise} 返回 result.data + */ +function request(options) { + return new Promise((resolve, reject) => { + wx.request({ + ...options, + success: (res) => { + const result = res.data + if (result && result.code === 0) { + resolve(result.data) + } else { + reject(new Error(result ? result.message : '请求失败')) + } + }, + fail: (err) => { + console.error('请求失败', options.url, err) + reject(err) + } + }) + }) +} + +/** + * 格式化记录中的 createTime 字段 + * @param {object} record - 含 createTime 的记录 + * @returns {object} 格式化后的记录 + */ +function formatRecord(record) { + if (!record || !record.createTime) return record + return { + ...record, + createTime: new Date(record.createTime).toLocaleString('zh-CN') + } +} + +/** + * 将后端 API 返回的预约记录映射为前端模板字段 + * 后端: id, visitDate, visitTime → 前端: _id, date, time + */ +function mapApiRecord(record) { + if (!record) return null + return { + ...record, + _id: record.id, + date: record.visitDate, + time: record.visitTime + } +} + +/** + * 预约相关 API + */ +const appointmentDB = { + /** + * 创建预约 + * @param {object} data - 预约表单数据(需包含 openid) + * @returns {Promise} 新记录 id + */ + async create(data) { + const result = await request({ + url: BASE_URL + API.APPOINTMENT_CREATE, + method: 'POST', + header: { 'content-type': 'application/json' }, + data: { + name: data.name, + phone: data.phone, + company: data.company, + reason: data.reason, + visitDate: data.date, + visitTime: data.time, + hostName: data.hostName, + area: data.area, + openid: data.openid + } + }) + return result.id + }, + + /** + * 获取当前用户的预约列表(按创建时间倒序) + * @param {string} openid + * @returns {Promise} + */ + async getList(openid) { + const list = await request({ + url: BASE_URL + API.APPOINTMENT_LIST, + method: 'GET', + data: { openid } + }) + return (list || []).map(item => mapApiRecord(item)) + }, + + /** + * 获取当前用户最新一条预约 + * @param {string} openid + * @returns {Promise} + */ + async getLatest(openid) { + const data = await request({ + url: BASE_URL + API.APPOINTMENT_LATEST, + method: 'GET', + data: { openid } + }) + return mapApiRecord(data) || null + }, + + /** + * 取消预约 + * @param {string} id - 预约记录 id + * @param {string} openid - 当前用户 openid + * @returns {Promise} 是否成功 + */ + async cancel(id, openid) { + const result = await request({ + url: BASE_URL + API.APPOINTMENT_CANCEL + '?id=' + encodeURIComponent(id) + '&openid=' + encodeURIComponent(openid), + method: 'PUT' + }) + return result === true + } +} + +module.exports = { + formatRecord, + appointmentDB +} diff --git a/utils/cloud.js b/utils/cloud.js deleted file mode 100644 index 1e4c040..0000000 --- a/utils/cloud.js +++ /dev/null @@ -1,196 +0,0 @@ -// 云数据库操作工具库 - -/** - * 延迟获取 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 -} diff --git a/utils/config.js b/utils/config.js new file mode 100644 index 0000000..f7c80fc --- /dev/null +++ b/utils/config.js @@ -0,0 +1,35 @@ +// 接口基础配置 + +// 环境地址配置 +const ENV_CONFIG = { + // 正式版 + release: 'https://xcx.yun.588580.xyz', + // 开发版 & 体验版 + develop: 'http://172.16.60.235:8080' +} + +// 自动判断当前运行环境 +function getBaseUrl() { + const accountInfo = wx.getAccountInfoSync() + const envVersion = accountInfo.miniProgram.envVersion + // release = 正式版, develop = 开发版, trial = 体验版 + return envVersion === 'release' ? ENV_CONFIG.release : ENV_CONFIG.develop +} + +const BASE_URL = getBaseUrl() + +// API 路径配置 +const API = { + LOGIN: '/api/wx-mini/login', + APPOINTMENT_LATEST: '/api/wx-mini/appointment/latest', + APPOINTMENT_LIST: '/api/wx-mini/appointment/list', + APPOINTMENT_CREATE: '/api/wx-mini/appointment/create', + APPOINTMENT_CANCEL: '/api/wx-mini/appointment/cancel' +} + +console.log('[config] 当前环境:', wx.getAccountInfoSync().miniProgram.envVersion, 'BASE_URL:', BASE_URL) + +module.exports = { + BASE_URL, + API +}