mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-10 09:52:53 +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
|
||||
|
||||
/**
|
||||
* 给apidoc项目增加顺序编号
|
||||
* 给apidoc项目增加顺序编号 / 支持恢复
|
||||
*/
|
||||
|
||||
@error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
|
||||
|
||||
$path = dirname(__FILE__). '/';
|
||||
$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";
|
||||
const NUMBER_WIDTH = 2;
|
||||
|
||||
/** ************************************************************** */
|
||||
/** ************************************************************** */
|
||||
/** ************************************************************** */
|
||||
$isRestore = isset($argv[1]) && strtolower($argv[1]) === 'restore';
|
||||
|
||||
/**
|
||||
* 替换所有空格
|
||||
* @param $str
|
||||
* @return mixed
|
||||
*/
|
||||
function __sRemove($str) {
|
||||
$str = str_replace(" ", " ", $str);
|
||||
if (__strExists($str, " ")) {
|
||||
return __sRemove($str);
|
||||
}
|
||||
return $str;
|
||||
$basePath = dirname(__FILE__) . '/';
|
||||
$controllerFiles = glob($basePath . '*Controller.php');
|
||||
|
||||
if (!$controllerFiles) {
|
||||
echo "No Controller.php files found\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
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
|
||||
* @return bool
|
||||
* 处理单个文件内容
|
||||
*
|
||||
* @param string $content
|
||||
* @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) {
|
||||
if (strlen($str) >= $length) {
|
||||
return $str;
|
||||
function renderAnnotation(string $method, string $endpoint, string $suffix = ''): string
|
||||
{
|
||||
$line = "* @api {" . $method . "} " . $endpoint;
|
||||
|
||||
if ($suffix !== '') {
|
||||
if ($suffix[0] !== ' ') {
|
||||
$line .= ' ';
|
||||
}
|
||||
$line .= $suffix;
|
||||
}
|
||||
$_str = '';
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$_str .= '0';
|
||||
}
|
||||
if ($after) {
|
||||
$_ret = substr($_str . $str, $length * -1);
|
||||
} else {
|
||||
$_ret = substr($str . $_str, 0, $length);
|
||||
}
|
||||
return $_ret;
|
||||
|
||||
return $line;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除已有编号部分
|
||||
*/
|
||||
function stripExistingNumbering(string $text): string
|
||||
{
|
||||
$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
|
||||
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
|
||||
container_exec php "php app/Http/Controllers/Api/apidoc.php restore"
|
||||
;;
|
||||
"debug")
|
||||
shift 1
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user