LVX · 文档

接口文档#

本文档覆盖 LVX 站点当前对外提供的 HTTP 接口:账号服务、论坛服务、管理接口、商店发布审核接口,以及商店 / 插件仓库接口。

浏览器跨域调用:除 /store.json 外,接口默认不带 CORS 头,只允许同源页面调用。第三方客户端请使用服务端请求。

通用约定#

鉴权#

需要登录的接口在请求头带 JWT:

Authorization: Bearer <token>

返回格式#

成功:

{ "ok": true }

失败:

{ "ok": false, "error": "人类可读的错误说明" }

HTTP 状态码与 error 同时使用,客户端应以 HTTP 状态码为准。

错误码#

HTTP含义典型场景
400参数不合法标题为空、JSON 不合法、颜色格式错误
401未登录 / 登录过期 / 密码错误缺少 Bearer、令牌被撤销
403无权限非管理员访问后台、被禁言后发帖
404资源不存在帖子已删除、用户不存在
409冲突用户名已被注册
413请求体过大备份上传超过 4GB
429请求过于频繁触发限流、发帖间隔不足
500服务异常未预期错误

限流#

范围限制
账号服务全部 /api/*300 次 / 分钟 / IP
登录、注册10 次 / 分钟 / IP
论坛全部 /api/forum/*240 次 / 分钟 / IP
发帖30 秒 / 条,30 条 / 天 / 用户
回复8 秒 / 条 / 用户
举报30 秒 / 次 / 用户
插件仓库 /repo/*300 次 / 分钟 / IP

触发限流返回 429。账号服务的全局限流会带 Retry-After: 30。

分页#

论坛列表类接口使用:

参数默认说明
page1页码,从 1 开始
limit20每页条数,最大 50

响应包含 page、limit、total、pages。

账号 API#

账号服务处理注册、登录、Token、设备、头像、应用备份与账号注销。以下路径均以 /api 开头。

注册与登录#

POST /api/register 注册账号

字段类型必填说明
usernamestring是3–20 位字母、数字、下划线或中文
passwordstring是6–64 位
emailstring否最长 100 字符
rememberboolean否true 返回 30 天令牌
deviceIdstring否客户端持久化的设备标识,4–64 字符
deviceNamestring否设备名称,最长 60 字符
platformstring否平台标识,最长 40 字符

请求:

{
  "username": "lvx_user",
  "password": "secret123",
  "email": "[email protected]",
  "remember": true,
  "deviceId": "6f1c2a9e-device",
  "deviceName": "Chrome / Windows",
  "platform": "web"
}

响应 201:

{
  "ok": true,
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "user": {
    "id": 1200,
    "username": "lvx_user",
    "email": "[email protected]",
    "createdAt": "2026-10-23 06:30:00",
    "lastLoginAt": null,
    "avatarAt": null
  }
}

错误:400 用户名 / 密码不合法,409 用户名已存在,429 触发登录注册限流。

POST /api/login 登录

字段类型必填说明
usernamestring是用户名
passwordstring是密码
rememberboolean否true 返回 30 天令牌
deviceIdstring否设备标识
deviceNamestring否设备名称
platformstring否平台标识

响应 200 与注册相同。密码错误统一返回 401,不区分「用户不存在」与「密码错误」。

资料与设备#

GET /api/me 当前用户

响应:

{
  "ok": true,
  "user": {
    "id": 1200,
    "username": "lvx_user",
    "email": "[email protected]",
    "createdAt": "2026-10-23 06:30:00",
    "lastLoginAt": "2026-10-23 06:31:00",
    "avatarAt": null
  }
}

POST /api/change-password 修改密码

字段类型必填说明
oldPasswordstring是原密码
newPasswordstring是新密码,6–64 位

成功返回 { "ok": true, "message": "密码修改成功" };原密码错误返回 401。

GET /api/devices 登录设备列表

响应:

{
  "ok": true,
  "current": 12,
  "devices": [
    {
      "id": 12,
      "deviceId": "6f1c2a9e-device",
      "name": "Chrome / Windows",
      "platform": "web",
      "createdAt": "2026-10-23 06:30:00",
      "lastSeenAt": "2026-10-23 06:35:00",
      "current": true
    }
  ]
}

每个账号最多保留 20 台设备,超出时自动移除最久未使用的一台。

POST /api/devices/bind 绑定当前设备并换发令牌

请求:{ "deviceId": "...", "deviceName": "...", "platform": "..." }

响应:{ "ok": true, "token": "...", "deviceId": 13 }

POST /api/devices/revoke 撤销设备

响应:{ "ok": true, "removed": 1 };撤销的是当前设备时额外带 "self": true。

POST /api/logout 退出当前设备

删除当前设备记录,令牌立即失效。响应 { "ok": true }。

头像 / 备份 / 账号#

POST /api/avatar 上传头像

请求:{ "dataUrl": "data:image/png;base64,..." }

响应:{ "ok": true, "avatarAt": "2026-10-23T06:40:00.000Z" }

GET /api/avatar/:uid 读取头像

需要登录,且只能读取自己的头像;返回图片二进制,未设置时 404。

POST /api/upload 上传应用备份

响应:

{
  "ok": true,
  "file": "momotalk_20261023064000.zip",
  "size": 1048576,
  "time": "2026-10-23T06:40:00.000Z",
  "replaced": true
}

GET /api/uploads 列出备份

{
  "ok": true,
  "quota": 1,
  "files": [
    { "name": "momotalk_20261023064000.zip", "size": 1048576, "time": "2026-10-23T06:40:00.000Z" }
  ]
}

POST /api/backup/delete 删除备份

请求:{ "name": "momotalk_20261023064000.zip" }

响应:{ "ok": true, "removed": "momotalk_20261023064000.zip" }

GET /api/download/:filename 下载备份

返回 application/octet-stream。文件名做了 basename 处理,不能穿越目录。

POST /api/account/delete 注销账号

字段类型必填说明
passwordstring是当前密码
confirmstring是原样输入用户名

会删除账号、设备记录、头像与备份,不可恢复。

GET /health 健康检查

无需登录,/health 不在 /api 前缀下:

{ "ok": true, "service": "momotalk-auth", "users": 1200, "time": "2026-10-23T06:40:00.000Z" }

论坛 API#

论坛接口统一前缀 /api/forum,复用账号服务的账号与 JWT。

帖子#

GET /api/forum/stats 站点统计

{
  "ok": true,
  "posts": 12,
  "replies": 34,
  "users": 1200,
  "categories": [
    { "name": "综合", "count": 8 },
    { "name": "求助", "count": 2 },
    { "name": "创作", "count": 1 },
    { "name": "闲聊", "count": 1 },
    { "name": "公告", "count": 0 }
  ]
}

GET /api/forum/me 当前论坛身份

需要登录。返回账号、是否管理员、头衔:

{
  "ok": true,
  "user": { "id": 1001, "username": "lvx_admin" },
  "isAdmin": true,
  "title": { "name": "管理员", "color": "#dc2626" }
}

GET /api/forum/posts 帖子列表

参数类型必填说明
pagenumber否页码,默认 1
limitnumber否每页条数,默认 20,最大 50
qstring否搜索标题或正文,最长 60 字符
categorystring否综合 / 求助 / 创作 / 闲聊 / 公告

响应:

{
  "ok": true,
  "page": 1,
  "limit": 20,
  "total": 12,
  "pages": 1,
  "q": "",
  "category": "",
  "posts": [
    {
      "id": 12,
      "title": "第一篇帖子",
      "excerpt": "正文摘要…",
      "image": "/forum/uploads/1690000000-abcd.webp",
      "username": "lvx_user",
      "userId": 1200,
      "createdAt": "2026-10-23 06:30:00",
      "replyCount": 3,
      "likeCount": 5,
      "category": "综合",
      "tags": ["教程", "新手"],
      "authorTitle": { "name": "创作者", "color": "#0d9488" },
      "file": { "name": "note.txt", "kind": "txt", "size": 19 }
    }
  ]
}

image、authorTitle、file 可能为 null;tags 始终是数组。列表里的 file 只有元数据,不含内容。

GET /api/forum/posts/:id 帖子详情

{
  "ok": true,
  "post": {
    "id": 12,
    "title": "第一篇帖子",
    "body": "完整正文",
    "meta": "{\"score\":42}",
    "image": null,
    "username": "lvx_user",
    "userId": 1200,
    "createdAt": "2026-10-23 06:30:00",
    "replyCount": 1,
    "likeCount": 5,
    "category": "综合",
    "tags": ["教程"],
    "authorTitle": null,
    "file": {
      "name": "note.txt",
      "kind": "txt",
      "size": 19,
      "content": "第一行\n第二行"
    }
  },
  "replies": [
    {
      "id": 8,
      "userId": 1201,
      "username": "another_user",
      "body": "一级回复",
      "createdAt": "2026-10-23 06:31:00",
      "parentId": null,
      "parentUsername": null,
      "authorTitle": null
    },
    {
      "id": 9,
      "userId": 1200,
      "username": "lvx_user",
      "body": "回复二级评论",
      "createdAt": "2026-10-23 06:32:00",
      "parentId": 8,
      "parentUsername": "another_user",
      "authorTitle": null
    }
  ],
  "liked": false,
  "mine": true,
  "canModerate": false
}

回复结构说明:

POST /api/forum/posts 发帖

需要登录。请求体:

字段类型必填说明
titlestring是1–80 字符
bodystring是1–5000 字符
categorystring否默认「综合」,必须是预设分类
tagsstring否逗号分隔,最多 5 个,每个 ≤12 字
metastring否旧字段:附加 JSON 文本,≤1KB(新客户端请用 file)
fileobject否附件 {name, kind, content},见下方
imagestring否Data URL,≤3MB,PNG / JPEG / WebP
{
  "title": "第一篇帖子",
  "body": "正文内容",
  "category": "综合",
  "tags": "教程, 新手",
  "file": {
    "name": "note.txt",
    "kind": "txt",
    "content": "第一行\n第二行"
  }
}

图片会压缩为最长边 1600px 的 WebP(q82,去 EXIF)。响应 201,返回 post 对象。

限制:30 秒/条,30 条/天/用户;内容含屏蔽词返回 400;被禁言返回 403。

附件文件 file

字段类型必填说明
namestring是文件名,1–80 字符;不能包含路径分隔符或特殊字符;缺少扩展名会自动补 .txt / .json
kindstring是txt 或 json
contentstring是文件内容,1–16KB;json 必须是合法 JSON

DELETE /api/forum/posts/:id 删除自己的帖子

软删除,同时隐藏该帖回复、删除相关通知、把举报标记为已处理。只能删除自己的帖子,否则 403。

POST /api/forum/posts/:id/like 点赞 / 取消点赞

切换当前用户对该帖的点赞状态。响应:

{ "ok": true, "liked": true, "likes": 6 }

回复 / 点赞#

POST /api/forum/posts/:id/replies 回复

字段类型必填说明
bodystring是1–2000 字符
parentIdnumber否要回复的评论 id;不传为一级回复

响应 201:

{
  "ok": true,
  "reply": {
    "id": 10,
    "userId": 1200,
    "username": "lvx_user",
    "body": "回复内容",
    "createdAt": "2026-10-23 06:33:00",
    "parentId": 8,
    "parentUsername": "another_user",
    "authorTitle": null
  }
}

限制:8 秒/条;被禁言返回 403。回复帖子作者会收到通知;回复某条评论时,该评论作者也会收到通知(不通知自己)。

DELETE /api/forum/replies/:id 删除自己的回复

软删除;如果删除的是一级评论,其下的二级回复一并隐藏,并重算帖子的回复数。

用户 / 通知 / 举报#

GET /api/forum/users/:id 用户主页

{
  "ok": true,
  "user": {
    "id": 1001,
    "username": "lvx_admin",
    "joinedAt": "2026-10-21 09:49:12",
    "avatarAt": null,
    "title": { "name": "管理员", "color": "#dc2626" }
  },
  "postCount": 2,
  "replyCount": 0,
  "posts": [],
  "replies": [
    {
      "id": 3,
      "postId": 12,
      "postTitle": "第一篇帖子",
      "body": "回复内容",
      "createdAt": "2026-10-23 06:33:00"
    }
  ]
}

GET /api/forum/avatar/:uid 公开头像

返回图片二进制;未设置头像时 404。论坛展示用,不需要登录。

GET /api/forum/notifications 通知列表

需要登录。返回未读数和最近 30 条:

{
  "ok": true,
  "unread": 1,
  "items": [
    {
      "id": 5,
      "type": "reply",
      "postId": 12,
      "replyId": 10,
      "from": "another_user",
      "excerpt": "回复内容",
      "postTitle": "第一篇帖子",
      "read": false,
      "createdAt": "2026-10-23 06:33:00"
    }
  ]
}

type:post 表示回复了你的帖子,reply 表示回复了你的评论。

POST /api/forum/notifications/read 标记已读

响应 { "ok": true }。

POST /api/forum/reports 举报

需要登录。

字段类型必填说明
postIdnumber二选一举报帖子
replyIdnumber二选一举报回复
reasonstring否原因,最长 200 字符

响应 { "ok": true }。30 秒/次/用户。

管理 API#

管理接口前缀 /api/forum/admin,全部需要管理员权限;非管理员返回 403。

举报与内容#

GET /api/forum/admin/reports 未处理举报

返回最近 100 条:

{
  "ok": true,
  "reports": [
    {
      "id": 3,
      "post_id": 12,
      "reply_id": null,
      "reporter_id": 1201,
      "reporter_name": "another_user",
      "reason": "广告",
      "created_at": "2026-10-23 06:35:00",
      "resolved": 0,
      "post_title": "第一篇帖子",
      "content": "被举报的正文",
      "kind": "post",
      "hidden": 0,
      "target_post_id": 12
    }
  ]
}

POST /api/forum/admin/reports/:id/resolve 标记举报已处理

响应 { "ok": true }。

POST /api/forum/admin/posts/:id/hide 隐藏帖子

软删除,可由管理员恢复;同时删除相关通知、把该帖及其回复的举报标记为已处理。

POST /api/forum/admin/posts/:id/restore 恢复帖子

把 deleted 置回 0。

POST /api/forum/admin/replies/:id/hide 隐藏回复

软删除并重算帖子的回复数,同时处理该回复的举报。

POST /api/forum/admin/replies/:id/restore 恢复回复

把 deleted 置回 0 并重算回复数。

用户 / 头衔#

GET /api/forum/admin/users?q= 搜索用户

按用户名或邮箱模糊搜索,最多 20 条。q 最长 60 字符。

{
  "ok": true,
  "users": [
    {
      "id": 1001,
      "username": "lvx_admin",
      "email": "[email protected]",
      "joinedAt": "2026-10-21 09:49:12",
      "role": "admin",
      "title": { "name": "管理员", "color": "#dc2626" },
      "banned": false,
      "banReason": null
    }
  ]
}

POST /api/forum/admin/users/:id/title 指派头衔

请求:{ "titleId": 3 };传 null 或空值清除头衔。

响应:{ "ok": true, "title": { "name": "创作者", "color": "#0d9488" } }。

POST /api/forum/admin/users/:id/role 设置角色

请求:{ "role": "admin" } 或 { "role": "user" }。

不能取消最后一位管理员,否则返回 400。

POST /api/forum/admin/users/:id/ban 禁言 / 解禁

请求:{ "banned": true, "reason": "广告" } 或 { "banned": false }。

管理员不能被禁言。禁言后不能发帖、回复、举报。

GET /api/forum/admin/titles 头衔列表

{
  "ok": true,
  "titles": [
    { "id": 1, "name": "管理员", "color": "#dc2626", "users": 1 },
    { "id": 2, "name": "版主", "color": "#ea580c", "users": 0 }
  ]
}

POST /api/forum/admin/titles 新建头衔

字段类型必填说明
namestring是1–12 字,不能重名
colorstring是#RRGGBB

最多 50 个头衔。响应 201。

DELETE /api/forum/admin/titles/:id 删除头衔

使用该头衔的用户会失去头衔。

商店与仓库#

商店索引#

GET /store.json 商店条目

结构:

{
  "store": "lvx",
  "kind": "store",
  "updated": "2026-11-03",
  "apps": [
    {
      "id": "lvx-store",
      "name": "lvx-store",
      "title": "LVX Store",
      "summary": "一句话简介",
      "description": "详细描述",
      "kind": "app",
      "version": "1.0.0",
      "package": "",
      "packageUrl": null,
      "source": "official",
      "tags": ["应用"],
      "media": null
    }
  ]
}

tags 为字符串数组,用于商店页的标签筛选(如 示例 / 模型 / 推理 / 开发 / 应用 / Vulkan / 测试 / 工具 / CPU / MomoTalk-X/AI);仅展示与筛选,不影响安装。

插件仓库#

仓库根地址:https://lvx-office.com/repo/

GET /repo/manifest.json 包索引

{
  "name": "lvx-official-repo",
  "version": "3.0.0",
  "packages": [
    {
      "name": "lvx-ai-dev",
      "version": "1.0.0",
      "desc": "包描述",
      "dependencies": [],
      "files": [
        {
          "file": "liblvx_importer_gguf.so",
          "sha256": "9d567e1dc8fa...",
          "size": 153344
        }
      ]
    }
  ]
}

GET /repo/<path> 下载包文件

GET /lvx/1.0.0/... LVX 安装包

静态安装包与校验文件,链接自带内容版本参数;发布目录按版本管理。

商店发布 API#

面向第三方开发者的投稿接口。上传的 .lvx 先进入服务器私有待审区,不会立即出现在商店;管理员审核通过后,文件保留在待发布区,再由管理员执行上架。

可用标签#

GET /api/store/tags 公开

{"ok":true,"tags":["示例","模型","推理","开发","应用","测试","Vulkan","工具","CPU","MomoTalk-X/AI"]}

提交发布#

POST /api/store/publish 需要登录

字段类型必填说明
filefile是.lvx 文件,≤512MB
namestring是2–40 位小写字母/数字/点/下划线/短横线;规范化后必须与 LVX 清单里的 name 一致
titlestring否显示名,1–80 字;默认取清单 name
versionstring否x.y.z;默认取清单 version
summarystring否一句话简介,1–200 字;默认取清单 desc
descriptionstring否详细描述,≤2000 字;默认同 summary
kindstring否app / plugin / model;默认取清单 kind 或 app
tagsstring否逗号分隔或 JSON 数组,最多 5 个,必须在可用标签内;默认「应用」

file 必须是合法的 LVX2 容器,且包含可读的 AppManifest(section type 13);否则返回 400。

示例:

TOKEN='登录后拿到的 token'

curl -X POST https://lvx-office.com/api/store/publish \
  -H "Authorization: Bearer $TOKEN" \
  -F "[email protected]" \
  -F "name=myapp" \
  -F "title=My App" \
  -F "version=1.0.0" \
  -F "summary=一句话介绍" \
  -F "description=更详细的说明" \
  -F "kind=app" \
  -F "tags=应用"

响应 201:

{
  "ok": true,
  "submission": {
    "id": "sub_1793707494027_cf9351bc",
    "status": "pending",
    "name": "myapp",
    "title": "My App",
    "version": "1.0.0",
    "tags": ["应用"],
    "size": 184,
    "sha256": "b7c306...",
    "createdAt": "2026-11-03 12:04:54",
    "downloadUrl": "/api/store/publish/sub_1793707494027_cf9351bc/file"
  }
}

错误:400 文件/字段/标签不合法,401 未登录,409 name 已存在或有同名待审,413 超过 512MB,429 提交过频,507 待审空间不足。

我的提交#

GET /api/store/publish/mine 需要登录

返回当前用户最近 50 条提交,含状态与拒绝原因。

GET /api/store/publish/:id 需要登录(本人或管理员)

GET /api/store/publish/:id/file 需要登录(本人或管理员)

下载原始 .lvx,application/octet-stream。

审核接口#

以下接口需要管理员权限(论坛 roles 中 role = admin)。

GET /api/store/admin/submissions?status=pending

status:pending(默认)/ approved / rejected / all;limit 最大 100。

GET /api/store/admin/submissions/:id/file 下载待审文件

POST /api/store/admin/submissions/:id/approve 通过

{"ok":true,"status":"approved","note":"已通过审核,文件保留在服务器待发布区;发布到商店索引需管理员后续执行"}

POST /api/store/admin/submissions/:id/reject 拒绝

{"reason":"缺少 AppManifest 或版本号不正确"}

DELETE /api/store/admin/submissions/:id 删除记录并清理文件

状态流转#

状态含义
pending已上传,等待审核
approved审核通过,文件在待发布区
rejected审核拒绝,用户可查看原因并重新提交

审核通过不会自动修改 store.json、仓库索引或商店页面;上架动作由管理员在审核后执行。这样可以在人工确认内容、许可证与包完整性后再发布。

数据模型#

Post#

字段类型说明
idnumber帖子 id
titlestring标题
bodystring正文(列表接口为 excerpt)
metastring/null旧字段:附加 JSON 文本
fileobject/null附件 {name, kind, size};详情额外含 content
imagestring/null图片 URL
usernamestring作者用户名
userIdnumber作者 id
createdAtstring创建时间(UTC)
replyCountnumber回复数
likeCountnumber点赞数
categorystring分类
tagsstring[]标签
authorTitleobject/null作者头衔 {name,color}

Reply#

字段类型说明
idnumber回复 id
userIdnumber作者 id
usernamestring作者用户名
bodystring内容
createdAtstring时间
parentIdnumber/null一级回复为 null;二级回复指向一级评论
parentUsernamestring/null实际被回复的人
authorTitleobject/null作者头衔

Notification#

字段类型说明
idnumber通知 id
typestringpost / reply
postIdnumber关联帖子
replyIdnumber关联回复
fromstring触发者用户名
excerptstring回复摘要
postTitlestring帖子标题
readboolean是否已读
createdAtstring时间

调用示例#

注册并登录#

curl -s https://lvx-office.com/api/register \
  -H 'Content-Type: application/json' \
  -d '{"username":"lvx_user","password":"secret123","email":"[email protected]"}'
TOKEN=$(curl -s https://lvx-office.com/api/login \
  -H 'Content-Type: application/json' \
  -d '{"username":"lvx_user","password":"secret123","remember":true}' \
  | python3 -c 'import sys,json;print(json.load(sys.stdin)["token"])')

发帖与回复#

curl -s https://lvx-office.com/api/forum/posts \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"title":"你好","body":"第一帖","category":"综合","tags":"新手,测试"}'
curl -s https://lvx-office.com/api/forum/posts/12/replies \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"body":"回复一下","parentId":8}'

搜索与通知#

curl -s 'https://lvx-office.com/api/forum/posts?q=%E6%95%99%E7%A8%8B&category=%E7%BB%BC%E5%90%88&page=1'
curl -s https://lvx-office.com/api/forum/notifications \
  -H "Authorization: Bearer $TOKEN"

前端 fetch#

const token = localStorage.getItem('lvx-token');

const res = await fetch('/api/forum/posts?limit=10', {
  headers: { Authorization: `Bearer ${token}` }
});
const data = await res.json();
if (!data.ok) throw new Error(data.error);
管理员接口需要账号在 roles 表中为 admin;普通用户调用会返回 403。
接口文档对应 2026-10-23 线上版本;如与代码不一致,以实际响应为准。