chenlong 1 year ago
parent
commit
1db2c1e042
  1. 48
      Controller/DemoController.php
  2. 118
      View/Document/view.blade.php

48
Controller/DemoController.php

@ -14,6 +14,7 @@ use Plugins\ApiDoc\Attributes\ApiQuery;
use Plugins\ApiDoc\Attributes\ApiReturn; use Plugins\ApiDoc\Attributes\ApiReturn;
use Plugins\ApiDoc\Attributes\ApiVersion; use Plugins\ApiDoc\Attributes\ApiVersion;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Sc\Util\Tool;
/** /**
* API文档demo * API文档demo
@ -176,4 +177,51 @@ class DemoController
{ {
return Response::json()->success(); return Response::json()->success();
} }
/**
* 登录示例
*
* @return ResponseInterface
*/
#[Api]
#[ApiBody('account', 'String', '账号')]
#[ApiBody('password', 'String', '密码')]
#[ApiReturn('user', 'Object', '用户信息')]
#[ApiReturn('user.name', 'String', '用户名')]
#[ApiReturn('user.age', 'Integer', '年龄')]
#[ApiReturn('user.avatar', 'String', '头像')]
#[ApiReturn('user.sex', 'String', '性别')]
#[ApiReturn('token', 'Object', 'Token')]
#[ApiReturn('token.token', 'String', 'Token')]
#[ApiReturn('token.token_exp', 'Integer', 'Token过期时间')]
#[PostMapping(path: 'login')]
public function login(): ResponseInterface
{
return Response::json()->success([
'user' => [
'name' => 'test',
'age' => 18,
'avatar' => 'https://test.test.com',
'sex' => '男',
],
'token' => Tool::jwt()->setData(['user_id' => 1])->getToken()
]);
}
/**
* 刷新token数据返回示例,实际程序会自动处理无需手动请求
*
* @return ResponseInterface
*/
#[Api]
#[ApiReturn('token', 'Object', 'Token')]
#[ApiReturn('token.token', 'String', 'Token')]
#[ApiReturn('token.token_exp', 'Integer', 'Token过期时间')]
#[GetMapping(path: 'refresh-token')]
public function refreshToken(): ResponseInterface
{
return Response::json()->body(Tool\JWT::EXPIRE_CODE, "token过期 自动刷新", [
'token' => Tool::jwt()->setData(['user_id' => 1])->getToken()
]);
}
} }

118
View/Document/view.blade.php

@ -71,21 +71,21 @@
<body> <body>
<div id="app"> <div id="app">
<el-container> <el-container>
<el-aside width="200px"> <el-aside width="200px" style="overflow: hidden">
<el-menu <el-menu
default-active="2" :default-active="apiActive"
class="el-menu-vertical-demo" class="el-menu-vertical-demo"
@select="handleSelect" @select="handleSelect"
background-color="#545c64" background-color="#545c64"
text-color="#fff" text-color="#fff"
active-text-color="#ffd04b"> active-text-color="#ffd04b">
<el-submenu v-for="(item, index) in ApiInfo.apiLists" :index="index"> <el-submenu v-for="(item, index) in ApiInfo.apiLists" v-if="searchP(item)" :index="index">
<template slot="title"> <template slot="title">
<i class="el-icon-location"></i> <i :class="item.children.filter(a => myMark.includes(a.url)).length > 0 ? 'el-icon-star-on' : 'el-icon-star-off'" style="color: #E6A23C"></i>
<span>@{{item.name}}</span> <span>@{{item.name}}</span>
</template> </template>
<el-menu-item v-for="(api, Aindex) in item.children" :index="index + '-' + Aindex"> <el-menu-item v-for="(api, Aindex) in item.children" v-if="search(api)" :index="index + '-' + Aindex">
<i class="el-icon-menu"></i> <i :class="myMark.includes(api.url) ? 'el-icon-star-on' : 'el-icon-star-off'" style="color: #E6A23C"></i>
<span slot="title">@{{api.name}}</span> <span slot="title">@{{api.name}}</span>
</el-menu-item> </el-menu-item>
</el-submenu> </el-submenu>
@ -93,14 +93,15 @@
</el-aside> </el-aside>
<el-container> <el-container>
<el-header> <el-header>
<el-button style="margin-top: 8px" type="primary" plain @click="editApiDoc = true">文档说明</el-button> <el-button style="margin-top: 8px" type="primary" plain @click="clearCurrentApi">文档说明</el-button>
<el-button style="margin-top: 8px" type="primary" plain >我的标记</el-button> <el-button style="margin-top: 8px" type="primary" plain @click="showMark = !showMark">我的标记</el-button>
</el-header> </el-header>
<el-main> <el-main>
<el-row v-if="currentApiInfo.name" :gutter="10"> <el-row v-if="currentApiInfo.name" :gutter="10">
<el-col :span="12"> <el-col :span="12">
<el-card class="box-card"> <el-card class="box-card">
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">
<i :class="myMark.includes(currentApiInfo.url) ? 'el-icon-star-on' : 'el-icon-star-off'" @click="mark(currentApiInfo.url)" style="color: #E6A23C;font-size: 25px;position: relative;top: 3px"></i>
<el-tag>@{{currentApiInfo.method}}</el-tag> <el-tag>@{{currentApiInfo.method}}</el-tag>
<el-link type="primary">@{{ApiInfo.host}}@{{currentApiInfo.url}}</el-link> <el-link type="primary">@{{ApiInfo.host}}@{{currentApiInfo.url}}</el-link>
<el-link :icon="sendIcon" type="success" @click="send" style="font-size:18px"></el-link> <el-link :icon="sendIcon" type="success" @click="send" style="font-size:18px"></el-link>
@ -221,14 +222,30 @@
</el-col> </el-col>
</el-row> </el-row>
<div v-else> <div v-else>
@{{ ApiInfo.des }} <el-alert title="页面介绍" type="success">
<div><i class="el-icon-star-on" style="color: #E6A23C"></i> 已做标记,可认为是收藏,接口详情点击可切换标记状态</div>
<div><i class="el-icon-star-off" style="color: #E6A23C"></i> 未做标记</div>
<div><i style="color:#F56C6C;" class="el-icon-s-check"></i>必须使用Token验证</div>
<div><i style="color:#67C23A;" class="el-icon-s-check"></i>使用Token数据, 不验证</div>
<div><i style="color:#909399;" class="el-icon-s-check"></i> 无需token</div>
<div><i class="el-icon-s-promotion"></i> 发送模拟请求</div>
</el-alert>
<el-alert title="响应介绍" type="warning">
<div><b>code:</b> 状态码</div>
<div><b>data:</b> 数据</div>
<div><b>msg:</b> 响应提示语</div>
<div><b>ts:</b> 当前时间戳(秒)</div>
<hr>
<div><b>code 值说明:</b></div>
<div><b style="margin-left: 10px">200:</b>成功</div>
<div><b style="margin-left: 10px">202:</b>失败</div>
<div><b style="margin-left: 10px">1001:</b>刷新token,此时响应数据会带上新的token</div>
<div><b style="margin-left: 10px">1002:</b>token无效,应要求用户重新登录</div>
</el-alert>
</div> </div>
</el-main> </el-main>
</el-container> </el-container>
</el-container> </el-container>
<el-dialog title="编辑API文档" :fullscreen="true" :visible.sync="editApiDoc">
123123123123
</el-dialog>
</div> </div>
</body> </body>
@ -250,7 +267,11 @@
scriptAfterRequest:`// 请求之后调用此段代码\n// ApiInfo 对象包含接口信息\n// response 对象包含响应的数据\n// console.log(ApiInfo);\n// console.log(response);`, scriptAfterRequest:`// 请求之后调用此段代码\n// ApiInfo 对象包含接口信息\n// response 对象包含响应的数据\n// console.log(ApiInfo);\n// console.log(response);`,
response:{}, response:{},
currentApiInfo:{}, currentApiInfo:{},
ApiInfo:{} ApiInfo:{},
myMark:[],
showMark:false,
searchText:"",
apiActive:-1
}, },
created(){ created(){
if (localStorage.getItem("ScBefore")){ if (localStorage.getItem("ScBefore")){
@ -260,13 +281,54 @@
this.scriptAfterRequest = localStorage.getItem("ScAfter"); this.scriptAfterRequest = localStorage.getItem("ScAfter");
} }
this.getApiInfo(); this.getApiInfo();
this.myMark = localStorage.getItem("myMark").split(',');
},
mounted(){
}, },
methods: { methods: {
mark(url){
let index = this.myMark.indexOf(url);
if(index >= 0){
this.myMark.splice(index, 1);
}else{
this.myMark.push(url);
}
localStorage.setItem("myMark", this.myMark);
},
searchP(item){
let show = true;
if(this.showMark && item.children.filter(a => this.myMark.includes(a.url)).length === 0){
show = false;
}
if(this.searchText){
let length = item.children.filter(a => {
return a.url.indexOf(this.searchText) < 0 || a.name.indexOf(this.searchText) < 0
});
if (length > 0) show = false;
}
return show;
},
search(a){
let show = true;
if(this.showMark && !this.myMark.includes(a.url)){
show = false;
}
if(this.searchText && (a.url.indexOf(this.searchText) < 0 || a.name.indexOf(this.searchText) < 0)){
show = false;
}
return show;
},
handleSelect(key, keyPath) { handleSelect(key, keyPath) {
let s = key.split('-') let s = key.split('-')
let currentApiInfo = this.ApiInfo.apiLists[s[0]].children[s[1]]; let currentApiInfo = this.ApiInfo.apiLists[s[0]].children[s[1]];
this.currentApiInfo = JSON.parse(JSON.stringify(currentApiInfo)); this.currentApiInfo = JSON.parse(JSON.stringify(currentApiInfo));
this.form = this.requestParamsResolve(this.currentApiInfo.requestParams); this.form = this.requestParamsResolve(this.currentApiInfo.requestParams);
this.paramShowJsonEl && this.paramShowJsonEl.set(this.form);
},
clearCurrentApi(){
this.currentApiInfo = {};
this.form = {};
}, },
getPath(){ getPath(){
try{ try{
@ -306,16 +368,18 @@
}, },
paramShowTypeToggle(el){ paramShowTypeToggle(el){
if (el.name === 'json') { if (el.name === 'json') {
if (!this.paramShowJsonEl) { setTimeout(() => {
this.paramShowJsonEl = new JSONEditor( if (!this.paramShowJsonEl) {
document.getElementById("paramShowJson"), this.paramShowJsonEl = new JSONEditor(
this.jsonEditorInitOptions('code', (jsonString) => { document.getElementById("paramShowJson"),
this.form = JSON.parse(jsonString); this.jsonEditorInitOptions('code', (jsonString) => {
}) this.form = JSON.parse(jsonString);
); })
} );
}
this.paramShowJsonEl.set(this.form); setTimeout(() => this.paramShowJsonEl.set(this.form), 5);
}, 10);
} else if (el.name === 'scriptBefore') { } else if (el.name === 'scriptBefore') {
if (!this.scriptBeforeRequestEl) { if (!this.scriptBeforeRequestEl) {
let myTextArea = document.getElementById('requestBefore'); let myTextArea = document.getElementById('requestBefore');
@ -373,7 +437,8 @@
let ApiInfo = JSON.parse(JSON.stringify(this.currentApiInfo)); let ApiInfo = JSON.parse(JSON.stringify(this.currentApiInfo));
if (this.scriptBeforeRequestEl){ if (this.scriptBeforeRequestEl){
(function (){ (function (){
eval(APP.scriptBeforeRequestEl.getValue()); let script = APP.scriptBeforeRequestEl ? APP.scriptBeforeRequestEl.getValue() : this.scriptBeforeRequest;
eval(script);
})(); })();
} }
@ -383,7 +448,8 @@
this.responseJsonHandle(); this.responseJsonHandle();
(function (){ (function (){
let response = JSON.parse(JSON.stringify(res.data)); let response = JSON.parse(JSON.stringify(res.data));
eval(APP.scriptAfterRequestEl.getValue()); let script = APP.scriptAfterRequestEl ? APP.scriptAfterRequestEl.getValue() : this.scriptAfterRequest;
eval(script);
})(); })();
}).catch((error) => { }).catch((error) => {
this.response = error; this.response = error;
@ -404,7 +470,8 @@
} else { } else {
this.responseJsonEl = null; this.responseJsonEl = null;
} }
}); console.log(this.response);
}, 10);
}, },
jsonEditorInitOptions(defaultMode = 'tree', change){ jsonEditorInitOptions(defaultMode = 'tree', change){
return { return {
@ -433,7 +500,6 @@
url:"/admin/plugins/api-doc/doc-data" url:"/admin/plugins/api-doc/doc-data"
}).then(res => { }).then(res => {
this.ApiInfo = res.data.data; this.ApiInfo = res.data.data;
console.log(111);
}) })
}, },
tableVersionClass({row, rowIndex}){ tableVersionClass({row, rowIndex}){

Loading…
Cancel
Save