mirror of
https://gitee.com/ulthon/ulthon_information.git
synced 2026-07-01 14:42:48 +08:00
feat(api): add article/attachment API endpoints, admin management, and API docs
- Articles API: list/detail/create/update/delete with source-based permission control - Attachments API: upload/list/delete with source-based permission control - ApiKeyInfo API: query current key permissions - Admin ApiKey management: generate/regenerate/toggle/permission settings with layui UI - Frontend API documentation page with complete interface reference
This commit is contained in:
130
app/admin/controller/ApiKey.php
Normal file
130
app/admin/controller/ApiKey.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\model\ApiKey as ApiKeyModel;
|
||||
use think\facade\Session;
|
||||
use think\facade\View;
|
||||
|
||||
class ApiKey extends Common
|
||||
{
|
||||
/**
|
||||
* API Key 管理页面
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$admin_id = Session::get('admin_id');
|
||||
$api_key = ApiKeyModel::where('admin_id', $admin_id)->find();
|
||||
|
||||
if (!empty($api_key)) {
|
||||
$api_key->api_key_preview = substr($api_key->getData('api_key'), 0, 8) . '...';
|
||||
$api_key->status_text = $api_key->status == 1 ? '启用' : '禁用';
|
||||
$api_key->create_time_text = date('Y-m-d H:i:s', $api_key->create_time);
|
||||
}
|
||||
|
||||
View::assign('api_key', $api_key);
|
||||
View::assign('admin_info', $this->adminInfo);
|
||||
|
||||
return View::fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 API Key
|
||||
*/
|
||||
public function generate()
|
||||
{
|
||||
$admin_id = Session::get('admin_id');
|
||||
$name = $this->request->param('name', '');
|
||||
|
||||
$exists = ApiKeyModel::where('admin_id', $admin_id)->find();
|
||||
if (!empty($exists)) {
|
||||
return json_message('您已有 API Key,如需更换请使用重新生成');
|
||||
}
|
||||
|
||||
$raw_key = ApiKeyModel::generateKey($admin_id, $name);
|
||||
|
||||
return json_message(['api_key' => $raw_key, 'name' => $name], 0, 'API Key 生成成功,请妥善保管');
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新生成 API Key
|
||||
*/
|
||||
public function regenerate()
|
||||
{
|
||||
$id = $this->request->param('id', 0);
|
||||
$admin_id = Session::get('admin_id');
|
||||
|
||||
$api_key = ApiKeyModel::find($id);
|
||||
if (empty($api_key) || $api_key->admin_id != $admin_id) {
|
||||
return json_message('API Key 不存在或无权操作');
|
||||
}
|
||||
|
||||
$raw_key = ApiKeyModel::regenerateKey($id);
|
||||
|
||||
return json_message(['api_key' => $raw_key], 0, 'API Key 已重新生成');
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用/禁用 API Key
|
||||
*/
|
||||
public function toggle()
|
||||
{
|
||||
$id = $this->request->param('id', 0);
|
||||
$admin_id = Session::get('admin_id');
|
||||
|
||||
$api_key = ApiKeyModel::find($id);
|
||||
if (empty($api_key) || $api_key->admin_id != $admin_id) {
|
||||
return json_message('API Key 不存在或无权操作');
|
||||
}
|
||||
|
||||
$api_key->status = $api_key->status == 1 ? 0 : 1;
|
||||
$api_key->save();
|
||||
|
||||
return json_message('', 0, '状态已更新');
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换写权限
|
||||
*/
|
||||
public function toggleWrite()
|
||||
{
|
||||
$id = $this->request->param('id', 0);
|
||||
$field = $this->request->param('field', '');
|
||||
$value = $this->request->param('value', 0);
|
||||
$admin_id = Session::get('admin_id');
|
||||
|
||||
if (!in_array($field, ['can_write_own', 'can_write_other'])) {
|
||||
return json_message('无效的权限字段');
|
||||
}
|
||||
|
||||
$api_key = ApiKeyModel::find($id);
|
||||
if (empty($api_key) || $api_key->admin_id != $admin_id) {
|
||||
return json_message('API Key 不存在或无权操作');
|
||||
}
|
||||
|
||||
$api_key->$field = $value ? 1 : 0;
|
||||
$api_key->save();
|
||||
|
||||
return json_message('', 0, '权限已更新');
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置删除权限
|
||||
*/
|
||||
public function updateDelete()
|
||||
{
|
||||
$id = $this->request->param('id', 0);
|
||||
$value = $this->request->param('value', 0);
|
||||
$admin_id = Session::get('admin_id');
|
||||
|
||||
$api_key = ApiKeyModel::find($id);
|
||||
if (empty($api_key) || $api_key->admin_id != $admin_id) {
|
||||
return json_message('API Key 不存在或无权操作');
|
||||
}
|
||||
|
||||
$api_key->can_delete = intval($value);
|
||||
$api_key->save();
|
||||
|
||||
return json_message('', 0, '删除权限已更新');
|
||||
}
|
||||
}
|
||||
33
app/api/controller/ApiKeyInfo.php
Normal file
33
app/api/controller/ApiKeyInfo.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
namespace app\api\controller;
|
||||
|
||||
use app\BaseController;
|
||||
|
||||
class ApiKeyInfo extends BaseController
|
||||
{
|
||||
protected $middleware = [\app\middleware\ApiKeyAuth::class];
|
||||
|
||||
public function info()
|
||||
{
|
||||
$request = $this->request;
|
||||
|
||||
$can_delete_text = '不能删除';
|
||||
if ($request->can_delete == 1) {
|
||||
$can_delete_text = '仅删除API数据';
|
||||
} elseif ($request->can_delete == 2) {
|
||||
$can_delete_text = '可删除所有数据';
|
||||
}
|
||||
|
||||
return json_message([
|
||||
'admin_id' => $request->admin_id,
|
||||
'can_write_own' => $request->can_write_own,
|
||||
'can_write_other' => $request->can_write_other,
|
||||
'can_delete' => $request->can_delete,
|
||||
'permissions_text' => [
|
||||
'can_write_own' => $request->can_write_own ? '可管理自己的数据' : '不可管理自己的数据',
|
||||
'can_write_other' => $request->can_write_other ? '可管理后台数据' : '不可管理后台数据',
|
||||
'can_delete' => $can_delete_text,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
241
app/api/controller/Articles.php
Normal file
241
app/api/controller/Articles.php
Normal file
@@ -0,0 +1,241 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
use app\BaseController;
|
||||
use app\model\Post;
|
||||
use app\model\PostCategory;
|
||||
use app\model\PostTag;
|
||||
use think\Request;
|
||||
|
||||
class Articles extends BaseController
|
||||
{
|
||||
protected $middleware = [\app\middleware\ApiKeyAuth::class];
|
||||
|
||||
/**
|
||||
* 文章列表
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$page = $request->param('page', 1, 'intval');
|
||||
$limit = $request->param('limit', 15, 'intval');
|
||||
$type = $request->param('type', '');
|
||||
$category_id = $request->param('category_id', 0, 'intval');
|
||||
$keyword = $request->param('keyword', '');
|
||||
|
||||
$model_list = Post::with(['categorys.category', 'tags.tag'])
|
||||
->order('id desc');
|
||||
|
||||
if (!empty($type)) {
|
||||
$model_list = $model_list->where('type', $type);
|
||||
}
|
||||
if (!empty($category_id)) {
|
||||
$model_list = $model_list->where('category_id', $category_id);
|
||||
}
|
||||
if (!empty($keyword)) {
|
||||
$model_list = $model_list->where('title', 'like', "%{$keyword}%");
|
||||
}
|
||||
|
||||
$list = $model_list->paginate([
|
||||
'page' => $page,
|
||||
'list_rows' => $limit,
|
||||
]);
|
||||
|
||||
return json_message([
|
||||
'list' => $list->items(),
|
||||
'total' => $list->total(),
|
||||
'page' => $page,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 文章详情
|
||||
*/
|
||||
public function read(Request $request)
|
||||
{
|
||||
$id = $request->param('id', 0, 'intval');
|
||||
if ($id <= 0) {
|
||||
return json_message('参数错误');
|
||||
}
|
||||
|
||||
$post = Post::with(['categorys.category', 'tags.tag'])->find($id);
|
||||
if (empty($post)) {
|
||||
return json_message('文章不存在');
|
||||
}
|
||||
|
||||
return json_message(['post' => $post]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文章
|
||||
*/
|
||||
public function save(Request $request)
|
||||
{
|
||||
if ($request->can_write_own != 1) {
|
||||
return json_message('无权操作', 403);
|
||||
}
|
||||
|
||||
$post_data = $request->post();
|
||||
|
||||
if (empty($post_data['title'])) {
|
||||
return json_message('标题必填');
|
||||
}
|
||||
|
||||
$categorys = [];
|
||||
$tags = [];
|
||||
if (isset($post_data['categorys'])) {
|
||||
$categorys = $post_data['categorys'];
|
||||
unset($post_data['categorys']);
|
||||
}
|
||||
if (isset($post_data['tags'])) {
|
||||
$tags = $post_data['tags'];
|
||||
unset($post_data['tags']);
|
||||
}
|
||||
|
||||
$post_data['uid'] = uniqid();
|
||||
$post_data['source'] = 'api';
|
||||
$post_data['create_time'] = time();
|
||||
$post_data['update_time'] = time();
|
||||
|
||||
if (!isset($post_data['type'])) {
|
||||
$post_data['type'] = '1';
|
||||
}
|
||||
if (!isset($post_data['status'])) {
|
||||
$post_data['status'] = 0;
|
||||
}
|
||||
|
||||
$model_post = Post::create($post_data);
|
||||
|
||||
foreach ($categorys as $category) {
|
||||
PostCategory::create([
|
||||
'post_id' => $model_post->id,
|
||||
'category_id' => $category,
|
||||
]);
|
||||
}
|
||||
foreach ($tags as $tag) {
|
||||
PostTag::create([
|
||||
'post_id' => $model_post->id,
|
||||
'tag_id' => $tag,
|
||||
]);
|
||||
}
|
||||
|
||||
return json_message(['id' => $model_post->id, 'uid' => $model_post->uid], 0, '创建成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑文章
|
||||
*/
|
||||
public function update(Request $request)
|
||||
{
|
||||
$id = $request->param('id', 0, 'intval');
|
||||
if ($id <= 0) {
|
||||
return json_message('参数错误');
|
||||
}
|
||||
|
||||
$model_post = Post::find($id);
|
||||
if (empty($model_post)) {
|
||||
return json_message('文章不存在');
|
||||
}
|
||||
|
||||
$source = $model_post->getData('source');
|
||||
if ($source === 'api') {
|
||||
if ($request->can_write_own != 1) {
|
||||
return json_message('无权操作', 403);
|
||||
}
|
||||
} else {
|
||||
if ($request->can_write_other != 1) {
|
||||
return json_message('无权操作', 403);
|
||||
}
|
||||
}
|
||||
|
||||
$post_data = $request->post();
|
||||
unset($post_data['id']);
|
||||
|
||||
// categorys diff update
|
||||
if (isset($post_data['categorys'])) {
|
||||
$categorys = $post_data['categorys'];
|
||||
unset($post_data['categorys']);
|
||||
|
||||
$old_category_list = PostCategory::where('post_id', $id)->select();
|
||||
$old_category_ids = array_column($old_category_list->toArray(), 'category_id');
|
||||
|
||||
// old has, new doesn't -> delete
|
||||
foreach ($old_category_list as $model_category) {
|
||||
if (!in_array($model_category->category_id, $categorys)) {
|
||||
$model_category->delete();
|
||||
}
|
||||
}
|
||||
// new has, old doesn't -> create
|
||||
foreach ($categorys as $category) {
|
||||
if (!in_array($category, $old_category_ids)) {
|
||||
PostCategory::create([
|
||||
'post_id' => $id,
|
||||
'category_id' => $category,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tags diff update
|
||||
if (isset($post_data['tags'])) {
|
||||
$tags = $post_data['tags'];
|
||||
unset($post_data['tags']);
|
||||
|
||||
$old_tag_list = PostTag::where('post_id', $id)->select();
|
||||
$old_tag_ids = array_column($old_tag_list->toArray(), 'tag_id');
|
||||
|
||||
foreach ($old_tag_list as $model_tag) {
|
||||
if (!in_array($model_tag->tag_id, $tags)) {
|
||||
$model_tag->delete();
|
||||
}
|
||||
}
|
||||
foreach ($tags as $tag) {
|
||||
if (!in_array($tag, $old_tag_ids)) {
|
||||
PostTag::create([
|
||||
'post_id' => $id,
|
||||
'tag_id' => $tag,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$model_post->save($post_data);
|
||||
|
||||
return json_message([], 0, '更新成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文章
|
||||
*/
|
||||
public function delete(Request $request)
|
||||
{
|
||||
$id = $request->param('id', 0, 'intval');
|
||||
if ($id <= 0) {
|
||||
return json_message('参数错误');
|
||||
}
|
||||
|
||||
$model_post = Post::find($id);
|
||||
if (empty($model_post)) {
|
||||
return json_message('文章不存在');
|
||||
}
|
||||
|
||||
$source = $model_post->getData('source');
|
||||
if ($source === 'api') {
|
||||
if ($request->can_delete < 1) {
|
||||
return json_message('无权删除', 403);
|
||||
}
|
||||
} else {
|
||||
if ($request->can_delete != 2) {
|
||||
return json_message('无权删除', 403);
|
||||
}
|
||||
}
|
||||
|
||||
$model_post->delete();
|
||||
PostCategory::where('post_id', $id)->delete();
|
||||
PostTag::where('post_id', $id)->delete();
|
||||
|
||||
return json_message([], 0, '删除成功');
|
||||
}
|
||||
}
|
||||
124
app/api/controller/Attachments.php
Normal file
124
app/api/controller/Attachments.php
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
use app\BaseController;
|
||||
use app\UploadFiles as AppUploadFiles;
|
||||
use app\model\UploadFiles as UploadFilesModel;
|
||||
use app\middleware\ApiKeyAuth;
|
||||
|
||||
class Attachments extends BaseController
|
||||
{
|
||||
protected $middleware = [ApiKeyAuth::class];
|
||||
|
||||
/**
|
||||
* 附件列表
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$page = $this->request->param('page', 1, 'intval');
|
||||
$limit = $this->request->param('limit', 20, 'intval');
|
||||
$type = $this->request->param('type', '');
|
||||
|
||||
$query = UploadFilesModel::order('id desc');
|
||||
|
||||
if (!empty($type)) {
|
||||
$query->where('type', $type);
|
||||
}
|
||||
|
||||
$list = $query->paginate([
|
||||
'list_rows' => $limit,
|
||||
'page' => $page,
|
||||
]);
|
||||
|
||||
$items = [];
|
||||
foreach ($list as $item) {
|
||||
$items[] = [
|
||||
'id' => $item->id,
|
||||
'name' => $item->getData('file_name'),
|
||||
'save_name' => $item->getData('save_name'),
|
||||
'url' => $item->src,
|
||||
'type' => $item->getData('type'),
|
||||
'size' => $item->getData('file_size'),
|
||||
'source' => $item->getData('source'),
|
||||
'create_time' => $item->create_time,
|
||||
];
|
||||
}
|
||||
|
||||
return json_message([
|
||||
'list' => $items,
|
||||
'total' => $list->total(),
|
||||
'page' => $page,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传附件
|
||||
*/
|
||||
public function upload()
|
||||
{
|
||||
if (empty($this->request->can_write_own)) {
|
||||
return json_message('无权操作', 403);
|
||||
}
|
||||
|
||||
$file = $this->request->file('file');
|
||||
if (empty($file)) {
|
||||
return json_message('请选择上传文件');
|
||||
}
|
||||
|
||||
try {
|
||||
AppUploadFiles::fileScan($file);
|
||||
$model_file = AppUploadFiles::saveFile($file, 'api_upload');
|
||||
|
||||
$upload_model = UploadFilesModel::where('save_name', $model_file->getData('save_name'))->find();
|
||||
if ($upload_model) {
|
||||
$upload_model->source = 'api';
|
||||
$upload_model->save();
|
||||
}
|
||||
|
||||
return json_message([
|
||||
'id' => $model_file->id,
|
||||
'name' => $model_file->getData('file_name'),
|
||||
'url' => $model_file->src,
|
||||
'size' => $model_file->getData('file_size'),
|
||||
], 0, '上传成功');
|
||||
} catch (\Throwable $th) {
|
||||
return json_message($th->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除附件
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$id = $this->request->param('id', 0, 'intval');
|
||||
if (empty($id)) {
|
||||
return json_message('缺少参数');
|
||||
}
|
||||
|
||||
$file = UploadFilesModel::find($id);
|
||||
if (empty($file)) {
|
||||
return json_message('附件不存在');
|
||||
}
|
||||
|
||||
$source = $file->getData('source');
|
||||
$can_delete = $this->request->can_delete;
|
||||
|
||||
if ($source === 'api' && $can_delete < 1) {
|
||||
return json_message('无权操作', 403);
|
||||
}
|
||||
|
||||
if ($source === 'admin' && $can_delete != 2) {
|
||||
return json_message('无权操作', 403);
|
||||
}
|
||||
|
||||
if (!in_array($source, ['api', 'admin']) && $can_delete < 2) {
|
||||
return json_message('无权操作', 403);
|
||||
}
|
||||
|
||||
$file->delete();
|
||||
|
||||
return json_message('', 0, '删除成功');
|
||||
}
|
||||
}
|
||||
16
app/index/controller/ApiDoc.php
Normal file
16
app/index/controller/ApiDoc.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace app\index\controller;
|
||||
|
||||
use think\facade\View;
|
||||
|
||||
class ApiDoc extends Common
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$page_title = 'API 文档';
|
||||
View::assign('page_title', $page_title);
|
||||
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
283
view/admin/api_key/index.html
Normal file
283
view/admin/api_key/index.html
Normal file
@@ -0,0 +1,283 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>API Key 管理</title>
|
||||
{include file="common/_require"}
|
||||
|
||||
<script>
|
||||
var currentHeaderNavItem = 'Admin';
|
||||
var currentLeftNavItem = 'apikey';
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body class="layui-layout-body">
|
||||
|
||||
<div class="layui-layout layui-layout-admin">
|
||||
{include file="common/_header"}
|
||||
|
||||
{include file="common/left_admin"}
|
||||
|
||||
<div class="layui-body">
|
||||
|
||||
<div style="padding:15px">
|
||||
<div class="main-header">
|
||||
<span class="layui-breadcrumb">
|
||||
<a>首页</a>
|
||||
<a><cite>API Key 管理</cite></a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="main-container">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">API Key 管理</div>
|
||||
<div class="layui-card-body">
|
||||
|
||||
{empty name="api_key"}
|
||||
<!-- 没有 Key 时显示生成按钮 -->
|
||||
<div style="padding: 20px 0;">
|
||||
<p style="margin-bottom: 15px;">您还没有 API Key,点击下方按钮生成一个。</p>
|
||||
<div class="layui-form">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">名称</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" id="key-name" placeholder="可选,给 Key 起个名字" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" id="btn-generate">生成 API Key</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{else /}
|
||||
<!-- 有 Key 时显示信息和操作 -->
|
||||
<div style="padding: 10px 0;">
|
||||
<table class="layui-table" lay-skin="line">
|
||||
<colgroup>
|
||||
<col width="150">
|
||||
<col>
|
||||
</colgroup>
|
||||
<tr>
|
||||
<td>名称</td>
|
||||
<td>{$api_key.name|default='-'}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Key</td>
|
||||
<td style="font-family: monospace; letter-spacing: 1px;">{$api_key.api_key_preview}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>状态</td>
|
||||
<td>
|
||||
{if condition="$api_key.status == 1"}
|
||||
<span class="layui-badge layui-bg-green">启用</span>
|
||||
{else /}
|
||||
<span class="layui-badge">禁用</span>
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>创建时间</td>
|
||||
<td>{$api_key.create_time_text}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- 权限设置区 -->
|
||||
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 30px;">
|
||||
<legend>权限设置</legend>
|
||||
</fieldset>
|
||||
<div class="layui-form" lay-filter="permissionForm">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">管理自己的数据</label>
|
||||
<div class="layui-input-block" style="padding-top: 8px;">
|
||||
<span style="margin-right: 10px; color: #666;">创建/编辑 API 数据</span>
|
||||
<input type="checkbox" name="can_write_own" lay-skin="switch" lay-text="开启|关闭"
|
||||
lay-filter="can_write_own"
|
||||
data-id="{$api_key.id}"
|
||||
{if condition="$api_key.can_write_own == 1"}checked{/if}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">管理后台数据</label>
|
||||
<div class="layui-input-block" style="padding-top: 8px;">
|
||||
<span style="margin-right: 10px; color: #666;">编辑后台创建的数据</span>
|
||||
<input type="checkbox" name="can_write_other" lay-skin="switch" lay-text="开启|关闭"
|
||||
lay-filter="can_write_other"
|
||||
data-id="{$api_key.id}"
|
||||
{if condition="$api_key.can_write_other == 1"}checked{/if}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">删除权限</label>
|
||||
<div class="layui-input-block" style="padding-top: 8px;">
|
||||
<input type="radio" name="can_delete" value="0" title="不能删除"
|
||||
lay-filter="can_delete"
|
||||
data-id="{$api_key.id}"
|
||||
{if condition="$api_key.can_delete == 0"}checked{/if}>
|
||||
<input type="radio" name="can_delete" value="1" title="仅删除API数据"
|
||||
lay-filter="can_delete"
|
||||
data-id="{$api_key.id}"
|
||||
{if condition="$api_key.can_delete == 1"}checked{/if}>
|
||||
<input type="radio" name="can_delete" value="2" title="可删除所有"
|
||||
lay-filter="can_delete"
|
||||
data-id="{$api_key.id}"
|
||||
{if condition="$api_key.can_delete == 2"}checked{/if}>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div style="margin-top: 20px; padding-top: 15px; border-top: 1px solid #e6e6e6;">
|
||||
<button class="layui-btn layui-btn-warm" id="btn-regenerate" data-id="{$api_key.id}">重新生成 Key</button>
|
||||
<button class="layui-btn layui-btn-danger" id="btn-toggle-status" data-id="{$api_key.id}">
|
||||
{if condition="$api_key.status == 1"}禁用 Key{else /}启用 Key{/if}
|
||||
</button>
|
||||
</div>
|
||||
{/empty}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{include file="common/_footer"}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
layui.use(['form', 'layer'], function () {
|
||||
var form = layui.form;
|
||||
var layer = layui.layer;
|
||||
var $ = layui.$;
|
||||
|
||||
form.render();
|
||||
|
||||
// 生成新 Key
|
||||
$('#btn-generate').click(function () {
|
||||
var name = $('#key-name').val();
|
||||
$.post('{:url("admin/ApiKey/generate")}', { name: name }, function (result) {
|
||||
if (result.code === 0) {
|
||||
layer.alert(
|
||||
'<div style="padding: 15px;">' +
|
||||
'<p style="color: #FF5722; font-weight: bold; margin-bottom: 10px;">请立即复制并妥善保管,此后无法再查看完整 Key!</p>' +
|
||||
'<div style="background: #f2f2f2; padding: 10px; word-break: break-all; font-family: monospace; font-size: 14px; user-select: all;">' + result.data.api_key + '</div>' +
|
||||
'</div>',
|
||||
{
|
||||
title: 'API Key 生成成功',
|
||||
area: ['500px', 'auto'],
|
||||
btn: ['我已复制']
|
||||
},
|
||||
function (index) {
|
||||
layer.close(index);
|
||||
location.reload();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
layer.msg(result.msg || '操作失败');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 重新生成 Key
|
||||
$('#btn-regenerate').click(function () {
|
||||
var id = $(this).data('id');
|
||||
layer.confirm('重新生成后旧 Key 将立即失效,确定继续?', function (confirmIndex) {
|
||||
layer.close(confirmIndex);
|
||||
$.post('{:url("admin/ApiKey/regenerate")}', { id: id }, function (result) {
|
||||
if (result.code === 0) {
|
||||
layer.alert(
|
||||
'<div style="padding: 15px;">' +
|
||||
'<p style="color: #FF5722; font-weight: bold; margin-bottom: 10px;">请立即复制并妥善保管,此后无法再查看完整 Key!</p>' +
|
||||
'<div style="background: #f2f2f2; padding: 10px; word-break: break-all; font-family: monospace; font-size: 14px; user-select: all;">' + result.data.api_key + '</div>' +
|
||||
'</div>',
|
||||
{
|
||||
title: 'API Key 已重新生成',
|
||||
area: ['500px', 'auto'],
|
||||
btn: ['我已复制']
|
||||
},
|
||||
function (index) {
|
||||
layer.close(index);
|
||||
location.reload();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
layer.msg(result.msg || '操作失败');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// 启用/禁用
|
||||
$('#btn-toggle-status').click(function () {
|
||||
var id = $(this).data('id');
|
||||
$.post('{:url("admin/ApiKey/toggle")}', { id: id }, function (result) {
|
||||
if (result.code === 0) {
|
||||
layer.msg(result.msg, { icon: 1 });
|
||||
setTimeout(function () {
|
||||
location.reload();
|
||||
}, 800);
|
||||
} else {
|
||||
layer.msg(result.msg || '操作失败');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 写权限开关
|
||||
form.on('switch(can_write_own)', function (data) {
|
||||
var id = $(data.elem).data('id');
|
||||
var value = data.elem.checked ? 1 : 0;
|
||||
$.post('{:url("admin/ApiKey/toggleWrite")}', {
|
||||
id: id,
|
||||
field: 'can_write_own',
|
||||
value: value
|
||||
}, function (result) {
|
||||
if (result.code === 0) {
|
||||
layer.msg(result.msg, { icon: 1 });
|
||||
} else {
|
||||
layer.msg(result.msg || '操作失败');
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
form.on('switch(can_write_other)', function (data) {
|
||||
var id = $(data.elem).data('id');
|
||||
var value = data.elem.checked ? 1 : 0;
|
||||
$.post('{:url("admin/ApiKey/toggleWrite")}', {
|
||||
id: id,
|
||||
field: 'can_write_other',
|
||||
value: value
|
||||
}, function (result) {
|
||||
if (result.code === 0) {
|
||||
layer.msg(result.msg, { icon: 1 });
|
||||
} else {
|
||||
layer.msg(result.msg || '操作失败');
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 删除权限单选
|
||||
form.on('radio(can_delete)', function (data) {
|
||||
var id = $(data.elem).data('id');
|
||||
$.post('{:url("admin/ApiKey/updateDelete")}', {
|
||||
id: id,
|
||||
value: data.value
|
||||
}, function (result) {
|
||||
if (result.code === 0) {
|
||||
layer.msg(result.msg, { icon: 1 });
|
||||
} else {
|
||||
layer.msg(result.msg || '操作失败');
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
538
view/index/api_doc/index.html
Normal file
538
view/index/api_doc/index.html
Normal file
@@ -0,0 +1,538 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{$page_title}-{:get_system_config('site_name')}</title>
|
||||
{include file='common/_require'/}
|
||||
<style>
|
||||
.api-doc-wrap {
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
padding: 24px 28px;
|
||||
line-height: 1.8;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
}
|
||||
.api-doc-wrap h2 {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
border-bottom: 2px solid #1E9FFF;
|
||||
padding-bottom: 8px;
|
||||
margin: 30px 0 16px;
|
||||
color: #1E9FFF;
|
||||
}
|
||||
.api-doc-wrap h2:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.api-doc-wrap h3 {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin: 20px 0 10px;
|
||||
color: #333;
|
||||
}
|
||||
.api-doc-wrap p {
|
||||
margin: 6px 0;
|
||||
}
|
||||
.api-method {
|
||||
display: inline-block;
|
||||
padding: 2px 10px;
|
||||
border-radius: 3px;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
vertical-align: middle;
|
||||
margin-right: 6px;
|
||||
}
|
||||
.api-method-get {
|
||||
background: #5FB878;
|
||||
}
|
||||
.api-method-post {
|
||||
background: #FF5722;
|
||||
}
|
||||
.api-endpoint {
|
||||
font-family: Consolas, 'Courier New', monospace;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
.api-section {
|
||||
background: #fafafa;
|
||||
border: 1px solid #e8e8e8;
|
||||
border-radius: 4px;
|
||||
padding: 16px 20px;
|
||||
margin: 12px 0 20px;
|
||||
}
|
||||
.api-section h4 {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin: 0 0 8px;
|
||||
color: #666;
|
||||
}
|
||||
.api-code {
|
||||
background: #282c34;
|
||||
color: #abb2bf;
|
||||
padding: 12px 16px;
|
||||
border-radius: 4px;
|
||||
font-family: Consolas, 'Courier New', monospace;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
overflow-x: auto;
|
||||
white-space: pre;
|
||||
margin: 8px 0;
|
||||
}
|
||||
.api-code .api-code-comment {
|
||||
color: #5c6370;
|
||||
font-style: italic;
|
||||
}
|
||||
.api-doc-wrap .layui-table {
|
||||
margin: 8px 0;
|
||||
}
|
||||
.api-doc-wrap .layui-table th {
|
||||
background: #f2f2f2;
|
||||
font-weight: bold;
|
||||
}
|
||||
.permission-tag {
|
||||
display: inline-block;
|
||||
background: #FFB800;
|
||||
color: #fff;
|
||||
padding: 1px 8px;
|
||||
border-radius: 3px;
|
||||
font-size: 12px;
|
||||
margin-left: 6px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="layui-container main-container">
|
||||
<div class="layui-row layui-col-space12">
|
||||
{include file='common/_left'/}
|
||||
<div class="layui-col-md7">
|
||||
<div class="main-container">
|
||||
<div class="api-doc-wrap">
|
||||
|
||||
<h2>1. 概述</h2>
|
||||
|
||||
<p><strong>API 基础 URL:</strong><code>{域名}/index.php/api/</code></p>
|
||||
|
||||
<h3>认证方式</h3>
|
||||
<p>所有 API 请求需在 Header 中携带 API Key,支持以下两种方式:</p>
|
||||
<div class="api-code">Authorization: Bearer {api_key}
|
||||
X-API-Key: {api_key}</div>
|
||||
|
||||
<h3>响应格式</h3>
|
||||
<div class="api-code">{
|
||||
"code": 0,
|
||||
"msg": "success",
|
||||
"data": {}
|
||||
}</div>
|
||||
<table class="layui-table" lay-skin="line">
|
||||
<thead>
|
||||
<tr><th>字段</th><th>类型</th><th>说明</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>code</td><td>int</td><td>状态码:0=成功, 401=认证失败, 403=权限不足, 500=业务错误</td></tr>
|
||||
<tr><td>msg</td><td>string</td><td>提示信息</td></tr>
|
||||
<tr><td>data</td><td>object/array</td><td>返回数据</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>2. 权限说明</h2>
|
||||
<p>每个 API Key 对应一组权限,由管理员在后台分配:</p>
|
||||
<table class="layui-table" lay-skin="line">
|
||||
<thead>
|
||||
<tr><th>权限字段</th><th>值</th><th>说明</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>can_write_own</td><td>0 或 1</td><td>能否创建和编辑通过 API 创建的数据</td></tr>
|
||||
<tr><td>can_write_other</td><td>0 或 1</td><td>能否编辑通过后台管理创建的数据</td></tr>
|
||||
<tr><td>can_delete</td><td>0 / 1 / 2</td><td>0=不能删除, 1=仅删除 API 创建的数据, 2=可删除所有数据</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3>权限组合示例</h3>
|
||||
<table class="layui-table" lay-skin="line">
|
||||
<thead>
|
||||
<tr><th>组合</th><th>can_write_own</th><th>can_write_other</th><th>can_delete</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>只读</td><td>0</td><td>0</td><td>0</td></tr>
|
||||
<tr><td>只管自己</td><td>1</td><td>0</td><td>1</td></tr>
|
||||
<tr><td>全权限</td><td>1</td><td>1</td><td>2</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>3. 文章接口</h2>
|
||||
|
||||
<h3>GET /api/articles/index - 文章列表 <span class="permission-tag">所有有效 Key</span></h3>
|
||||
<div class="api-section">
|
||||
<h4>请求参数</h4>
|
||||
<table class="layui-table" lay-skin="line">
|
||||
<thead>
|
||||
<tr><th>参数</th><th>类型</th><th>必填</th><th>说明</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>page</td><td>int</td><td>否</td><td>页码,默认 1</td></tr>
|
||||
<tr><td>limit</td><td>int</td><td>否</td><td>每页数量,默认 15</td></tr>
|
||||
<tr><td>type</td><td>string</td><td>否</td><td>文章类型</td></tr>
|
||||
<tr><td>category_id</td><td>int</td><td>否</td><td>分类 ID</td></tr>
|
||||
<tr><td>keyword</td><td>string</td><td>否</td><td>搜索关键词</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h4>请求示例</h4>
|
||||
<div class="api-code">curl -X GET \
|
||||
"https://example.com/index.php/api/articles/index?page=1&limit=10" \
|
||||
-H "Authorization: Bearer your_api_key"</div>
|
||||
|
||||
<h4>返回示例</h4>
|
||||
<div class="api-code">{
|
||||
"code": 0,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"list": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "文章标题",
|
||||
"content": "文章内容",
|
||||
"type": "1",
|
||||
"status": 1,
|
||||
"source": "api",
|
||||
"create_time": 1700000000,
|
||||
"update_time": 1700000000,
|
||||
"categorys": [...],
|
||||
"tags": [...]
|
||||
}
|
||||
],
|
||||
"total": 100,
|
||||
"page": 1
|
||||
}
|
||||
}</div>
|
||||
</div>
|
||||
|
||||
<h3>GET /api/articles/read - 文章详情 <span class="permission-tag">所有有效 Key</span></h3>
|
||||
<div class="api-section">
|
||||
<h4>请求参数</h4>
|
||||
<table class="layui-table" lay-skin="line">
|
||||
<thead>
|
||||
<tr><th>参数</th><th>类型</th><th>必填</th><th>说明</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>id</td><td>int</td><td>是</td><td>文章 ID</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h4>请求示例</h4>
|
||||
<div class="api-code">curl -X GET \
|
||||
"https://example.com/index.php/api/articles/read?id=1" \
|
||||
-H "Authorization: Bearer your_api_key"</div>
|
||||
|
||||
<h4>返回示例</h4>
|
||||
<div class="api-code">{
|
||||
"code": 0,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"post": {
|
||||
"id": 1,
|
||||
"title": "文章标题",
|
||||
"content": "文章内容",
|
||||
"content_html": "<p>HTML内容</p>",
|
||||
"desc": "摘要",
|
||||
"poster": "/uploads/poster.jpg",
|
||||
"type": "1",
|
||||
"status": 1,
|
||||
"source": "api"
|
||||
},
|
||||
"categories": [...],
|
||||
"tags": [...]
|
||||
}
|
||||
}</div>
|
||||
</div>
|
||||
|
||||
<h3>POST /api/articles/save - 创建文章 <span class="permission-tag" style="background:#FF5722;">can_write_own=1</span></h3>
|
||||
<div class="api-section">
|
||||
<p>Content-Type: <code>application/json</code></p>
|
||||
<p>通过此接口创建的文章会自动标记 <code>source='api'</code></p>
|
||||
|
||||
<h4>请求参数</h4>
|
||||
<table class="layui-table" lay-skin="line">
|
||||
<thead>
|
||||
<tr><th>参数</th><th>类型</th><th>必填</th><th>说明</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>title</td><td>string</td><td>是</td><td>文章标题</td></tr>
|
||||
<tr><td>content</td><td>string</td><td>否</td><td>文章内容(Markdown)</td></tr>
|
||||
<tr><td>content_html</td><td>string</td><td>否</td><td>文章内容(HTML)</td></tr>
|
||||
<tr><td>desc</td><td>string</td><td>否</td><td>文章摘要</td></tr>
|
||||
<tr><td>poster</td><td>string</td><td>否</td><td>封面图 URL</td></tr>
|
||||
<tr><td>type</td><td>string</td><td>否</td><td>文章类型,默认 "1"</td></tr>
|
||||
<tr><td>status</td><td>int</td><td>否</td><td>状态,默认 0(草稿)</td></tr>
|
||||
<tr><td>categorys</td><td>array</td><td>否</td><td>分类 ID 数组,如 [1, 2]</td></tr>
|
||||
<tr><td>tags</td><td>array</td><td>否</td><td>标签 ID 数组,如 [1, 2]</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h4>请求示例</h4>
|
||||
<div class="api-code">curl -X POST \
|
||||
"https://example.com/index.php/api/articles/save" \
|
||||
-H "Authorization: Bearer your_api_key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"title": "新文章标题",
|
||||
"content": "文章内容",
|
||||
"status": 1,
|
||||
"categorys": [1, 2],
|
||||
"tags": [3]
|
||||
}'</div>
|
||||
|
||||
<h4>返回示例</h4>
|
||||
<div class="api-code">{
|
||||
"code": 0,
|
||||
"msg": "创建成功",
|
||||
"data": {
|
||||
"id": 42,
|
||||
"uid": "6501a2b3c4d5e"
|
||||
}
|
||||
}</div>
|
||||
</div>
|
||||
|
||||
<h3>POST /api/articles/update - 编辑文章 <span class="permission-tag" style="background:#FF5722;">需对应写入权限</span></h3>
|
||||
<div class="api-section">
|
||||
<p>Content-Type: <code>application/json</code></p>
|
||||
<p>权限规则:</p>
|
||||
<ul style="padding-left:20px; margin:4px 0;">
|
||||
<li><code>source='api'</code> 的文章:需要 <code>can_write_own=1</code></li>
|
||||
<li><code>source='admin'</code> 的文章:需要 <code>can_write_other=1</code></li>
|
||||
</ul>
|
||||
|
||||
<h4>请求参数</h4>
|
||||
<table class="layui-table" lay-skin="line">
|
||||
<thead>
|
||||
<tr><th>参数</th><th>类型</th><th>必填</th><th>说明</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>id</td><td>int</td><td>是</td><td>文章 ID</td></tr>
|
||||
<tr><td>title</td><td>string</td><td>否</td><td>文章标题</td></tr>
|
||||
<tr><td>content</td><td>string</td><td>否</td><td>文章内容(Markdown)</td></tr>
|
||||
<tr><td>content_html</td><td>string</td><td>否</td><td>文章内容(HTML)</td></tr>
|
||||
<tr><td>desc</td><td>string</td><td>否</td><td>文章摘要</td></tr>
|
||||
<tr><td>poster</td><td>string</td><td>否</td><td>封面图 URL</td></tr>
|
||||
<tr><td>status</td><td>int</td><td>否</td><td>状态</td></tr>
|
||||
<tr><td>categorys</td><td>array</td><td>否</td><td>分类 ID 数组(全量覆盖)</td></tr>
|
||||
<tr><td>tags</td><td>array</td><td>否</td><td>标签 ID 数组(全量覆盖)</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h4>请求示例</h4>
|
||||
<div class="api-code">curl -X POST \
|
||||
"https://example.com/index.php/api/articles/update" \
|
||||
-H "Authorization: Bearer your_api_key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"id": 42,
|
||||
"title": "修改后的标题",
|
||||
"status": 1
|
||||
}'</div>
|
||||
|
||||
<h4>返回示例</h4>
|
||||
<div class="api-code">{
|
||||
"code": 0,
|
||||
"msg": "更新成功",
|
||||
"data": []
|
||||
}</div>
|
||||
</div>
|
||||
|
||||
<h3>POST /api/articles/delete - 删除文章 <span class="permission-tag" style="background:#FF5722;">需对应删除权限</span></h3>
|
||||
<div class="api-section">
|
||||
<p>权限规则:</p>
|
||||
<ul style="padding-left:20px; margin:4px 0;">
|
||||
<li><code>source='api'</code> 的文章:需要 <code>can_delete >= 1</code></li>
|
||||
<li><code>source='admin'</code> 的文章:需要 <code>can_delete = 2</code></li>
|
||||
</ul>
|
||||
|
||||
<h4>请求参数</h4>
|
||||
<table class="layui-table" lay-skin="line">
|
||||
<thead>
|
||||
<tr><th>参数</th><th>类型</th><th>必填</th><th>说明</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>id</td><td>int</td><td>是</td><td>文章 ID</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h4>请求示例</h4>
|
||||
<div class="api-code">curl -X POST \
|
||||
"https://example.com/index.php/api/articles/delete" \
|
||||
-H "Authorization: Bearer your_api_key" \
|
||||
-d "id=42"</div>
|
||||
|
||||
<h4>返回示例</h4>
|
||||
<div class="api-code">{
|
||||
"code": 0,
|
||||
"msg": "删除成功",
|
||||
"data": []
|
||||
}</div>
|
||||
</div>
|
||||
|
||||
<h2>4. 附件接口</h2>
|
||||
|
||||
<h3>GET /api/attachments/index - 附件列表 <span class="permission-tag">所有有效 Key</span></h3>
|
||||
<div class="api-section">
|
||||
<h4>请求参数</h4>
|
||||
<table class="layui-table" lay-skin="line">
|
||||
<thead>
|
||||
<tr><th>参数</th><th>类型</th><th>必填</th><th>说明</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>page</td><td>int</td><td>否</td><td>页码,默认 1</td></tr>
|
||||
<tr><td>limit</td><td>int</td><td>否</td><td>每页数量,默认 20</td></tr>
|
||||
<tr><td>type</td><td>string</td><td>否</td><td>附件类型</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h4>请求示例</h4>
|
||||
<div class="api-code">curl -X GET \
|
||||
"https://example.com/index.php/api/attachments/index?page=1&limit=10" \
|
||||
-H "Authorization: Bearer your_api_key"</div>
|
||||
|
||||
<h4>返回示例</h4>
|
||||
<div class="api-code">{
|
||||
"code": 0,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"list": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "image.png",
|
||||
"save_name": "20260401_abc.png",
|
||||
"url": "/uploads/20260401_abc.png",
|
||||
"type": "image",
|
||||
"size": 102400,
|
||||
"source": "api",
|
||||
"create_time": 1700000000
|
||||
}
|
||||
],
|
||||
"total": 50,
|
||||
"page": 1
|
||||
}
|
||||
}</div>
|
||||
</div>
|
||||
|
||||
<h3>POST /api/attachments/upload - 上传附件 <span class="permission-tag" style="background:#FF5722;">can_write_own=1</span></h3>
|
||||
<div class="api-section">
|
||||
<p>Content-Type: <code>multipart/form-data</code></p>
|
||||
<p>上传的附件会自动标记 <code>source='api'</code></p>
|
||||
|
||||
<h4>请求参数</h4>
|
||||
<table class="layui-table" lay-skin="line">
|
||||
<thead>
|
||||
<tr><th>参数</th><th>类型</th><th>必填</th><th>说明</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>file</td><td>file</td><td>是</td><td>上传的文件</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h4>请求示例</h4>
|
||||
<div class="api-code">curl -X POST \
|
||||
"https://example.com/index.php/api/attachments/upload" \
|
||||
-H "Authorization: Bearer your_api_key" \
|
||||
-F "file=@/path/to/image.png"</div>
|
||||
|
||||
<h4>返回示例</h4>
|
||||
<div class="api-code">{
|
||||
"code": 0,
|
||||
"msg": "上传成功",
|
||||
"data": {
|
||||
"id": 10,
|
||||
"name": "image.png",
|
||||
"url": "/uploads/20260401_abc.png",
|
||||
"size": 102400
|
||||
}
|
||||
}</div>
|
||||
</div>
|
||||
|
||||
<h3>POST /api/attachments/delete - 删除附件 <span class="permission-tag" style="background:#FF5722;">需对应删除权限</span></h3>
|
||||
<div class="api-section">
|
||||
<p>权限规则:</p>
|
||||
<ul style="padding-left:20px; margin:4px 0;">
|
||||
<li><code>source='api'</code> 的附件:需要 <code>can_delete >= 1</code></li>
|
||||
<li><code>source='admin'</code> 的附件:需要 <code>can_delete = 2</code></li>
|
||||
</ul>
|
||||
|
||||
<h4>请求参数</h4>
|
||||
<table class="layui-table" lay-skin="line">
|
||||
<thead>
|
||||
<tr><th>参数</th><th>类型</th><th>必填</th><th>说明</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>id</td><td>int</td><td>是</td><td>附件 ID</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h4>请求示例</h4>
|
||||
<div class="api-code">curl -X POST \
|
||||
"https://example.com/index.php/api/attachments/delete" \
|
||||
-H "Authorization: Bearer your_api_key" \
|
||||
-d "id=10"</div>
|
||||
|
||||
<h4>返回示例</h4>
|
||||
<div class="api-code">{
|
||||
"code": 0,
|
||||
"msg": "删除成功",
|
||||
"data": []
|
||||
}</div>
|
||||
</div>
|
||||
|
||||
<h2>5. 权限查询接口</h2>
|
||||
|
||||
<h3>GET /api/api_key_info/info - 查询当前 Key 权限 <span class="permission-tag">所有有效 Key</span></h3>
|
||||
<div class="api-section">
|
||||
<p>查询当前 API Key 的权限信息,无需额外参数。</p>
|
||||
|
||||
<h4>请求示例</h4>
|
||||
<div class="api-code">curl -X GET \
|
||||
"https://example.com/index.php/api/api_key_info/info" \
|
||||
-H "Authorization: Bearer your_api_key"</div>
|
||||
|
||||
<h4>返回示例</h4>
|
||||
<div class="api-code">{
|
||||
"code": 0,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"admin_id": 1,
|
||||
"can_write_own": 1,
|
||||
"can_write_other": 0,
|
||||
"can_delete": 1,
|
||||
"permissions_text": {
|
||||
"can_write_own": "可管理自己的数据",
|
||||
"can_write_other": "不可管理后台数据",
|
||||
"can_delete": "仅删除API数据"
|
||||
}
|
||||
}
|
||||
}</div>
|
||||
</div>
|
||||
|
||||
<h2>6. 错误码</h2>
|
||||
<table class="layui-table" lay-skin="line">
|
||||
<thead>
|
||||
<tr><th>错误码</th><th>说明</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>0</td><td>成功</td></tr>
|
||||
<tr><td>401</td><td>认证失败(无效或已禁用的 API Key)</td></tr>
|
||||
<tr><td>403</td><td>权限不足</td></tr>
|
||||
<tr><td>500</td><td>业务错误(参数缺失、资源不存在等)</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{include file='common/_right'/}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user