Appearance
前端交互接口完整参考
本文档详细列出 DJAOD 前端可用的全部 AJAX 接口,由 Ajax.js 控制器(controller/Ajax.js)提供。
接口约定
通用响应格式
json
{
"code": 200, // 状态码:200=成功, 400=参数错误, 401=未登录, 403=权限不足, 500=服务器错误
"msg": "ok", // 提示消息
"data": {} // 响应数据
}请求头约定
| 头部 | 值 | 说明 |
|---|---|---|
Content-Type | application/json | 请求体格式 |
x-requested-with | XMLHttpRequest | AJAX 标记(用于服务端判断是否返回 JSON) |
uuid | 浏览器指纹 | 音频接口等安全接口使用 |
全局 AJAX 接口
1. AJAX 列表加载(HTML 片段返回)
用于前端「加载更多」或「筛选切换」场景,返回渲染好的 HTML 片段。
- 地址:
GET /ajax/index - 鉴权:无需登录(
noNeedLogin) - Content-Type:
text/html或application/html
请求参数
| 参数 | 类型 | 必需 | 默认值 | 说明 |
|---|---|---|---|---|
modename | String | 否 | music_song | 数据模型名(白名单限制) |
orderway | String | 否 | - | 排序方向:asc 或 desc |
orderby | String | 否 | createtime | 排序字段(白名单限制) |
whereTime | String | 否 | - | 时间筛选:today/yesterday/week/lastWeek/month/lastMonth/year |
page | Number | 否 | 1 | 页码 |
tplid | String | 否 | - | 渲染模板标识:item-dynamic/hot-cell/swiper-slide/music-cell/slide-author/music-block/store-item |
query | String | 否 | - | 查询条件(URL 编码的 JSON 字符串) |
num | Number | 否 | 20 | 每页数量(最大 30) |
cachetime | Number | 否 | 600 | 缓存时间(秒) |
查询条件 $ 操作符白名单(安全限制):$eq、$ne、$in、$gt、$gte、$lt、$lte
排序字段白名单:createtime、updatetime、price、views、likes、sort、plays、downs
示例
http
GET /ajax/index?modename=music_song&orderby=createtime&orderway=desc&page=1&tplid=music-cell&query=%7B%22type_ids%22%3A%5B%22abc%22%5D%7D
x-requested-with: XMLHttpRequest
Content-Type: application/html响应为渲染好的 HTML 片段,直接插入 DOM:
html
<div class="swiper-slide column is-3-tablet is-2-desktop">
<figure class="image is-1by1">...</figure>
<p class="title is-6">歌曲标题</p>
</div>
<div class="swiper-slide column is-3-tablet is-2-desktop">
...
</div>2. 音频播放器接口(加密通信)
- 地址:
GET /ajax/audioplayer - 鉴权:无需登录(
noNeedLogin) - 安全机制:WASM AES-256 加密 + 浏览器指纹
请求参数
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
signature | String | 是 | WASM 加密的参数(加密 JSON.stringify({ id, type })) |
请求头
| 头部 | 说明 |
|---|---|
uuid | 浏览器指纹(FingerprintJS 生成) |
加密流程
js
import init, { encrypt, decrypt } from '/wasm_decrypt/xcore.js';
await init();
// 1. 获取 signature Cookie
let secret = getCookie('signature');
// 2. 构造查询
let query = { id: "abc123", type: "music" };
// 3. 加密
const data = {
signature: await encrypt(JSON.stringify(query), secret, 'string')
};
// 4. 发送请求
const params = new URLSearchParams(data).toString();
fetch(`/ajax/audioplayer?${params}`, {
headers: { 'uuid': uuid }
})
.then(res => res.json())
.then(({ code, msg, data }) => {
// 5. 解密响应
const obj = JSON.parse(decrypt(data, secret, 'string'));
// obj 包含播放列表数据
});响应
json
{
"code": 200,
"msg": "OK",
"data": "加密后的 base64 字符串..."
}解密后得到播放列表数据,包含:下载地址、封面图、标题、作者、波形数据等。
3. 购买下载接口
- 地址:
POST /ajax/buyDownload - 鉴权:需要登录
请求参数
| 参数 | 类型 | 说明 |
|---|---|---|
id | String | 资源 ID |
type | String | 资源类型(music/video/album/product) |
presale | String | 是否为预售(1=是) |
响应 data 字段
| 字段 | 类型 | 说明 |
|---|---|---|
isPaid | Boolean | 是否已付费 |
isLogin | Boolean | 是否已登录 |
isvip | Boolean | 是否为 VIP |
price | Number | 价格 |
score | Number | 所需积分 |
pay_params | Array | 可用支付方式列表 |
pay_params[].paytype | String | 支付方式:wechat/alipay/balance/score/vip |
pay_params[].title | String | 支付方式标题 |
vipurl | String | VIP 购买 URL |
isWechat | Boolean | 是否在微信中 |
4. 生成下载签名接口
- 地址:
POST /ajax/signature - 返回格式:
.html(实际返回 JSON)
请求参数
| 参数 | 类型 | 说明 |
|---|---|---|
id | String | 资源 ID |
model | String | 数据模型 |
type | String | 操作类型(download) |
响应
json
{
"code": 200,
"data": [
{
"type": "qiniu",
"url": "https://...",
"fileName": "song.mp3",
"icon": "<svg>...</svg>"
},
{
"type": "pan",
"url": "https://pan.baidu.com/...",
"password": "abcd",
"icon": "<svg>...</svg>"
}
]
}5. 关注/取消关注
- 地址:
POST /ajax/follow - 鉴权:需要登录
请求参数
| 参数 | 类型 | 说明 |
|---|---|---|
id | String | 目标对象 ID |
type | String | 目标类型:user(关注作者)或 author(作者关注用户) |
event | String | 操作:add(关注)或 remove(取消关注) |
业务规则
type=user时,不能关注自己(自己关注自己的作者身份)- 已关注时执行
add或未关注时执行remove,返回当前状态(幂等操作)
6. 收藏/取消收藏
- 地址:
POST /ajax/collect - 鉴权:需要登录
请求参数
| 参数 | 类型 | 说明 |
|---|---|---|
model | String | 目标模型类型 |
targetId | String | 目标资源 ID |
7. 点赞/踩/反应
- 地址:
POST /ajax/reactions - 鉴权:需要登录
请求参数
| 参数 | 类型 | 说明 |
|---|---|---|
type | String | 反应类型:likes(点赞)、dislikes(点踩) |
model | String | 目标模型类型(如 comment) |
targetId | String | 目标资源 ID |
响应
json
{
"code": 200,
"msg": "ok",
"data": {
"type": "add" // "add" 或 "remove"
}
}8. 分享接口
- 地址:
POST /ajax/share - 鉴权:无需登录(
noNeedLogin)
请求参数
| 参数 | 类型 | 说明 |
|---|---|---|
type | String | 资源类型:music/album/author/circle/movie/goods/special |
id | String | 资源 ID |
share | String | 分享目标:wechat(微信)或其他 |
响应(share != "wechat" 时)
json
{
"code": 200,
"data": [
{
"title": "复制链接",
"icon": "fa fa-copy",
"name": "copy",
"url": "https://..."
},
{
"title": "分享到QQ",
"icon": "fab fa-qq",
"name": "qq",
"url": "http://connect.qq.com/widget/shareqq/..."
},
{
"title": "分享到微博",
"icon": "fab fa-weibo",
"name": "weibo",
"url": "https://service.weibo.com/share/..."
},
{
"title": "微信扫一扫",
"icon": "fab fa-weixin",
"name": "wechat",
"url": "https://..."
}
]
}响应(share == "wechat" 时)
json
{
"code": 200,
"data": {
"appId": "wx...",
"timestamp": "1234567890",
"nonceStr": "abc...",
"signature": "def...",
"obj": {
"title": "分享标题",
"desc": "分享描述",
"image": "https://...",
"url": "https://..."
}
}
}9. 上传配置接口
- 地址:
GET /ajax/uploadConfig - 鉴权:需要登录 + 签名验证
请求参数
| 参数 | 类型 | 说明 |
|---|---|---|
signature | String | 加密的上传参数(JSON.stringified 后 AES 加密) |
安全机制
- 验证
signatureCookie(Redis 中是否存在且未被消费) - Cookie 使用后立即删除(一次性签名,防重放)
- 对请求体中的
signature进行解密 - 检测
_fake字段防伪造请求 - 上传记录写入 Redis(
upload:temp:<user_id>),用于后续文件归属验证
10. 上传回调通知
- 地址:
POST /ajax/uploadNotify - 鉴权:需要登录
响应云存储上传完成后的回调,更新播放/下载地址到 Redis。
11. 发送短信验证码
- 地址:
POST /ajax/sendSms - 鉴权:无需登录(
noNeedLogin)
请求参数
| 参数 | 类型 | 说明 |
|---|---|---|
mobile | String | 手机号码 |
event | String | 事件类型(如 register、login) |
captcha | String | 点选验证码加密串 |
12. 发送邮件验证码
- 地址:
POST /ajax/sendEmail - 鉴权:无需登录(
noNeedLogin)
请求参数
| 参数 | 类型 | 说明 |
|---|---|---|
email | String | 邮箱地址 |
event | String | 事件类型 |
captcha | String | 点选验证码加密串 |
13. 点选验证码
- 地址:
GET /ajax/captcha - 鉴权:无需登录(
noNeedLogin)
请求参数
| 参数 | 类型 | 说明 |
|---|---|---|
t | String | 当前表单数据的 MD5 值 |
响应
json
{
"code": 200,
"data": {
"hint": "base64图片...", // 提示图(需要点击的顺序)
"image": "base64图片...", // 验证码大图
"token": "abc..." // 验证令牌(用于加密点击坐标)
}
}返回验证结果
前端将点击坐标加密后,作为 captcha 参数随业务请求一起提交:
js
const encryptedClickList = encryptForNodeJS(clickPositions, captchaToken);
// 将 encryptedClickList 作为 captcha 参数提交14. 草稿箱接口
- 地址:
GET|POST /ajax/draft - 鉴权:需要登录
查询参数
| 参数 | 类型 | 说明 |
|---|---|---|
type | String | 草稿类型:single/set/album/circle |
mode | String | 操作模式:get(获取)、set(保存)、delete_file(删除文件)、del(删除草稿) |
POST 请求体(保存草稿时)
| 参数 | 类型 | 说明 |
|---|---|---|
id | String | 编辑的数据 ID |
listName | String | 列表名称(如下载列表、播放列表) |
index | Number | 删除文件时的索引 |
item | Object | 文件项 |
downlist | Array | 下载列表 |
playlist | Array | 播放列表 |
安全特性:
- 删除文件前验证文件是否属于当前用户(通过 Redis 中的上传记录校验)
- 草稿数据存储在 Redis 中,key 格式:
draft_<type>_<user_id> - 草稿过期时间为 24 小时
15. 数据存在性检查
- 地址:
GET /ajax/checkExist
请求参数
| 参数 | 类型 | 说明 |
|---|---|---|
model | String | 数据模型(music/album) |
field | String | 字段名 |
value | String | 字段值 |
响应
json
{
"code": 200,
"msg": "已存在",
"data": true
}16. 通知数量
- 地址:
GET /ajax/getNotifyCount
响应
json
{
"code": 200,
"data": {
"all": 5, // 总通知数
"comments": 2, // 评论通知数
"like": 1, // 点赞通知数
"follower": 2 // 粉丝通知数
}
}17. 购物车数量
- 地址:
GET /ajax/getCartCount
响应
json
{
"code": 200,
"data": {
"all": 3 // 购物车总数量
}
}18. 汉字转拼音
- 地址:
GET /ajax/pinyin
请求参数
| 参数 | 类型 | 说明 |
|---|---|---|
value | String | 需要转换的汉字 |
19. 创建打包文件(下载合集 ZIP)
- 地址:
POST /ajax/mkzip - 鉴权:需要登录
请求参数
| 参数 | 类型 | 说明 |
|---|---|---|
name | String | 打包缓存名(从 Redis 获取打包数据) |
后台通过 Bull 队列异步执行打包,支持失败重试 3 次。
其他控制器提供的接口
创作相关内容
| 接口 | 方法 | 控制器 | 说明 |
|---|---|---|---|
/author/post_music | GET/POST | Author | 发布音乐(获取表单/提交) |
/author/post_album | GET/POST | Author | 发布专辑 |
/author/ajax_image | GET | Author | 获取作者图片列表 |
/author/music | GET/POST | Author | 音乐管理 |
/author/album | GET/POST | Author | 专辑管理 |
/author/opanapi | GET | Author | 开放 API 管理 |
用户相关
| 接口 | 方法 | 控制器 | 说明 |
|---|---|---|---|
/user/ajax_login | GET | User | 登录弹窗 HTML |
/user/ajax_register | GET | User | 注册弹窗 HTML |
/user/ajax_resetpwd | GET | User | 重置密码弹窗 |
/user/ajax_share | GET | User | 分享弹窗 |
/user/logout | GET | User | 退出登录 |
VIP 相关
| 接口 | 方法 | 控制器 | 说明 |
|---|---|---|---|
/vip/ajax_vip | GET | Vip | VIP 弹窗 HTML |
/vip/ajax_redeem | GET | Vip | 卡密兑换弹窗 |
/vip/submit | POST | Vip | 提交 VIP 订单 |
/vip/download | POST | Vip | VIP 下载 |
/vip/query-order-status | POST | Vip | 查询订单支付状态 |
订单相关
| 接口 | 方法 | 控制器 | 说明 |
|---|---|---|---|
/order/submit | POST | Order | 提交订单 |
/order/status | GET | Order | 查询订单状态(轮询用) |
购物车
| 接口 | 方法 | 控制器 | 说明 |
|---|---|---|---|
/cart/add | POST | Cart | 加入购物车 |
歌单
| 接口 | 方法 | 控制器 | 说明 |
|---|---|---|---|
/special/add | POST | Special | 添加歌曲到歌单 |
评论
| 接口 | 方法 | 控制器 | 说明 |
|---|---|---|---|
/comment/submit | POST | Comment | 提交评论 |
/comment/list | GET | Comment | 评论列表 |
访客追踪
| 接口 | 方法 | 控制器 | 说明 |
|---|---|---|---|
/visit | POST | Index | 记录页面访问 |
/index/link | GET | Index | 分享中间页(跳转到详情页) |