mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-11 18:42:54 +00:00
no message
This commit is contained in:
parent
e3067b685c
commit
7d08c735ef
378
app/Http/Controllers/Api/apidoc.md
Normal file
378
app/Http/Controllers/Api/apidoc.md
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
# apiDoc 参数标签说明(完整速查)
|
||||||
|
|
||||||
|
apiDoc 使用内联注释为 RESTful API 自动生成文档。
|
||||||
|
以下为所有官方支持的参数与其说明。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @api
|
||||||
|
**定义 API 方法的基本信息**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@api {method} path title
|
||||||
|
```
|
||||||
|
|
||||||
|
- **method**:请求方法,如 `GET`、`POST`、`PUT`、`DELETE` 等
|
||||||
|
- **path**:请求路径,例如 `/user/:id`
|
||||||
|
- **title**:简短标题(显示在文档中)
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@api {get} /user/:id Get user info
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiBody
|
||||||
|
**定义请求体参数**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiBody [{type}] [field=defaultValue] [description]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `{type}` 参数类型(如 String, Number, Object, String[])
|
||||||
|
- `[field]` 可选字段(方括号表示可选)
|
||||||
|
- `=defaultValue` 默认值
|
||||||
|
- `description` 参数说明
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiBody {String} lastname Mandatory Lastname.
|
||||||
|
@apiBody {Object} [address] Optional address object.
|
||||||
|
@apiBody {String} [address[city]] Optional city.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiDefine
|
||||||
|
**定义可复用的文档块**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiDefine name [title] [description]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `name`:唯一标识
|
||||||
|
- `title`:简短标题
|
||||||
|
- `description`:多行描述
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiDefine MyError
|
||||||
|
@apiError UserNotFound The <code>id</code> of the User was not found.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiDeprecated
|
||||||
|
**标记接口为弃用状态**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiDeprecated [text]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `text`:提示文本,可带链接到新方法
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiDeprecated use now (#User:GetDetails)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiDescription
|
||||||
|
**描述接口详细说明**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiDescription text
|
||||||
|
```
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiDescription This is the Description.
|
||||||
|
It is multiline capable.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiError
|
||||||
|
**定义错误返回参数**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiError [(group)] [{type}] field [description]
|
||||||
|
```
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiError UserNotFound The id of the User was not found.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiErrorExample
|
||||||
|
**定义错误返回示例**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiErrorExample [{type}] [title]
|
||||||
|
example
|
||||||
|
```
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiErrorExample {json} Error-Response:
|
||||||
|
HTTP/1.1 404 Not Found
|
||||||
|
{ "error": "UserNotFound" }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiExample
|
||||||
|
**定义接口使用示例**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiExample [{type}] title
|
||||||
|
example
|
||||||
|
```
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiExample {curl} Example usage:
|
||||||
|
curl -i http://localhost/user/4711
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiGroup
|
||||||
|
**定义所属分组**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiGroup name
|
||||||
|
```
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiGroup User
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiHeader
|
||||||
|
**定义请求头参数**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiHeader [(group)] [{type}] [field=defaultValue] [description]
|
||||||
|
```
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiHeader {String} access-key Users unique access-key.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiHeaderExample
|
||||||
|
**定义请求头示例**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiHeaderExample [{type}] [title]
|
||||||
|
example
|
||||||
|
```
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiHeaderExample {json} Header-Example:
|
||||||
|
{
|
||||||
|
"Accept-Encoding": "gzip, deflate"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiIgnore
|
||||||
|
**忽略当前文档块**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiIgnore [hint]
|
||||||
|
```
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiIgnore Not finished method
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiName
|
||||||
|
**定义接口唯一名称**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiName name
|
||||||
|
```
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiName GetUser
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiParam
|
||||||
|
**定义请求参数**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiParam [(group)] [{type}] [field=defaultValue] [description]
|
||||||
|
```
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiParam {Number} id Users unique ID.
|
||||||
|
@apiParam {String} [firstname] Optional firstname.
|
||||||
|
@apiParam {String} country="DE" Mandatory with default.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiParamExample
|
||||||
|
**定义参数请求示例**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiParamExample [{type}] [title]
|
||||||
|
example
|
||||||
|
```
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiParamExample {json} Request-Example:
|
||||||
|
{ "id": 4711 }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiPermission
|
||||||
|
**定义权限要求**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiPermission name
|
||||||
|
```
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiPermission admin
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiPrivate
|
||||||
|
**标记接口为私有(可过滤)**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiPrivate
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiQuery
|
||||||
|
**定义查询参数(?query)**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiQuery [{type}] [field=defaultValue] [description]
|
||||||
|
```
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiQuery {Number} id Users unique ID.
|
||||||
|
@apiQuery {String} [sort="asc"] Sort order.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiSampleRequest
|
||||||
|
**定义接口测试请求 URL**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiSampleRequest url
|
||||||
|
```
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiSampleRequest http://test.github.com/some_path/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiSuccess
|
||||||
|
**定义成功返回参数**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiSuccess [(group)] [{type}] field [description]
|
||||||
|
```
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiSuccess {String} firstname Firstname of the User.
|
||||||
|
@apiSuccess {String} lastname Lastname of the User.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiSuccessExample
|
||||||
|
**定义成功返回示例**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiSuccessExample [{type}] [title]
|
||||||
|
example
|
||||||
|
```
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiSuccessExample {json} Success-Response:
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
{ "firstname": "John", "lastname": "Doe" }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiUse
|
||||||
|
**引用定义块(@apiDefine)**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiUse name
|
||||||
|
```
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiDefine MySuccess
|
||||||
|
@apiSuccess {String} firstname User firstname.
|
||||||
|
|
||||||
|
@apiUse MySuccess
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## @apiVersion
|
||||||
|
**定义接口版本**
|
||||||
|
|
||||||
|
```js
|
||||||
|
@apiVersion version
|
||||||
|
```
|
||||||
|
|
||||||
|
📘 示例:
|
||||||
|
```js
|
||||||
|
@apiVersion 1.6.2
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 附录:常用标签速查表
|
||||||
|
|
||||||
|
| 标签 | 作用 | 示例 |
|
||||||
|
|------|------|------|
|
||||||
|
| `@api` | 定义接口 | `@api {get} /user/:id` |
|
||||||
|
| `@apiName` | 唯一名称 | `@apiName GetUser` |
|
||||||
|
| `@apiGroup` | 所属分组 | `@apiGroup User` |
|
||||||
|
| `@apiParam` | 请求参数 | `@apiParam {Number} id Users unique ID.` |
|
||||||
|
| `@apiBody` | 请求体参数 | `@apiBody {String} name Username.` |
|
||||||
|
| `@apiQuery` | 查询参数 | `@apiQuery {String} keyword Search term.` |
|
||||||
|
| `@apiHeader` | Header 参数 | `@apiHeader {String} token Auth token.` |
|
||||||
|
| `@apiSuccess` | 成功返回字段 | `@apiSuccess {String} name Username.` |
|
||||||
|
| `@apiError` | 错误返回字段 | `@apiError NotFound User not found.` |
|
||||||
|
| `@apiVersion` | 版本号 | `@apiVersion 1.0.0` |
|
||||||
@ -1,89 +1,137 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 给apidoc项目增加顺序编号
|
* 给apidoc项目增加顺序编号 / 支持恢复
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
|
@error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
|
||||||
|
|
||||||
$path = dirname(__FILE__). '/';
|
const NUMBER_WIDTH = 2;
|
||||||
$lists = scandir($path);
|
|
||||||
//
|
|
||||||
foreach ($lists AS $item) {
|
|
||||||
$fillPath = $path . $item;
|
|
||||||
if (str_ends_with($fillPath, 'Controller.php')) {
|
|
||||||
$content = file_get_contents($fillPath);
|
|
||||||
preg_match_all("/\* @api \{(.+?)\} (.*?)\n/i", $content, $matchs);
|
|
||||||
$i = 1;
|
|
||||||
foreach ($matchs[2] AS $key=>$text) {
|
|
||||||
if (in_array(strtolower($matchs[1][$key]), array('get', 'post'))) {
|
|
||||||
$expl = explode(" ", __sRemove($text));
|
|
||||||
$end = $expl[1];
|
|
||||||
if ($expl[2]) {
|
|
||||||
$end = '';
|
|
||||||
foreach ($expl AS $k=>$v) { if ($k >= 2) { $end.= " ".$v; } }
|
|
||||||
}
|
|
||||||
$newtext = "* @api {".$matchs[1][$key]."} ".$expl[0]." ".__zeroFill($i, 2).". ".trim($end);
|
|
||||||
$content = str_replace("* @api {".$matchs[1][$key]."} ".$text, $newtext, $content);
|
|
||||||
$i++;
|
|
||||||
//
|
|
||||||
echo $newtext;
|
|
||||||
echo "\r\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($i > 1) {
|
|
||||||
file_put_contents($fillPath, $content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
echo "Success \n";
|
|
||||||
|
|
||||||
/** ************************************************************** */
|
$isRestore = isset($argv[1]) && strtolower($argv[1]) === 'restore';
|
||||||
/** ************************************************************** */
|
|
||||||
/** ************************************************************** */
|
|
||||||
|
|
||||||
/**
|
$basePath = dirname(__FILE__) . '/';
|
||||||
* 替换所有空格
|
$controllerFiles = glob($basePath . '*Controller.php');
|
||||||
* @param $str
|
|
||||||
* @return mixed
|
if (!$controllerFiles) {
|
||||||
*/
|
echo "No Controller.php files found\n";
|
||||||
function __sRemove($str) {
|
exit(0);
|
||||||
$str = str_replace(" ", " ", $str);
|
|
||||||
if (__strExists($str, " ")) {
|
|
||||||
return __sRemove($str);
|
|
||||||
}
|
|
||||||
return $str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($controllerFiles as $filePath) {
|
||||||
|
$original = file_get_contents($filePath);
|
||||||
|
[$updated, $linesChanged] = processFile($original, $isRestore);
|
||||||
|
|
||||||
|
if (count($linesChanged) === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_put_contents($filePath, $updated);
|
||||||
|
|
||||||
|
foreach ($linesChanged as $line) {
|
||||||
|
echo $line . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo $isRestore ? "Restore Success \n" : "Success \n";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否包含字符
|
* 处理单个文件内容
|
||||||
* @param $string
|
*
|
||||||
* @param $find
|
* @param string $content
|
||||||
* @return bool
|
* @param bool $restore
|
||||||
|
* @return array{string, array<int, string>}
|
||||||
*/
|
*/
|
||||||
function __strExists($string, $find)
|
function processFile(string $content, bool $restore): array
|
||||||
{
|
{
|
||||||
return str_contains($string, $find);
|
$lineChanges = [];
|
||||||
|
$counter = 1;
|
||||||
|
|
||||||
|
$pattern = '/\* @api \{([^\}]+)\}\s+([^\s]+)([^\r\n]*)(\r?\n)/';
|
||||||
|
|
||||||
|
$updated = preg_replace_callback(
|
||||||
|
$pattern,
|
||||||
|
function (array $matches) use ($restore, &$counter, &$lineChanges) {
|
||||||
|
$method = trim($matches[1]);
|
||||||
|
if (!in_array(strtolower($method), ['get', 'post'], true)) {
|
||||||
|
return $matches[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$endpoint = trim($matches[2]);
|
||||||
|
$suffix = normalizeDescription(stripExistingNumbering($matches[3]));
|
||||||
|
|
||||||
|
if (!$restore) {
|
||||||
|
$numberedSuffix = formatNumber($counter) . '.';
|
||||||
|
if ($suffix !== '') {
|
||||||
|
$numberedSuffix .= ' ' . $suffix;
|
||||||
|
}
|
||||||
|
$counter++;
|
||||||
|
} else {
|
||||||
|
$numberedSuffix = $suffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
$newLine = renderAnnotation($method, $endpoint, $numberedSuffix);
|
||||||
|
|
||||||
|
if ($newLine !== rtrim($matches[0], "\r\n")) {
|
||||||
|
$lineChanges[] = $newLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $newLine . $matches[4];
|
||||||
|
},
|
||||||
|
$content
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($updated === null) {
|
||||||
|
return [$content, []];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$updated, $lineChanges];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $str 补零
|
* 生成格式化后的注释行
|
||||||
* @param int $length
|
|
||||||
* @param int $after
|
|
||||||
* @return bool|string
|
|
||||||
*/
|
*/
|
||||||
function __zeroFill($str, $length = 0, $after = 1) {
|
function renderAnnotation(string $method, string $endpoint, string $suffix = ''): string
|
||||||
if (strlen($str) >= $length) {
|
{
|
||||||
return $str;
|
$line = "* @api {" . $method . "} " . $endpoint;
|
||||||
|
|
||||||
|
if ($suffix !== '') {
|
||||||
|
if ($suffix[0] !== ' ') {
|
||||||
|
$line .= ' ';
|
||||||
|
}
|
||||||
|
$line .= $suffix;
|
||||||
}
|
}
|
||||||
$_str = '';
|
|
||||||
for ($i = 0; $i < $length; $i++) {
|
return $line;
|
||||||
$_str .= '0';
|
}
|
||||||
}
|
|
||||||
if ($after) {
|
/**
|
||||||
$_ret = substr($_str . $str, $length * -1);
|
* 移除已有编号部分
|
||||||
} else {
|
*/
|
||||||
$_ret = substr($str . $_str, 0, $length);
|
function stripExistingNumbering(string $text): string
|
||||||
}
|
{
|
||||||
return $_ret;
|
$trimmed = ltrim($text);
|
||||||
|
$pattern = '/^\d+\.\s*/';
|
||||||
|
return preg_replace($pattern, '', $trimmed) ?? $trimmed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 压缩多余空格
|
||||||
|
*/
|
||||||
|
function normalizeDescription(string $text): string
|
||||||
|
{
|
||||||
|
$text = trim($text);
|
||||||
|
if ($text === '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return preg_replace('/\s+/', ' ', $text) ?? $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成固定宽度的数字
|
||||||
|
*/
|
||||||
|
function formatNumber(int $number): string
|
||||||
|
{
|
||||||
|
return str_pad((string) $number, NUMBER_WIDTH, '0', STR_PAD_LEFT);
|
||||||
}
|
}
|
||||||
|
|||||||
1
cmd
1
cmd
@ -805,6 +805,7 @@ case "$1" in
|
|||||||
shift 1
|
shift 1
|
||||||
container_exec php "php app/Http/Controllers/Api/apidoc.php"
|
container_exec php "php app/Http/Controllers/Api/apidoc.php"
|
||||||
docker run -it --rm -v ${WORK_DIR}:/home/node/apidoc kuaifan/apidoc -i app/Http/Controllers/Api -o public/docs
|
docker run -it --rm -v ${WORK_DIR}:/home/node/apidoc kuaifan/apidoc -i app/Http/Controllers/Api -o public/docs
|
||||||
|
container_exec php "php app/Http/Controllers/Api/apidoc.php restore"
|
||||||
;;
|
;;
|
||||||
"debug")
|
"debug")
|
||||||
shift 1
|
shift 1
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user