const db = uniCloud.database() const collection = db.collection('uni-cms-articles') const uniID = require('uni-id-common') const isAdmin = (payload) => (payload.role || []).includes('admin') module.exports = { _before: function () { // 通用预处理器 this.uniID = uniID.createInstance({ context: this.getClientInfo() }) }, /** 校验登录并返回 payload;未登录抛错 */ async _requireLogin() { const payload = await this.uniID.checkToken(this.getUniIdToken()) if (payload.errCode) throw new Error('登录状态失效,请重新登录') return payload }, /** 校验当前用户是该文章作者(或管理员) */ async _requireOwner(id, payload) { if (!id) throw new Error('缺少文章 id') const res = await collection.doc(id).field({ user_id: true }).get() const doc = res.data && res.data[0] if (!doc) throw new Error('文章不存在') if (doc.user_id !== payload.uid && !isAdmin(payload)) { throw new Error('无权操作他人文章') } return doc }, async del_cms_articles(query) { try { const payload = await this._requireLogin() const { id } = query || {} await this._requireOwner(id, payload) await collection.doc(id).remove() return { code: 200 } } catch (e) { return { code: 500, msg: e.message } } }, async get_cms_articles_for_userId(query) { try { // 只能查自己的文章列表;管理员可指定他人 const payload = await this._requireLogin() const requested = query && query.user_id if (requested && requested !== payload.uid && !isAdmin(payload)) { return { code: 403, msg: '无权查看他人文章' } } const user_id = isAdmin(payload) && requested ? requested : payload.uid const res = await collection.where({ user_id: user_id, "edit_type": "mobile" }).get() return { code: 200, data: res.data } } catch (e) { console.error(e.message) return { code: 500, msg: e.message } } }, async update_cms_articles(query) { try { const payload = await this._requireLogin() const { id } = query || {} await this._requireOwner(id, payload) const { title, title_html, title_delta, thumbnail, p_type, category_id, temp_id, edit_type, excerpt, cmsLst, article_status } = query const now = new Date() const r = await collection.doc(id).update({ title, // 作者不可被客户端改写,始终以数据库中的归属为准 title_html, title_delta, thumbnail, p_type, category_id, temp_id, edit_type, excerpt, cmsLst, // 修改不应重置发布时间,只更新最后修改时间 last_modify_date: now, last_modify_ip: this.getClientInfo().clientIP, article_status }) if (!r.updated) { return { code: 500, msg: '更新失败' } } const res = await collection.doc(id).get() return { code: 200, res: { data: res.data[0], _id: id, user_id: payload.uid } } } catch (e) { return { code: 500, msg: e.message } } }, async add_cms_articles(query) { try { const payload = await this._requireLogin() const { title, title_html, title_delta, thumbnail, p_type, category_id, temp_id, edit_type, excerpt, cmsLst, article_status } = query const now = new Date() const r = await collection.add({ title, // 作者一律取登录态,不接受客户端传入 user_id: payload.uid, title_html, title_delta, thumbnail, p_type, category_id, temp_id, edit_type, excerpt, // 计数类字段由服务端维护,初始为 0 view_count: 0, like_count: 0, collect_count: 0, cmsLst, publish_date: now, last_modify_date: now, last_modify_ip: this.getClientInfo().clientIP, article_status }) const res = await collection.doc(r.id).get() return { code: 200, res: { data: res.data[0], _id: r.id, user_id: payload.uid } } } catch (e) { return { code: 500, msg: e.message } } }, async getTemp(query) { try { await this._requireLogin() const { temp_id } = query || {} if (!temp_id) return { code: 400, msg: '缺少 temp_id' } const res = await db.collection("cms-temp").doc(temp_id).get() return { code: 200, data: res.data[0] } } catch (e) { return { code: 500, msg: e.message } } }, async getTotal() { try { const res = await collection.where({ article_status: 1 }).count() return { code: 200, message: 'success', total: res.total } } catch (err) { return { code: 500, message: err.message } } }, // 文章访问日志服务 async detailLog(query) { try { const payload = await this._requireLogin() const articleId = query && query.articleId if (!articleId) return { code: -1, msg: '缺少文章 ID' } // 必须按「用户 + 文章」定位记录。只按 article_id 查询会命中别人的行, // 导致多人共用一条日志、自己的阅读时间永远不更新。 const userId = payload.uid const where = { user_id: userId, article_id: articleId } const { data: existingLog } = await db.collection('cms-articles-log').where(where).get() const now = new Date() if (existingLog.length > 0) { await db.collection('cms-articles-log') .doc(existingLog[0]._id) .update({ last_view_time: now, view_count: db.command.inc(1) }) } else { await db.collection('cms-articles-log').add({ user_id: userId, article_id: articleId, view_count: 1, first_view_time: now, last_view_time: now }) } return { code: 0, msg: '日志记录成功' } } catch (err) { console.error('日志记录失败:', err) return { code: -1, msg: '系统异常,请重试' } } } }