## 阻断性缺陷 - list.vue 是 0 字节空文件、slist.vue 与 search/search.vue 从未存在, 而前者是 tabBar 首页、后者是 tabBar「搜索」页 —— 开屏即白屏。 按 .nvue 原型与详情页契约重建三页(CSS 渐变主视觉、分类筛选、搜索历史/热搜/联想)。 - parse-image-url.js 对空封面调 undefined.startsWith 直接抛错,列表页整页崩。 - 云函数目录缺 uni-cms-articles / uni-cms-categories / uni-cms-unlock-record schema 与 schema.ext.js,线上内容渲染与解锁逻辑无配置可用。 ## 越权与数据一致性 - uni-cms-articles:del/update/add 全部无鉴权,未登录即可删任意文章、 改他人文章作者与阅读量。补 login + 作者归属校验,作者与计数改为服务端取值。 - comments.likeComment/relikeComment:直接采信客户端传入的 user_id, 可冒名点赞刷计数。改为以令牌为准,并纳入事务。 - comments.updateComment:对数组取 .author_id,权限判断恒失败; 字段名 updateTime 与 ip_location 类型与 schema 不符。 - comments.deleteComment:`!root_id === 0` 优先级错误导致计数恒不减; 且误更新 uni-cms-articles、按不存在的 type 字段删点赞明细产生孤儿数据。 - cms-articles-like/collect:查重条件混入本次请求时间戳,防重永远失效, 可无限重复刷计数;补唯一索引并事务化。 - cms-vote:读-改-写票数导致并发丢票,记录与统计非原子;改为事务 + 原子自增。 - cms-articles-log:忽略传入 user_id 直接返回全表,泄露全站浏览记录。 - article_info:get() 使用未定义变量必崩;读接口全部无鉴权。 - user-info:公开资料接口可查任意用户 last_login_ip。 ## 资源与数据 - 全项目清空失效的签名外链(expire_at 均为 2025-03,必然 403), 改为本地生成资源:6 套文章模板、8 个编辑器图标、2 张文章配图。 - 新增分类 / 模板 / 礼物 / 热搜词种子数据,并在 db_init.json 登记, 同时补上点赞、收藏、投票、浏览日志的唯一索引。 ## 功能 - 草稿箱:预览页拆出「发布」与「存为草稿」,作品列表按状态筛选并显示徽标。 原实现有 4 个 tab 但只有 1 个有内容,且 article_status 在 UI 上无体现。 - 编辑中断恢复:接上原本空实现的「编辑草稿」回调,区分新建与编辑已有文章。 ## 工具 - tools/audit-project.js:编码 / 页面路由 / 云调用 / 云函数鉴权 / 敏感信息检查 - tools/check-vue.js:SFC 脚本语法(词法扫描处理 import·export 与条件编译) - tools/verify.js:一键验证;两个检查器各带自测,防止"永远通过" - tools/gen-*.py:模板与图标资源生成脚本
194 lines
6.7 KiB
JSON
194 lines
6.7 KiB
JSON
{
|
|
"uni-cms-categories": {
|
|
"data": [
|
|
{ "name": "新四军", "description": "新四军历史与老兵口述", "sort": 1, "article_count": 0, "create_date": 1740787200000 },
|
|
{ "name": "抗美援朝", "description": "抗美援朝战争亲历者回忆", "sort": 2, "article_count": 0, "create_date": 1740787200000 },
|
|
{ "name": "抗美援越", "description": "抗美援越时期的部队记忆", "sort": 3, "article_count": 0, "create_date": 1740787200000 },
|
|
{ "name": "对越自卫反击战", "description": "对越自卫反击战参战老兵纪实", "sort": 4, "article_count": 0, "create_date": 1740787200000 },
|
|
{ "name": "和平时期退役兵", "description": "和平年代参军、退役军人的故事", "sort": 5, "article_count": 0, "create_date": 1740787200000 },
|
|
{ "name": "老兵故事", "description": "老兵口述历史与人生经历", "sort": 6, "article_count": 0, "create_date": 1740787200000 },
|
|
{ "name": "军歌嘹亮", "description": "军旅歌曲、部队文艺与集体记忆", "sort": 7, "article_count": 0, "create_date": 1740787200000 },
|
|
{ "name": "英雄人物", "description": "战斗英雄与模范人物事迹", "sort": 8, "article_count": 0, "create_date": 1740787200000 }
|
|
]
|
|
},
|
|
"cms-temp": {
|
|
"data": [
|
|
{
|
|
"temptele_name": "军旅红(默认)",
|
|
"select_src": "/static/template/default.png",
|
|
"temptele_src": "/static/template/default.png",
|
|
"font_color": "#FFFFFF",
|
|
"backgrond_color": "#C11C1F",
|
|
"select_icon_color": "#FFFFFF",
|
|
"icon_color": "#F0C9C9",
|
|
"user_name_color": "#FFE3C2",
|
|
"btn_color": "#FFFFFF"
|
|
},
|
|
{
|
|
"temptele_name": "夜色",
|
|
"select_src": "/static/template/dark.png",
|
|
"temptele_src": "/static/template/dark.png",
|
|
"font_color": "#EBEBEB",
|
|
"backgrond_color": "#222831",
|
|
"select_icon_color": "#4ECDC4",
|
|
"icon_color": "#8A929B",
|
|
"user_name_color": "#F2C94C",
|
|
"btn_color": "#EBEBEB"
|
|
},
|
|
{
|
|
"temptele_name": "八一金",
|
|
"select_src": "/static/template/gold.png",
|
|
"temptele_src": "/static/template/gold.png",
|
|
"font_color": "#FFFAEB",
|
|
"backgrond_color": "#B07A28",
|
|
"select_icon_color": "#FFF3C4",
|
|
"icon_color": "#E3C48A",
|
|
"user_name_color": "#FFFFFF",
|
|
"btn_color": "#FFFAEB"
|
|
},
|
|
{
|
|
"temptele_name": "军绿",
|
|
"select_src": "/static/template/olive.png",
|
|
"temptele_src": "/static/template/olive.png",
|
|
"font_color": "#F0F5EB",
|
|
"backgrond_color": "#4A5E3A",
|
|
"select_icon_color": "#C8E6A0",
|
|
"icon_color": "#A8BC96",
|
|
"user_name_color": "#FFE9A8",
|
|
"btn_color": "#F0F5EB"
|
|
},
|
|
{
|
|
"temptele_name": "钢蓝",
|
|
"select_src": "/static/template/steel.png",
|
|
"temptele_src": "/static/template/steel.png",
|
|
"font_color": "#F0F4F8",
|
|
"backgrond_color": "#56687A",
|
|
"select_icon_color": "#9ED8FF",
|
|
"icon_color": "#B4C6D4",
|
|
"user_name_color": "#FFE3A8",
|
|
"btn_color": "#F0F4F8"
|
|
},
|
|
{
|
|
"temptele_name": "素白",
|
|
"select_src": "/static/template/light.png",
|
|
"temptele_src": "/static/template/light.png",
|
|
"font_color": "#3A322C",
|
|
"backgrond_color": "#FAF8F5",
|
|
"select_icon_color": "#C11C1F",
|
|
"icon_color": "#9A9088",
|
|
"user_name_color": "#8A6A3A",
|
|
"btn_color": "#C11C1F"
|
|
}
|
|
]
|
|
},
|
|
"gifts": {
|
|
"data": [
|
|
{ "url": "https://qnycdn.mymoyu.top/static/gift/honghua.png", "price": 100 },
|
|
{ "url": "https://qnycdn.mymoyu.top/static/gift/dahonghua.png", "price": 500 },
|
|
{ "url": "https://qnycdn.mymoyu.top/static/gift/junxie.png", "price": 1000 },
|
|
{ "url": "https://qnycdn.mymoyu.top/static/gift/junmao.png", "price": 2000 },
|
|
{ "url": "https://qnycdn.mymoyu.top/static/gift/jiangzhang.png", "price": 5000 },
|
|
{ "url": "https://qnycdn.mymoyu.top/static/gift/jinqi.png", "price": 10000 }
|
|
]
|
|
},
|
|
"opendb-search-hot": {
|
|
"data": [
|
|
{ "content": "新四军", "count": 0, "create_date": 1740787200000 },
|
|
{ "content": "抗美援朝", "count": 0, "create_date": 1740787200000 },
|
|
{ "content": "老兵故事", "count": 0, "create_date": 1740787200000 },
|
|
{ "content": "军歌", "count": 0, "create_date": 1740787200000 },
|
|
{ "content": "对越自卫反击战", "count": 0, "create_date": 1740787200000 },
|
|
{ "content": "抗美援越", "count": 0, "create_date": 1740787200000 },
|
|
{ "content": "退役军人", "count": 0, "create_date": 1740787200000 },
|
|
{ "content": "战斗英雄", "count": 0, "create_date": 1740787200000 },
|
|
{ "content": "军旅回忆", "count": 0, "create_date": 1740787200000 }
|
|
]
|
|
},
|
|
"cms-articles-like": {
|
|
"data": [],
|
|
"index": [
|
|
{
|
|
"IndexName": "user_article_unique",
|
|
"MgoKeySchema": {
|
|
"MgoIndexKeys": [
|
|
{ "Name": "user_id", "Direction": "1" },
|
|
{ "Name": "article_id", "Direction": "1" }
|
|
],
|
|
"MgoIsUnique": true
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"cms-articles-collect": {
|
|
"data": [],
|
|
"index": [
|
|
{
|
|
"IndexName": "user_article_unique",
|
|
"MgoKeySchema": {
|
|
"MgoIndexKeys": [
|
|
{ "Name": "user_id", "Direction": "1" },
|
|
{ "Name": "article_id", "Direction": "1" }
|
|
],
|
|
"MgoIsUnique": true
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"cms-vote": {
|
|
"data": [],
|
|
"index": [
|
|
{
|
|
"IndexName": "user_vote_unique",
|
|
"MgoKeySchema": {
|
|
"MgoIndexKeys": [
|
|
{ "Name": "user_id", "Direction": "1" },
|
|
{ "Name": "vote_id", "Direction": "1" }
|
|
],
|
|
"MgoIsUnique": true
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"cms-articles-log": {
|
|
"data": [],
|
|
"index": [
|
|
{
|
|
"IndexName": "user_article_unique",
|
|
"MgoKeySchema": {
|
|
"MgoIndexKeys": [
|
|
{ "Name": "user_id", "Direction": "1" },
|
|
{ "Name": "article_id", "Direction": "1" }
|
|
],
|
|
"MgoIsUnique": true
|
|
}
|
|
},
|
|
{
|
|
"IndexName": "article_last_view",
|
|
"MgoKeySchema": {
|
|
"MgoIndexKeys": [
|
|
{ "Name": "article_id", "Direction": "1" },
|
|
{ "Name": "last_view_time", "Direction": "-1" }
|
|
],
|
|
"MgoIsUnique": false
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"uni-cms-unlock-record": {
|
|
"data": [],
|
|
"index": [
|
|
{
|
|
"IndexName": "unique_article_trans_",
|
|
"MgoKeySchema": {
|
|
"MgoIndexKeys": [
|
|
{ "Name": "unique_id", "Direction": "1" },
|
|
{ "Name": "article_id", "Direction": "1" },
|
|
{ "Name": "trans_id", "Direction": "1" }
|
|
],
|
|
"MgoIsUnique": false
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|