- TmdbScraperService: 添加EncryptUtil.decrypt()调用解密API Key - 修复tmdb_api_key字段未自动解密导致API调用失败的问题
3442 lines
182 KiB
HTML
3442 lines
182 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>网盘系统 API 接口文档</title>
|
||
<style>
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
min-height: 100vh;
|
||
padding: 20px;
|
||
}
|
||
.container {
|
||
background: white;
|
||
border-radius: 16px;
|
||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
||
max-width: 1000px;
|
||
margin: 0 auto;
|
||
overflow: hidden;
|
||
}
|
||
.header {
|
||
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
||
color: white;
|
||
padding: 30px 40px;
|
||
text-align: center;
|
||
}
|
||
.header h1 { font-size: 28px; margin-bottom: 8px; }
|
||
.header p { color: #a0aec0; font-size: 14px; }
|
||
.gateway-badge {
|
||
display: inline-block;
|
||
background: #48bb78;
|
||
color: white;
|
||
padding: 6px 16px;
|
||
border-radius: 20px;
|
||
font-size: 13px;
|
||
margin-top: 12px;
|
||
font-family: monospace;
|
||
}
|
||
.nav {
|
||
display: flex;
|
||
background: #f7fafc;
|
||
border-bottom: 1px solid #e2e8f0;
|
||
overflow-x: auto;
|
||
}
|
||
.nav-item {
|
||
padding: 14px 24px;
|
||
cursor: pointer;
|
||
border-bottom: 3px solid transparent;
|
||
white-space: nowrap;
|
||
font-size: 14px;
|
||
color: #4a5568;
|
||
transition: all 0.2s;
|
||
}
|
||
.nav-item:hover { background: #edf2f7; }
|
||
.nav-item.active {
|
||
border-bottom-color: #667eea;
|
||
color: #667eea;
|
||
font-weight: 600;
|
||
}
|
||
.badge-danger { background: #e53e3e; color: white; padding: 2px 8px; border-radius: 4px; font-size: 12px; }
|
||
.content { padding: 24px 40px; }
|
||
.section { display: none; }
|
||
.section.active { display: block; }
|
||
.service-card {
|
||
background: #f7fafc;
|
||
border-radius: 12px;
|
||
padding: 20px;
|
||
margin-bottom: 20px;
|
||
border-left: 4px solid #667eea;
|
||
}
|
||
.service-card h2 {
|
||
font-size: 18px;
|
||
color: #2d3748;
|
||
margin-bottom: 4px;
|
||
}
|
||
.service-card .port {
|
||
font-size: 12px;
|
||
color: #718096;
|
||
font-family: monospace;
|
||
}
|
||
.api-item {
|
||
background: white;
|
||
border: 1px solid #e2e8f0;
|
||
border-radius: 8px;
|
||
margin: 12px 0;
|
||
overflow: hidden;
|
||
}
|
||
.api-header {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 14px 18px;
|
||
cursor: pointer;
|
||
transition: background 0.2s;
|
||
}
|
||
.api-header:hover { background: #f7fafc; }
|
||
.method {
|
||
display: inline-block;
|
||
padding: 4px 10px;
|
||
border-radius: 4px;
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
font-family: monospace;
|
||
margin-right: 12px;
|
||
min-width: 65px;
|
||
text-align: center;
|
||
}
|
||
.method.GET { background: #c6f6d5; color: #276749; }
|
||
.method.POST { background: #bee3f8; color: #2a4365; }
|
||
.method.PUT { background: #fefcbf; color: #744210; }
|
||
.method.DELETE { background: #fed7d7; color: #742a2a; }
|
||
.api-path {
|
||
font-family: monospace;
|
||
font-size: 14px;
|
||
color: #2d3748;
|
||
flex: 1;
|
||
}
|
||
.api-desc {
|
||
font-size: 13px;
|
||
color: #718096;
|
||
margin-left: 12px;
|
||
}
|
||
.api-detail {
|
||
display: none;
|
||
padding: 0 18px 18px;
|
||
border-top: 1px solid #e2e8f0;
|
||
}
|
||
.api-detail.show { display: block; }
|
||
.detail-section { margin: 12px 0; }
|
||
.detail-section h4 {
|
||
font-size: 13px;
|
||
color: #4a5568;
|
||
margin-bottom: 6px;
|
||
font-weight: 600;
|
||
}
|
||
.param-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
font-size: 13px;
|
||
}
|
||
.param-table th, .param-table td {
|
||
padding: 8px 12px;
|
||
text-align: left;
|
||
border-bottom: 1px solid #e2e8f0;
|
||
}
|
||
.param-table th {
|
||
background: #f7fafc;
|
||
color: #4a5568;
|
||
font-weight: 600;
|
||
}
|
||
.param-table td { color: #2d3748; }
|
||
.code-block {
|
||
background: #1a202c;
|
||
color: #a0aec0;
|
||
padding: 14px 18px;
|
||
border-radius: 6px;
|
||
font-family: 'Fira Code', monospace;
|
||
font-size: 12px;
|
||
overflow-x: auto;
|
||
line-height: 1.6;
|
||
}
|
||
.code-block .key { color: #63b3ed; }
|
||
.code-block .string { color: #68d391; }
|
||
.code-block .number { color: #f6ad55; }
|
||
.code-block .keyword { color: #fc8181; }
|
||
.status-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
margin-top: 12px;
|
||
}
|
||
.status-table th, .status-table td {
|
||
padding: 10px 14px;
|
||
text-align: left;
|
||
border-bottom: 1px solid #e2e8f0;
|
||
font-size: 13px;
|
||
}
|
||
.status-table th { background: #f7fafc; color: #4a5568; }
|
||
.arch-diagram {
|
||
background: #f7fafc;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
text-align: center;
|
||
margin: 16px 0;
|
||
}
|
||
.arch-flow {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-wrap: wrap;
|
||
gap: 8px;
|
||
font-size: 13px;
|
||
}
|
||
.arch-box {
|
||
padding: 8px 16px;
|
||
border-radius: 6px;
|
||
color: white;
|
||
font-weight: 600;
|
||
}
|
||
.arch-box.gateway { background: #48bb78; }
|
||
.arch-box.user { background: #4299e1; }
|
||
.arch-box.drive { background: #ed8936; }
|
||
.arch-box.tmdb { background: #9f7aea; }
|
||
.arch-arrow { color: #a0aec0; font-size: 18px; }
|
||
|
||
/* 认证标识 */
|
||
.auth-badge {
|
||
display: inline-block;
|
||
background: #ed8936;
|
||
color: white;
|
||
padding: 2px 8px;
|
||
border-radius: 10px;
|
||
font-size: 10px;
|
||
font-weight: 600;
|
||
margin-left: 8px;
|
||
vertical-align: middle;
|
||
}
|
||
|
||
/* 搜索框样式 */
|
||
.search-container {
|
||
padding: 16px 40px;
|
||
background: #f7fafc;
|
||
border-bottom: 1px solid #e2e8f0;
|
||
}
|
||
.search-box {
|
||
display: flex;
|
||
align-items: center;
|
||
background: white;
|
||
border: 2px solid #e2e8f0;
|
||
border-radius: 8px;
|
||
padding: 10px 16px;
|
||
transition: all 0.2s;
|
||
}
|
||
.search-box:focus-within {
|
||
border-color: #667eea;
|
||
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
||
}
|
||
.search-icon {
|
||
color: #a0aec0;
|
||
margin-right: 10px;
|
||
font-size: 16px;
|
||
}
|
||
.search-input {
|
||
flex: 1;
|
||
border: none;
|
||
outline: none;
|
||
font-size: 14px;
|
||
color: #2d3748;
|
||
}
|
||
.search-input::placeholder {
|
||
color: #a0aec0;
|
||
}
|
||
.search-clear {
|
||
cursor: pointer;
|
||
color: #a0aec0;
|
||
font-size: 18px;
|
||
padding: 0 4px;
|
||
display: none;
|
||
}
|
||
.search-clear:hover {
|
||
color: #e53e3e;
|
||
}
|
||
.search-clear.show {
|
||
display: block;
|
||
}
|
||
.search-result-count {
|
||
font-size: 12px;
|
||
color: #718096;
|
||
margin-top: 8px;
|
||
display: none;
|
||
}
|
||
.search-result-count.show {
|
||
display: block;
|
||
}
|
||
/* 搜索高亮 */
|
||
.highlight {
|
||
background: #fefcbf;
|
||
padding: 1px 2px;
|
||
border-radius: 2px;
|
||
}
|
||
/* 搜索时隐藏不匹配的项 */
|
||
.api-item.search-hidden {
|
||
display: none;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<div class="header">
|
||
<h1>网盘系统 API 接口文档</h1>
|
||
<p>微服务架构 · 统一网关入口</p>
|
||
<div class="gateway-badge">网关地址:http://localhost:8888</div>
|
||
</div>
|
||
|
||
<div class="nav">
|
||
<div class="nav-item active" data-section="overview">架构总览</div>
|
||
<div class="nav-item" data-section="user">用户服务</div>
|
||
<div class="nav-item" data-section="users">用户管理</div>
|
||
<div class="nav-item" data-section="profile">个人资料</div>
|
||
<div class="nav-item" data-section="drive">网盘服务</div>
|
||
<div class="nav-item" data-section="icon">Icon服务</div>
|
||
<div class="nav-item" data-section="tmdb">TMDB服务</div>
|
||
<div class="nav-item" data-section="status">状态码</div>
|
||
</div>
|
||
|
||
<!-- 搜索框 -->
|
||
<div class="search-container">
|
||
<div class="search-box">
|
||
<span class="search-icon">🔍</span>
|
||
<input type="text" class="search-input" id="apiSearch" placeholder="搜索接口路径、描述或功能...">
|
||
<span class="search-clear" id="searchClear">×</span>
|
||
</div>
|
||
<div class="search-result-count" id="searchResultCount"></div>
|
||
</div>
|
||
|
||
<div class="content">
|
||
<!-- 架构总览 -->
|
||
<div class="section active" id="overview">
|
||
<div class="arch-diagram">
|
||
<h3 style="margin-bottom: 16px; color: #2d3748;">服务架构图</h3>
|
||
<div class="arch-flow">
|
||
<div class="arch-box" style="background: #4a5568;">前端</div>
|
||
<span class="arch-arrow">→</span>
|
||
<div class="arch-box gateway">Gateway:8888</div>
|
||
<span class="arch-arrow">→</span>
|
||
<div class="arch-box user">User:8081</div>
|
||
</div>
|
||
<div class="arch-flow" style="margin-top: 8px;">
|
||
<div class="arch-box" style="background: #4a5568; visibility: hidden;">前端</div>
|
||
<span class="arch-arrow" style="visibility: hidden;">→</span>
|
||
<div class="arch-box gateway" style="visibility: hidden;">Gateway</div>
|
||
<span class="arch-arrow">→</span>
|
||
<div class="arch-box drive">Drive:8082</div>
|
||
</div>
|
||
<div class="arch-flow" style="margin-top: 8px;">
|
||
<div class="arch-box" style="background: #4a5568; visibility: hidden;">前端</div>
|
||
<span class="arch-arrow" style="visibility: hidden;">→</span>
|
||
<div class="arch-box gateway" style="visibility: hidden;">Gateway</div>
|
||
<span class="arch-arrow">→</span>
|
||
<div class="arch-box tmdb">TMDB:8083</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="service-card">
|
||
<h2>路由规则</h2>
|
||
<table class="param-table">
|
||
<tr><th>请求路径</th><th>转发服务</th><th>说明</th></tr>
|
||
<tr><td>/api/login, /api/register</td><td>user-service</td><td>登录注册</td></tr>
|
||
<tr><td>/api/token/**, /api/login-logs/**</td><td>user-service</td><td>令牌/日志</td></tr>
|
||
<tr><td>/api/users/**</td><td>user-service</td><td>用户管理</td></tr>
|
||
<tr><td>/api/profile/**</td><td>user-service</td><td>个人资料</td></tr>
|
||
<tr><td>/api/drive/**</td><td>drive-service</td><td>网盘管理</td></tr>
|
||
<tr><td>/api/icon/**</td><td>drive-service</td><td>Icon管理</td></tr>
|
||
<tr><td>/api/movies/**</td><td>tmdb-service</td><td>电影管理</td></tr>
|
||
<tr><td>/api/tmdb/**, /api/tmdb-scraper/**</td><td>tmdb-service</td><td>TMDB刮削</td></tr>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 用户服务 -->
|
||
<div class="section" id="user">
|
||
<div class="service-card">
|
||
<h2>用户认证服务</h2>
|
||
<span class="port">wangpan-user-service : 8081</span>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method POST">POST</span>
|
||
<span class="api-path">/api/login</span>
|
||
<span class="api-desc">用户登录</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>请求体</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"username"</span>: <span class="string">"用户名"</span>,
|
||
<span class="key">"password"</span>: <span class="string">"密码"</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"登录成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">7</span>,
|
||
<span class="key">"username"</span>: <span class="string">"lrq"</span>,
|
||
<span class="key">"userType"</span>: <span class="number">0</span>, <span style="color:#718096">// 0=普通用户, 1=VIP, 2=管理员</span>
|
||
<span class="key">"status"</span>: <span class="number">1</span>,
|
||
<span class="key">"email"</span>: <span class="string">"xxx@xx.com"</span>,
|
||
<span class="key">"phone"</span>: <span class="string">"138****0000"</span>,
|
||
<span class="key">"realName"</span>: <span class="string">"张三"</span>,
|
||
<span class="key">"avatarUrl"</span>: <span class="string">""</span>,
|
||
<span class="key">"lastLoginIp"</span>: <span class="string">"127.0.0.1"</span>,
|
||
<span class="key">"lastLoginTime"</span>: <span class="string">"2026-06-10T11:20:21"</span>,
|
||
<span class="key">"hasTmdbKey"</span>: <span class="keyword">false</span>,
|
||
<span class="key">"token"</span>: <span class="string">"tk_xxx..."</span>,
|
||
<span class="key">"tokenType"</span>: <span class="string">"Bearer"</span>,
|
||
<span class="key">"expireIn"</span>: <span class="number">604800</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 用户名或密码错误</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">400</span>,
|
||
<span class="key">"message"</span>: <span class="string">"用户名或密码错误"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 账号被禁用</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">403</span>,
|
||
<span class="key">"message"</span>: <span class="string">"账号已被禁用,请联系管理员"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 参数缺失</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">400</span>,
|
||
<span class="key">"message"</span>: <span class="string">"用户名和密码不能为空"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>userType 说明</h4>
|
||
<table class="param-table">
|
||
<tr><th>值</th><th>角色</th><th>权限说明</th></tr>
|
||
<tr><td><strong>0</strong></td><td>普通用户</td><td>仅访问自己的数据(如日志只看自己的)</td></tr>
|
||
<tr><td><strong>1</strong></td><td>VIP 用户</td><td>普通用户 + 更多存储空间</td></tr>
|
||
<tr><td><strong>2</strong></td><td>管理员</td><td>可查看所有用户数据(如全部日志)</td></tr>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method POST">POST</span>
|
||
<span class="api-path">/api/register</span>
|
||
<span class="api-desc">用户注册</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>请求体</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"username"</span>: <span class="string">"用户名"</span>,
|
||
<span class="key">"password"</span>: <span class="string">"密码"</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"注册成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">10</span>,
|
||
<span class="key">"username"</span>: <span class="string">"newuser"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 用户名已存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">409</span>,
|
||
<span class="key">"message"</span>: <span class="string">"用户名已被占用"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 参数缺失</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">400</span>,
|
||
<span class="key">"message"</span>: <span class="string">"用户名和密码不能为空"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/token/validate</span>
|
||
<span class="api-desc">令牌验证</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>请求头</h4>
|
||
<div class="code-block">Authorization: Bearer <token></div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例 — Token 有效</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"Token 有效"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"valid"</span>: <span class="keyword">true</span>,
|
||
<span class="key">"userId"</span>: <span class="number">7</span>,
|
||
<span class="key">"username"</span>: <span class="string">"lrq"</span>,
|
||
<span class="key">"expireTime"</span>: <span class="string">"2026-06-17T11:20:21"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — Token 无效或已过期</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"Token 无效或已过期"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/login-logs</span>
|
||
<span class="api-desc">登录日志查询</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>权限说明</h4>
|
||
<table class="param-table">
|
||
<tr><th>用户类型</th><th>可见范围</th></tr>
|
||
<tr><td>普通用户(userType=0/1)</td><td style="color:#e53e3e">仅自己的登录记录</td></tr>
|
||
<tr><td>管理员(userType=2)</td><td style="color:#38a169">所有用户的登录记录</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>查询参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>必填</th><th>说明</th></tr>
|
||
<tr><td>username</td><td>String</td><td>否</td><td>按用户名模糊筛选(管理员可用)</td></tr>
|
||
<tr><td>result</td><td>String</td><td>否</td><td>登录结果:success / fail</td></tr>
|
||
<tr><td>startDate</td><td>String</td><td>否</td><td>开始日期(含),格式:yyyy-MM-dd,如 2026-06-01</td></tr>
|
||
<tr><td>endDate</td><td>String</td><td>否</td><td>结束日期(含),格式:yyyy-MM-dd,如 2026-06-10</td></tr>
|
||
<tr><td>pageNo</td><td>int</td><td>否</td><td>页码,默认 1</td></tr>
|
||
<tr><td>pageSize</td><td>int</td><td>否</td><td>每页条数,默认 20</td></tr>
|
||
</table>
|
||
<p style="color:#718096; font-size:13px; margin-top:8px;">提示:可组合使用多个筛选条件,如 ?result=fail&startDate=2026-06-01&endDate=2026-06-10</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"total"</span>: <span class="number">10</span>,
|
||
<span class="key">"list"</span>: [
|
||
{
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"userId"</span>: <span class="number">7</span>,
|
||
<span class="key">"username"</span>: <span class="string">"lrq"</span>,
|
||
<span class="key">"loginIp"</span>: <span class="string">"127.0.0.1"</span>,
|
||
<span class="key">"loginTime"</span>: <span class="string">"2026-06-10T11:20:21"</span>,
|
||
<span class="key">"result"</span>: <span class="string">"success"</span>,
|
||
<span class="key">"userAgent"</span>: <span class="string">"Mozilla/5.0..."</span>
|
||
}
|
||
],
|
||
<span class="key">"pageNo"</span>: <span class="number">1</span>,
|
||
<span class="key">"pageSize"</span>: <span class="number">20</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 无效"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 权限不足</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">403</span>,
|
||
<span class="key">"message"</span>: <span class="string">"权限不足,无法查看其他用户的登录日志"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 用户管理(管理员专用) -->
|
||
<div class="section" id="users">
|
||
<div class="service-card">
|
||
<h2>用户管理</h2>
|
||
<span class="port">wangpan-user-service : 8081</span>
|
||
<span class="badge badge-danger">仅管理员 (userType=2)</span>
|
||
</div>
|
||
|
||
<!-- 查询用户列表 -->
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/users</span>
|
||
<span class="api-desc">查询用户列表</span><span class="auth-badge">需Token + 管理员</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>权限说明</h4>
|
||
<table class="param-table">
|
||
<tr><th>角色</th><th>访问权限</th></tr>
|
||
<tr><td>普通/VIP 用户</td><td style="color:#e53e3e">403 权限不足</td></tr>
|
||
<tr><td><strong>管理员</strong></td><td style="color:#38a169">可查看所有用户列表</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>查询参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>必填</th><th>说明</th></tr>
|
||
<tr><td>username</td><td>String</td><td>否</td><td>用户名模糊搜索</td></tr>
|
||
<tr><td>status</td><td>int</td><td>否</td><td>状态:0=禁用, 1=正常, 2=锁定</td></tr>
|
||
<tr><td>userType</td><td>int</td><td>否</td><td>角色:0=普通, 1=VIP, 2=管理员</td></tr>
|
||
<tr><td>pageNo</td><td>int</td><td>否</td><td>页码,默认 1</td></tr>
|
||
<tr><td>pageSize</td><td>int</td><td>否</td><td>每页条数,默认 20</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"total"</span>: <span class="number">5</span>,
|
||
<span class="key">"list"</span>: [
|
||
{ <span class="key">"id"</span>: <span class="number">7</span>, <span class="key">"username"</span>: <span class="string">"lrq"</span>, <span class="key">"userType"</span>: <span class="number">0</span>, <span class="key">"status"</span>: <span class="number">1</span>, ... }
|
||
],
|
||
<span class="key">"pageNo"</span>: <span class="number">1</span>,
|
||
<span class="key">"pageSize"</span>: <span class="number">20</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 权限不足</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">403</span>,
|
||
<span class="key">"message"</span>: <span class="string">"权限不足,仅管理员可访问"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 无效"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 新增用户 -->
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method POST">POST</span>
|
||
<span class="api-path">/api/users</span>
|
||
<span class="api-desc">新增用户</span><span class="auth-badge">需Token + 管理员</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>请求体</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"username"</span>: <span class="string">"必填"</span>,
|
||
<span class="key">"password"</span>: <span class="string">"必填"</span>,
|
||
<span class="key">"email"</span>: <span class="string">"可选"</span>,
|
||
<span class="key">"phone"</span>: <span class="string">"可选"</span>,
|
||
<span class="key">"realName"</span>: <span class="string">"可选"</span>,
|
||
<span class="key">"status"</span>: <span class="number">1</span>, <span style="color:#718096">// 可选:0=禁用, 1=正常, 默认1</span>
|
||
<span class="key">"userType"</span>: <span class="number">0</span> <span style="color:#718096">// 可选:0=普通, 1=VIP, 2=管理员, 默认0</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"用户创建成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">10</span>,
|
||
<span class="key">"username"</span>: <span class="string">"newuser"</span>,
|
||
<span class="key">"email"</span>: <span class="string">"new@test.com"</span>,
|
||
<span class="key">"status"</span>: <span class="number">1</span>,
|
||
<span class="key">"userType"</span>: <span class="number">0</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 用户名已存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">409</span>,
|
||
<span class="key">"message"</span>: <span class="string">"用户名已被占用"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 参数缺失</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">400</span>,
|
||
<span class="key">"message"</span>: <span class="string">"用户名或密码不能为空"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 权限不足</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">403</span>,
|
||
<span class="key">"message"</span>: <span class="string">"非管理员,无权限操作"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 服务器错误</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">500</span>,
|
||
<span class="key">"message"</span>: <span class="string">"服务器内部错误"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 修改用户 -->
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method PUT">PUT</span>
|
||
<span class="api-path">/api/users/{userId}</span>
|
||
<span class="api-desc">修改用户信息</span><span class="auth-badge">需Token + 管理员</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>userId</td><td>Long</td><td>目标用户 ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>请求体(部分更新,只传需要修改的字段)</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"email"</span>: <span class="string">"新邮箱"</span>, <span style="color:#718096">// 可选</span>
|
||
<span class="key">"phone"</span>: <span class="string">"新手机号"</span>, <span style="color:#718096">// 可选</span>
|
||
<span class="key">"realName"</span>: <span class="string">"新姓名"</span>, <span style="color:#718096">// 可选</span>
|
||
<span class="key">"status"</span>: <span class="number">0</span>, <span style="color:#718096">// 可选:0=禁用, 1=正常, 2=锁定</span>
|
||
<span class="key">"userType"</span>: <span class="number">1</span> <span style="color:#718096">// 可选:0=普通, 1=VIP, 2=管理员</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"用户信息更新成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">10</span>,
|
||
<span class="key">"username"</span>: <span class="string">"newuser"</span>,
|
||
<span class="key">"email"</span>: <span class="string">"new@test.com"</span>,
|
||
<span class="key">"status"</span>: <span class="number">1</span>,
|
||
<span class="key">"userType"</span>: <span class="number">0</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 用户不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"目标用户不存在"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 参数缺失</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">400</span>,
|
||
<span class="key">"message"</span>: <span class="string">"没有需要更新的字段"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 权限不足</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">403</span>,
|
||
<span class="key">"message"</span>: <span class="string">"非管理员,无权限操作"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 服务器错误</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">500</span>,
|
||
<span class="key">"message"</span>: <span class="string">"服务器内部错误"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 删除用户 -->
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method DELETE">DELETE</span>
|
||
<span class="api-path">/api/users/{userId}</span>
|
||
<span class="api-desc">删除用户(软删除)</span><span class="auth-badge">需Token + 管理员</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>userId</td><td>Long</td><td>要删除的用户 ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>说明</h4>
|
||
<p>软删除操作,将 <code>is_deleted</code> 设为 1,不物理删除数据。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"用户删除成功"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 用户不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"目标用户不存在"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 删除失败</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">400</span>,
|
||
<span class="key">"message"</span>: <span class="string">"删除失败,用户可能已被删除"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 权限不足</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">403</span>,
|
||
<span class="key">"message"</span>: <span class="string">"非管理员,无权限操作"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 服务器错误</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">500</span>,
|
||
<span class="key">"message"</span>: <span class="string">"服务器内部错误"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 个人资料 -->
|
||
<div class="section" id="profile">
|
||
<div class="service-card">
|
||
<h2>个人资料</h2>
|
||
<span class="port">wangpan-user-service : 8081</span>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/profile</span>
|
||
<span class="api-desc">获取当前用户个人资料</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>功能说明</h4>
|
||
<p>获取当前登录用户的基本信息(不含密码等敏感字段)。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"username"</span>: <span class="string">"admin"</span>,
|
||
<span class="key">"email"</span>: <span class="string">"admin@example.com"</span>,
|
||
<span class="key">"phone"</span>: <span class="string">"13800138000"</span>,
|
||
<span class="key">"realName"</span>: <span class="string">"管理员"</span>,
|
||
<span class="key">"avatarUrl"</span>: <span class="string">"http://..."</span>,
|
||
<span class="key">"userType"</span>: <span class="number">2</span>,
|
||
<span class="key">"status"</span>: <span class="number">1</span>,
|
||
<span class="key">"createTime"</span>: <span class="string">"2024-01-01T00:00:00"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 无效"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 用户不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"用户不存在"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method PUT">PUT</span>
|
||
<span class="api-path">/api/profile/username</span>
|
||
<span class="api-desc">修改用户名</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>功能说明</h4>
|
||
<p>修改当前登录用户的用户名。</p>
|
||
<p><strong>校验规则:</strong></p>
|
||
<ul>
|
||
<li>用户名不能为空</li>
|
||
<li>新用户名不能与当前用户名相同</li>
|
||
<li>新用户名不能被其他用户占用</li>
|
||
</ul>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>请求体</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"username"</span>: <span class="string">"新用户名"</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"用户名修改成功"</span>,
|
||
<span class="key">"data"</span>: null
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 用户名已存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">409</span>,
|
||
<span class="key">"message"</span>: <span class="string">"用户名已被其他用户使用"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 参数错误</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">400</span>,
|
||
<span class="key">"message"</span>: <span class="string">"新用户名不能为空或与当前用户名相同"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method PUT">PUT</span>
|
||
<span class="api-path">/api/profile/avatar</span>
|
||
<span class="api-desc">修改头像</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>功能说明</h4>
|
||
<p>修改当前登录用户的头像。</p>
|
||
<p><strong>流程:</strong></p>
|
||
<ol>
|
||
<li>接收 Base64 编码的图片数据</li>
|
||
<li>解析 MIME 类型和 Base64 内容</li>
|
||
<li>上传到 MinIO(路径:avatar/{userId}_{timestamp}.{ext})</li>
|
||
<li>更新数据库中的 avatar_url 字段</li>
|
||
</ol>
|
||
<p><strong>支持的图片格式:</strong>PNG、JPG/JPEG、GIF、WebP</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>请求体</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"avatarData"</span>: <span class="string">"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"头像更新成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"avatarUrl"</span>: <span class="string">"http://118.178.238.159:39000/wangpan/avatar/1_1719234567890.png?..."</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 图片格式不支持</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">400</span>,
|
||
<span class="key">"message"</span>: <span class="string">"不支持的图片格式,仅支持 PNG、JPG、GIF、WebP"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — MinIO 上传失败</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">500</span>,
|
||
<span class="key">"message"</span>: <span class="string">"头像上传失败,请稍后重试"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 网盘服务 -->
|
||
<div class="section" id="drive">
|
||
<div class="service-card">
|
||
<h2>网盘管理服务</h2>
|
||
<span class="port">wangpan-drive-service : 8082</span>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method POST">POST</span>
|
||
<span class="api-path">/api/drive</span>
|
||
<span class="api-desc">创建网盘</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>请求体</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"name"</span>: <span class="string">"网盘名称"</span>,
|
||
<span class="key">"description"</span>: <span class="string">"网盘描述"</span>,
|
||
<span class="key">"logoData"</span>: <span class="string">"data:image/png;base64,iVBOR..."</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>参数说明</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>必填</th><th>说明</th></tr>
|
||
<tr><td>name</td><td>String</td><td>是</td><td>网盘名称</td></tr>
|
||
<tr><td>description</td><td>String</td><td>否</td><td>网盘描述</td></tr>
|
||
<tr><td>logoData</td><td>String</td><td>否</td><td>Logo图片Base64编码,支持 data:image/xxx;base64, 前缀格式,上传后存储到MinIO,数据库仅保存URL</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"创建成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"name"</span>: <span class="string">"我的网盘"</span>,
|
||
<span class="key">"description"</span>: <span class="string">"个人网盘"</span>,
|
||
<span class="key">"logoUrl"</span>: <span class="string">"http://118.178.238.159:39000/wangpan/drive/1/logo.png"</span>,
|
||
<span class="key">"createTime"</span>: <span class="string">"2026-06-26T10:00:00"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 参数缺失</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">400</span>,
|
||
<span class="key">"message"</span>: <span class="string">"网盘名称不能为空"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 无效"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/drive</span>
|
||
<span class="api-desc">查询网盘列表</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>查询参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>默认值</th><th>说明</th></tr>
|
||
<tr><td>pageNo</td><td>1</td><td>页码</td></tr>
|
||
<tr><td>pageSize</td><td>20</td><td>每页条数</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>响应字段</h4>
|
||
<table class="param-table">
|
||
<tr><th>字段</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>id</td><td>Long</td><td>网盘ID</td></tr>
|
||
<tr><td>name</td><td>String</td><td>网盘名称</td></tr>
|
||
<tr><td>description</td><td>String</td><td>网盘描述</td></tr>
|
||
<tr><td>logoUrl</td><td>String</td><td>网盘Logo图片链接(MinIO存储地址)</td></tr>
|
||
<tr><td>folderCount</td><td>Integer</td><td>文件夹数量</td></tr>
|
||
<tr><td>fileCount</td><td>Integer</td><td>文件数量</td></tr>
|
||
<tr><td>totalSize</td><td>Long</td><td>总大小(字节)</td></tr>
|
||
<tr><td>status</td><td>String</td><td>状态</td></tr>
|
||
<tr><td>createTime</td><td>String</td><td>创建时间</td></tr>
|
||
<tr><td>updateTime</td><td>String</td><td>更新时间</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"total"</span>: <span class="number">2</span>,
|
||
<span class="key">"list"</span>: [
|
||
{
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"name"</span>: <span class="string">"我的网盘"</span>,
|
||
<span class="key">"description"</span>: <span class="string">"个人网盘"</span>,
|
||
<span class="key">"logoUrl"</span>: <span class="string">"http://118.178.238.159:39000/wangpan/drive/1/logo.png"</span>,
|
||
<span class="key">"folderCount"</span>: <span class="number">5</span>,
|
||
<span class="key">"fileCount"</span>: <span class="number">20</span>,
|
||
<span class="key">"totalSize"</span>: <span class="number">10737418240</span>,
|
||
<span class="key">"status"</span>: <span class="string">"active"</span>,
|
||
<span class="key">"createTime"</span>: <span class="string">"2026-06-26T10:00:00"</span>,
|
||
<span class="key">"updateTime"</span>: <span class="string">"2026-06-26T10:00:00"</span>
|
||
}
|
||
],
|
||
<span class="key">"pageNo"</span>: <span class="number">1</span>,
|
||
<span class="key">"pageSize"</span>: <span class="number">20</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 无效"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/drive/{id}</span>
|
||
<span class="api-desc">查询网盘详情</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>id</td><td>Long</td><td>网盘ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>响应字段</h4>
|
||
<table class="param-table">
|
||
<tr><th>字段</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>id</td><td>Long</td><td>网盘ID</td></tr>
|
||
<tr><td>name</td><td>String</td><td>网盘名称</td></tr>
|
||
<tr><td>description</td><td>String</td><td>网盘描述</td></tr>
|
||
<tr><td>logoUrl</td><td>String</td><td>网盘Logo图片链接(MinIO存储地址)</td></tr>
|
||
<tr><td>folderCount</td><td>Integer</td><td>文件夹数量</td></tr>
|
||
<tr><td>fileCount</td><td>Integer</td><td>文件数量</td></tr>
|
||
<tr><td>totalSize</td><td>Long</td><td>总大小(字节)</td></tr>
|
||
<tr><td>status</td><td>String</td><td>状态</td></tr>
|
||
<tr><td>createTime</td><td>String</td><td>创建时间</td></tr>
|
||
<tr><td>updateTime</td><td>String</td><td>更新时间</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"name"</span>: <span class="string">"我的网盘"</span>,
|
||
<span class="key">"description"</span>: <span class="string">"个人网盘"</span>,
|
||
<span class="key">"logoUrl"</span>: <span class="string">"http://118.178.238.159:39000/wangpan/drive/1/logo.png"</span>,
|
||
<span class="key">"folderCount"</span>: <span class="number">5</span>,
|
||
<span class="key">"fileCount"</span>: <span class="number">20</span>,
|
||
<span class="key">"totalSize"</span>: <span class="number">10737418240</span>,
|
||
<span class="key">"status"</span>: <span class="string">"active"</span>,
|
||
<span class="key">"createTime"</span>: <span class="string">"2026-06-26T10:00:00"</span>,
|
||
<span class="key">"updateTime"</span>: <span class="string">"2026-06-26T10:00:00"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 网盘不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"网盘不存在"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 无效"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method PUT">PUT</span>
|
||
<span class="api-path">/api/drive/{id}</span>
|
||
<span class="api-desc">更新网盘</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>请求体</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"name"</span>: <span class="string">"新网盘名称"</span>,
|
||
<span class="key">"description"</span>: <span class="string">"新描述"</span>,
|
||
<span class="key">"logoData"</span>: <span class="string">"data:image/png;base64,iVBOR..."</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>参数说明</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>必填</th><th>说明</th></tr>
|
||
<tr><td>name</td><td>String</td><td>否</td><td>网盘名称</td></tr>
|
||
<tr><td>description</td><td>String</td><td>否</td><td>网盘描述</td></tr>
|
||
<tr><td>logoData</td><td>String</td><td>否</td><td>新的Logo图片Base64编码,传入后覆盖旧Logo;不传则保留原Logo</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"更新成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"name"</span>: <span class="string">"新网盘名称"</span>,
|
||
<span class="key">"description"</span>: <span class="string">"新描述"</span>,
|
||
<span class="key">"logoUrl"</span>: <span class="string">"http://118.178.238.159:39000/wangpan/drive/1/logo.png"</span>,
|
||
<span class="key">"updateTime"</span>: <span class="string">"2026-06-26T11:00:00"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 网盘不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"网盘不存在"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 权限不足</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">403</span>,
|
||
<span class="key">"message"</span>: <span class="string">"无权修改该网盘"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method DELETE">DELETE</span>
|
||
<span class="api-path">/api/drive/{id}</span>
|
||
<span class="api-desc">删除网盘</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>id</td><td>Long</td><td>网盘ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"删除成功"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 网盘不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"网盘不存在"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 权限不足</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">403</span>,
|
||
<span class="key">"message"</span>: <span class="string">"无权删除该网盘"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method POST">POST</span>
|
||
<span class="api-path">/api/drive/{driveId}/folders</span>
|
||
<span class="api-desc">创建文件夹</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>请求体</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"name"</span>: <span class="string">"文件夹名称"</span>,
|
||
<span class="key">"parentId"</span>: <span class="number">0</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"创建成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"driveId"</span>: <span class="number">1</span>,
|
||
<span class="key">"parentId"</span>: <span class="number">0</span>,
|
||
<span class="key">"name"</span>: <span class="string">"我的电影"</span>,
|
||
<span class="key">"description"</span>: <span class="string">""</span>,
|
||
<span class="key">"depth"</span>: <span class="number">0</span>,
|
||
<span class="key">"createTime"</span>: <span class="string">"2026-06-26T10:00:00"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 参数缺失</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">400</span>,
|
||
<span class="key">"message"</span>: <span class="string">"文件夹名称不能为空"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 网盘不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"网盘不存在"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/drive/{driveId}/folders</span>
|
||
<span class="api-desc">查询文件夹列表</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>查询参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>默认值</th><th>说明</th></tr>
|
||
<tr><td>parentId</td><td>0</td><td>父文件夹 ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: [
|
||
{
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"driveId"</span>: <span class="number">1</span>,
|
||
<span class="key">"parentId"</span>: <span class="number">0</span>,
|
||
<span class="key">"name"</span>: <span class="string">"我的电影"</span>,
|
||
<span class="key">"description"</span>: <span class="string">""</span>,
|
||
<span class="key">"depth"</span>: <span class="number">0</span>,
|
||
<span class="key">"childFolderCount"</span>: <span class="number">2</span>,
|
||
<span class="key">"fileCount"</span>: <span class="number">5</span>,
|
||
<span class="key">"createTime"</span>: <span class="string">"2026-06-26T10:00:00"</span>
|
||
}
|
||
]
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 网盘不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"网盘不存在"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 无效"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/drive/{driveId}/folders/{folderId}</span>
|
||
<span class="api-desc">查询文件夹详情</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>driveId</td><td>Long</td><td>网盘ID</td></tr>
|
||
<tr><td>folderId</td><td>Long</td><td>文件夹ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>响应字段</h4>
|
||
<table class="param-table">
|
||
<tr><th>字段</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>id</td><td>Long</td><td>文件夹ID</td></tr>
|
||
<tr><td>driveId</td><td>Long</td><td>所属网盘ID</td></tr>
|
||
<tr><td>parentId</td><td>Long</td><td>父文件夹ID(0表示根目录)</td></tr>
|
||
<tr><td>name</td><td>String</td><td>文件夹名称</td></tr>
|
||
<tr><td>description</td><td>String</td><td>文件夹描述</td></tr>
|
||
<tr><td>depth</td><td>Integer</td><td>层级深度</td></tr>
|
||
<tr><td>childFolderCount</td><td>Integer</td><td>子文件夹数量</td></tr>
|
||
<tr><td>fileCount</td><td>Integer</td><td>文件数量</td></tr>
|
||
<tr><td>totalSize</td><td>Long</td><td>总大小(字节)</td></tr>
|
||
<tr><td>createTime</td><td>String</td><td>创建时间</td></tr>
|
||
<tr><td>updateTime</td><td>String</td><td>更新时间</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"driveId"</span>: <span class="number">1</span>,
|
||
<span class="key">"parentId"</span>: <span class="number">0</span>,
|
||
<span class="key">"name"</span>: <span class="string">"我的电影"</span>,
|
||
<span class="key">"description"</span>: <span class="string">"收藏的电影"</span>,
|
||
<span class="key">"depth"</span>: <span class="number">0</span>,
|
||
<span class="key">"childFolderCount"</span>: <span class="number">2</span>,
|
||
<span class="key">"fileCount"</span>: <span class="number">5</span>,
|
||
<span class="key">"totalSize"</span>: <span class="number">5368709120</span>,
|
||
<span class="key">"createTime"</span>: <span class="string">"2026-06-26T10:00:00"</span>,
|
||
<span class="key">"updateTime"</span>: <span class="string">"2026-06-26T10:00:00"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 文件夹不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"文件夹不存在"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 无效"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method PUT">PUT</span>
|
||
<span class="api-path">/api/drive/{driveId}/folders/{folderId}</span>
|
||
<span class="api-desc">更新文件夹</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>driveId</td><td>Long</td><td>网盘ID</td></tr>
|
||
<tr><td>folderId</td><td>Long</td><td>文件夹ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>请求体(部分更新)</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"name"</span>: <span class="string">"新文件夹名称"</span>,
|
||
<span class="key">"description"</span>: <span class="string">"新描述"</span>,
|
||
<span class="key">"parentId"</span>: <span class="number">0</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>参数说明</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>必填</th><th>说明</th></tr>
|
||
<tr><td>name</td><td>String</td><td>否</td><td>文件夹名称</td></tr>
|
||
<tr><td>description</td><td>String</td><td>否</td><td>文件夹描述</td></tr>
|
||
<tr><td>parentId</td><td>Long</td><td>否</td><td>父文件夹ID(可移动文件夹)</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"更新成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"driveId"</span>: <span class="number">1</span>,
|
||
<span class="key">"parentId"</span>: <span class="number">0</span>,
|
||
<span class="key">"name"</span>: <span class="string">"新文件夹名称"</span>,
|
||
<span class="key">"description"</span>: <span class="string">"新描述"</span>,
|
||
<span class="key">"updateTime"</span>: <span class="string">"2026-06-26T11:00:00"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 文件夹不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"文件夹不存在"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 权限不足</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">403</span>,
|
||
<span class="key">"message"</span>: <span class="string">"无权修改该文件夹"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method DELETE">DELETE</span>
|
||
<span class="api-path">/api/drive/{driveId}/folders/{folderId}</span>
|
||
<span class="api-desc">删除文件夹</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>driveId</td><td>Long</td><td>网盘ID</td></tr>
|
||
<tr><td>folderId</td><td>Long</td><td>文件夹ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>说明</h4>
|
||
<p>删除文件夹前会检查文件夹是否为空,如果包含子文件夹或电影文件则拒绝删除。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>错误码</h4>
|
||
<table class="param-table">
|
||
<tr><th>code</th><th>说明</th></tr>
|
||
<tr><td>400</td><td>文件夹不为空或数据库操作失败</td></tr>
|
||
<tr><td>401</td><td>未登录或Token无效</td></tr>
|
||
<tr><td>403</td><td>无权访问该文件夹</td></tr>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method POST">POST</span>
|
||
<span class="api-path">/api/drive/{driveId}/movies</span>
|
||
<span class="api-desc">创建电影(只传文件名)</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>driveId</td><td>Long</td><td>网盘ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>请求体</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"title"</span>: <span class="string">"文件名.mp4"</span>, <span style="color:#718096">// 必填,文件名(同时作为电影标题)</span>
|
||
<span class="key">"folderId"</span>: <span class="number">0</span> <span style="color:#718096">// 可选,默认0(根目录)</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>参数说明</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>必填</th><th>说明</th></tr>
|
||
<tr><td>title</td><td>String</td><td>是</td><td>文件名(同时作为电影标题,后续通过 TMDB 刮削补充信息)</td></tr>
|
||
<tr><td>folderId</td><td>Long</td><td>否</td><td>目标文件夹ID,默认0(根目录)</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>说明</h4>
|
||
<p>只记录文件名,不上传文件数据。创建后通过 TMDB 刮削接口补充电影的海报、描述、评分等信息。自动检测 MIME 类型(mp4/mkv/avi → video/mp4)。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"创建成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"driveId"</span>: <span class="number">1</span>,
|
||
<span class="key">"folderId"</span>: <span class="number">0</span>,
|
||
<span class="key">"title"</span>: <span class="string">"电影.mp4"</span>,
|
||
<span class="key">"originalName"</span>: <span class="string">"电影.mp4"</span>,
|
||
<span class="key">"mimeType"</span>: <span class="string">"video/mp4"</span>,
|
||
<span class="key">"createTime"</span>: <span class="string">"2026-06-26T10:00:00"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 参数缺失</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">400</span>,
|
||
<span class="key">"message"</span>: <span class="string">"文件名不能为空"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 网盘不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"网盘不存在"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/drive/{driveId}/folders/{folderId}/movies</span>
|
||
<span class="api-desc">查询电影文件列表</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>driveId</td><td>Long</td><td>网盘ID</td></tr>
|
||
<tr><td>folderId</td><td>Long</td><td>文件夹ID(0表示根目录)</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>查询参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>默认值</th><th>说明</th></tr>
|
||
<tr><td>pageNo</td><td>1</td><td>页码</td></tr>
|
||
<tr><td>pageSize</td><td>20</td><td>每页条数(最大100)</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>响应字段</h4>
|
||
<table class="param-table">
|
||
<tr><th>字段</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>list[].id</td><td>Long</td><td>电影ID</td></tr>
|
||
<tr><td>list[].title</td><td>String</td><td>电影名称</td></tr>
|
||
<tr><td>list[].originalName</td><td>String</td><td>原始文件名</td></tr>
|
||
<tr><td>list[].mimeType</td><td>String</td><td>MIME类型</td></tr>
|
||
<tr><td>list[].fileSize</td><td>Long</td><td>文件大小(字节)</td></tr>
|
||
<tr><td>list[].extension</td><td>String</td><td>文件扩展名</td></tr>
|
||
<tr><td>list[].minioUrl</td><td>String</td><td>MinIO文件访问URL</td></tr>
|
||
<tr><td>list[].rating</td><td>Integer</td><td>评分</td></tr>
|
||
<tr><td>list[].tags</td><td>String</td><td>标签</td></tr>
|
||
<tr><td>total</td><td>Integer</td><td>总数</td></tr>
|
||
<tr><td>pageNo</td><td>Integer</td><td>当前页码</td></tr>
|
||
<tr><td>pageSize</td><td>Integer</td><td>每页条数</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"total"</span>: <span class="number">5</span>,
|
||
<span class="key">"pageNo"</span>: <span class="number">1</span>,
|
||
<span class="key">"pageSize"</span>: <span class="number">20</span>,
|
||
<span class="key">"list"</span>: [
|
||
{
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"title"</span>: <span class="string">"电影.mp4"</span>,
|
||
<span class="key">"originalName"</span>: <span class="string">"电影.mp4"</span>,
|
||
<span class="key">"mimeType"</span>: <span class="string">"video/mp4"</span>,
|
||
<span class="key">"fileSize"</span>: <span class="number">1073741824</span>,
|
||
<span class="key">"extension"</span>: <span class="string">"mp4"</span>,
|
||
<span class="key">"minioUrl"</span>: <span class="string">"http://..."</span>,
|
||
<span class="key">"rating"</span>: <span class="number">85</span>,
|
||
<span class="key">"tags"</span>: <span class="string">"动作,科幻"</span>
|
||
}
|
||
]
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 网盘不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"网盘不存在"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 无效"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/drive/{driveId}/movies/{movieId}</span>
|
||
<span class="api-desc">查询电影文件详情</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>driveId</td><td>Long</td><td>网盘ID</td></tr>
|
||
<tr><td>movieId</td><td>Long</td><td>电影ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>响应字段</h4>
|
||
<table class="param-table">
|
||
<tr><th>字段</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>id</td><td>Long</td><td>电影ID</td></tr>
|
||
<tr><td>driveId</td><td>Long</td><td>所属网盘ID</td></tr>
|
||
<tr><td>folderId</td><td>Long</td><td>所属文件夹ID</td></tr>
|
||
<tr><td>title</td><td>String</td><td>电影名称</td></tr>
|
||
<tr><td>subtitle</td><td>String</td><td>副标题</td></tr>
|
||
<tr><td>originalName</td><td>String</td><td>原始文件名</td></tr>
|
||
<tr><td>mimeType</td><td>String</td><td>MIME类型</td></tr>
|
||
<tr><td>fileSize</td><td>Long</td><td>文件大小(字节)</td></tr>
|
||
<tr><td>extension</td><td>String</td><td>文件扩展名</td></tr>
|
||
<tr><td>description</td><td>String</td><td>描述</td></tr>
|
||
<tr><td>resourceLibrary</td><td>String</td><td>资源库</td></tr>
|
||
<tr><td>maintainer</td><td>String</td><td>维护者</td></tr>
|
||
<tr><td>status</td><td>String</td><td>状态</td></tr>
|
||
<tr><td>category</td><td>String</td><td>分类</td></tr>
|
||
<tr><td>scrapeType</td><td>String</td><td>刮削类型</td></tr>
|
||
<tr><td>rating</td><td>Integer</td><td>评分</td></tr>
|
||
<tr><td>tags</td><td>String</td><td>标签</td></tr>
|
||
<tr><td>minioUrl</td><td>String</td><td>MinIO文件访问URL</td></tr>
|
||
<tr><td>posterUrl</td><td>String</td><td>海报URL</td></tr>
|
||
<tr><td>createTime</td><td>String</td><td>创建时间</td></tr>
|
||
<tr><td>updateTime</td><td>String</td><td>更新时间</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"driveId"</span>: <span class="number">1</span>,
|
||
<span class="key">"folderId"</span>: <span class="number">0</span>,
|
||
<span class="key">"title"</span>: <span class="string">"电影.mp4"</span>,
|
||
<span class="key">"subtitle"</span>: <span class="string">"副标题"</span>,
|
||
<span class="key">"originalName"</span>: <span class="string">"电影.mp4"</span>,
|
||
<span class="key">"mimeType"</span>: <span class="string">"video/mp4"</span>,
|
||
<span class="key">"fileSize"</span>: <span class="number">1073741824</span>,
|
||
<span class="key">"extension"</span>: <span class="string">"mp4"</span>,
|
||
<span class="key">"description"</span>: <span class="string">"电影描述"</span>,
|
||
<span class="key">"rating"</span>: <span class="number">85</span>,
|
||
<span class="key">"tags"</span>: <span class="string">"动作,科幻"</span>,
|
||
<span class="key">"posterUrl"</span>: <span class="string">"http://..."</span>,
|
||
<span class="key">"minioUrl"</span>: <span class="string">"http://..."</span>,
|
||
<span class="key">"createTime"</span>: <span class="string">"2026-06-26T10:00:00"</span>,
|
||
<span class="key">"updateTime"</span>: <span class="string">"2026-06-26T10:00:00"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 电影不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"电影不存在"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 无效"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method PUT">PUT</span>
|
||
<span class="api-path">/api/drive/{driveId}/movies/{movieId}</span>
|
||
<span class="api-desc">更新电影文件信息</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>driveId</td><td>Long</td><td>网盘ID</td></tr>
|
||
<tr><td>movieId</td><td>Long</td><td>电影ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>请求体(部分更新,所有字段可选)</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"title"</span>: <span class="string">"新电影名称"</span>,
|
||
<span class="key">"originalName"</span>: <span class="string">"新文件名.mp4"</span>,
|
||
<span class="key">"subtitle"</span>: <span class="string">"新副标题"</span>,
|
||
<span class="key">"description"</span>: <span class="string">"新描述"</span>,
|
||
<span class="key">"rating"</span>: <span class="number">90</span>,
|
||
<span class="key">"tags"</span>: <span class="string">"新标签"</span>,
|
||
<span class="key">"category"</span>: <span class="string">"新分类"</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>参数说明</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>title</td><td>String</td><td>电影名称</td></tr>
|
||
<tr><td>originalName</td><td>String</td><td>原始文件名(用于 TMDB 刮削有误时修改)</td></tr>
|
||
<tr><td>subtitle</td><td>String</td><td>副标题</td></tr>
|
||
<tr><td>description</td><td>String</td><td>描述</td></tr>
|
||
<tr><td>rating</td><td>Integer</td><td>评分 0-100</td></tr>
|
||
<tr><td>tags</td><td>String</td><td>标签</td></tr>
|
||
<tr><td>category</td><td>String</td><td>分类</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>说明</h4>
|
||
<p>用于 TMDB 刮削有误时,用户可自定义修改文件名等信息。所有字段均为可选,只更新传入的字段。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"更新成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"title"</span>: <span class="string">"新电影名称"</span>,
|
||
<span class="key">"rating"</span>: <span class="number">90</span>,
|
||
<span class="key">"updateTime"</span>: <span class="string">"2026-06-26T11:00:00"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 电影不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"电影不存在"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 权限不足</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">403</span>,
|
||
<span class="key">"message"</span>: <span class="string">"无权修改该电影"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method DELETE">DELETE</span>
|
||
<span class="api-path">/api/drive/{driveId}/movies/{movieId}</span>
|
||
<span class="api-desc">删除电影文件</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>driveId</td><td>Long</td><td>网盘ID</td></tr>
|
||
<tr><td>movieId</td><td>Long</td><td>电影ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>说明</h4>
|
||
<p>逻辑删除(软删除),删除后自动更新网盘和文件夹的统计信息。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"删除成功"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 电影不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"电影不存在"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 权限不足</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">403</span>,
|
||
<span class="key">"message"</span>: <span class="string">"无权删除该电影"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 重复电影检查 -->
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/drive/movies/duplicates</span>
|
||
<span class="api-desc">检查重复电影</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>功能说明</h4>
|
||
<p>查询当前用户所有网盘下所有文件夹中的电影,按标题(title)分组找出重复的电影。返回每组重复电影的详细信息,包括所在文件夹的完整路径,前端可让用户选择删除其中一个。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"duplicateGroups"</span>: [
|
||
{
|
||
<span class="key">"title"</span>: <span class="string">"电影名称"</span>,
|
||
<span class="key">"count"</span>: <span class="number">2</span>,
|
||
<span class="key">"movies"</span>: [
|
||
{
|
||
<span class="key">"id"</span>: <span class="number">10</span>,
|
||
<span class="key">"driveId"</span>: <span class="number">1</span>,
|
||
<span class="key">"folderId"</span>: <span class="number">5</span>,
|
||
<span class="key">"title"</span>: <span class="string">"电影名称"</span>,
|
||
<span class="key">"originalName"</span>: <span class="string">"电影名称.mp4"</span>,
|
||
<span class="key">"fileSize"</span>: <span class="number">1073741824</span>,
|
||
<span class="key">"extension"</span>: <span class="string">"mp4"</span>,
|
||
<span class="key">"category"</span>: <span class="string">"sci-fi"</span>,
|
||
<span class="key">"rating"</span>: <span class="number">85</span>,
|
||
<span class="key">"createTime"</span>: <span class="string">"2025-01-01T10:00:00"</span>,
|
||
<span class="key">"folderPath"</span>: <span class="string">"我的电影库/科幻/2024"</span>
|
||
},
|
||
{
|
||
<span class="key">"id"</span>: <span class="number">20</span>,
|
||
<span class="key">"driveId"</span>: <span class="number">1</span>,
|
||
<span class="key">"folderId"</span>: <span class="number">8</span>,
|
||
<span class="key">"title"</span>: <span class="string">"电影名称"</span>,
|
||
<span class="key">"originalName"</span>: <span class="string">"电影名称.mkv"</span>,
|
||
<span class="key">"fileSize"</span>: <span class="number">2147483648</span>,
|
||
<span class="key">"extension"</span>: <span class="string">"mkv"</span>,
|
||
<span class="key">"category"</span>: <span class="string">"sci-fi"</span>,
|
||
<span class="key">"rating"</span>: <span class="keyword">null</span>,
|
||
<span class="key">"createTime"</span>: <span class="string">"2025-02-01T15:00:00"</span>,
|
||
<span class="key">"folderPath"</span>: <span class="string">"我的电影库/动作"</span>
|
||
}
|
||
]
|
||
}
|
||
],
|
||
<span class="key">"totalGroups"</span>: <span class="number">1</span>,
|
||
<span class="key">"totalDuplicates"</span>: <span class="number">2</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>返回字段说明</h4>
|
||
<table class="param-table">
|
||
<tr><th>字段</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>duplicateGroups</td><td>Array</td><td>重复电影分组列表</td></tr>
|
||
<tr><td>duplicateGroups[].title</td><td>String</td><td>重复的电影标题</td></tr>
|
||
<tr><td>duplicateGroups[].count</td><td>Integer</td><td>该标题下的重复数量</td></tr>
|
||
<tr><td>duplicateGroups[].movies</td><td>Array</td><td>该标题下的所有电影记录</td></tr>
|
||
<tr><td>duplicateGroups[].movies[].id</td><td>Long</td><td>电影ID(可用于删除接口)</td></tr>
|
||
<tr><td>duplicateGroups[].movies[].folderPath</td><td>String</td><td>所在文件夹完整路径,如"网盘名/文件夹1/文件夹2"</td></tr>
|
||
<tr><td>totalGroups</td><td>Integer</td><td>重复组总数</td></tr>
|
||
<tr><td>totalDuplicates</td><td>Integer</td><td>涉及重复的电影总数</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>错误码</h4>
|
||
<table class="param-table">
|
||
<tr><th>code</th><th>说明</th></tr>
|
||
<tr><td>401</td><td>未登录或 Token 无效</td></tr>
|
||
<tr><td>500</td><td>服务器内部错误</td></tr>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Icon服务 -->
|
||
<div class="section" id="icon">
|
||
<div class="service-card">
|
||
<h2>Icon 管理服务</h2>
|
||
<span class="port">wangpan-drive-service : 8082</span>
|
||
</div>
|
||
|
||
<!-- 创建 Icon -->
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method POST">POST</span>
|
||
<span class="api-path">/api/icon</span>
|
||
<span class="api-desc">创建 Icon</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>请求体(JSON)</h4>
|
||
<table class="param-table">
|
||
<tr><th>字段</th><th>类型</th><th>必填</th><th>说明</th></tr>
|
||
<tr><td>name</td><td>String</td><td>是</td><td>Icon 名称(最大100字符)</td></tr>
|
||
<tr><td>url</td><td>String</td><td>条件必填</td><td>外网链接 URL(最大500字符,linkType为external或both时必填)</td></tr>
|
||
<tr><td>internalUrl</td><td>String</td><td>条件必填</td><td>内网链接 URL(最大500字符,linkType为internal或both时必填)</td></tr>
|
||
<tr><td>linkType</td><td>String</td><td>否</td><td>链接类型:external(仅外网,默认)/ internal(仅内网)/ both(内外网)</td></tr>
|
||
<tr><td>description</td><td>String</td><td>否</td><td>Icon 描述(最大500字符)</td></tr>
|
||
<tr><td>sortOrder</td><td>Integer</td><td>否</td><td>排序值,数字越小越靠前,默认0</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>请求示例(仅外网)</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"name"</span>: <span class="string">"百度"</span>,
|
||
<span class="key">"url"</span>: <span class="string">"https://www.baidu.com"</span>,
|
||
<span class="key">"linkType"</span>: <span class="string">"external"</span>,
|
||
<span class="key">"description"</span>: <span class="string">"搜索引擎"</span>,
|
||
<span class="key">"sortOrder"</span>: <span class="number">1</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>请求示例(内外网都有)</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"name"</span>: <span class="string">"内部系统"</span>,
|
||
<span class="key">"url"</span>: <span class="string">"https://system.example.com"</span>,
|
||
<span class="key">"internalUrl"</span>: <span class="string">"http://192.168.1.100:8080"</span>,
|
||
<span class="key">"linkType"</span>: <span class="string">"both"</span>,
|
||
<span class="key">"description"</span>: <span class="string">"内部管理系统"</span>,
|
||
<span class="key">"sortOrder"</span>: <span class="number">2</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应(200)</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"创建成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"name"</span>: <span class="string">"百度"</span>,
|
||
<span class="key">"url"</span>: <span class="string">"https://www.baidu.com"</span>,
|
||
<span class="key">"internalUrl"</span>: <span class="keyword">null</span>,
|
||
<span class="key">"linkType"</span>: <span class="string">"external"</span>,
|
||
<span class="key">"description"</span>: <span class="string">"搜索引擎"</span>,
|
||
<span class="key">"sortOrder"</span>: <span class="number">1</span>,
|
||
<span class="key">"status"</span>: <span class="string">"active"</span>,
|
||
<span class="key">"logoUrl"</span>: <span class="string">"http://118.178.238.159:39000/wangpan/icons/2/1718265600000.png"</span>,
|
||
<span class="key">"createTime"</span>: <span class="string">"2026-06-13T16:00:00"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 查询 Icon 列表 -->
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/icon</span>
|
||
<span class="api-desc">查询当前用户的 Icon 列表</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>功能说明</h4>
|
||
<p>查询当前登录用户的所有 Icon,按 sortOrder 升序、createTime 降序排列。每个用户只能看到自己创建的 Icon。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应(200)</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"list"</span>: [
|
||
{
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"name"</span>: <span class="string">"百度"</span>,
|
||
<span class="key">"url"</span>: <span class="string">"https://www.baidu.com"</span>,
|
||
<span class="key">"internalUrl"</span>: <span class="keyword">null</span>,
|
||
<span class="key">"linkType"</span>: <span class="string">"external"</span>,
|
||
<span class="key">"description"</span>: <span class="string">"搜索引擎"</span>,
|
||
<span class="key">"sortOrder"</span>: <span class="number">1</span>,
|
||
<span class="key">"status"</span>: <span class="string">"active"</span>,
|
||
<span class="key">"logoUrl"</span>: <span class="string">"http://118.178.238.159:39000/wangpan/icons/2/1718265600000.png"</span>,
|
||
<span class="key">"createTime"</span>: <span class="string">"2026-06-13T16:00:00"</span>,
|
||
<span class="key">"updateTime"</span>: <span class="string">"2026-06-13T16:00:00"</span>
|
||
}
|
||
],
|
||
<span class="key">"total"</span>: <span class="number">1</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 查询单个 Icon -->
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/icon/{id}</span>
|
||
<span class="api-desc">查询单个 Icon 详情</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>id</td><td>Long</td><td>Icon ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应(200)</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"name"</span>: <span class="string">"百度"</span>,
|
||
<span class="key">"url"</span>: <span class="string">"https://www.baidu.com"</span>,
|
||
<span class="key">"internalUrl"</span>: <span class="keyword">null</span>,
|
||
<span class="key">"linkType"</span>: <span class="string">"external"</span>,
|
||
<span class="key">"description"</span>: <span class="string">"搜索引擎"</span>,
|
||
<span class="key">"sortOrder"</span>: <span class="number">1</span>,
|
||
<span class="key">"status"</span>: <span class="string">"active"</span>,
|
||
<span class="key">"logoUrl"</span>: <span class="string">"http://118.178.238.159:39000/wangpan/icons/2/1718265600000.png"</span>,
|
||
<span class="key">"createTime"</span>: <span class="string">"2026-06-13T16:00:00"</span>,
|
||
<span class="key">"updateTime"</span>: <span class="string">"2026-06-13T16:00:00"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — Icon 不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"Icon 不存在或无权访问"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 无效"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 更新 Icon -->
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method PUT">PUT</span>
|
||
<span class="api-path">/api/icon/{id}</span>
|
||
<span class="api-desc">更新 Icon</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>id</td><td>Long</td><td>Icon ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>请求体(JSON,所有字段可选)</h4>
|
||
<table class="param-table">
|
||
<tr><th>字段</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>name</td><td>String</td><td>Icon 名称</td></tr>
|
||
<tr><td>url</td><td>String</td><td>外网链接</td></tr>
|
||
<tr><td>internalUrl</td><td>String</td><td>内网链接</td></tr>
|
||
<tr><td>linkType</td><td>String</td><td>链接类型:external / internal / both</td></tr>
|
||
<tr><td>description</td><td>String</td><td>Icon 描述</td></tr>
|
||
<tr><td>sortOrder</td><td>Integer</td><td>排序值</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>请求示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"name"</span>: <span class="string">"新名称"</span>,
|
||
<span class="key">"url"</span>: <span class="string">"https://new-url.com"</span>,
|
||
<span class="key">"internalUrl"</span>: <span class="string">"http://192.168.1.100:8080"</span>,
|
||
<span class="key">"linkType"</span>: <span class="string">"both"</span>,
|
||
<span class="key">"sortOrder"</span>: <span class="number">2</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应(200)</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"更新成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"name"</span>: <span class="string">"新名称"</span>,
|
||
<span class="key">"url"</span>: <span class="string">"https://new-url.com"</span>,
|
||
<span class="key">"internalUrl"</span>: <span class="string">"http://192.168.1.100:8080"</span>,
|
||
<span class="key">"linkType"</span>: <span class="string">"both"</span>,
|
||
<span class="key">"description"</span>: <span class="string">"搜索引擎"</span>,
|
||
<span class="key">"sortOrder"</span>: <span class="number">2</span>,
|
||
<span class="key">"status"</span>: <span class="string">"active"</span>,
|
||
<span class="key">"logoUrl"</span>: <span class="string">"http://118.178.238.159:39000/wangpan/icons/2/1718265600000.png"</span>,
|
||
<span class="key">"createTime"</span>: <span class="string">"2026-06-13T16:00:00"</span>,
|
||
<span class="key">"updateTime"</span>: <span class="string">"2026-06-13T17:00:00"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>错误码</h4>
|
||
<table class="param-table">
|
||
<tr><th>code</th><th>说明</th></tr>
|
||
<tr><td>401</td><td>未登录或 Token 无效</td></tr>
|
||
<tr><td>500</td><td>Icon 不存在或无权修改</td></tr>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 删除 Icon -->
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method DELETE">DELETE</span>
|
||
<span class="api-path">/api/icon/{id}</span>
|
||
<span class="api-desc">删除 Icon</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>id</td><td>Long</td><td>Icon ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应(200)</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"删除成功"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>错误码</h4>
|
||
<table class="param-table">
|
||
<tr><th>code</th><th>说明</th></tr>
|
||
<tr><td>401</td><td>未登录或 Token 无效</td></tr>
|
||
<tr><td>500</td><td>Icon 不存在或无权删除</td></tr>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 上传自定义图标 -->
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method POST">POST</span>
|
||
<span class="api-path">/api/icon/{id}/logo</span>
|
||
<span class="api-desc">上传自定义图标图片</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>功能说明</h4>
|
||
<p>上传自定义图标图片替换自动抓取的 logo。上传后会自动删除旧的 MinIO 图片,防止硬盘空间浪费。系统每 24 小时自动清理无用图片。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>id</td><td>Long</td><td>Icon ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>请求格式</h4>
|
||
<p><code>multipart/form-data</code></p>
|
||
<table class="param-table">
|
||
<tr><th>字段</th><th>类型</th><th>必填</th><th>说明</th></tr>
|
||
<tr><td>file</td><td>File</td><td>是</td><td>图片文件(png/jpg/jpeg/gif/webp/ico,最大 1MB)</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>请求示例(curl)</h4>
|
||
<div class="code-block">curl -X POST http://localhost:8888/api/icon/1/logo \
|
||
-H "Authorization: Bearer <token>" \
|
||
-F "file=@/path/to/icon.png"</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应(200)</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"图标上传成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"name"</span>: <span class="string">"百度"</span>,
|
||
<span class="key">"logoUrl"</span>: <span class="string">"http://118.178.238.159:39000/wangpan/icons/2/1718265600000.png"</span>,
|
||
<span class="key">"updateTime"</span>: <span class="string">"2026-06-15T10:00:00"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 文件为空</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">400</span>,
|
||
<span class="key">"message"</span>: <span class="string">"上传文件为空"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 文件格式不支持</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">400</span>,
|
||
<span class="key">"message"</span>: <span class="string">"不支持的文件格式,仅支持 png/jpg/jpeg/gif/webp/ico"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 文件超过 1MB</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">400</span>,
|
||
<span class="key">"message"</span>: <span class="string">"文件大小超过限制(最大 1MB)"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — Icon 不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"Icon 不存在"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- TMDB服务 -->
|
||
<div class="section" id="tmdb">
|
||
<div class="service-card">
|
||
<h2>TMDB 刮削服务</h2>
|
||
<span class="port">wangpan-tmdb-service : 8083</span>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/movies/recommend</span>
|
||
<span class="api-desc">今日推荐(每天固定3部电影)</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>功能说明</h4>
|
||
<p>从当前用户的电影库中随机抽取3部电影用于首页展示。</p>
|
||
<p><strong>推荐规则:</strong></p>
|
||
<ul>
|
||
<li>从 00:00 到 23:59 返回固定的3部电影</li>
|
||
<li>当天不管查询多少次都返回相同的结果</li>
|
||
<li>第二天 00:00 后重新随机挑选3部</li>
|
||
<li>推荐结果缓存在 wp_daily_recommend 表中</li>
|
||
</ul>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"list"</span>: [
|
||
{
|
||
<span class="key">"id"</span>: <span class="number">10</span>,
|
||
<span class="key">"title"</span>: <span class="string">"电影名称1"</span>,
|
||
<span class="key">"subtitle"</span>: <span class="string">"副标题"</span>,
|
||
<span class="key">"posterUrl"</span>: <span class="string">"海报URL"</span>,
|
||
<span class="key">"rating"</span>: <span class="number">85</span>,
|
||
<span class="key">"category"</span>: <span class="string">"动作"</span>,
|
||
<span class="key">"tags"</span>: <span class="string">"标签1,标签2"</span>,
|
||
<span class="key">"createTime"</span>: <span class="string">"2025-01-01T10:00:00"</span>
|
||
},
|
||
{
|
||
<span class="key">"id"</span>: <span class="number">20</span>,
|
||
<span class="key">"title"</span>: <span class="string">"电影名称2"</span>,
|
||
...
|
||
},
|
||
{
|
||
<span class="key">"id"</span>: <span class="number">30</span>,
|
||
<span class="key">"title"</span>: <span class="string">"电影名称3"</span>,
|
||
...
|
||
}
|
||
],
|
||
<span class="key">"count"</span>: <span class="number">3</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>返回字段说明</h4>
|
||
<table class="param-table">
|
||
<tr><th>字段</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>list</td><td>Array</td><td>推荐的电影列表(最多3部)</td></tr>
|
||
<tr><td>list[].id</td><td>Long</td><td>电影ID</td></tr>
|
||
<tr><td>list[].title</td><td>String</td><td>电影标题</td></tr>
|
||
<tr><td>list[].subtitle</td><td>String</td><td>副标题</td></tr>
|
||
<tr><td>list[].posterUrl</td><td>String</td><td>海报URL</td></tr>
|
||
<tr><td>list[].rating</td><td>Integer</td><td>评分(0-100)</td></tr>
|
||
<tr><td>list[].category</td><td>String</td><td>分类</td></tr>
|
||
<tr><td>list[].tags</td><td>String</td><td>标签</td></tr>
|
||
<tr><td>list[].createTime</td><td>String</td><td>创建时间</td></tr>
|
||
<tr><td>count</td><td>Integer</td><td>实际返回的电影数量(可能小于3)</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录或 Token 无效</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 已过期"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 服务器内部错误</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">500</span>,
|
||
<span class="key">"message"</span>: <span class="string">"服务器内部错误,请稍后重试"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/movies</span>
|
||
<span class="api-desc">电影列表查询(按文件夹分组,每组最多10条)</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>功能说明</h4>
|
||
<p>从 <code>wp_drive_movie</code> 表查询当前用户所有电影,按文件夹分组返回,每个文件夹最多返回 10 条电影数据。支持分页:pageNo 控制文件夹分页。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>查询参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>必填</th><th>说明</th></tr>
|
||
<tr><td>keyword</td><td>String</td><td>否</td><td>搜索关键词</td></tr>
|
||
<tr><td>status</td><td>String</td><td>否</td><td>电影状态:active(正常)/ deleted(已删除)</td></tr>
|
||
<tr><td>scrapeType</td><td>String</td><td>否</td><td>刮削类型:tmdb / manual / none</td></tr>
|
||
<tr><td>sortBy</td><td>String</td><td>否</td><td>排序字段(如 createTime、rating、title)</td></tr>
|
||
<tr><td>sortOrder</td><td>String</td><td>否</td><td>排序方向:asc / desc</td></tr>
|
||
<tr><td>pageNo</td><td>int</td><td>否</td><td>页码,默认 1</td></tr>
|
||
<tr><td>pageSize</td><td>int</td><td>否</td><td>每页条数(文件夹数),默认 20</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>响应字段说明</h4>
|
||
<table class="param-table">
|
||
<tr><th>字段</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>totalFolders</td><td>Integer</td><td>文件夹总数</td></tr>
|
||
<tr><td>pageNo</td><td>Integer</td><td>当前页码</td></tr>
|
||
<tr><td>pageSize</td><td>Integer</td><td>每页条数</td></tr>
|
||
<tr><td>folderGroups[].folderId</td><td>Long</td><td>文件夹ID</td></tr>
|
||
<tr><td>folderGroups[].movieCount</td><td>Integer</td><td>该文件夹下返回的电影数量</td></tr>
|
||
<tr><td>folderGroups[].movies[].id</td><td>Long</td><td>电影ID</td></tr>
|
||
<tr><td>folderGroups[].movies[].driveId</td><td>Long</td><td>所属网盘ID</td></tr>
|
||
<tr><td>folderGroups[].movies[].folderId</td><td>Long</td><td>所属文件夹ID</td></tr>
|
||
<tr><td>folderGroups[].movies[].title</td><td>String</td><td>电影名称</td></tr>
|
||
<tr><td>folderGroups[].movies[].subtitle</td><td>String</td><td>副标题</td></tr>
|
||
<tr><td>folderGroups[].movies[].originalName</td><td>String</td><td>原始文件名</td></tr>
|
||
<tr><td>folderGroups[].movies[].mimeType</td><td>String</td><td>MIME类型</td></tr>
|
||
<tr><td>folderGroups[].movies[].fileSize</td><td>Long</td><td>文件大小(字节)</td></tr>
|
||
<tr><td>folderGroups[].movies[].extension</td><td>String</td><td>文件扩展名</td></tr>
|
||
<tr><td>folderGroups[].movies[].description</td><td>String</td><td>描述</td></tr>
|
||
<tr><td>folderGroups[].movies[].scrapeStatus</td><td>String</td><td>刮削状态</td></tr>
|
||
<tr><td>folderGroups[].movies[].rating</td><td>Integer</td><td>评分(0-100)</td></tr>
|
||
<tr><td>folderGroups[].movies[].tags</td><td>String</td><td>标签</td></tr>
|
||
<tr><td>folderGroups[].movies[].posterUrl</td><td>String</td><td>竖版海报URL(2:3 比例)</td></tr>
|
||
<tr><td>folderGroups[].movies[].backdropUrl</td><td>String</td><td>横版背景图URL(16:9 比例)</td></tr>
|
||
<tr><td>folderGroups[].movies[].minioUrl</td><td>String</td><td>MinIO 文件访问URL</td></tr>
|
||
<tr><td>folderGroups[].movies[].createTime</td><td>String</td><td>创建时间</td></tr>
|
||
<tr><td>folderGroups[].movies[].updateTime</td><td>String</td><td>更新时间</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"totalFolders"</span>: <span class="number">5</span>,
|
||
<span class="key">"pageNo"</span>: <span class="number">1</span>,
|
||
<span class="key">"pageSize"</span>: <span class="number">20</span>,
|
||
<span class="key">"folderGroups"</span>: [
|
||
{
|
||
<span class="key">"folderId"</span>: <span class="number">3</span>,
|
||
<span class="key">"movieCount"</span>: <span class="number">2</span>,
|
||
<span class="key">"movies"</span>: [
|
||
{
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"driveId"</span>: <span class="number">1</span>,
|
||
<span class="key">"folderId"</span>: <span class="number">3</span>,
|
||
<span class="key">"title"</span>: <span class="string">"肖申克的救赎"</span>,
|
||
<span class="key">"posterUrl"</span>: <span class="string">"http://...:39000/wangpan/posters/1/poster_xxx.jpg"</span>,
|
||
<span class="key">"backdropUrl"</span>: <span class="string">"http://...:39000/wangpan/posters/1/backdrop_xxx.jpg"</span>,
|
||
<span class="key">"rating"</span>: <span class="number">93</span>,
|
||
...
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录或 Token 无效</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 已过期"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 参数错误</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">400</span>,
|
||
<span class="key">"message"</span>: <span class="string">"请求参数错误"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/movies/{id}</span>
|
||
<span class="api-desc">电影详情查询</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>功能说明</h4>
|
||
<p>查询单部电影的完整详情信息,包括基本信息、海报、评分等。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>id</td><td>Long</td><td>电影ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"driveId"</span>: <span class="number">1</span>,
|
||
<span class="key">"folderId"</span>: <span class="number">3</span>,
|
||
<span class="key">"title"</span>: <span class="string">"肖申克的救赎"</span>,
|
||
<span class="key">"subtitle"</span>: <span class="string">"The Shawshank Redemption"</span>,
|
||
<span class="key">"originalName"</span>: <span class="string">"肖申克的救赎.mp4"</span>,
|
||
<span class="key">"mimeType"</span>: <span class="string">"video/mp4"</span>,
|
||
<span class="key">"fileSize"</span>: <span class="number">2147483648</span>,
|
||
<span class="key">"extension"</span>: <span class="string">"mp4"</span>,
|
||
<span class="key">"description"</span>: <span class="string">"电影描述"</span>,
|
||
<span class="key">"scrapeStatus"</span>: <span class="string">"success"</span>,
|
||
<span class="key">"rating"</span>: <span class="number">93</span>,
|
||
<span class="key">"posterUrl"</span>: <span class="string">"http://...:39000/wangpan/posters/1/poster_xxx.jpg"</span>,
|
||
<span class="key">"backdropUrl"</span>: <span class="string">"http://...:39000/wangpan/posters/1/backdrop_xxx.jpg"</span>,
|
||
<span class="key">"tags"</span>: <span class="string">"剧情,犯罪"</span>,
|
||
<span class="key">"createTime"</span>: <span class="string">"2025-01-01T10:00:00"</span>,
|
||
<span class="key">"updateTime"</span>: <span class="string">"2025-01-15T10:00:00"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 电影不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"电影不存在或无权访问"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录或 Token 无效</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 已过期"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/movies/{id}/scrape-status</span>
|
||
<span class="api-desc">查询单部电影刮削状态</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>功能说明</h4>
|
||
<p>查询单部电影的刮削状态,返回三种状态:刮削中(scraping)、刮削失败(failed)、刮削成功(success)。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>id</td><td>Long</td><td>电影ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>响应字段说明</h4>
|
||
<table class="param-table">
|
||
<tr><th>字段</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>movieId</td><td>Long</td><td>电影ID</td></tr>
|
||
<tr><td>title</td><td>String</td><td>电影名称</td></tr>
|
||
<tr><td>status</td><td>String</td><td>刮削状态:scraping / failed / success / unknown</td></tr>
|
||
<tr><td>message</td><td>String</td><td>状态描述信息</td></tr>
|
||
<tr><td>error</td><td>String</td><td>失败原因(仅 status=failed 时返回)</td></tr>
|
||
<tr><td>posterUrl</td><td>String</td><td>竖版海报URL(仅 status=success 时返回)</td></tr>
|
||
<tr><td>backdropUrl</td><td>String</td><td>横版背景图URL(仅 status=success 时返回)</td></tr>
|
||
<tr><td>rating</td><td>Integer</td><td>评分(仅 status=success 时返回)</td></tr>
|
||
<tr><td>category</td><td>String</td><td>分类(仅 status=success 时返回)</td></tr>
|
||
<tr><td>tags</td><td>String</td><td>标签(仅 status=success 时返回)</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>响应示例 - 刮削中</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"movieId"</span>: <span class="number">1</span>,
|
||
<span class="key">"title"</span>: <span class="string">"电影名称"</span>,
|
||
<span class="key">"status"</span>: <span class="string">"scraping"</span>,
|
||
<span class="key">"message"</span>: <span class="string">"正在刮削中,请稍候..."</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>响应示例 - 刮削失败</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"movieId"</span>: <span class="number">1</span>,
|
||
<span class="key">"title"</span>: <span class="string">"电影名称"</span>,
|
||
<span class="key">"status"</span>: <span class="string">"failed"</span>,
|
||
<span class="key">"message"</span>: <span class="string">"刮削失败"</span>,
|
||
<span class="key">"error"</span>: <span class="string">"TMDB API 请求失败"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>响应示例 - 刮削成功</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"movieId"</span>: <span class="number">1</span>,
|
||
<span class="key">"title"</span>: <span class="string">"电影名称"</span>,
|
||
<span class="key">"status"</span>: <span class="string">"success"</span>,
|
||
<span class="key">"message"</span>: <span class="string">"刮削成功"</span>,
|
||
<span class="key">"posterUrl"</span>: <span class="string">"http://...:39000/wangpan/posters/1/poster_xxx.jpg"</span>,
|
||
<span class="key">"backdropUrl"</span>: <span class="string">"http://...:39000/wangpan/posters/1/backdrop_xxx.jpg"</span>,
|
||
<span class="key">"rating"</span>: <span class="number">85</span>,
|
||
<span class="key">"category"</span>: <span class="string">"动作"</span>,
|
||
<span class="key">"tags"</span>: <span class="string">"动作,科幻"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录或 Token 无效</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 已过期"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 电影不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"电影不存在或无权访问"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method POST">POST</span>
|
||
<span class="api-path">/api/movies</span>
|
||
<span class="api-desc">创建电影</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>功能说明</h4>
|
||
<p>创建新的电影记录,title 为必填字段。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>请求体(所有字段可选,title 必填)</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"title"</span>: <span class="string">"电影名称"</span>, <span style="color:#718096">// 必填</span>
|
||
<span class="key">"subtitle"</span>: <span class="string">"副标题"</span>, <span style="color:#718096">// 可选</span>
|
||
<span class="key">"resourceLibrary"</span>: <span class="string">"资源库"</span>, <span style="color:#718096">// 可选</span>
|
||
<span class="key">"maintainer"</span>: <span class="string">"维护者"</span>, <span style="color:#718096">// 可选</span>
|
||
<span class="key">"status"</span>: <span class="string">"active"</span>, <span style="color:#718096">// 可选:active / deleted</span>
|
||
<span class="key">"category"</span>: <span class="string">"动作"</span>, <span style="color:#718096">// 可选</span>
|
||
<span class="key">"scrapeType"</span>: <span class="string">"tmdb"</span>, <span style="color:#718096">// 可选:tmdb / manual / none</span>
|
||
<span class="key">"rating"</span>: <span class="number">85</span>, <span style="color:#718096">// 可选:0-100</span>
|
||
<span class="key">"posterUrl"</span>: <span class="string">"海报URL"</span>, <span style="color:#718096">// 可选</span>
|
||
<span class="key">"tags"</span>: <span class="string">"标签1,标签2"</span> <span style="color:#718096">// 可选</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"创建成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"title"</span>: <span class="string">"电影名称"</span>,
|
||
<span class="key">"subtitle"</span>: <span class="string">"副标题"</span>,
|
||
<span class="key">"createTime"</span>: <span class="string">"2025-01-01T10:00:00"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 缺少必填字段</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">400</span>,
|
||
<span class="key">"message"</span>: <span class="string">"电影名称不能为空"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录或 Token 无效</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 已过期"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method PUT">PUT</span>
|
||
<span class="api-path">/api/movies/{id}</span>
|
||
<span class="api-desc">更新电影</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>功能说明</h4>
|
||
<p>更新指定电影的信息,支持部分更新。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>id</td><td>Long</td><td>电影ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>请求体(部分更新,所有字段可选)</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"title"</span>: <span class="string">"新电影名称"</span>,
|
||
<span class="key">"subtitle"</span>: <span class="string">"新副标题"</span>,
|
||
<span class="key">"resourceLibrary"</span>: <span class="string">"新资源库"</span>,
|
||
<span class="key">"maintainer"</span>: <span class="string">"新维护者"</span>,
|
||
<span class="key">"status"</span>: <span class="string">"active"</span>,
|
||
<span class="key">"category"</span>: <span class="string">"新分类"</span>,
|
||
<span class="key">"scrapeType"</span>: <span class="string">"tmdb"</span>,
|
||
<span class="key">"rating"</span>: <span class="number">90</span>,
|
||
<span class="key">"posterUrl"</span>: <span class="string">"新海报URL"</span>,
|
||
<span class="key">"tags"</span>: <span class="string">"新标签"</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"更新成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"title"</span>: <span class="string">"新电影名称"</span>,
|
||
<span class="key">"updateTime"</span>: <span class="string">"2025-01-15T10:00:00"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 电影不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"电影不存在"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录或 Token 无效</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 已过期"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method DELETE">DELETE</span>
|
||
<span class="api-path">/api/movies/{id}</span>
|
||
<span class="api-desc">删除电影</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>功能说明</h4>
|
||
<p>删除指定的电影记录。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>id</td><td>Long</td><td>电影ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"删除成功"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 电影不存在</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">404</span>,
|
||
<span class="key">"message"</span>: <span class="string">"电影不存在"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录或 Token 无效</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 已过期"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method POST">POST</span>
|
||
<span class="api-path">/api/movies/batch-delete</span>
|
||
<span class="api-desc">批量删除电影</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>功能说明</h4>
|
||
<p>批量删除多个电影记录。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>请求体</h4>
|
||
<div class="code-block">{ <span class="key">"ids"</span>: [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>] }</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"批量删除成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"deletedCount"</span>: <span class="number">3</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 参数错误</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">400</span>,
|
||
<span class="key">"message"</span>: <span class="string">"电影ID列表不能为空"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录或 Token 无效</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 已过期"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/movies/stats</span>
|
||
<span class="api-desc">电影统计</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>功能说明</h4>
|
||
<p>获取当前用户的电影数量统计,按刮削类型和分类分组。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"totalCount"</span>: <span class="number">10</span>,
|
||
<span class="key">"scrapedCount"</span>: <span class="number">8</span>,
|
||
<span class="key">"pendingCount"</span>: <span class="number">2</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录或 Token 无效</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 已过期"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/tmdb/key</span>
|
||
<span class="api-desc">获取 TMDB API Key</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>功能说明</h4>
|
||
<p>获取当前用户配置的 TMDB API Key。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>成功响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"查询成功"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"tmdbApiKey"</span>: <span class="string">"your_api_key_here"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>失败响应示例 — 未登录或 Token 无效</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">401</span>,
|
||
<span class="key">"message"</span>: <span class="string">"未登录或 Token 已过期"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method POST">POST</span>
|
||
<span class="api-path">/api/tmdb/key</span>
|
||
<span class="api-desc">设置 TMDB API Key</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>请求体</h4>
|
||
<div class="code-block">{ <span class="key">"tmdbApiKey"</span>: <span class="string">"你的API Key"</span> }</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method POST">POST</span>
|
||
<span class="api-path">/api/tmdb-scraper/scrape</span>
|
||
<span class="api-desc">单部电影刮削</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>请求方式</h4>
|
||
<p>支持两种方式传递 movieId:</p>
|
||
<p>1. <strong>URL 查询参数</strong>:<code>?movieId=1</code></p>
|
||
<p>2. <strong>请求体 JSON</strong>:</p>
|
||
<div class="code-block">{ <span class="key">"movieId"</span>: <span class="number">1</span> }</div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"刮削完成"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"movieId"</span>: <span class="number">1</span>,
|
||
<span class="key">"title"</span>: <span class="string">"电影名称"</span>,
|
||
<span class="key">"rating"</span>: <span class="number">85</span>,
|
||
<span class="key">"posterUrl"</span>: <span class="string">"海报URL"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method POST">POST</span>
|
||
<span class="api-path">/api/tmdb-scraper/batch-scrape</span>
|
||
<span class="api-desc">批量刮削</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>请求体(movieIds 可选)</h4>
|
||
<div class="code-block">{ <span class="key">"movieIds"</span>: [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>] } <span style="color:#718096">// 可选:不传则自动查找需要刮削的电影</span></div>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"批量刮削完成"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"successCount"</span>: <span class="number">2</span>,
|
||
<span class="key">"failCount"</span>: <span class="number">0</span>,
|
||
<span class="key">"total"</span>: <span class="number">2</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/tmdb-scraper/caches</span>
|
||
<span class="api-desc">查询缓存列表</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>查询参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>默认值</th><th>说明</th></tr>
|
||
<tr><td>pageNo</td><td>1</td><td>页码</td></tr>
|
||
<tr><td>pageSize</td><td>20</td><td>每页条数</td></tr>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/tmdb-scraper/stats</span>
|
||
<span class="api-desc">刮削统计</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"totalCaches"</span>: <span class="number">5</span>,
|
||
<span class="key">"activeCaches"</span>: <span class="number">3</span>,
|
||
<span class="key">"expiredCaches"</span>: <span class="number">2</span>,
|
||
<span class="key">"userId"</span>: <span class="number">2</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method POST">POST</span>
|
||
<span class="api-path">/api/tmdb-scraper/trigger</span>
|
||
<span class="api-desc">手动触发定时任务</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>功能说明</h4>
|
||
<p>手动触发 TMDB 定时扫描任务,查找需要刮削的电影并执行刮削。无需请求体。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"扫描任务已触发"</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"message"</span>: <span class="string">"扫描任务已触发"</span>,
|
||
<span class="key">"triggeredBy"</span>: <span class="number">2</span>,
|
||
<span class="key">"triggerType"</span>: <span class="string">"manual"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method GET">GET</span>
|
||
<span class="api-path">/api/tmdb-scraper/scraper-logs</span>
|
||
<span class="api-desc">查询刮削日志</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>查询参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>默认值</th><th>说明</th></tr>
|
||
<tr><td>pageNo</td><td>1</td><td>页码</td></tr>
|
||
<tr><td>pageSize</td><td>20</td><td>每页条数</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"data"</span>: {
|
||
<span class="key">"total"</span>: <span class="number">10</span>,
|
||
<span class="key">"list"</span>: [
|
||
{
|
||
<span class="key">"id"</span>: <span class="number">1</span>,
|
||
<span class="key">"scanTime"</span>: <span class="string">"2026-06-18T10:00:00"</span>,
|
||
<span class="key">"totalMovies"</span>: <span class="number">5</span>,
|
||
<span class="key">"successCount"</span>: <span class="number">4</span>,
|
||
<span class="key">"failCount"</span>: <span class="number">1</span>
|
||
}
|
||
],
|
||
<span class="key">"pageNo"</span>: <span class="number">1</span>,
|
||
<span class="key">"pageSize"</span>: <span class="number">20</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="api-item">
|
||
<div class="api-header" onclick="toggleDetail(this)">
|
||
<span class="method DELETE">DELETE</span>
|
||
<span class="api-path">/api/tmdb-scraper/cache/{movieId}</span>
|
||
<span class="api-desc">删除缓存</span><span class="auth-badge">需Token</span>
|
||
</div>
|
||
<div class="api-detail">
|
||
<div class="detail-section">
|
||
<h4>路径参数</h4>
|
||
<table class="param-table">
|
||
<tr><th>参数</th><th>类型</th><th>说明</th></tr>
|
||
<tr><td>movieId</td><td>Long</td><td>电影ID</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>功能说明</h4>
|
||
<p>删除指定电影的 TMDB 刮削缓存,下次刮削时将重新从 TMDB 获取数据。</p>
|
||
</div>
|
||
<div class="detail-section">
|
||
<h4>响应示例</h4>
|
||
<div class="code-block">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"缓存删除成功"</span>,
|
||
<span class="key">"data"</span>: <span class="keyword">null</span>
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 状态码 -->
|
||
<div class="section" id="status">
|
||
<div class="service-card">
|
||
<h2>通用响应格式</h2>
|
||
<div class="code-block" style="margin-top: 12px;">{
|
||
<span class="key">"code"</span>: <span class="number">200</span>,
|
||
<span class="key">"message"</span>: <span class="string">"操作结果描述"</span>,
|
||
<span class="key">"data"</span>: { <span class="string">...</span> }
|
||
}</div>
|
||
</div>
|
||
|
||
<div class="service-card">
|
||
<h2>状态码说明</h2>
|
||
<table class="status-table">
|
||
<tr><th>状态码</th><th>说明</th></tr>
|
||
<tr><td>200</td><td>请求成功</td></tr>
|
||
<tr><td>400</td><td>请求参数错误</td></tr>
|
||
<tr><td>401</td><td>未授权 / 令牌无效</td></tr>
|
||
<tr><td>403</td><td>权限不足</td></tr>
|
||
<tr><td>404</td><td>资源不存在</td></tr>
|
||
<tr><td>500</td><td>服务器内部错误</td></tr>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="service-card">
|
||
<h2>认证说明</h2>
|
||
<p style="font-size: 14px; color: #4a5568; line-height: 1.8;">
|
||
除以下 <strong>3 个接口</strong> 外,所有接口都需要在请求头中携带访问令牌:<br><br>
|
||
|
||
<strong>无需 Token 的接口:</strong><br>
|
||
<code style="background:#c6f6d5;padding:2px 8px;border-radius:4px;">POST /api/login</code> 用户登录<br>
|
||
<code style="background:#c6f6d5;padding:2px 8px;border-radius:4px;">POST /api/register</code> 用户注册<br>
|
||
<code style="background:#c6f6d5;padding:2px 8px;border-radius:4px;">GET /api/token/validate?token=xxx</code> 令牌验证(token 通过 URL 参数传递)<br><br>
|
||
|
||
<strong>需要 Token 的接口(带 <span style="background:#ed8936;color:white;padding:1px 6px;border-radius:10px;font-size:10px;font-weight:600;">需Token</span> 标识):</strong><br>
|
||
在请求头中添加:<code style="background: #edf2f7; padding: 2px 8px; border-radius: 4px;">Authorization: Bearer <token></code>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// 导航切换
|
||
document.querySelectorAll('.nav-item').forEach(item => {
|
||
item.addEventListener('click', function() {
|
||
document.querySelectorAll('.nav-item').forEach(n => n.classList.remove('active'));
|
||
document.querySelectorAll('.section').forEach(s => s.classList.remove('active'));
|
||
this.classList.add('active');
|
||
document.getElementById(this.dataset.section).classList.add('active');
|
||
});
|
||
});
|
||
|
||
// API 详情展开/收起
|
||
function toggleDetail(header) {
|
||
const detail = header.nextElementSibling;
|
||
detail.classList.toggle('show');
|
||
}
|
||
|
||
// 搜索功能
|
||
const searchInput = document.getElementById('apiSearch');
|
||
const searchClear = document.getElementById('searchClear');
|
||
const searchResultCount = document.getElementById('searchResultCount');
|
||
let searchTimeout;
|
||
|
||
searchInput.addEventListener('input', function() {
|
||
clearTimeout(searchTimeout);
|
||
searchTimeout = setTimeout(() => performSearch(this.value), 200);
|
||
|
||
// 显示/隐藏清除按钮
|
||
searchClear.classList.toggle('show', this.value.length > 0);
|
||
});
|
||
|
||
searchClear.addEventListener('click', function() {
|
||
searchInput.value = '';
|
||
performSearch('');
|
||
searchClear.classList.remove('show');
|
||
searchInput.focus();
|
||
});
|
||
|
||
// 支持快捷键 Ctrl/Cmd + K 聚焦搜索框
|
||
document.addEventListener('keydown', function(e) {
|
||
if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
|
||
e.preventDefault();
|
||
searchInput.focus();
|
||
searchInput.select();
|
||
}
|
||
// ESC 键清除搜索
|
||
if (e.key === 'Escape' && document.activeElement === searchInput) {
|
||
searchInput.value = '';
|
||
performSearch('');
|
||
searchClear.classList.remove('show');
|
||
}
|
||
});
|
||
|
||
function performSearch(keyword) {
|
||
const apiItems = document.querySelectorAll('.api-item');
|
||
const sections = document.querySelectorAll('.section');
|
||
|
||
// 清除之前的高亮
|
||
document.querySelectorAll('.highlight').forEach(el => {
|
||
const parent = el.parentNode;
|
||
parent.replaceChild(document.createTextNode(el.textContent), el);
|
||
parent.normalize();
|
||
});
|
||
|
||
if (!keyword.trim()) {
|
||
// 恢复所有项目
|
||
apiItems.forEach(item => item.classList.remove('search-hidden'));
|
||
searchResultCount.classList.remove('show');
|
||
|
||
// 恢复导航栏
|
||
document.querySelectorAll('.nav-item').forEach(item => {
|
||
item.style.display = '';
|
||
});
|
||
|
||
// 恢复 section 显示状态
|
||
sections.forEach(section => {
|
||
section.style.display = '';
|
||
});
|
||
return;
|
||
}
|
||
|
||
const lowerKeyword = keyword.toLowerCase();
|
||
let matchCount = 0;
|
||
const matchedSections = new Set();
|
||
|
||
// 全局搜索:遍历所有分类中的所有接口
|
||
apiItems.forEach(item => {
|
||
const path = item.querySelector('.api-path');
|
||
const desc = item.querySelector('.api-desc');
|
||
const method = item.querySelector('.method');
|
||
|
||
if (!path || !desc) return;
|
||
|
||
const pathText = path.textContent.toLowerCase();
|
||
const descText = desc.textContent.toLowerCase();
|
||
const methodText = method ? method.textContent.toLowerCase() : '';
|
||
|
||
const isMatch = pathText.includes(lowerKeyword) ||
|
||
descText.includes(lowerKeyword) ||
|
||
methodText.includes(lowerKeyword);
|
||
|
||
if (isMatch) {
|
||
item.classList.remove('search-hidden');
|
||
matchCount++;
|
||
|
||
// 记录匹配的 section
|
||
const section = item.closest('.section');
|
||
if (section) {
|
||
matchedSections.add(section.id);
|
||
}
|
||
|
||
// 高亮匹配内容
|
||
highlightText(path, keyword);
|
||
highlightText(desc, keyword);
|
||
|
||
// 自动展开匹配的详情
|
||
const detail = item.querySelector('.api-detail');
|
||
if (detail && !detail.classList.contains('show')) {
|
||
detail.classList.add('show');
|
||
}
|
||
} else {
|
||
item.classList.add('search-hidden');
|
||
}
|
||
});
|
||
|
||
// 全局搜索模式:显示所有有匹配结果的分类
|
||
sections.forEach(section => {
|
||
if (section.id === 'overview' || section.id === 'status') {
|
||
// 架构总览和状态码始终显示
|
||
section.style.display = '';
|
||
} else if (matchedSections.has(section.id)) {
|
||
// 有匹配结果的分类强制显示
|
||
section.style.display = 'block';
|
||
} else {
|
||
// 无匹配结果的分类隐藏
|
||
section.style.display = 'none';
|
||
}
|
||
});
|
||
|
||
// 更新导航栏显示(只显示有匹配结果的分类)
|
||
document.querySelectorAll('.nav-item').forEach(item => {
|
||
const sectionId = item.dataset.section;
|
||
if (sectionId === 'overview' || sectionId === 'status') {
|
||
item.style.display = '';
|
||
} else if (matchedSections.has(sectionId)) {
|
||
item.style.display = '';
|
||
} else {
|
||
item.style.display = 'none';
|
||
}
|
||
});
|
||
|
||
// 显示搜索结果
|
||
searchResultCount.textContent = `找到 ${matchCount} 个匹配的接口(跨 ${matchedSections.size} 个分类)`;
|
||
searchResultCount.classList.add('show');
|
||
}
|
||
|
||
function highlightText(element, keyword) {
|
||
const text = element.textContent;
|
||
const lowerText = text.toLowerCase();
|
||
const lowerKeyword = keyword.toLowerCase();
|
||
const index = lowerText.indexOf(lowerKeyword);
|
||
|
||
if (index === -1) return;
|
||
|
||
const before = text.substring(0, index);
|
||
const match = text.substring(index, index + keyword.length);
|
||
const after = text.substring(index + keyword.length);
|
||
|
||
element.innerHTML = '';
|
||
if (before) element.appendChild(document.createTextNode(before));
|
||
|
||
const highlight = document.createElement('span');
|
||
highlight.className = 'highlight';
|
||
highlight.textContent = match;
|
||
element.appendChild(highlight);
|
||
|
||
if (after) element.appendChild(document.createTextNode(after));
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|