fix: 修改二次开发文档

This commit is contained in:
gaoxiaolin.gao 2018-01-31 17:36:13 +08:00
parent dbb9146ade
commit a470ef4278
81 changed files with 5469 additions and 57 deletions

View File

@ -148,7 +148,7 @@ class InterfaceEditForm extends Component {
handleSubmit = (e) => {
e.preventDefault();
this.setState({
this.setState({
submitStatus: true
})
try {
@ -824,7 +824,7 @@ class InterfaceEditForm extends Component {
</pre>}>
<Icon type="question-circle-o" style={{ color: "#086dbf" }} />
</Tooltip>
全局编辑 退出全屏 请按 F9
<span style={{ color: 'rgb(0, 168, 84)' }}>全局编辑 </span> 退 F9
</Col>
<Col id="req_body_json" style={{ minHeight: "300px" }}>
</Col>
@ -886,7 +886,7 @@ class InterfaceEditForm extends Component {
</pre>}>
<Icon type="question-circle-o" style={{ color: "#086dbf" }} />
</Tooltip> ,具体使用方法请 <span className="href" onClick={() => window.open('https://yapi.ymfe.org/mock.html', '_blank')}>查看文档</span>
全局编辑 退出全屏 请按 F9
<span style={{ color: 'rgb(0, 168, 84)' }}>全局编辑 </span> 退 F9
</h3>
<div id="res_body_json" style={{ minHeight: "300px", display: this.state.jsonType === 'tpl' ? 'block' : 'none' }} ></div>
<div id="mock-preview" style={{ backgroundColor: "#eee", lineHeight: "20px", minHeight: "300px", display: this.state.jsonType === 'preview' ? 'block' : 'none' }}></div>

View File

@ -97,8 +97,8 @@ class ProjectMember extends Component {
});
}
handleOk =()=>{
this.addMembers(this.state.inputUids)
handleOk = () => {
this.addMembers(this.state.inputUids)
}
// 增 - 添加成员
@ -176,13 +176,13 @@ class ProjectMember extends Component {
}
// 确定批量导入模态框
handleModalOk =async () => {
handleModalOk = async () => {
// 获取项目中的成员列表
const menberList = await this.props.getProjectMemberList(this.state.selectProjectId);
const memberUidList = menberList.payload.data.data.map(item =>{
const memberUidList = menberList.payload.data.data.map(item => {
return item.uid
})
this.addMembers(memberUidList)
this.addMembers(memberUidList)
}
@ -193,7 +193,7 @@ class ProjectMember extends Component {
}
async componentWillMount() {
const groupMemberList = await this.props.fetchGroupMemberList(this.props.projectMsg.group_id);
const groupMsg = await this.props.fetchGroupMsg(this.props.projectMsg.group_id);
const projectMemberList = await this.props.getProjectMemberList(this.props.match.params.id);

View File

@ -1,28 +1,164 @@
## 运行开发服务器
## 安装环境
首先确保安装了 ykit, 没有安装请执行 npm install -g ykit
安装 Node.js<a target="_blank" href="https://nodejs.org/en/download/package-manager/">官方安装方法</a>
```bash
# On RHEL, CentOS or Fedora, for Node.js v8 LTS:
curl --silent --location https://rpm.nodesource.com/setup_8.x | sudo bash -
# Alternatively for Node.js 9:
curl --silent --location https://rpm.nodesource.com/setup_9.x | sudo bash -
# 安装 Node.js
sudo yum -y install nodejs
# Enterprise LinuxRHEL和CentOS用户可以使用EPEL存储库中的Node.js和npm包。
# 为您的版本安装相应的epel-release RPM在EPEL存储库主页上找到然后运行
sudo yum install nodejs npm --enablerepo=epel
```
安装构建工具要从npm编译和安装本地插件您可能还需要安装构建工具
```bash
sudo yum install gcc-c++ make
# or: sudo yum groupinstall 'Development Tools'
```
安装 MongoDB首先创建源创建 `mongodb.repo` 文件,
<a target="_blank" href="https://docs.mongodb.com/manual/installation/">官方安装方法</a>
```bash
# 在/etc/yum.repos.d/目录下创建文件mongodb.repo它包含MongoDB仓库的配置信息内容如下
# 复制代码, 代码如下:
[mongodb]
name=MongoDB Repository
baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/
gpgcheck=0
enabled=1
```
yum 安装 MongoDB
```
mkdir yapi
cd yapi
git clone https://github.com/YMFE/yapi.git vendors
cp vendors/config_example.json ./config.json //复制完成后请修改相关配置
sudo yum install mongodb-org
```
为 YApi 初始数据库
```js
use yapi // 创建yapi数据库
db.wong.insert({"name":"kenny wong"}) // 插入一条数据,将在数据库列表中展示
show dbs // 查看所有数据库
db.addUser('yapi','yapi321') // 老的,数据库加用户的命令
db.createUser(
{
user: "yapi",
pwd: "yapi321",
roles:
[
{
role: "userAdminAnyDatabase",
db: "yapi"
}
]
}
)
```
## 安装YApi
1.创建工程目录
```bash
mkdir yapi && cd yapi
git clone https://github.com/YMFE/yapi.git vendors --depth=1 # 或者下载 zip 包解压到 vendors 目录
```
2.修改配置
```bash
cp vendors/config_example.json ./config.json # 复制完成后请修改相关配置
vi ./config.json
```
配置如下,主要配置 MongoDB 数据库,以及 Admin 账号。
```json
{
"port": "3011",
"adminAccount": "admin@admin.com",
"db": {
"servername": "127.0.0.1",
"DATABASE": "yapi",
"port": 27017,
"user": "yapi",
"pass": "yapi123"
},
"mail": {
"enable": true,
"host": "smtp.163.com",
"port": 465,
"from": "***@163.com",
"auth": {
"user": "***@163.com",
"pass": "*****"
}
}
}
```
3.安装依赖
```bash
cd vendors
npm install
npm run install-server //安装程序会初始化数据库索引和管理员账号,管理员账号名可在 config.json 配置
npm run dev //启动服务器后,请访问 127.0.0.1:{config.json配置的端口},初次运行会有个编译的过程,请耐心等候
npm install --production --registry https://registry.npm.taobao.org # 安装依赖
```
## 安装成功后的目录结构
4.初始化
```bash
npm run install-server # 安装程序会初始化数据库索引和管理员账号,管理员账号名可在 config.json 配置
# 默认输出
# 初始化管理员账号成功,账号名:"admin@admin.com",密码:"ymfe.org"
```
5.启动服务
```bash
# 后台启动输出日志yapi.log
node server/app.js >> yapi.log 2>&1 &
# 启动服务器后,请访问 127.0.0.1:{config.json配置的端口},初次运行会有个编译的过程,请耐心等候
# 127.0.0.1:3011
```
目录结构
```
yapi
config.json //服务器配置,可参考 vendors/config_example.json
vendors //yapi
init.lock //安装锁文件,重新安装需要删除此文件
log //运行日志
|-- config.json
|-- init.lock
|-- log
| `-- 2018-1.log
`-- vendors
|-- CHANGELOG.md
|-- LICENSE
|-- README.md
|-- client
|-- common
|-- config_example.json
|-- doc
|-- exts
|-- nodemon.json
|-- npm-debug.log
|-- package.json
|-- plugin.json
|-- server
|-- static
|-- test
|-- webpack.alias.js
|-- yapi-base-flow.jpg
|-- ydocfile.js
`-- ykit.config.js
```
## 技术栈说明
后端: koa mongoose

View File

@ -32,7 +32,7 @@ function connect(callback) {
});
db.then(function () {
yapi.commons.log('mongodb load success...');
yapi.commons.log('mongodb load success ..., please visit localhost:3000');
if(typeof callback === 'function'){
callback.call(db)

238
static/doc/devops 2.html Normal file
View File

@ -0,0 +1,238 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta name="format-detection" content="telephone=no,email=no" />
<meta http-equiv="X-UA-Compatible" content="ie=edge, chrome=1">
<meta name="description" content="description of your site">
<meta name="author" content="author of the site">
<title>YApi 接口管理平台 内网部署</title>
<link rel="shortcut icon" href="./favicon.ico" />
<link rel="stylesheet" href="source/main.css" />
<link rel="stylesheet" href="styles/theme.css" />
</head>
<body>
<div class="ydoc">
<header class="ydoc-header">
<div class="ydoc-header-area">
<a href="./index.html" class="navbar-brand"><img src="./images/logo_header@2x.png" /> &nbsp;YAPI</a>
<button class="ydocIcon navbar-toggle">&#xf020;</button>
<nav class="ydoc-nav">
<ul class="navbar-left">
<li class="">
<a href="index.html"></a>
</li>
<li class="">
<a href="usage.html">使用手册</a>
</li>
<li class="active">
<a href="devops.html">内网部署</a>
</li>
<li class="">
<a href="plugin.html">插件 Wiki</a>
</li>
<li class="">
<a href="qa.html">常见问题</a>
</li>
<li class="">
<a href="releases.html">版本记录</a>
</li>
<li class="">
<a href="http://yapi.demo.qunar.com/" target="_blank">demo 站点</a>
</li>
<li class="">
<a href="api.html"></a>
</li>
</ul>
</nav>
</div>
</header>
<!-- <header style="height:20px"></header> -->
<!-- Docs page layout -->
<div class="ydoc-banner-bg">
<div class="ydoc-banner ">
<div class="ydoc-banner-area">
<h1 >内网部署</h1>
<p class="desc ">部署 YApi 平台是非常容易的,即便您不懂 nodejs 或者 mongodb</p>
</div>
</div>
<div class="ydoc-container">
<div class="ydoc-container-content ">
<div class="content-left staticsidenav" role="complementary">
<nav class="docs-sidebar hidden-print hidden-xs hidden-sm">
<ul class="nav docs-sidenav">
<!-- <li > -->
<li >
<a href="#环境要求">环境要求</a>
</li>
<!-- <li > -->
<li >
<a href="#安装">安装</a>
</li>
<ul class="nav docs-sidenav-extend" >
<li >
<a href="#方式一. 可视化部署[推荐]">方式一. 可视化部署[推荐]</a>
</li>
<li >
<a href="#方式二. 命令行部署">方式二. 命令行部署</a>
</li>
</ul>
<!-- <li > -->
<li >
<a href="#服务器管理">服务器管理</a>
</li>
<!-- <li > -->
<li >
<a href="#升级">升级</a>
</li>
<!-- <li > -->
<li >
<a href="#配置邮箱 (仅支持 SMTP)">配置邮箱 (仅支持 SMTP)</a>
</li>
<!-- <li > -->
<li >
<a href="#配置LDAP登录">配置LDAP登录</a>
</li>
</ul>
</nav>
</div>
<div class="content-right markdown-body use-sidebar" role="main">
<h1 class="subject" id="内网部署">内网部署 <a class="hashlink" href="#内网部署">#</a></h1><p>使用我们提供的 yapi-cli 工具,部署 YApi 平台是非常容易的。建议部署成 http 站点,因 chrome 浏览器安全限制,部署成 https 会导致测试功能在请求 http 站点时文件上传功能异常。</p>
<p>如果您是将服务器代理到 nginx 服务器,请配置 nginx 支持 websocket。</p>
<pre><code>在location /添加
proxy_http_version <span class="token number">1.1</span><span class="token punctuation">;</span>
proxy_set_header Upgrade $http_upgrade<span class="token punctuation">;</span>
proxy_set_header Connection <span class="token string">"upgrade"</span><span class="token punctuation">;</span>
</code></pre><h2 class="subject" id="环境要求">环境要求 <a class="hashlink" href="#环境要求">#</a></h2><ul>
<li>nodejs7.6+)</li><li>mongodb2.6+</li></ul>
<h2 class="subject" id="安装">安装 <a class="hashlink" href="#安装">#</a></h2><h3 class="subject" id="方式一._可视化部署[推荐]">方式一. 可视化部署[推荐] <a class="hashlink" href="#方式一._可视化部署[推荐]">#</a></h3><p>执行 yapi server 启动可视化部署程序,输入相应的配置和点击开始部署,就能完成整个网站的部署。部署完成之后,可按照提示信息,执行 node/{网站路径/server/app.js} 启动服务器。在浏览器打开指定url, 点击登录输入您刚才设置的管理员邮箱,默认密码(ymfe.org) 登录系统(默认密码可在个人中心修改)。</p>
<pre><code>npm install -g yapi-cli --registry https<span class="token operator">:</span>//registry.npm.taobao.org
yapi server
</code></pre><h3 class="subject" id="方式二._命令行部署">方式二. 命令行部署 <a class="hashlink" href="#方式二._命令行部署">#</a></h3><p>如果 github 压缩文件无法下载,或需要部署到一些特殊的服务器,可尝试此方法</p>
<pre><code>mkdir yapi
cd yapi
git clone https<span class="token operator">:</span>//github.com/YMFE/yapi.git vendors //或者下载 zip 包解压到 vendors 目录
cp vendors/config_example.json ./config.json //复制完成后请修改相关配置
cd vendors
npm install --production --registry https<span class="token operator">:</span>//registry.npm.taobao.org
npm run install-server //安装程序会初始化数据库索引和管理员账号,管理员账号名可在 config.json 配置
node server/app.js //启动服务器后,请访问 <span class="token number">127.0</span>.<span class="token number">0.1</span><span class="token operator">:</span><span class="token punctuation">{</span>config.json配置的端口<span class="token punctuation">}</span>,初次运行会有个编译的过程,请耐心等候
</code></pre><h2 class="subject" id="服务器管理">服务器管理 <a class="hashlink" href="#服务器管理">#</a></h2><p>推荐使用 pm2 管理 node 服务器启动,停止,具体使用方法可参考下面的教程:</p>
<ul>
<li><a href="http://pm2.keymetrics.io/docs/usage/quick-start/">官网文档</a></li><li><a href="http://imweb.io/topic/57c8cbb27f226f687b365636">PM2实用入门指南</a> </li></ul>
<h2 class="subject" id="升级">升级 <a class="hashlink" href="#升级">#</a></h2><p>升级项目版本是非常容易的,并且不会影响已有的项目数据,只会同步 vendors 目录下的源码文件。</p>
<pre><code>cd <span class="token punctuation">{</span>项目目录<span class="token punctuation">}</span>
yapi ls //查看版本号列表
yapi update //升级到最新版本
yapi update -v v1<span class="token number">.1</span>.<span class="token number">0</span> //升级到指定版本
</code></pre><h2 class="subject" id="配置邮箱__仅支持_SMTP_">配置邮箱 (仅支持 SMTP) <a class="hashlink" href="#配置邮箱__仅支持_SMTP_">#</a></h2><p>打开项目目录 config.json 文件,新增 mail 配置, 替换默认的邮箱配置</p>
<pre><code><span class="token punctuation">{</span>
<span class="token property">"port"</span><span class="token operator">:</span> <span class="token string">"*****"</span><span class="token punctuation">,</span>
<span class="token property">"adminAccount"</span><span class="token operator">:</span> <span class="token string">"********"</span><span class="token punctuation">,</span>
<span class="token property">"db"</span><span class="token operator">:</span> <span class="token punctuation">{</span>...<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token property">"mail"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"enable"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
<span class="token property">"host"</span><span class="token operator">:</span> <span class="token string">"smtp.163.com"</span><span class="token punctuation">,</span> //邮箱服务器
<span class="token property">"port"</span><span class="token operator">:</span> <span class="token number">465</span><span class="token punctuation">,</span> //端口
<span class="token property">"from"</span><span class="token operator">:</span> <span class="token string">"***@163.com"</span><span class="token punctuation">,</span> //发送人邮箱
<span class="token property">"auth"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"user"</span><span class="token operator">:</span> <span class="token string">"***@163.com"</span><span class="token punctuation">,</span> //邮箱服务器账号
<span class="token property">"pass"</span><span class="token operator">:</span> <span class="token string">"*****"</span> //邮箱服务器密码
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>如何申请STMP服务器账号和密码可以参考下面的教程<a href="https://jingyan.baidu.com/article/fdbd42771da9b0b89e3f48a8.html">如何开通电子邮箱的SMTP功能</a></p>
<h2 class="subject" id="配置LDAP登录">配置LDAP登录 <a class="hashlink" href="#配置LDAP登录">#</a></h2><p>打开项目目录 config.json 文件,添加如下字段: </p>
<pre><code><span class="token property">"ldapLogin"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"enable"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
<span class="token property">"server"</span><span class="token operator">:</span> <span class="token string">"ldap://l-ldapt1.ops.dev.cn0.qunar.com"</span><span class="token punctuation">,</span>
<span class="token property">"baseDn"</span><span class="token operator">:</span> <span class="token string">"CN=Admin,CN=Users,DC=test,DC=com"</span><span class="token punctuation">,</span>
<span class="token property">"bindPassword"</span><span class="token operator">:</span> <span class="token string">"password123"</span><span class="token punctuation">,</span>
<span class="token property">"searchDn"</span><span class="token operator">:</span> <span class="token string">"OU=UserContainer,DC=test,DC=com"</span><span class="token punctuation">,</span>
<span class="token property">"searchStandard"</span><span class="token operator">:</span> <span class="token string">"mail"</span>
<span class="token punctuation">}</span>
</code></pre><p>这里面的配置项含义如下: </p>
<ul>
<li><code>enable</code> 表示是否配置LDAP登录true(支持LDAP登录)/false(不支持LDAP登录);</li><li><code>server</code> LDAP服务器地址前面需要加上 ldap:// 前缀也可以是ldaps:// 表示是通过SSL连接;</li><li><code>baseDn</code> LDAP服务器的登录用户名必须是从根结点到用户节点的全路径;</li><li><code>bindPassword</code> 登录该LDAP服务器的密码;</li><li><code>searchDn</code> 查询用户数据的路径,类似数据库中的一张表的地址,注意这里也必须是全路径;</li><li><code>searchStandard</code> 查询条件这里是mail表示查询用户信息是通过邮箱信息来查询的。注意该字段信息与LDAP数据库存储数据的字段相对应如果如果存储用户邮箱信息的字段是email, 这里就需要修改成email.</li></ul>
<p><br><br><br><br><br></p>
</div>
</div>
</div>
</div>
<footer class="footer">
<div class="copyright">
&copy; 2017 <a href="https://ymfe.org">YMFE</a> Team. Build by <a href="http://ued.qunar.com/ydoc/">ydoc</a>&nbsp;
</div>
</footer>
</div>
<div class="open-panel"></div>
<div class="mask"></div>
<script src="source/main.js"></script>
<script src="source/app.js"></script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
static/doc/images/case_add 2.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

BIN
static/doc/images/case_list 2.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 584 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
static/doc/images/jd 2.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 927 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 946 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

BIN
static/doc/images/ykit 2.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -101,7 +101,7 @@
<p class="home-version">当前版本v1.3.4</p>
<p class="home-version">当前版本v1.3.5</p>
</div>

284
static/doc/plugin 2.html Normal file
View File

@ -0,0 +1,284 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta name="format-detection" content="telephone=no,email=no" />
<meta http-equiv="X-UA-Compatible" content="ie=edge, chrome=1">
<meta name="description" content="description of your site">
<meta name="author" content="author of the site">
<title>YApi 接口管理平台 插件 Wiki</title>
<link rel="shortcut icon" href="./favicon.ico" />
<link rel="stylesheet" href="source/main.css" />
<link rel="stylesheet" href="styles/theme.css" />
</head>
<body>
<div class="ydoc">
<header class="ydoc-header">
<div class="ydoc-header-area">
<a href="./index.html" class="navbar-brand"><img src="./images/logo_header@2x.png" /> &nbsp;YAPI</a>
<button class="ydocIcon navbar-toggle">&#xf020;</button>
<nav class="ydoc-nav">
<ul class="navbar-left">
<li class="">
<a href="index.html"></a>
</li>
<li class="">
<a href="usage.html">使用手册</a>
</li>
<li class="">
<a href="devops.html">内网部署</a>
</li>
<li class="active">
<a href="plugin.html">插件 Wiki</a>
</li>
<li class="">
<a href="qa.html">常见问题</a>
</li>
<li class="">
<a href="releases.html">版本记录</a>
</li>
<li class="">
<a href="http://yapi.demo.qunar.com/" target="_blank">demo 站点</a>
</li>
<li class="">
<a href="api.html"></a>
</li>
</ul>
</nav>
</div>
</header>
<!-- <header style="height:20px"></header> -->
<!-- Docs page layout -->
<div class="ydoc-banner-bg">
<div class="ydoc-banner ">
<div class="ydoc-banner-area">
<h1 >插件</h1>
<p class="desc ">可根据业务需求,定制化功能</p>
</div>
</div>
<div class="ydoc-container">
<div class="ydoc-container-content ">
<div class="content-left staticsidenav" role="complementary">
<nav class="docs-sidebar hidden-print hidden-xs hidden-sm">
<ul class="nav docs-sidenav">
<!-- <li > -->
<li >
<a href="redev.html">二次开发</a>
</li>
<!-- <li > -->
<li >
<a href="plugin-index.html">插件管理</a>
</li>
<!-- <li > -->
<li >
<a href="plugin-dev.html">插件开发</a>
</li>
<!-- <li > -->
<li >
<a href="plugin-hooks.html">钩子列表</a>
</li>
<!-- <li > -->
<li >
<a href="plugin-list.html">插件列表</a>
</li>
</ul>
</nav>
</div>
<div class="content-right markdown-body use-sidebar" role="main">
<h2 class="subject" id="安装环境">安装环境 <a class="hashlink" href="#安装环境">#</a></h2><p>安装 Node.js<a href="https://nodejs.org/en/download/package-manager/">官方安装方法</a></p>
<pre><code class="lang-bash"><span class="token comment"># On RHEL, CentOS or Fedora, for Node.js v8 LTS:</span>
curl --silent --location https://rpm.nodesource.com/setup_8.x <span class="token operator">|</span> <span class="token function">sudo</span> <span class="token function">bash</span> -
<span class="token comment"># Alternatively for Node.js 9:</span>
curl --silent --location https://rpm.nodesource.com/setup_9.x <span class="token operator">|</span> <span class="token function">sudo</span> <span class="token function">bash</span> -
<span class="token comment"># 安装 Node.js</span>
<span class="token function">sudo</span> yum -y <span class="token function">install</span> nodejs
<span class="token comment"># Enterprise LinuxRHEL和CentOS用户可以使用EPEL存储库中的Node.js和npm包。</span>
<span class="token comment"># 为您的版本安装相应的epel-release RPM在EPEL存储库主页上找到然后运行</span>
<span class="token function">sudo</span> yum <span class="token function">install</span> nodejs <span class="token function">npm</span> --enablerepo<span class="token operator">=</span>epel
</code></pre>
<p>安装构建工具要从npm编译和安装本地插件您可能还需要安装构建工具</p>
<pre><code class="lang-bash"><span class="token function">sudo</span> yum <span class="token function">install</span> gcc-c++ <span class="token function">make</span>
<span class="token comment"># or: sudo yum groupinstall 'Development Tools'</span>
</code></pre>
<p>安装 MongoDB首先创建源创建 <code>mongodb.repo</code> 文件, <a href="https://docs.mongodb.com/manual/installation/">官方安装方法</a></p>
<pre><code class="lang-bash"><span class="token comment"># 在/etc/yum.repos.d/目录下创建文件mongodb.repo它包含MongoDB仓库的配置信息内容如下</span>
<span class="token comment"># 复制代码, 代码如下:</span>
<span class="token punctuation">[</span>mongodb<span class="token punctuation">]</span>
name<span class="token operator">=</span>MongoDB Repository
baseurl<span class="token operator">=</span>http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/
gpgcheck<span class="token operator">=</span>0
enabled<span class="token operator">=</span>1
</code></pre>
<p>yum 安装 MongoDB </p>
<pre><code>sudo yum install mongodb-org
</code></pre><p>为 YApi 初始数据库</p>
<pre><code class="lang-js">use yapi <span class="token comment">// 创建yapi数据库 </span>
db<span class="token punctuation">.</span>wong<span class="token punctuation">.</span><span class="token function">insert</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token string">"name"</span><span class="token punctuation">:</span><span class="token string">"kenny wong"</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment">// 插入一条数据,将在数据库列表中展示</span>
show dbs <span class="token comment">// 查看所有数据库</span>
db<span class="token punctuation">.</span><span class="token function">addUser</span><span class="token punctuation">(</span><span class="token string">'yapi'</span><span class="token punctuation">,</span><span class="token string">'yapi321'</span><span class="token punctuation">)</span> <span class="token comment">// 老的,数据库加用户的命令</span>
db<span class="token punctuation">.</span><span class="token function">createUser</span><span class="token punctuation">(</span>
<span class="token punctuation">{</span>
user<span class="token punctuation">:</span> <span class="token string">"yapi"</span><span class="token punctuation">,</span>
pwd<span class="token punctuation">:</span> <span class="token string">"yapi321"</span><span class="token punctuation">,</span>
roles<span class="token punctuation">:</span>
<span class="token punctuation">[</span>
<span class="token punctuation">{</span>
role<span class="token punctuation">:</span> <span class="token string">"userAdminAnyDatabase"</span><span class="token punctuation">,</span>
db<span class="token punctuation">:</span> <span class="token string">"yapi"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span>
<span class="token punctuation">}</span>
<span class="token punctuation">)</span>
</code></pre>
<h2 class="subject" id="安装YApi">安装YApi <a class="hashlink" href="#安装YApi">#</a></h2><p>1.创建工程目录</p>
<pre><code class="lang-bash"><span class="token function">mkdir</span> yapi <span class="token operator">&amp;&amp;</span> <span class="token function">cd</span> yapi
<span class="token function">git</span> clone https://github.com/YMFE/yapi.git vendors --depth<span class="token operator">=</span>1 <span class="token comment"># 或者下载 zip 包解压到 vendors 目录</span>
</code></pre>
<p>2.修改配置</p>
<pre><code class="lang-bash"><span class="token function">cp</span> vendors/config_example.json ./config.json <span class="token comment"># 复制完成后请修改相关配置</span>
<span class="token function">vi</span> ./config.json
</code></pre>
<p>配置如下,主要配置 MongoDB 数据库,以及 Admin 账号。</p>
<pre><code class="lang-json"><span class="token punctuation">{</span>
<span class="token property">"port"</span><span class="token operator">:</span> <span class="token string">"3011"</span><span class="token punctuation">,</span>
<span class="token property">"adminAccount"</span><span class="token operator">:</span> <span class="token string">"admin@admin.com"</span><span class="token punctuation">,</span>
<span class="token property">"db"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"servername"</span><span class="token operator">:</span> <span class="token string">"127.0.0.1"</span><span class="token punctuation">,</span>
<span class="token property">"DATABASE"</span><span class="token operator">:</span> <span class="token string">"yapi"</span><span class="token punctuation">,</span>
<span class="token property">"port"</span><span class="token operator">:</span> <span class="token number">27017</span><span class="token punctuation">,</span>
<span class="token property">"user"</span><span class="token operator">:</span> <span class="token string">"yapi"</span><span class="token punctuation">,</span>
<span class="token property">"pass"</span><span class="token operator">:</span> <span class="token string">"yapi123"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token property">"mail"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"enable"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
<span class="token property">"host"</span><span class="token operator">:</span> <span class="token string">"smtp.163.com"</span><span class="token punctuation">,</span>
<span class="token property">"port"</span><span class="token operator">:</span> <span class="token number">465</span><span class="token punctuation">,</span>
<span class="token property">"from"</span><span class="token operator">:</span> <span class="token string">"***@163.com"</span><span class="token punctuation">,</span>
<span class="token property">"auth"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"user"</span><span class="token operator">:</span> <span class="token string">"***@163.com"</span><span class="token punctuation">,</span>
<span class="token property">"pass"</span><span class="token operator">:</span> <span class="token string">"*****"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
<p>3.安装依赖</p>
<pre><code class="lang-bash"><span class="token function">cd</span> vendors
<span class="token function">npm</span> <span class="token function">install</span> --production --registry https://registry.npm.taobao.org <span class="token comment"># 安装依赖</span>
</code></pre>
<p>4.初始化</p>
<pre><code class="lang-bash"><span class="token function">npm</span> run install-server <span class="token comment"># 安装程序会初始化数据库索引和管理员账号,管理员账号名可在 config.json 配置</span>
<span class="token comment"># 默认输出</span>
<span class="token comment"># 初始化管理员账号成功,账号名:"admin@admin.com",密码:"ymfe.org"</span>
</code></pre>
<p>5.启动服务</p>
<pre><code class="lang-bash"><span class="token comment"># 后台启动输出日志yapi.log</span>
node server/app.js <span class="token operator">>></span> yapi.log 2<span class="token operator">></span><span class="token operator">&amp;</span>1 <span class="token operator">&amp;</span>
<span class="token comment"># 启动服务器后,请访问 127.0.0.1:{config.json配置的端口},初次运行会有个编译的过程,请耐心等候</span>
<span class="token comment"># 127.0.0.1:3011</span>
</code></pre>
<p>目录结构</p>
<pre><code>|-- config.json
|-- init.lock
|-- log
| `-- <span class="token number">2018</span>-<span class="token number">1</span>.log
`-- vendors
|-- CHANGELOG.md
|-- LICENSE
|-- README.md
|-- client
|-- common
|-- config_example.json
|-- doc
|-- exts
|-- nodemon.json
|-- npm-debug.log
|-- package.json
|-- plugin.json
|-- server
|-- static
|-- test
|-- webpack.alias.js
|-- yapi-base-flow.jpg
|-- ydocfile.js
`-- ykit.config.js
</code></pre><h2 class="subject" id="技术栈说明">技术栈说明 <a class="hashlink" href="#技术栈说明">#</a></h2><p>后端: koa mongoose</p>
<p>前端: react redux</p>
<h2 class="subject" id="启动_prd_环境服务器">启动 prd 环境服务器 <a class="hashlink" href="#启动_prd_环境服务器">#</a></h2><pre><code> cd vendors
ykit pack -m
node server/app.js
</code></pre>
</div>
</div>
</div>
</div>
<footer class="footer">
<div class="copyright">
&copy; 2017 <a href="https://ymfe.org">YMFE</a> Team. Build by <a href="http://ued.qunar.com/ydoc/">ydoc</a>&nbsp;
</div>
</footer>
</div>
<div class="open-panel"></div>
<div class="mask"></div>
<script src="source/main.js"></script>
<script src="source/app.js"></script>
</body>
</html>

View File

@ -0,0 +1,227 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta name="format-detection" content="telephone=no,email=no" />
<meta http-equiv="X-UA-Compatible" content="ie=edge, chrome=1">
<meta name="description" content="description of your site">
<meta name="author" content="author of the site">
<title>YApi 接口管理平台 插件 Wiki</title>
<link rel="shortcut icon" href="./favicon.ico" />
<link rel="stylesheet" href="source/main.css" />
<link rel="stylesheet" href="styles/theme.css" />
</head>
<body>
<div class="ydoc">
<header class="ydoc-header">
<div class="ydoc-header-area">
<a href="./index.html" class="navbar-brand"><img src="./images/logo_header@2x.png" /> &nbsp;YAPI</a>
<button class="ydocIcon navbar-toggle">&#xf020;</button>
<nav class="ydoc-nav">
<ul class="navbar-left">
<li class="">
<a href="index.html"></a>
</li>
<li class="">
<a href="usage.html">使用手册</a>
</li>
<li class="">
<a href="devops.html">内网部署</a>
</li>
<li class="active">
<a href="plugin.html">插件 Wiki</a>
</li>
<li class="">
<a href="qa.html">常见问题</a>
</li>
<li class="">
<a href="releases.html">版本记录</a>
</li>
<li class="">
<a href="http://yapi.demo.qunar.com/" target="_blank">demo 站点</a>
</li>
<li class="">
<a href="api.html"></a>
</li>
</ul>
</nav>
</div>
</header>
<!-- <header style="height:20px"></header> -->
<!-- Docs page layout -->
<div class="ydoc-banner-bg">
<div class="ydoc-banner ">
<div class="ydoc-banner-area">
<h1 >插件</h1>
<p class="desc ">可根据业务需求,定制化功能</p>
</div>
</div>
<div class="ydoc-container">
<div class="ydoc-container-content ">
<div class="content-left staticsidenav" role="complementary">
<nav class="docs-sidebar hidden-print hidden-xs hidden-sm">
<ul class="nav docs-sidenav">
<!-- <li > -->
<li >
<a href="redev.html">二次开发</a>
</li>
<!-- <li > -->
<li >
<a href="plugin-index.html">插件管理</a>
</li>
<!-- <li class="active" class="active" > -->
<li class="active" >
<a href="plugin-dev.html">插件开发</a>
</li>
<ul class="nav docs-sidenav-extend" >
<li >
<a href="#运行开发服务器(参考二次开发)">运行开发服务器(参考二次开发)</a>
</li>
<li >
<a href="#加载插件">加载插件</a>
</li>
<li >
<a href="#初始化目录">初始化目录</a>
</li>
<li >
<a href="#index.js 配置说明">index.js 配置说明</a>
</li>
<li >
<a href="#server.js">server.js</a>
</li>
<li >
<a href="#client.js">client.js</a>
</li>
</ul>
<!-- <li > -->
<li >
<a href="plugin-hooks.html">钩子列表</a>
</li>
<!-- <li > -->
<li >
<a href="plugin-list.html">插件列表</a>
</li>
</ul>
</nav>
</div>
<div class="content-right markdown-body use-sidebar" role="main">
<h2 class="subject" id="运行开发服务器_参考二次开发_">运行开发服务器(参考二次开发) <a class="hashlink" href="#运行开发服务器_参考二次开发_">#</a></h2><pre><code>npm install
npm install -g ykit //依赖 ykit
npm run dev //启动开发服务器
</code></pre><h2 class="subject" id="加载插件">加载插件 <a class="hashlink" href="#加载插件">#</a></h2><p>在config.json plugins配置项加入 demo 插件,</p>
<pre><code><span class="token punctuation">{</span>
<span class="token property">"port"</span><span class="token operator">:</span> <span class="token string">"3000"</span><span class="token punctuation">,</span>
<span class="token property">"db"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"servername"</span><span class="token operator">:</span> <span class="token string">"127.0.0.1"</span><span class="token punctuation">,</span>
<span class="token property">"DATABASE"</span><span class="token operator">:</span> <span class="token string">"yapi"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
...
<span class="token property">"plugins"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span>
<span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"demo"</span>
<span class="token property">"options"</span><span class="token operator">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>
</code></pre><h2 class="subject" id="初始化目录">初始化目录 <a class="hashlink" href="#初始化目录">#</a></h2><p>可参考 项目vendors/exts 目录下的插件</p>
<p>在 vendors/node_modules 下新建 yapi-plugin-demo 目录和 npm init,最后生成的目录接口如下</p>
<pre><code>yapi-plugin-demo
client.js //客户端入口文件
server.js //服务端入口文件
packjson.json //插件依赖管理
index.js //插件配置文件
</code></pre><h2 class="subject" id="index.js_配置说明">index.js 配置说明 <a class="hashlink" href="#index.js_配置说明">#</a></h2><pre><code>server<span class="token operator">:</span> <span class="token boolean">true</span> // 如果为<span class="token boolean">true</span><span class="token punctuation">,</span>表名该插件需要经过后端服务器加载
client<span class="token operator">:</span> <span class="token boolean">true</span> // 如果为<span class="token boolean">true</span><span class="token punctuation">,</span>表名该插件需要经过前端编译
</code></pre><h2 class="subject" id="server.js">server.js <a class="hashlink" href="#server.js">#</a></h2><p>在server.js 需要导出一个 function ,例如: module.exports = function(options){}</p>
<p>options 可在 config.json 配置</p>
<h3 class="subject" id="绑定钩子">绑定钩子 <a class="hashlink" href="#绑定钩子">#</a></h3><pre><code>this.bindHook(hookname<span class="token punctuation">,</span> listener<span class="token punctuation">)</span> //绑定钩子
hookname //钩子名
listener //监听函数,可以是普通函数,也可以是 asyncFunction
</code></pre><h3 class="subject" id="如何使用_YApi_vendors_server_目录下的模块">如何使用 YApi vendors/server 目录下的模块 <a class="hashlink" href="#如何使用_YApi_vendors_server_目录下的模块">#</a></h3><p>可以直接 require vendors 目录下的模块,注意:后端 node 不能使用 import关键字只能使用 require
例如: require(&#39;yapi&#39;)</p>
<h3 class="subject" id="controller_和_model">controller 和 model <a class="hashlink" href="#controller_和_model">#</a></h3><p>新增 controller 需要继承 baseController(controller/base.js)</p>
<p>新增 model 需要继承 baseModel(model/base.js)</p>
<h2 class="subject" id="client.js">client.js <a class="hashlink" href="#client.js">#</a></h2><h3 class="subject" id="绑定钩子_同后端_server.js__">绑定钩子(同后端 server.js ) <a class="hashlink" href="#绑定钩子_同后端_server.js__">#</a></h3><pre><code>this.bindHook(hookname<span class="token punctuation">,</span> listener<span class="token punctuation">)</span> //绑定钩子
hookname //钩子名
listener //监听函数,可以是普通函数,也可以是 asyncFunction
</code></pre>
</div>
</div>
</div>
</div>
<footer class="footer">
<div class="copyright">
&copy; 2017 <a href="https://ymfe.org">YMFE</a> Team. Build by <a href="http://ued.qunar.com/ydoc/">ydoc</a>&nbsp;
</div>
</footer>
</div>
<div class="open-panel"></div>
<div class="mask"></div>
<script src="source/main.js"></script>
<script src="source/app.js"></script>
</body>
</html>

View File

@ -0,0 +1,350 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta name="format-detection" content="telephone=no,email=no" />
<meta http-equiv="X-UA-Compatible" content="ie=edge, chrome=1">
<meta name="description" content="description of your site">
<meta name="author" content="author of the site">
<title>YApi 接口管理平台 插件 Wiki</title>
<link rel="shortcut icon" href="./favicon.ico" />
<link rel="stylesheet" href="source/main.css" />
<link rel="stylesheet" href="styles/theme.css" />
</head>
<body>
<div class="ydoc">
<header class="ydoc-header">
<div class="ydoc-header-area">
<a href="./index.html" class="navbar-brand"><img src="./images/logo_header@2x.png" /> &nbsp;YAPI</a>
<button class="ydocIcon navbar-toggle">&#xf020;</button>
<nav class="ydoc-nav">
<ul class="navbar-left">
<li class="">
<a href="index.html"></a>
</li>
<li class="">
<a href="usage.html">使用手册</a>
</li>
<li class="">
<a href="devops.html">内网部署</a>
</li>
<li class="active">
<a href="plugin.html">插件 Wiki</a>
</li>
<li class="">
<a href="qa.html">常见问题</a>
</li>
<li class="">
<a href="releases.html">版本记录</a>
</li>
<li class="">
<a href="http://yapi.demo.qunar.com/" target="_blank">demo 站点</a>
</li>
<li class="">
<a href="api.html"></a>
</li>
</ul>
</nav>
</div>
</header>
<!-- <header style="height:20px"></header> -->
<!-- Docs page layout -->
<div class="ydoc-banner-bg">
<div class="ydoc-banner ">
<div class="ydoc-banner-area">
<h1 >插件</h1>
<p class="desc ">可根据业务需求,定制化功能</p>
</div>
</div>
<div class="ydoc-container">
<div class="ydoc-container-content ">
<div class="content-left staticsidenav" role="complementary">
<nav class="docs-sidebar hidden-print hidden-xs hidden-sm">
<ul class="nav docs-sidenav">
<!-- <li > -->
<li >
<a href="redev.html">二次开发</a>
</li>
<!-- <li > -->
<li >
<a href="plugin-index.html">插件管理</a>
</li>
<!-- <li > -->
<li >
<a href="plugin-dev.html">插件开发</a>
</li>
<!-- <li class="active" class="active" > -->
<li class="active" >
<a href="plugin-hooks.html">钩子列表</a>
</li>
<ul class="nav docs-sidenav-extend" >
<li >
<a href="#后端 hookList">后端 hookList</a>
</li>
<li >
<a href="#前端 hookList">前端 hookList</a>
</li>
</ul>
<!-- <li > -->
<li >
<a href="plugin-list.html">插件列表</a>
</li>
</ul>
</nav>
</div>
<div class="content-right markdown-body use-sidebar" role="main">
<h2 class="subject" id="后端_hookList">后端 hookList <a class="hashlink" href="#后端_hookList">#</a></h2><p>目前 hooksList 只有下面列出的部分,如果您有其他的需求,可提建议到 github 或者 qq群</p>
<pre><code>/**
* 钩子配置
*/
var hooks = <span class="token punctuation">{</span>
/**
* 第三方sso登录钩子暂只支持设置一个
* @param ctx
* @return 必需返回一个 promise 对象resolve(<span class="token punctuation">{</span>username<span class="token operator">:</span> ''<span class="token punctuation">,</span> email<span class="token operator">:</span> ''<span class="token punctuation">}</span><span class="token punctuation">)</span>
*/
'third_login'<span class="token operator">:</span> <span class="token punctuation">{</span>
type<span class="token operator">:</span> 'single'<span class="token punctuation">,</span>
listener<span class="token operator">:</span> <span class="token null">null</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
/**
* 客户端增加接口成功后触发
* @param id 接口id
*/
'interface_add'<span class="token operator">:</span> <span class="token punctuation">{</span>
type<span class="token operator">:</span> 'multi'<span class="token punctuation">,</span>
listener<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
/**
* 客户端删除接口成功后触发
* @param id 接口id
*/
'interface_del'<span class="token operator">:</span> <span class="token punctuation">{</span>
type<span class="token operator">:</span> 'multi'<span class="token punctuation">,</span>
listener<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
/**
* 客户端更新接口成功后触发
* @param id 接口id
*/
'interface_update'<span class="token operator">:</span><span class="token punctuation">{</span>
type<span class="token operator">:</span> 'multi'<span class="token punctuation">,</span>
listener<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
/**
* 客户端获取接口数据列表
* @param id project_id
*/
'interface_list'<span class="token operator">:</span><span class="token punctuation">{</span>
type<span class="token operator">:</span> 'multi'<span class="token punctuation">,</span>
listener<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
/**
* 客户端获取一条接口信息触发
* @param id 接口id
*/
'interface_get'<span class="token operator">:</span><span class="token punctuation">{</span>
type<span class="token operator">:</span> 'multi'<span class="token punctuation">,</span>
listener<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
/**
* 客户端增加一个新项目
* @param id 项目id
*/
'project_add'<span class="token operator">:</span><span class="token punctuation">{</span>
type<span class="token operator">:</span> 'multi'<span class="token punctuation">,</span>
listener<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
/**
* 客户端删除删除一个项目
* @param id 项目id
*/
'project_del'<span class="token operator">:</span><span class="token punctuation">{</span>
type<span class="token operator">:</span> 'multi'<span class="token punctuation">,</span>
listener<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
/**
* MockServer生成mock数据后触发
* @param context Object
* <span class="token punctuation">{</span>
* projectData<span class="token operator">:</span> project<span class="token punctuation">,</span>
interfaceData<span class="token operator">:</span> interfaceData<span class="token punctuation">,</span>
ctx<span class="token operator">:</span> ctx<span class="token punctuation">,</span>
mockJson<span class="token operator">:</span> res
* <span class="token punctuation">}</span>
*
*/
mock_after<span class="token operator">:</span> <span class="token punctuation">{</span>
type<span class="token operator">:</span> 'multi'<span class="token punctuation">,</span>
listener<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
/**
* 增加路由的钩子
* type Sync
* @param addPluginRouter Function
* addPLuginPLugin(config<span class="token punctuation">)</span>
* config = <span class="token punctuation">{</span>
* path<span class="token punctuation">,</span> // String
* method<span class="token punctuation">,</span> // String
* controller // Class 继承baseController的class
* action // String controller的Action
* <span class="token punctuation">}</span>
*/
add_router<span class="token operator">:</span> <span class="token punctuation">{</span>
type<span class="token operator">:</span> 'multi'<span class="token punctuation">,</span>
listener<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre><h2 class="subject" id="前端_hookList">前端 hookList <a class="hashlink" href="#前端_hookList">#</a></h2><pre><code>/**
* type component 组件
* listener 监听函数
* mulit 是否绑定多个监听函数
*
*/
hooks = <span class="token punctuation">{</span>
/**
* 第三方登录 //可参考 yapi-plugin-qsso 插件
*/
third_login<span class="token operator">:</span> <span class="token punctuation">{</span>
type<span class="token operator">:</span> 'component'<span class="token punctuation">,</span>
mulit<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
listener<span class="token operator">:</span> <span class="token null">null</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
/**
* 导出数据
* @param Object exportDataModule
* @param projectId
* @info
* exportDataModule = <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
* exportDataModule.pdf = <span class="token punctuation">{</span>
* name<span class="token operator">:</span> 'Pdf'<span class="token punctuation">,</span>
* route<span class="token operator">:</span> '/api/plugin/export/pdf'<span class="token punctuation">,</span>
* desc<span class="token operator">:</span> '导出项目接口文档为 pdf 文件'
* <span class="token punctuation">}</span>
*/
export_data<span class="token operator">:</span> <span class="token punctuation">{</span>
type<span class="token operator">:</span> 'listener'<span class="token punctuation">,</span>
mulit<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
listener<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
/**
* 导入数据
* @param importDataModule
*
* @info
* 可参考 vendors/exts/yapi-plugin-import-swagger插件
* importDataModule = <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
*
*/
import_data<span class="token operator">:</span> <span class="token punctuation">{</span>
type<span class="token operator">:</span> 'listener'<span class="token punctuation">,</span>
mulit<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
listener<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
/**
* 接口页面 tab 钩子
* @param InterfaceTabs
*
* @info
* 可参考 vendors/exts/yapi-plugin-advanced-mock
* let InterfaceTabs = <span class="token punctuation">{</span>
view<span class="token operator">:</span> <span class="token punctuation">{</span>
component<span class="token operator">:</span> View<span class="token punctuation">,</span>
name<span class="token operator">:</span> '预览'
<span class="token punctuation">}</span><span class="token punctuation">,</span>
edit<span class="token operator">:</span> <span class="token punctuation">{</span>
component<span class="token operator">:</span> Edit<span class="token punctuation">,</span>
name<span class="token operator">:</span> '编辑'
<span class="token punctuation">}</span><span class="token punctuation">,</span>
run<span class="token operator">:</span> <span class="token punctuation">{</span>
component<span class="token operator">:</span> Run<span class="token punctuation">,</span>
name<span class="token operator">:</span> '运行'
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
*/
interface_tab<span class="token operator">:</span> <span class="token punctuation">{</span>
type<span class="token operator">:</span> 'listener'<span class="token punctuation">,</span>
mulit<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
listener<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre>
</div>
</div>
</div>
</div>
<footer class="footer">
<div class="copyright">
&copy; 2017 <a href="https://ymfe.org">YMFE</a> Team. Build by <a href="http://ued.qunar.com/ydoc/">ydoc</a>&nbsp;
</div>
</footer>
</div>
<div class="open-panel"></div>
<div class="mask"></div>
<script src="source/main.js"></script>
<script src="source/app.js"></script>
</body>
</html>

View File

@ -0,0 +1,180 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta name="format-detection" content="telephone=no,email=no" />
<meta http-equiv="X-UA-Compatible" content="ie=edge, chrome=1">
<meta name="description" content="description of your site">
<meta name="author" content="author of the site">
<title>YApi 接口管理平台 插件 Wiki</title>
<link rel="shortcut icon" href="./favicon.ico" />
<link rel="stylesheet" href="source/main.css" />
<link rel="stylesheet" href="styles/theme.css" />
</head>
<body>
<div class="ydoc">
<header class="ydoc-header">
<div class="ydoc-header-area">
<a href="./index.html" class="navbar-brand"><img src="./images/logo_header@2x.png" /> &nbsp;YAPI</a>
<button class="ydocIcon navbar-toggle">&#xf020;</button>
<nav class="ydoc-nav">
<ul class="navbar-left">
<li class="">
<a href="index.html"></a>
</li>
<li class="">
<a href="usage.html">使用手册</a>
</li>
<li class="">
<a href="devops.html">内网部署</a>
</li>
<li class="active">
<a href="plugin.html">插件 Wiki</a>
</li>
<li class="">
<a href="qa.html">常见问题</a>
</li>
<li class="">
<a href="releases.html">版本记录</a>
</li>
<li class="">
<a href="http://yapi.demo.qunar.com/" target="_blank">demo 站点</a>
</li>
<li class="">
<a href="api.html"></a>
</li>
</ul>
</nav>
</div>
</header>
<!-- <header style="height:20px"></header> -->
<!-- Docs page layout -->
<div class="ydoc-banner-bg">
<div class="ydoc-banner ">
<div class="ydoc-banner-area">
<h1 >插件</h1>
<p class="desc ">可根据业务需求,定制化功能</p>
</div>
</div>
<div class="ydoc-container">
<div class="ydoc-container-content ">
<div class="content-left staticsidenav" role="complementary">
<nav class="docs-sidebar hidden-print hidden-xs hidden-sm">
<ul class="nav docs-sidenav">
<!-- <li > -->
<li >
<a href="redev.html">二次开发</a>
</li>
<!-- <li class="active" class="active" > -->
<li class="active" >
<a href="plugin-index.html">插件管理</a>
</li>
<ul class="nav docs-sidenav-extend" >
<li >
<a href="#安装">安装</a>
</li>
<li >
<a href="#卸载插件">卸载插件</a>
</li>
</ul>
<!-- <li > -->
<li >
<a href="plugin-dev.html">插件开发</a>
</li>
<!-- <li > -->
<li >
<a href="plugin-hooks.html">钩子列表</a>
</li>
<!-- <li > -->
<li >
<a href="plugin-list.html">插件列表</a>
</li>
</ul>
</nav>
</div>
<div class="content-right markdown-body use-sidebar" role="main">
<h2 class="subject" id="安装">安装 <a class="hashlink" href="#安装">#</a></h2><p>假设插件名为yapi-plugin-demo,安装方法如下:</p>
<pre><code>cd <span class="token punctuation">{</span>项目目录<span class="token punctuation">}</span>
yapi plugin yapi-plugin-demo
</code></pre><h2 class="subject" id="卸载插件">卸载插件 <a class="hashlink" href="#卸载插件">#</a></h2><p>假设插件名为yapi-plugin-demo,卸载方法如下:</p>
<pre><code>cd <span class="token punctuation">{</span>项目目录<span class="token punctuation">}</span>
yapi unplugin yapi-plugin-demo
</code></pre>
</div>
</div>
</div>
</div>
<footer class="footer">
<div class="copyright">
&copy; 2017 <a href="https://ymfe.org">YMFE</a> Team. Build by <a href="http://ued.qunar.com/ydoc/">ydoc</a>&nbsp;
</div>
</footer>
</div>
<div class="open-panel"></div>
<div class="mask"></div>
<script src="source/main.js"></script>
<script src="source/app.js"></script>
</body>
</html>

View File

@ -0,0 +1,191 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta name="format-detection" content="telephone=no,email=no" />
<meta http-equiv="X-UA-Compatible" content="ie=edge, chrome=1">
<meta name="description" content="description of your site">
<meta name="author" content="author of the site">
<title>YApi 接口管理平台 插件 Wiki</title>
<link rel="shortcut icon" href="./favicon.ico" />
<link rel="stylesheet" href="source/main.css" />
<link rel="stylesheet" href="styles/theme.css" />
</head>
<body>
<div class="ydoc">
<header class="ydoc-header">
<div class="ydoc-header-area">
<a href="./index.html" class="navbar-brand"><img src="./images/logo_header@2x.png" /> &nbsp;YAPI</a>
<button class="ydocIcon navbar-toggle">&#xf020;</button>
<nav class="ydoc-nav">
<ul class="navbar-left">
<li class="">
<a href="index.html"></a>
</li>
<li class="">
<a href="usage.html">使用手册</a>
</li>
<li class="">
<a href="devops.html">内网部署</a>
</li>
<li class="active">
<a href="plugin.html">插件 Wiki</a>
</li>
<li class="">
<a href="qa.html">常见问题</a>
</li>
<li class="">
<a href="releases.html">版本记录</a>
</li>
<li class="">
<a href="http://yapi.demo.qunar.com/" target="_blank">demo 站点</a>
</li>
<li class="">
<a href="api.html"></a>
</li>
</ul>
</nav>
</div>
</header>
<!-- <header style="height:20px"></header> -->
<!-- Docs page layout -->
<div class="ydoc-banner-bg">
<div class="ydoc-banner ">
<div class="ydoc-banner-area">
<h1 >插件</h1>
<p class="desc ">可根据业务需求,定制化功能</p>
</div>
</div>
<div class="ydoc-container">
<div class="ydoc-container-content ">
<div class="content-left staticsidenav" role="complementary">
<nav class="docs-sidebar hidden-print hidden-xs hidden-sm">
<ul class="nav docs-sidenav">
<!-- <li > -->
<li >
<a href="redev.html">二次开发</a>
</li>
<!-- <li > -->
<li >
<a href="plugin-index.html">插件管理</a>
</li>
<!-- <li > -->
<li >
<a href="plugin-dev.html">插件开发</a>
</li>
<!-- <li > -->
<li >
<a href="plugin-hooks.html">钩子列表</a>
</li>
<!-- <li class="active" > -->
<li class="active" >
<a href="plugin-list.html">插件列表</a>
</li>
<ul class="nav docs-sidenav-extend" >
<li >
<a href="#怎么分享我的插件?">怎么分享我的插件?</a>
</li>
<li class="active" >
<a href="#插件列表">插件列表</a>
</li>
</ul>
</ul>
</nav>
</div>
<div class="content-right markdown-body use-sidebar" role="main">
<h2 class="subject" id="怎么分享我的插件?">怎么分享我的插件? <a class="hashlink" href="#怎么分享我的插件?">#</a></h2><p>Fork github.com/ymfe/yapi ,编辑根目录下的 plugin.json 文件, 然后 Pull-Request 到 ymfe/yapi</p>
<h2 class="subject" id="插件列表">插件列表 <a class="hashlink" href="#插件列表">#</a></h2><ul id="list">
</ul>
<script>
window.onload = function(){
var list = [{
title: 'yapi-plugin-qsso',
url: 'https://github.com/ymfe/yapi-plugin-qsso',
desc: 'qunar 专用 sso 第三方登录'
}];
var el = $('#list');
list.forEach(function(item){
el.append("<li>" + '<a target="_black" href=' + item.url + ">" + item.title + "</a>" + "&nbsp;" + item.desc + "</li>")
})
}
</script>
</div>
</div>
</div>
</div>
<footer class="footer">
<div class="copyright">
&copy; 2017 <a href="https://ymfe.org">YMFE</a> Team. Build by <a href="http://ued.qunar.com/ydoc/">ydoc</a>&nbsp;
</div>
</footer>
</div>
<div class="open-panel"></div>
<div class="mask"></div>
<script src="source/main.js"></script>
<script src="source/app.js"></script>
</body>
</html>

View File

@ -133,20 +133,124 @@
<div class="content-right markdown-body use-sidebar" role="main">
<h2 class="subject" id="运行开发服务器">运行开发服务器 <a class="hashlink" href="#运行开发服务器">#</a></h2><p>首先确保安装了 ykit, 没有安装请执行 npm install -g ykit</p>
<pre><code>mkdir yapi
cd yapi
git clone https<span class="token operator">:</span>//github.com/YMFE/yapi.git vendors
cp vendors/config_example.json ./config.json //复制完成后请修改相关配置
cd vendors
npm install
npm run install-server //安装程序会初始化数据库索引和管理员账号,管理员账号名可在 config.json 配置
npm run dev //启动服务器后,请访问 <span class="token number">127.0</span>.<span class="token number">0.1</span><span class="token operator">:</span><span class="token punctuation">{</span>config.json配置的端口<span class="token punctuation">}</span>,初次运行会有个编译的过程,请耐心等候
</code></pre><h2 class="subject" id="安装成功后的目录结构">安装成功后的目录结构 <a class="hashlink" href="#安装成功后的目录结构">#</a></h2><pre><code>yapi
config.json //服务器配置,可参考 vendors/config_example.json
vendors //yapi
init.lock //安装锁文件,重新安装需要删除此文件
log //运行日志
<h2 class="subject" id="安装环境">安装环境 <a class="hashlink" href="#安装环境">#</a></h2><p>安装 Node.js<a target="_blank" href="https://nodejs.org/en/download/package-manager/">官方安装方法</a></p>
<pre><code class="lang-bash"><span class="token comment"># On RHEL, CentOS or Fedora, for Node.js v8 LTS:</span>
curl --silent --location https://rpm.nodesource.com/setup_8.x <span class="token operator">|</span> <span class="token function">sudo</span> <span class="token function">bash</span> -
<span class="token comment"># Alternatively for Node.js 9:</span>
curl --silent --location https://rpm.nodesource.com/setup_9.x <span class="token operator">|</span> <span class="token function">sudo</span> <span class="token function">bash</span> -
<span class="token comment"># 安装 Node.js</span>
<span class="token function">sudo</span> yum -y <span class="token function">install</span> nodejs
<span class="token comment"># Enterprise LinuxRHEL和CentOS用户可以使用EPEL存储库中的Node.js和npm包。</span>
<span class="token comment"># 为您的版本安装相应的epel-release RPM在EPEL存储库主页上找到然后运行</span>
<span class="token function">sudo</span> yum <span class="token function">install</span> nodejs <span class="token function">npm</span> --enablerepo<span class="token operator">=</span>epel
</code></pre>
<p>安装构建工具要从npm编译和安装本地插件您可能还需要安装构建工具</p>
<pre><code class="lang-bash"><span class="token function">sudo</span> yum <span class="token function">install</span> gcc-c++ <span class="token function">make</span>
<span class="token comment"># or: sudo yum groupinstall 'Development Tools'</span>
</code></pre>
<p>安装 MongoDB首先创建源创建 <code>mongodb.repo</code> 文件,
<a target="_blank" href="https://docs.mongodb.com/manual/installation/">官方安装方法</a></p>
<pre><code class="lang-bash"><span class="token comment"># 在/etc/yum.repos.d/目录下创建文件mongodb.repo它包含MongoDB仓库的配置信息内容如下</span>
<span class="token comment"># 复制代码, 代码如下:</span>
<span class="token punctuation">[</span>mongodb<span class="token punctuation">]</span>
name<span class="token operator">=</span>MongoDB Repository
baseurl<span class="token operator">=</span>http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/
gpgcheck<span class="token operator">=</span>0
enabled<span class="token operator">=</span>1
</code></pre>
<p>yum 安装 MongoDB </p>
<pre><code>sudo yum install mongodb-org
</code></pre><p>为 YApi 初始数据库</p>
<pre><code class="lang-js">use yapi <span class="token comment">// 创建yapi数据库 </span>
db<span class="token punctuation">.</span>wong<span class="token punctuation">.</span><span class="token function">insert</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token string">"name"</span><span class="token punctuation">:</span><span class="token string">"kenny wong"</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment">// 插入一条数据,将在数据库列表中展示</span>
show dbs <span class="token comment">// 查看所有数据库</span>
db<span class="token punctuation">.</span><span class="token function">addUser</span><span class="token punctuation">(</span><span class="token string">'yapi'</span><span class="token punctuation">,</span><span class="token string">'yapi321'</span><span class="token punctuation">)</span> <span class="token comment">// 老的,数据库加用户的命令</span>
db<span class="token punctuation">.</span><span class="token function">createUser</span><span class="token punctuation">(</span>
<span class="token punctuation">{</span>
user<span class="token punctuation">:</span> <span class="token string">"yapi"</span><span class="token punctuation">,</span>
pwd<span class="token punctuation">:</span> <span class="token string">"yapi321"</span><span class="token punctuation">,</span>
roles<span class="token punctuation">:</span>
<span class="token punctuation">[</span>
<span class="token punctuation">{</span>
role<span class="token punctuation">:</span> <span class="token string">"userAdminAnyDatabase"</span><span class="token punctuation">,</span>
db<span class="token punctuation">:</span> <span class="token string">"yapi"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span>
<span class="token punctuation">}</span>
<span class="token punctuation">)</span>
</code></pre>
<h2 class="subject" id="安装YApi">安装YApi <a class="hashlink" href="#安装YApi">#</a></h2><p>1.创建工程目录</p>
<pre><code class="lang-bash"><span class="token function">mkdir</span> yapi <span class="token operator">&amp;&amp;</span> <span class="token function">cd</span> yapi
<span class="token function">git</span> clone https://github.com/YMFE/yapi.git vendors --depth<span class="token operator">=</span>1 <span class="token comment"># 或者下载 zip 包解压到 vendors 目录</span>
</code></pre>
<p>2.修改配置</p>
<pre><code class="lang-bash"><span class="token function">cp</span> vendors/config_example.json ./config.json <span class="token comment"># 复制完成后请修改相关配置</span>
<span class="token function">vi</span> ./config.json
</code></pre>
<p>配置如下,主要配置 MongoDB 数据库,以及 Admin 账号。</p>
<pre><code class="lang-json"><span class="token punctuation">{</span>
<span class="token property">"port"</span><span class="token operator">:</span> <span class="token string">"3011"</span><span class="token punctuation">,</span>
<span class="token property">"adminAccount"</span><span class="token operator">:</span> <span class="token string">"admin@admin.com"</span><span class="token punctuation">,</span>
<span class="token property">"db"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"servername"</span><span class="token operator">:</span> <span class="token string">"127.0.0.1"</span><span class="token punctuation">,</span>
<span class="token property">"DATABASE"</span><span class="token operator">:</span> <span class="token string">"yapi"</span><span class="token punctuation">,</span>
<span class="token property">"port"</span><span class="token operator">:</span> <span class="token number">27017</span><span class="token punctuation">,</span>
<span class="token property">"user"</span><span class="token operator">:</span> <span class="token string">"yapi"</span><span class="token punctuation">,</span>
<span class="token property">"pass"</span><span class="token operator">:</span> <span class="token string">"yapi123"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token property">"mail"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"enable"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
<span class="token property">"host"</span><span class="token operator">:</span> <span class="token string">"smtp.163.com"</span><span class="token punctuation">,</span>
<span class="token property">"port"</span><span class="token operator">:</span> <span class="token number">465</span><span class="token punctuation">,</span>
<span class="token property">"from"</span><span class="token operator">:</span> <span class="token string">"***@163.com"</span><span class="token punctuation">,</span>
<span class="token property">"auth"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"user"</span><span class="token operator">:</span> <span class="token string">"***@163.com"</span><span class="token punctuation">,</span>
<span class="token property">"pass"</span><span class="token operator">:</span> <span class="token string">"*****"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
<p>3.安装依赖</p>
<pre><code class="lang-bash"><span class="token function">cd</span> vendors
<span class="token function">npm</span> <span class="token function">install</span> --production --registry https://registry.npm.taobao.org <span class="token comment"># 安装依赖</span>
</code></pre>
<p>4.初始化</p>
<pre><code class="lang-bash"><span class="token function">npm</span> run install-server <span class="token comment"># 安装程序会初始化数据库索引和管理员账号,管理员账号名可在 config.json 配置</span>
<span class="token comment"># 默认输出</span>
<span class="token comment"># 初始化管理员账号成功,账号名:"admin@admin.com",密码:"ymfe.org"</span>
</code></pre>
<p>5.启动服务</p>
<pre><code class="lang-bash"><span class="token comment"># 后台启动输出日志yapi.log</span>
node server/app.js <span class="token operator">>></span> yapi.log 2<span class="token operator">></span><span class="token operator">&amp;</span>1 <span class="token operator">&amp;</span>
<span class="token comment"># 启动服务器后,请访问 127.0.0.1:{config.json配置的端口},初次运行会有个编译的过程,请耐心等候</span>
<span class="token comment"># 127.0.0.1:3011</span>
</code></pre>
<p>目录结构</p>
<pre><code>|-- config.json
|-- init.lock
|-- log
| `-- <span class="token number">2018</span>-<span class="token number">1</span>.log
`-- vendors
|-- CHANGELOG.md
|-- LICENSE
|-- README.md
|-- client
|-- common
|-- config_example.json
|-- doc
|-- exts
|-- nodemon.json
|-- npm-debug.log
|-- package.json
|-- plugin.json
|-- server
|-- static
|-- test
|-- webpack.alias.js
|-- yapi-base-flow.jpg
|-- ydocfile.js
`-- ykit.config.js
</code></pre><h2 class="subject" id="技术栈说明">技术栈说明 <a class="hashlink" href="#技术栈说明">#</a></h2><p>后端: koa mongoose</p>
<p>前端: react redux</p>
<h2 class="subject" id="启动_prd_环境服务器">启动 prd 环境服务器 <a class="hashlink" href="#启动_prd_环境服务器">#</a></h2><pre><code> cd vendors

191
static/doc/qa 2.html Normal file
View File

@ -0,0 +1,191 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta name="format-detection" content="telephone=no,email=no" />
<meta http-equiv="X-UA-Compatible" content="ie=edge, chrome=1">
<meta name="description" content="description of your site">
<meta name="author" content="author of the site">
<title>YApi 接口管理平台 常见问题</title>
<link rel="shortcut icon" href="./favicon.ico" />
<link rel="stylesheet" href="source/main.css" />
<link rel="stylesheet" href="styles/theme.css" />
</head>
<body>
<div class="ydoc">
<header class="ydoc-header">
<div class="ydoc-header-area">
<a href="./index.html" class="navbar-brand"><img src="./images/logo_header@2x.png" /> &nbsp;YAPI</a>
<button class="ydocIcon navbar-toggle">&#xf020;</button>
<nav class="ydoc-nav">
<ul class="navbar-left">
<li class="">
<a href="index.html"></a>
</li>
<li class="">
<a href="usage.html">使用手册</a>
</li>
<li class="">
<a href="devops.html">内网部署</a>
</li>
<li class="">
<a href="plugin.html">插件 Wiki</a>
</li>
<li class="active">
<a href="qa.html">常见问题</a>
</li>
<li class="">
<a href="releases.html">版本记录</a>
</li>
<li class="">
<a href="http://yapi.demo.qunar.com/" target="_blank">demo 站点</a>
</li>
<li class="">
<a href="api.html"></a>
</li>
</ul>
</nav>
</div>
</header>
<!-- <header style="height:20px"></header> -->
<!-- Docs page layout -->
<div class="ydoc-banner-bg">
<div class="ydoc-banner ">
<div class="ydoc-banner-area">
<h1 >常见问题</h1>
<p class="desc ">这里列举了常见的问题</p>
</div>
</div>
<div class="ydoc-container">
<div class="ydoc-container-content ">
<div class="content-left staticsidenav" role="complementary">
<nav class="docs-sidebar hidden-print hidden-xs hidden-sm">
<ul class="nav docs-sidenav">
<!-- <li > -->
<li >
<a href="#Q1 怎样联系组长?">Q1 怎样联系组长?</a>
</li>
<!-- <li > -->
<li >
<a href="#Q2 怎么快速迁移旧项目?">Q2 怎么快速迁移旧项目?</a>
</li>
<!-- <li > -->
<li >
<a href="#Q3 忘记密码怎么办?">Q3 忘记密码怎么办?</a>
</li>
<!-- <li > -->
<li >
<a href="#Q4 发现了 Bug 怎么办?">Q4 发现了 Bug 怎么办?</a>
</li>
<!-- <li > -->
<li >
<a href="#Q5 可视化部署一直处于 github 压缩包下载状态怎么办?">Q5 可视化部署一直处于 github 压缩包下载状态怎么办?</a>
</li>
<!-- <li > -->
<li >
<a href="#Q6 部署YApi遇到的问题">Q6 部署YApi遇到的问题</a>
</li>
</ul>
</nav>
</div>
<div class="content-right markdown-body use-sidebar" role="main">
<p>本页面罗列了大家使用 YApi 时遇到的常见问题.</p>
<p>如果没有找到您要的答案,请联系管理员.</p>
<h2 class="subject" id="Q1_怎样联系组长">Q1 怎样联系组长? <a class="hashlink" href="#Q1_怎样联系组长">#</a></h2><p>组长分为 <code>分组组长</code><code>项目组长</code>:</p>
<ul>
<li>分组组长:选择首页左侧的分组,点击右侧面板的 <code>成员列表</code>,成员右侧显示着 <code>组长/开发者</code> 的权限信息。
<img src="./images/usage/manage_find_manager.png" /></li><li>项目组长: 点击项目页的 <code>设置</code> - <code>成员列表</code>,成员右侧显示着 <code>组长/开发者</code> 的权限信息。
<img src="./images/usage/manage_find_project_owner.png" /></li></ul>
<h2 class="subject" id="Q2_怎么快速迁移旧项目">Q2 怎么快速迁移旧项目? <a class="hashlink" href="#Q2_怎么快速迁移旧项目">#</a></h2><p>第一步. 使用 Chrome 浏览器开发者工具录制功能</p>
<p>第二步 录制当前项目所有请求,导出到 har 文件</p>
<p>第三步 将Har数据导入到 YApi 平台</p>
<p>具体使用方法请参考 YApi <a href="./data.html#HAR%08%08_数据导入">文档</a></p>
<h2 class="subject" id="Q3_忘记密码怎么办">Q3 忘记密码怎么办? <a class="hashlink" href="#Q3_忘记密码怎么办">#</a></h2><p>请联系 <code>超级管理员</code> ,只有超级管理员能重置密码。</p>
<h2 class="subject" id="Q4_发现了_Bug_怎么办">Q4 发现了 Bug 怎么办? <a class="hashlink" href="#Q4_发现了_Bug_怎么办">#</a></h2><p>请反馈到 <a href="https://github.com/YMFE/yapi/issues" _blank="target">Github</a>,功能性的问题我们会在一周内修复,并在每周一发布新的版本 Tag.</p>
<h2 class="subject" id="Q5_可视化部署一直处于_github_压缩包下载状态怎么办">Q5 可视化部署一直处于 github 压缩包下载状态怎么办? <a class="hashlink" href="#Q5_可视化部署一直处于_github_压缩包下载状态怎么办">#</a></h2><p>可按 Ctrl + c 中断部署操作,然后删除之前部署的文件,重新部署。</p>
<p>如果还是不行,请参考 文档 -&gt; 内网部署 -&gt; <a href="./devops.html#方式二. 命令行部署" >命令行部署</a> 文档</p>
<h2 class="subject" id="Q6_部署YApi遇到的问题">Q6 部署YApi遇到的问题 <a class="hashlink" href="#Q6_部署YApi遇到的问题">#</a></h2><ul>
<li><a href="http://blog.csdn.net/ll657418802/article/details/50846313?locationNum=7" _blank="target">mongodb3.03以上开启认证,解决程序认证连接报错以及第三方客户端无法认证问题</a></li></ul>
<p><br>
<br>
<br>
<br>
<br>
<br></p>
</div>
</div>
</div>
</div>
<footer class="footer">
<div class="copyright">
&copy; 2017 <a href="https://ymfe.org">YMFE</a> Team. Build by <a href="http://ued.qunar.com/ydoc/">ydoc</a>&nbsp;
</div>
</footer>
</div>
<div class="open-panel"></div>
<div class="mask"></div>
<script src="source/main.js"></script>
<script src="source/app.js"></script>
</body>
</html>

304
static/doc/redev 2.html Normal file
View File

@ -0,0 +1,304 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta name="format-detection" content="telephone=no,email=no" />
<meta http-equiv="X-UA-Compatible" content="ie=edge, chrome=1">
<meta name="description" content="description of your site">
<meta name="author" content="author of the site">
<title>YApi 接口管理平台 插件 Wiki</title>
<link rel="shortcut icon" href="./favicon.ico" />
<link rel="stylesheet" href="source/main.css" />
<link rel="stylesheet" href="styles/theme.css" />
</head>
<body>
<div class="ydoc">
<header class="ydoc-header">
<div class="ydoc-header-area">
<a href="./index.html" class="navbar-brand"><img src="./images/logo_header@2x.png" /> &nbsp;YAPI</a>
<button class="ydocIcon navbar-toggle">&#xf020;</button>
<nav class="ydoc-nav">
<ul class="navbar-left">
<li class="">
<a href="index.html"></a>
</li>
<li class="">
<a href="usage.html">使用手册</a>
</li>
<li class="">
<a href="devops.html">内网部署</a>
</li>
<li class="active">
<a href="plugin.html">插件 Wiki</a>
</li>
<li class="">
<a href="qa.html">常见问题</a>
</li>
<li class="">
<a href="releases.html">版本记录</a>
</li>
<li class="">
<a href="http://yapi.demo.qunar.com/" target="_blank">demo 站点</a>
</li>
<li class="">
<a href="api.html"></a>
</li>
</ul>
</nav>
</div>
</header>
<!-- <header style="height:20px"></header> -->
<!-- Docs page layout -->
<div class="ydoc-banner-bg">
<div class="ydoc-banner ">
<div class="ydoc-banner-area">
<h1 >插件</h1>
<p class="desc ">可根据业务需求,定制化功能</p>
</div>
</div>
<div class="ydoc-container">
<div class="ydoc-container-content ">
<div class="content-left staticsidenav" role="complementary">
<nav class="docs-sidebar hidden-print hidden-xs hidden-sm">
<ul class="nav docs-sidenav">
<!-- <li class="active" class="active" > -->
<li class="active" >
<a href="redev.html">二次开发</a>
</li>
<ul class="nav docs-sidenav-extend" >
<li >
<a href="#安装环境">安装环境</a>
</li>
<li >
<a href="#安装YApi">安装YApi</a>
</li>
<li >
<a href="#技术栈说明">技术栈说明</a>
</li>
<li >
<a href="#启动 prd 环境服务器">启动 prd 环境服务器</a>
</li>
</ul>
<!-- <li > -->
<li >
<a href="plugin-index.html">插件管理</a>
</li>
<!-- <li > -->
<li >
<a href="plugin-dev.html">插件开发</a>
</li>
<!-- <li > -->
<li >
<a href="plugin-hooks.html">钩子列表</a>
</li>
<!-- <li > -->
<li >
<a href="plugin-list.html">插件列表</a>
</li>
</ul>
</nav>
</div>
<div class="content-right markdown-body use-sidebar" role="main">
<h2 class="subject" id="安装环境">安装环境 <a class="hashlink" href="#安装环境">#</a></h2><p>安装 Node.js<a href="https://nodejs.org/en/download/package-manager/">官方安装方法</a></p>
<pre><code class="lang-bash"><span class="token comment"># On RHEL, CentOS or Fedora, for Node.js v8 LTS:</span>
curl --silent --location https://rpm.nodesource.com/setup_8.x <span class="token operator">|</span> <span class="token function">sudo</span> <span class="token function">bash</span> -
<span class="token comment"># Alternatively for Node.js 9:</span>
curl --silent --location https://rpm.nodesource.com/setup_9.x <span class="token operator">|</span> <span class="token function">sudo</span> <span class="token function">bash</span> -
<span class="token comment"># 安装 Node.js</span>
<span class="token function">sudo</span> yum -y <span class="token function">install</span> nodejs
<span class="token comment"># Enterprise LinuxRHEL和CentOS用户可以使用EPEL存储库中的Node.js和npm包。</span>
<span class="token comment"># 为您的版本安装相应的epel-release RPM在EPEL存储库主页上找到然后运行</span>
<span class="token function">sudo</span> yum <span class="token function">install</span> nodejs <span class="token function">npm</span> --enablerepo<span class="token operator">=</span>epel
</code></pre>
<p>安装构建工具要从npm编译和安装本地插件您可能还需要安装构建工具</p>
<pre><code class="lang-bash"><span class="token function">sudo</span> yum <span class="token function">install</span> gcc-c++ <span class="token function">make</span>
<span class="token comment"># or: sudo yum groupinstall 'Development Tools'</span>
</code></pre>
<p>安装 MongoDB首先创建源创建 <code>mongodb.repo</code> 文件, <a href="https://docs.mongodb.com/manual/installation/">官方安装方法</a></p>
<pre><code class="lang-bash"><span class="token comment"># 在/etc/yum.repos.d/目录下创建文件mongodb.repo它包含MongoDB仓库的配置信息内容如下</span>
<span class="token comment"># 复制代码, 代码如下:</span>
<span class="token punctuation">[</span>mongodb<span class="token punctuation">]</span>
name<span class="token operator">=</span>MongoDB Repository
baseurl<span class="token operator">=</span>http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/
gpgcheck<span class="token operator">=</span>0
enabled<span class="token operator">=</span>1
</code></pre>
<p>yum 安装 MongoDB </p>
<pre><code>sudo yum install mongodb-org
</code></pre><p>为 YApi 初始数据库</p>
<pre><code class="lang-js">use yapi <span class="token comment">// 创建yapi数据库 </span>
db<span class="token punctuation">.</span>wong<span class="token punctuation">.</span><span class="token function">insert</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token string">"name"</span><span class="token punctuation">:</span><span class="token string">"kenny wong"</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment">// 插入一条数据,将在数据库列表中展示</span>
show dbs <span class="token comment">// 查看所有数据库</span>
db<span class="token punctuation">.</span><span class="token function">addUser</span><span class="token punctuation">(</span><span class="token string">'yapi'</span><span class="token punctuation">,</span><span class="token string">'yapi321'</span><span class="token punctuation">)</span> <span class="token comment">// 老的,数据库加用户的命令</span>
db<span class="token punctuation">.</span><span class="token function">createUser</span><span class="token punctuation">(</span>
<span class="token punctuation">{</span>
user<span class="token punctuation">:</span> <span class="token string">"yapi"</span><span class="token punctuation">,</span>
pwd<span class="token punctuation">:</span> <span class="token string">"yapi321"</span><span class="token punctuation">,</span>
roles<span class="token punctuation">:</span>
<span class="token punctuation">[</span>
<span class="token punctuation">{</span>
role<span class="token punctuation">:</span> <span class="token string">"userAdminAnyDatabase"</span><span class="token punctuation">,</span>
db<span class="token punctuation">:</span> <span class="token string">"yapi"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span>
<span class="token punctuation">}</span>
<span class="token punctuation">)</span>
</code></pre>
<h2 class="subject" id="安装YApi">安装YApi <a class="hashlink" href="#安装YApi">#</a></h2><p>1.创建工程目录</p>
<pre><code class="lang-bash"><span class="token function">mkdir</span> yapi <span class="token operator">&amp;&amp;</span> <span class="token function">cd</span> yapi
<span class="token function">git</span> clone https://github.com/YMFE/yapi.git vendors --depth<span class="token operator">=</span>1 <span class="token comment"># 或者下载 zip 包解压到 vendors 目录</span>
</code></pre>
<p>2.修改配置</p>
<pre><code class="lang-bash"><span class="token function">cp</span> vendors/config_example.json ./config.json <span class="token comment"># 复制完成后请修改相关配置</span>
<span class="token function">vi</span> ./config.json
</code></pre>
<p>配置如下,主要配置 MongoDB 数据库,以及 Admin 账号。</p>
<pre><code class="lang-json"><span class="token punctuation">{</span>
<span class="token property">"port"</span><span class="token operator">:</span> <span class="token string">"3011"</span><span class="token punctuation">,</span>
<span class="token property">"adminAccount"</span><span class="token operator">:</span> <span class="token string">"admin@admin.com"</span><span class="token punctuation">,</span>
<span class="token property">"db"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"servername"</span><span class="token operator">:</span> <span class="token string">"127.0.0.1"</span><span class="token punctuation">,</span>
<span class="token property">"DATABASE"</span><span class="token operator">:</span> <span class="token string">"yapi"</span><span class="token punctuation">,</span>
<span class="token property">"port"</span><span class="token operator">:</span> <span class="token number">27017</span><span class="token punctuation">,</span>
<span class="token property">"user"</span><span class="token operator">:</span> <span class="token string">"yapi"</span><span class="token punctuation">,</span>
<span class="token property">"pass"</span><span class="token operator">:</span> <span class="token string">"yapi123"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token property">"mail"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"enable"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
<span class="token property">"host"</span><span class="token operator">:</span> <span class="token string">"smtp.163.com"</span><span class="token punctuation">,</span>
<span class="token property">"port"</span><span class="token operator">:</span> <span class="token number">465</span><span class="token punctuation">,</span>
<span class="token property">"from"</span><span class="token operator">:</span> <span class="token string">"***@163.com"</span><span class="token punctuation">,</span>
<span class="token property">"auth"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"user"</span><span class="token operator">:</span> <span class="token string">"***@163.com"</span><span class="token punctuation">,</span>
<span class="token property">"pass"</span><span class="token operator">:</span> <span class="token string">"*****"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
<p>3.安装依赖</p>
<pre><code class="lang-bash"><span class="token function">cd</span> vendors
<span class="token function">npm</span> <span class="token function">install</span> --production --registry https://registry.npm.taobao.org <span class="token comment"># 安装依赖</span>
</code></pre>
<p>4.初始化</p>
<pre><code class="lang-bash"><span class="token function">npm</span> run install-server <span class="token comment"># 安装程序会初始化数据库索引和管理员账号,管理员账号名可在 config.json 配置</span>
<span class="token comment"># 默认输出</span>
<span class="token comment"># 初始化管理员账号成功,账号名:"admin@admin.com",密码:"ymfe.org"</span>
</code></pre>
<p>5.启动服务</p>
<pre><code class="lang-bash"><span class="token comment"># 后台启动输出日志yapi.log</span>
node server/app.js <span class="token operator">>></span> yapi.log 2<span class="token operator">></span><span class="token operator">&amp;</span>1 <span class="token operator">&amp;</span>
<span class="token comment"># 启动服务器后,请访问 127.0.0.1:{config.json配置的端口},初次运行会有个编译的过程,请耐心等候</span>
<span class="token comment"># 127.0.0.1:3011</span>
</code></pre>
<p>目录结构</p>
<pre><code>|-- config.json
|-- init.lock
|-- log
| `-- <span class="token number">2018</span>-<span class="token number">1</span>.log
`-- vendors
|-- CHANGELOG.md
|-- LICENSE
|-- README.md
|-- client
|-- common
|-- config_example.json
|-- doc
|-- exts
|-- nodemon.json
|-- npm-debug.log
|-- package.json
|-- plugin.json
|-- server
|-- static
|-- test
|-- webpack.alias.js
|-- yapi-base-flow.jpg
|-- ydocfile.js
`-- ykit.config.js
</code></pre><h2 class="subject" id="技术栈说明">技术栈说明 <a class="hashlink" href="#技术栈说明">#</a></h2><p>后端: koa mongoose</p>
<p>前端: react redux</p>
<h2 class="subject" id="启动_prd_环境服务器">启动 prd 环境服务器 <a class="hashlink" href="#启动_prd_环境服务器">#</a></h2><pre><code> cd vendors
ykit pack -m
node server/app.js
</code></pre>
</div>
</div>
</div>
</div>
<footer class="footer">
<div class="copyright">
&copy; 2017 <a href="https://ymfe.org">YMFE</a> Team. Build by <a href="http://ued.qunar.com/ydoc/">ydoc</a>&nbsp;
</div>
</footer>
</div>
<div class="open-panel"></div>
<div class="mask"></div>
<script src="source/main.js"></script>
<script src="source/app.js"></script>
</body>
</html>

View File

@ -106,11 +106,11 @@
<ul class="nav docs-sidenav-extend" >
<li >
<a href="#运行开发服务器">运行开发服务器</a>
<a href="#安装环境">安装环境</a>
</li>
<li >
<a href="#安装成功后的目录结构">安装成功后的目录结构</a>
<a href="#安装YApi">安装YApi</a>
</li>
<li >
@ -153,20 +153,124 @@
<div class="content-right markdown-body use-sidebar" role="main">
<h2 class="subject" id="运行开发服务器">运行开发服务器 <a class="hashlink" href="#运行开发服务器">#</a></h2><p>首先确保安装了 ykit, 没有安装请执行 npm install -g ykit</p>
<pre><code>mkdir yapi
cd yapi
git clone https<span class="token operator">:</span>//github.com/YMFE/yapi.git vendors
cp vendors/config_example.json ./config.json //复制完成后请修改相关配置
cd vendors
npm install
npm run install-server //安装程序会初始化数据库索引和管理员账号,管理员账号名可在 config.json 配置
npm run dev //启动服务器后,请访问 <span class="token number">127.0</span>.<span class="token number">0.1</span><span class="token operator">:</span><span class="token punctuation">{</span>config.json配置的端口<span class="token punctuation">}</span>,初次运行会有个编译的过程,请耐心等候
</code></pre><h2 class="subject" id="安装成功后的目录结构">安装成功后的目录结构 <a class="hashlink" href="#安装成功后的目录结构">#</a></h2><pre><code>yapi
config.json //服务器配置,可参考 vendors/config_example.json
vendors //yapi
init.lock //安装锁文件,重新安装需要删除此文件
log //运行日志
<h2 class="subject" id="安装环境">安装环境 <a class="hashlink" href="#安装环境">#</a></h2><p>安装 Node.js<a target="_blank" href="https://nodejs.org/en/download/package-manager/">官方安装方法</a></p>
<pre><code class="lang-bash"><span class="token comment"># On RHEL, CentOS or Fedora, for Node.js v8 LTS:</span>
curl --silent --location https://rpm.nodesource.com/setup_8.x <span class="token operator">|</span> <span class="token function">sudo</span> <span class="token function">bash</span> -
<span class="token comment"># Alternatively for Node.js 9:</span>
curl --silent --location https://rpm.nodesource.com/setup_9.x <span class="token operator">|</span> <span class="token function">sudo</span> <span class="token function">bash</span> -
<span class="token comment"># 安装 Node.js</span>
<span class="token function">sudo</span> yum -y <span class="token function">install</span> nodejs
<span class="token comment"># Enterprise LinuxRHEL和CentOS用户可以使用EPEL存储库中的Node.js和npm包。</span>
<span class="token comment"># 为您的版本安装相应的epel-release RPM在EPEL存储库主页上找到然后运行</span>
<span class="token function">sudo</span> yum <span class="token function">install</span> nodejs <span class="token function">npm</span> --enablerepo<span class="token operator">=</span>epel
</code></pre>
<p>安装构建工具要从npm编译和安装本地插件您可能还需要安装构建工具</p>
<pre><code class="lang-bash"><span class="token function">sudo</span> yum <span class="token function">install</span> gcc-c++ <span class="token function">make</span>
<span class="token comment"># or: sudo yum groupinstall 'Development Tools'</span>
</code></pre>
<p>安装 MongoDB首先创建源创建 <code>mongodb.repo</code> 文件,
<a target="_blank" href="https://docs.mongodb.com/manual/installation/">官方安装方法</a></p>
<pre><code class="lang-bash"><span class="token comment"># 在/etc/yum.repos.d/目录下创建文件mongodb.repo它包含MongoDB仓库的配置信息内容如下</span>
<span class="token comment"># 复制代码, 代码如下:</span>
<span class="token punctuation">[</span>mongodb<span class="token punctuation">]</span>
name<span class="token operator">=</span>MongoDB Repository
baseurl<span class="token operator">=</span>http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/
gpgcheck<span class="token operator">=</span>0
enabled<span class="token operator">=</span>1
</code></pre>
<p>yum 安装 MongoDB </p>
<pre><code>sudo yum install mongodb-org
</code></pre><p>为 YApi 初始数据库</p>
<pre><code class="lang-js">use yapi <span class="token comment">// 创建yapi数据库 </span>
db<span class="token punctuation">.</span>wong<span class="token punctuation">.</span><span class="token function">insert</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token string">"name"</span><span class="token punctuation">:</span><span class="token string">"kenny wong"</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment">// 插入一条数据,将在数据库列表中展示</span>
show dbs <span class="token comment">// 查看所有数据库</span>
db<span class="token punctuation">.</span><span class="token function">addUser</span><span class="token punctuation">(</span><span class="token string">'yapi'</span><span class="token punctuation">,</span><span class="token string">'yapi321'</span><span class="token punctuation">)</span> <span class="token comment">// 老的,数据库加用户的命令</span>
db<span class="token punctuation">.</span><span class="token function">createUser</span><span class="token punctuation">(</span>
<span class="token punctuation">{</span>
user<span class="token punctuation">:</span> <span class="token string">"yapi"</span><span class="token punctuation">,</span>
pwd<span class="token punctuation">:</span> <span class="token string">"yapi321"</span><span class="token punctuation">,</span>
roles<span class="token punctuation">:</span>
<span class="token punctuation">[</span>
<span class="token punctuation">{</span>
role<span class="token punctuation">:</span> <span class="token string">"userAdminAnyDatabase"</span><span class="token punctuation">,</span>
db<span class="token punctuation">:</span> <span class="token string">"yapi"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span>
<span class="token punctuation">}</span>
<span class="token punctuation">)</span>
</code></pre>
<h2 class="subject" id="安装YApi">安装YApi <a class="hashlink" href="#安装YApi">#</a></h2><p>1.创建工程目录</p>
<pre><code class="lang-bash"><span class="token function">mkdir</span> yapi <span class="token operator">&amp;&amp;</span> <span class="token function">cd</span> yapi
<span class="token function">git</span> clone https://github.com/YMFE/yapi.git vendors --depth<span class="token operator">=</span>1 <span class="token comment"># 或者下载 zip 包解压到 vendors 目录</span>
</code></pre>
<p>2.修改配置</p>
<pre><code class="lang-bash"><span class="token function">cp</span> vendors/config_example.json ./config.json <span class="token comment"># 复制完成后请修改相关配置</span>
<span class="token function">vi</span> ./config.json
</code></pre>
<p>配置如下,主要配置 MongoDB 数据库,以及 Admin 账号。</p>
<pre><code class="lang-json"><span class="token punctuation">{</span>
<span class="token property">"port"</span><span class="token operator">:</span> <span class="token string">"3011"</span><span class="token punctuation">,</span>
<span class="token property">"adminAccount"</span><span class="token operator">:</span> <span class="token string">"admin@admin.com"</span><span class="token punctuation">,</span>
<span class="token property">"db"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"servername"</span><span class="token operator">:</span> <span class="token string">"127.0.0.1"</span><span class="token punctuation">,</span>
<span class="token property">"DATABASE"</span><span class="token operator">:</span> <span class="token string">"yapi"</span><span class="token punctuation">,</span>
<span class="token property">"port"</span><span class="token operator">:</span> <span class="token number">27017</span><span class="token punctuation">,</span>
<span class="token property">"user"</span><span class="token operator">:</span> <span class="token string">"yapi"</span><span class="token punctuation">,</span>
<span class="token property">"pass"</span><span class="token operator">:</span> <span class="token string">"yapi123"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token property">"mail"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"enable"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
<span class="token property">"host"</span><span class="token operator">:</span> <span class="token string">"smtp.163.com"</span><span class="token punctuation">,</span>
<span class="token property">"port"</span><span class="token operator">:</span> <span class="token number">465</span><span class="token punctuation">,</span>
<span class="token property">"from"</span><span class="token operator">:</span> <span class="token string">"***@163.com"</span><span class="token punctuation">,</span>
<span class="token property">"auth"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"user"</span><span class="token operator">:</span> <span class="token string">"***@163.com"</span><span class="token punctuation">,</span>
<span class="token property">"pass"</span><span class="token operator">:</span> <span class="token string">"*****"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
<p>3.安装依赖</p>
<pre><code class="lang-bash"><span class="token function">cd</span> vendors
<span class="token function">npm</span> <span class="token function">install</span> --production --registry https://registry.npm.taobao.org <span class="token comment"># 安装依赖</span>
</code></pre>
<p>4.初始化</p>
<pre><code class="lang-bash"><span class="token function">npm</span> run install-server <span class="token comment"># 安装程序会初始化数据库索引和管理员账号,管理员账号名可在 config.json 配置</span>
<span class="token comment"># 默认输出</span>
<span class="token comment"># 初始化管理员账号成功,账号名:"admin@admin.com",密码:"ymfe.org"</span>
</code></pre>
<p>5.启动服务</p>
<pre><code class="lang-bash"><span class="token comment"># 后台启动输出日志yapi.log</span>
node server/app.js <span class="token operator">>></span> yapi.log 2<span class="token operator">></span><span class="token operator">&amp;</span>1 <span class="token operator">&amp;</span>
<span class="token comment"># 启动服务器后,请访问 127.0.0.1:{config.json配置的端口},初次运行会有个编译的过程,请耐心等候</span>
<span class="token comment"># 127.0.0.1:3011</span>
</code></pre>
<p>目录结构</p>
<pre><code>|-- config.json
|-- init.lock
|-- log
| `-- <span class="token number">2018</span>-<span class="token number">1</span>.log
`-- vendors
|-- CHANGELOG.md
|-- LICENSE
|-- README.md
|-- client
|-- common
|-- config_example.json
|-- doc
|-- exts
|-- nodemon.json
|-- npm-debug.log
|-- package.json
|-- plugin.json
|-- server
|-- static
|-- test
|-- webpack.alias.js
|-- yapi-base-flow.jpg
|-- ydocfile.js
`-- ykit.config.js
</code></pre><h2 class="subject" id="技术栈说明">技术栈说明 <a class="hashlink" href="#技术栈说明">#</a></h2><p>后端: koa mongoose</p>
<p>前端: react redux</p>
<h2 class="subject" id="启动_prd_环境服务器">启动 prd 环境服务器 <a class="hashlink" href="#启动_prd_环境服务器">#</a></h2><pre><code> cd vendors

276
static/doc/releases 2.html Normal file
View File

@ -0,0 +1,276 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta name="format-detection" content="telephone=no,email=no" />
<meta http-equiv="X-UA-Compatible" content="ie=edge, chrome=1">
<meta name="description" content="description of your site">
<meta name="author" content="author of the site">
<title>YApi 接口管理平台 版本记录</title>
<link rel="shortcut icon" href="./favicon.ico" />
<link rel="stylesheet" href="source/main.css" />
<link rel="stylesheet" href="styles/theme.css" />
</head>
<body>
<div class="ydoc">
<header class="ydoc-header">
<div class="ydoc-header-area">
<a href="./index.html" class="navbar-brand"><img src="./images/logo_header@2x.png" /> &nbsp;YAPI</a>
<button class="ydocIcon navbar-toggle">&#xf020;</button>
<nav class="ydoc-nav">
<ul class="navbar-left">
<li class="">
<a href="index.html"></a>
</li>
<li class="">
<a href="usage.html">使用手册</a>
</li>
<li class="">
<a href="devops.html">内网部署</a>
</li>
<li class="">
<a href="plugin.html">插件 Wiki</a>
</li>
<li class="">
<a href="qa.html">常见问题</a>
</li>
<li class="active">
<a href="releases.html">版本记录</a>
</li>
<li class="">
<a href="http://yapi.demo.qunar.com/" target="_blank">demo 站点</a>
</li>
<li class="">
<a href="api.html"></a>
</li>
</ul>
</nav>
</div>
</header>
<!-- <header style="height:20px"></header> -->
<!-- Docs page layout -->
<div class="ydoc-banner-bg">
<div class="ydoc-banner ">
<div class="ydoc-banner-area">
<h1 >YApi</h1>
<p class="desc ">这里列举了 YApi 的历史版本、发布时间及变更记录,帮助你追溯到每个版本的演进过程。</p>
</div>
</div>
<div class="ydoc-container">
<div class="ydoc-container-content ">
<div class="content-left staticsidenav" role="complementary">
<nav class="docs-sidebar hidden-print hidden-xs hidden-sm">
<ul class="nav docs-sidenav">
<li >
<a href="#v1.3.6">v1.3.6</a>
</li>
<li >
<a href="#v1.3.5">v1.3.5</a>
</li>
<li >
<a href="#v1.3.4">v1.3.4</a>
</li>
<li >
<a href="#v1.3.3">v1.3.3</a>
</li>
<li >
<a href="#v1.3.2">v1.3.2</a>
</li>
<li >
<a href="#v1.3.1">v1.3.1</a>
</li>
<li >
<a href="#v1.3.0">v1.3.0</a>
</li>
<li >
<a href="#v1.2.9">v1.2.9</a>
</li>
<li >
<a href="#v1.2.8">v1.2.8</a>
</li>
<li >
<a href="#v1.2.7">v1.2.7</a>
</li>
<li >
<a href="#v1.2.6">v1.2.6</a>
</li>
<li >
<a href="#v1.2.5">v1.2.5</a>
</li>
<li >
<a href="#v1.2.4">v1.2.4</a>
</li>
<li >
<a href="#v1.2.0">v1.2.0</a>
</li>
<li >
<a href="#v1.1.2">v1.1.2</a>
</li>
<li >
<a href="#v1.1.1">v1.1.1</a>
</li>
<li >
<a href="#v1.1.0">v1.1.0</a>
</li>
<li >
<a href="#v1.0.2">v1.0.2</a>
</li>
<li >
<a href="#v1.0.1">v1.0.1</a>
</li>
</ul>
</ul>
</nav>
</div>
<div class="content-right markdown-body use-sidebar" role="main">
<h3 class="subject" id="v1.3.6">v1.3.6 <a class="hashlink" href="#v1.3.6">#</a></h3><h4 class="subject" id="Feature">Feature <a class="hashlink" href="#Feature">#</a></h4><ul>
<li>增加项目成员批量导入</li></ul>
<h3 class="subject" id="v1.3.5">v1.3.5 <a class="hashlink" href="#v1.3.5">#</a></h3><h4 class="subject" id="Feature">Feature <a class="hashlink" href="#Feature">#</a></h4><ul>
<li>数据导入同步数据导入支持swagger 3.0</li><li>swagger 数据导入支持 2xx 的httpcode</li><li>新增系统信息页面</li></ul>
<h4 class="subject" id="Bug_Fixed">Bug Fixed <a class="hashlink" href="#Bug_Fixed">#</a></h4><ul>
<li>修复离开接口编辑页面的 confirm 框有时候会触发两次 &amp; confirm 的 X 按钮无效</li><li>修复添加集合后测试集合list不更新问题</li><li>测试集合点击对应接口侧边栏不切换</li><li>测试集合处,点击删除不成功</li><li>修改编辑接口后,再回到测试集合处数据不更新问题</li><li>修复mongodb帐号密码配置错误时引发的错误</li><li>修复删除分组后侧边数据没哟更新问题</li></ul>
<h3 class="subject" id="v1.3.4">v1.3.4 <a class="hashlink" href="#v1.3.4">#</a></h3><h4 class="subject" id="Feature">Feature <a class="hashlink" href="#Feature">#</a></h4><ul>
<li>进入project页面加入loading</li><li>接口list页table中加入分页</li><li>项目添加者自动变成项目组长</li></ul>
<h4 class="subject" id="Bug_Fixed">Bug Fixed <a class="hashlink" href="#Bug_Fixed">#</a></h4><ul>
<li>修复无权限进入项目bug</li><li>修复复制接口query 等参数无法复制bug</li><li>修复导出html markdown参数丢失问题</li></ul>
<h3 class="subject" id="v1.3.3">v1.3.3 <a class="hashlink" href="#v1.3.3">#</a></h3><h4 class="subject" id="Feature">Feature <a class="hashlink" href="#Feature">#</a></h4><ul>
<li>邮件功能中: 1接口信息改动增加通知对应项目所有的成员2默认开启接口改动邮件提醒3) 增加邮件内容的jsondiff信息</li></ul>
<h4 class="subject" id="Bug_Fixed">Bug Fixed <a class="hashlink" href="#Bug_Fixed">#</a></h4><ul>
<li>优化接口运行页面插件提醒</li><li>完善 log 记录不到的问题</li><li>修复接口内容改动不发送邮件问题</li><li>修复部分swagger数据导入丢失问题</li></ul>
<h3 class="subject" id="v1.3.2">v1.3.2 <a class="hashlink" href="#v1.3.2">#</a></h3><h4 class="subject" id="Feature">Feature <a class="hashlink" href="#Feature">#</a></h4><ul>
<li>分组中新增接口自定义字段,便于用户在项目中添加额外字段数据</li><li>导入数据时新增导入loading显示</li></ul>
<h3 class="subject" id="v1.3.1">v1.3.1 <a class="hashlink" href="#v1.3.1">#</a></h3><h4 class="subject" id="Bug_Fixed">Bug Fixed <a class="hashlink" href="#Bug_Fixed">#</a></h4><ol>
<li>修复接口状态和req_params参数无法更新问题</li><li>修复搜索测试集合不展开问题</li><li>修复测试过程中全局header不存在的问题</li></ol>
<h3 class="subject" id="v1.3.0">v1.3.0 <a class="hashlink" href="#v1.3.0">#</a></h3><h4 class="subject" id="Feature">Feature <a class="hashlink" href="#Feature">#</a></h4><ul>
<li>yapi 默认集成 ldap 登录方式</li><li>yapi 做一个 sso 登录插件,基于现有的 qsso 改造成大多数公司可用的</li><li>环境设置支持全局 header</li><li>接口运行页面选择环境增加管理环境的弹层</li><li>接口运行支持加工运行前后的 request 和 response ,主要是处理加密的接口或各种 token 参数问题</li><li>自动化测试除提供自定义脚本外,还提供可视化表单形式验证一些数据,例如 statusCode、bodyContent </li><li>增加查看接口详细改动</li><li>支持接口运行页面 body 全屏编辑</li><li>数据导出到 html 支持了分类</li></ul>
<h4 class="subject" id="Bug_Fixed">Bug Fixed <a class="hashlink" href="#Bug_Fixed">#</a></h4><ul>
<li>修复了高级 Mock 无法获取到真实客户端 ip </li></ul>
<h3 class="subject" id="v1.2.9">v1.2.9 <a class="hashlink" href="#v1.2.9">#</a></h3><h4 class="subject" id="Bug_Fixed">Bug Fixed <a class="hashlink" href="#Bug_Fixed">#</a></h4><ol>
<li>Api 路径兼容 postman {varible}</li><li>View Response Height 问题</li></ol>
<h4 class="subject" id="Feature">Feature <a class="hashlink" href="#Feature">#</a></h4><ol>
<li>新增克隆测试集功能</li><li>高级 Mock 期望支持 mockjs</li><li>pathname 允许只有一个 /</li></ol>
<h3 class="subject" id="v1.2.8">v1.2.8 <a class="hashlink" href="#v1.2.8">#</a></h3><h4 class="subject" id="Bug_Fixed">Bug Fixed <a class="hashlink" href="#Bug_Fixed">#</a></h4><ol>
<li>修复接口运行 json 格式问题</li><li>修复测试报告显示问题</li><li>增加了接口数量统计</li><li>多参数表达式改用双大括号{{}}</li><li>修复了环境变量设置样式问题</li></ol>
<h4 class="subject" id="Feature">Feature <a class="hashlink" href="#Feature">#</a></h4><ol>
<li>测试用例增加自定义测试脚本功能</li></ol>
<h3 class="subject" id="v1.2.7">v1.2.7 <a class="hashlink" href="#v1.2.7">#</a></h3><h4 class="subject" id="Bug_Fixed">Bug Fixed <a class="hashlink" href="#Bug_Fixed">#</a></h4><ol>
<li>修复接口运行功能,当 httpCode 不是200时导致无法获取 response body 问题</li><li>修复路径参数无法删除优化测试集 table 页面,当文字超出一定长度会换行的问题</li><li>优化测试集断言错误提示</li><li>优化接口编辑 save 按钮样式</li></ol>
<h4 class="subject" id="Feature">Feature <a class="hashlink" href="#Feature">#</a></h4><ol>
<li>测试集断言增加 log 方法,用于输出调试日志</li><li>可视化动态参数表达式生成器,生成类似表达式 {@email | concat: pass | md5 | substr: 1,10} </li></ol>
<h3 class="subject" id="v1.2.6">v1.2.6 <a class="hashlink" href="#v1.2.6">#</a></h3><h4 class="subject" id="Bug_Fixed">Bug Fixed <a class="hashlink" href="#Bug_Fixed">#</a></h4><ol>
<li>修复路径参数无法删除</li></ol>
<h4 class="subject" id="Feature">Feature <a class="hashlink" href="#Feature">#</a></h4><ol>
<li>参数值支持多个动态参数,类似 str{@email}str{$.55.body.id}</li><li>参数值支持管道表达式,例如 {@email | concat: pass | md5 | substr: 1,10}</li><li>接口编辑参数<strong>可拖动排序</strong></li><li>修复路径参数无法删除问题</li></ol>
<h3 class="subject" id="v1.2.5">v1.2.5 <a class="hashlink" href="#v1.2.5">#</a></h3><h4 class="subject" id="Bug_Fixed">Bug Fixed <a class="hashlink" href="#Bug_Fixed">#</a></h4><ol>
<li>成员如果第一次添加成员时选择组长接着再添加下一个成员如果select是默认的开发者这时候会出现与上次select相同的值</li><li>如果添加了一个不存在的成员还是会提示添加成功,并且发送的数据是原来发送成功的数据,这里需要重置初始值并在未找到对应用户名时对未找到的人名应该提示用户不存在</li><li>Fix 接口集自动化测试 header 没有解析 mock 和 变量参数</li><li>在接口开发阶段,多个人并行改接口,如果最后一个人改之前没刷新页面,会把之前的人修改过的都冲掉了</li><li>修复cross-requestresponse header字段重复bug</li></ol>
<h4 class="subject" id="Feature">Feature <a class="hashlink" href="#Feature">#</a></h4><ol>
<li>优化了分组添加,编辑交互</li><li>cross-request 计算了接口请求时间</li><li>新增接口文档导出 html, markdown 功能</li></ol>
<h3 class="subject" id="v1.2.4">v1.2.4 <a class="hashlink" href="#v1.2.4">#</a></h3><h4 class="subject" id="Bug_Fixed">Bug Fixed <a class="hashlink" href="#Bug_Fixed">#</a></h4><ol>
<li>期望值输入时候换成字符串导致diff时因类型不一致匹配不上</li><li>swagger 导入数据时出现的 id 未定义bug</li><li>fix: kerberos dependencies 导致安装依赖需要编译的问题</li><li>修复了高级 mock 期望过滤参数为空时匹配不到的 bug</li><li>将接口编辑页的保存按钮变成一直在窗口底部</li><li>修改需求文档中项目操作处修改项目中的接口测试a链接指向的网页错误问题</li><li>添加接口时重名,现在提示“已存在”,并在提示信息中告知用户删改接口的位置</li><li>已添加的成员,再次添加会提示“添加成功”,优化提示为已成功添加人数,和已存在人数</li><li>添加分组和修改分组时有个权限问题没有更新,切换列表才更新,该问题已解决</li><li>解决修改和删除公共分类名称处,在添加接口时,选择接口分类名称没有修改的问题</li></ol>
<h4 class="subject" id="Feature">Feature <a class="hashlink" href="#Feature">#</a></h4><ol>
<li>接口 path 支持了后面带 /</li><li>cross-request支持了不安全的 header如 cookie, referer...</li><li>支持了 path 带特殊符号&quot;!&quot;</li><li>请求参数可改变顺序,目前只是对必需和非必需进行自动排序</li><li>用户头像上传问题txt改成jpg格式上传用户头像显示空白然后无法再次上传头像。无法再次上传的问题已经解决</li><li>解决用户头像改变但是header处图片不变的问题。问题描述用户上传头像成功但是Header处的头像没有改变并且点击其他页面后再回到个人中心里面的头像又变成没有重新上传时的图片必须重新刷新才可以将Header处的图片更新</li><li>解决导入 postman 接口动态路由无法导入的 Bug</li></ol>
<h3 class="subject" id="v1.2.0">v1.2.0 <a class="hashlink" href="#v1.2.0">#</a></h3><h4 class="subject" id="Features">Features <a class="hashlink" href="#Features">#</a></h4><ul>
<li>增加高级 Mock 期望功能,根据设置的请求过滤规则,返回期望数据。</li><li>增加统计功能</li><li>增加自动化测试功能,写断言脚本,实现精准测试</li></ul>
<h4 class="subject" id="Bug_Fixed">Bug Fixed <a class="hashlink" href="#Bug_Fixed">#</a></h4><ul>
<li>修复了切换集合环境的 Bug</li><li>修复了 mockServer 拿不到 Post 请求 Body</li><li>修复了接口调试 pathParams 无法使用 mock 参数和变量参数</li></ul>
<h3 class="subject" id="v1.1.2">v1.1.2 <a class="hashlink" href="#v1.1.2">#</a></h3><h4 class="subject" id="Features">Features <a class="hashlink" href="#Features">#</a></h4><ul>
<li>接口运行增加了 query 和 body 的 enable 选项,可选择是否请求该字段</li><li>Mock 支持了时间戳占位符 @timestamp</li><li>接口集运行页面可选择环境</li><li>接口集动态参数格式由原来的 $.{key}.{jsonPath} 改为 $.{key}.{body|params}.{jsonPath}</li></ul>
<h4 class="subject" id="Bug_Fixed">Bug Fixed <a class="hashlink" href="#Bug_Fixed">#</a></h4><ul>
<li>修复了接口集运行功能会忽略环境配置的 domain 路径</li><li>修复了动态路由 mock 返回结果不是该接口定义返回数据</li><li>修复了日志链接错误问题</li><li>修复了添加用户 loading 问题</li><li>修复了用户名编辑,前台未更新问题</li><li>修复了复制接口导致 GET 请求显示 request-body 问题</li><li>修复了接口集页面刷新后跳转到第一个接口集问题</li><li>修复了接口用例页面修改 header 参数值没有效果 bug</li><li>修复了接口集页面导入接口会导致 reqBody 清空 bug</li></ul>
<h3 class="subject" id="v1.1.1">v1.1.1 <a class="hashlink" href="#v1.1.1">#</a></h3><h4 class="subject" id="Features">Features <a class="hashlink" href="#Features">#</a></h4><ul>
<li>添加插件开发文档</li><li>接口和测试用例可拖动</li><li>优化动态提示</li></ul>
<h4 class="subject" id="Bug_Fixed">Bug Fixed <a class="hashlink" href="#Bug_Fixed">#</a></h4><ul>
<li>修复接口状态将接口方法重置为 get</li><li>环境配置域名带 path 无效</li><li>修复Swagger数据导入分类 bug</li><li>MockServer 支持 CORS 跨域</li><li>优化JSON-SCHEMA转化为JSON的逻辑由原来随机转换不被required字段改为转换全部字段</li><li>修复了项目成员无法看到该项目的Bug</li><li>修复了无法查看公共项目的Bug</li><li>优化了部分样式和交互</li></ul>
<h3 class="subject" id="v1.1.0">v1.1.0 <a class="hashlink" href="#v1.1.0">#</a></h3><h4 class="subject" id="Features">Features <a class="hashlink" href="#Features">#</a></h4><ul>
<li>新增个人空间功能,拥有这个分组的全部权限,可以在这个分组里探索 YApi 的功能</li><li>新增分组动态功能</li><li>优化接口运行页面交互</li><li>CrossRequest 扩展支持 https</li><li>增加了 Swagger 数据导入功能</li></ul>
<h3 class="subject" id="v1.0.2">v1.0.2 <a class="hashlink" href="#v1.0.2">#</a></h3><h4 class="subject" id="Features">Features <a class="hashlink" href="#Features">#</a></h4><ul>
<li>网站改为100%布局</li><li>优化搜索的提示</li><li>支持了 queryPath</li><li>接口浏览页面和编辑页面交互</li><li>新增高级 Mock 功能,可通过 js 代码去控制 mock 数据的生成</li><li>测试集支持了自动化测试</li><li>增加复制接口功能</li><li>在组长和开发者权限基础上,添加了 查看着 权限</li></ul>
<h3 class="subject" id="v1.0.1">v1.0.1 <a class="hashlink" href="#v1.0.1">#</a></h3><h4 class="subject" id="Fix_Bug">Fix Bug <a class="hashlink" href="#Fix_Bug">#</a></h4><ul>
<li>修改接口名字后,需要刷新页面左边的侧边栏才会显示正确的名字 </li><li>mockJson 出现 nullmock 出现格式不对问题 </li><li>没有权限的分组不可选 </li><li>项目列表图标设计大小优化下 </li><li>关注的项目不显眼 </li><li>添加接口之后,再次选择添加接口,会保留上次填写的信息 </li><li>用例名称太长,导致无法使用删除功能 </li><li>别人知道项目id虽然没有权限但能看到里面所有内容 </li></ul>
<h4 class="subject" id="Features">Features <a class="hashlink" href="#Features">#</a></h4><ul>
<li>接口备注集成了富文本编辑 </li><li>支持 har 协议的接口数据导入 </li></ul>
</div>
</div>
</div>
</div>
<footer class="footer">
<div class="copyright">
&copy; 2017 <a href="https://ymfe.org">YMFE</a> Team. Build by <a href="http://ued.qunar.com/ydoc/">ydoc</a>&nbsp;
</div>
</footer>
</div>
<div class="open-panel"></div>
<div class="mask"></div>
<script src="source/main.js"></script>
<script src="source/app.js"></script>
</body>
</html>

View File

@ -97,6 +97,10 @@
<nav class="docs-sidebar hidden-print hidden-xs hidden-sm">
<ul class="nav docs-sidenav">
<li >
<a href="#v1.3.6">v1.3.6</a>
</li>
<li >
<a href="#v1.3.5">v1.3.5</a>
</li>
@ -177,7 +181,9 @@
<div class="content-right markdown-body use-sidebar" role="main">
<h3 class="subject" id="v1.3.5">v1.3.5 <a class="hashlink" href="#v1.3.5">#</a></h3><h4 class="subject" id="Feature">Feature <a class="hashlink" href="#Feature">#</a></h4><ul>
<h3 class="subject" id="v1.3.6">v1.3.6 <a class="hashlink" href="#v1.3.6">#</a></h3><h4 class="subject" id="Feature">Feature <a class="hashlink" href="#Feature">#</a></h4><ul>
<li>增加项目成员批量导入</li></ul>
<h3 class="subject" id="v1.3.5">v1.3.5 <a class="hashlink" href="#v1.3.5">#</a></h3><h4 class="subject" id="Feature">Feature <a class="hashlink" href="#Feature">#</a></h4><ul>
<li>数据导入同步数据导入支持swagger 3.0</li><li>swagger 数据导入支持 2xx 的httpcode</li><li>新增系统信息页面</li></ul>
<h4 class="subject" id="Bug_Fixed">Bug Fixed <a class="hashlink" href="#Bug_Fixed">#</a></h4><ul>
<li>修复离开接口编辑页面的 confirm 框有时候会触发两次 &amp; confirm 的 X 按钮无效</li><li>修复添加集合后测试集合list不更新问题</li><li>测试集合点击对应接口侧边栏不切换</li><li>测试集合处,点击删除不成功</li><li>修改编辑接口后,再回到测试集合处数据不更新问题</li><li>修复mongodb帐号密码配置错误时引发的错误</li><li>修复删除分组后侧边数据没哟更新问题</li></ul>

View File

@ -0,0 +1,195 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no" />
<title>YApi : ./server/controllers/follow.js</title>
<link type="text/css" rel="stylesheet" href="../../../source/code.css"/>
<script type="text/javascript" src="../../../source/shCore.js"></script>
<script type="text/javascript" src="../../../source/shBrush-js.js"></script>
<style>
.syntaxhighlighter .number1 .spaces,.syntaxhighlighter .toolbar{ display: none;}
.syntaxhighlighter table td.gutter .line.highlight { background-color: #6ce26c !important; color: white; }
</style>
</head>
<body>
<div class="ydoc">
<div class="ydoc-banner-bg">
<div class="ydoc-banner" id="content" tabindex="-1">
<div class="ydoc-banner-area">
<h1>YApi : ./server/controllers/follow.js</h1>
<p>源代码</p>
</div>
</div>
<div class="ydoc-container">
<div class="ydoc-container-content">
<div class="static-code-content" role="main">
<pre class="brush: js;">
const yapi = require('../yapi.js');
const baseController = require('./base.js');
const followModel = require('../models/follow');
const projectModel = require('../models/project');
class followController extends baseController {
constructor(ctx) {
super(ctx);
this.Model = yapi.getInst(followModel);
this.projectModel = yapi.getInst(projectModel);
}
/**
* 获取关注项目列表
* @interface /follow/list
* @method GET
* @category follow
* @foldnumber 10
* @param {Number} [page] 分页页码
* @param {Number} [limit] 分页大小
* @returns {Object}
* @example /follow/list
*/
async list(ctx) {
let uid = this.getUid();
// 关注列表暂时不分页 page & limit 为分页配置
// page = ctx.request.query.page || 1,
// limit = ctx.request.query.limit || 10;
if (!uid) {
return ctx.body = yapi.commons.resReturn(null, 400, '用户id不能为空');
}
try {
let result = await this.Model.list(uid);
ctx.body = yapi.commons.resReturn({
list: result
});
} catch (err) {
ctx.body = yapi.commons.resReturn(null, 402, err.message);
}
}
/**
* 取消关注
* @interface /follow/del
* @method POST
* @category follow
* @foldnumber 10
* @param {Number} projectid
* @returns {Object}
* @example /follow/del
*/
async del(ctx) {
let params = ctx.request.body, uid = this.getUid();
if(!params.projectid){
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
}
let checkRepeat = await this.Model.checkProjectRepeat(uid,params.projectid);
if (checkRepeat == 0) {
return ctx.body = yapi.commons.resReturn(null, 401, '项目未关注');
}
try {
let result = await this.Model.del(params.projectid, this.getUid());
ctx.body = yapi.commons.resReturn(result);
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}
}
/**
* 添加关注
* @interface /follow/add
* @method GET
* @category follow
* @foldnumber 10
* @param {Number} projectid 项目id
* @param {String} projectname 项目名
* @param {String} icon 项目icon
* @returns {Object}
* @example /follow/add
*/
async add(ctx) {
let params = ctx.request.body;
params = yapi.commons.handleParams(params, {
projectid: 'number'
});
let uid = this.getUid();
if (!params.projectid) {
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
}
let checkRepeat = await this.Model.checkProjectRepeat(uid,params.projectid);
if (checkRepeat) {
return ctx.body = yapi.commons.resReturn(null, 401, '项目已关注');
}
try {
let project = await this.projectModel.get(params.projectid);
let data = {
uid: uid,
projectid: params.projectid,
projectname: project.name,
icon: project.icon,
color: project.color
};
let result = await this.Model.save(data);
result = yapi.commons.fieldSelect(result, ['_id', 'uid', 'projectid', 'projectname', 'icon', 'color']);
ctx.body = yapi.commons.resReturn(result);
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}
}
}
module.exports = followController;
</pre>
</div>
</div>
</div>
</div>
<!-- <div class="docs-header" id="content" tabindex="-1">
<div class="container">
<h1>YApi : ./server/controllers/follow.js</h1>
<p>源代码</p>
</div>
</div> -->
<footer class="docs-footer" role="contentinfo">
<div class="container">
<p></p>
</div>
</footer>
</div>
<script type="text/javascript">
SyntaxHighlighter.all();
function getTop(node){
return node.offsetTop + (node.offsetParent ? getTop(node.offsetParent) : 0);
}
document.addEventListener('DOMContentLoaded', function() {
setTimeout(function() {
try {
var lineNum = (parseInt(location.hash.replace(/#/g, '')) - 1) || 0,
node = document.querySelectorAll('div.line')[lineNum];
document.body.scrollTop = getTop(node);
node.className += ' highlight';
} catch(e) {}
}, 500);
}, false);
</script>
</body>
</html>

View File

@ -0,0 +1,556 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no" />
<title>YApi : ./server/controllers/group.js</title>
<link type="text/css" rel="stylesheet" href="../../../source/code.css"/>
<script type="text/javascript" src="../../../source/shCore.js"></script>
<script type="text/javascript" src="../../../source/shBrush-js.js"></script>
<style>
.syntaxhighlighter .number1 .spaces,.syntaxhighlighter .toolbar{ display: none;}
.syntaxhighlighter table td.gutter .line.highlight { background-color: #6ce26c !important; color: white; }
</style>
</head>
<body>
<div class="ydoc">
<div class="ydoc-banner-bg">
<div class="ydoc-banner" id="content" tabindex="-1">
<div class="ydoc-banner-area">
<h1>YApi : ./server/controllers/group.js</h1>
<p>源代码</p>
</div>
</div>
<div class="ydoc-container">
<div class="ydoc-container-content">
<div class="static-code-content" role="main">
<pre class="brush: js;">
const groupModel = require('../models/group.js');
const yapi = require('../yapi.js');
const baseController = require('./base.js');
const projectModel = require('../models/project.js');
const userModel = require('../models/user.js');
const interfaceModel = require('../models/interface.js');
const interfaceColModel = require('../models/interfaceCol.js');
const interfaceCaseModel = require('../models/interfaceCase.js');
const rolename = {
owner: "组长",
dev: "开发者",
guest: "访客"
};
class groupController extends baseController {
constructor(ctx) {
super(ctx);
const id = 'number';
const group_name = {
type: 'string',
minLength: 1
};
const group_desc = 'string';
const role = {
type: "string",
enum: ["owner", "dev", "guest"]
}
const member_uids = {
type: "array",
items: 'number',
minItems: 1
}
this.schemaMap = {
get: {
"*id": id
},
add: {
"*group_name": group_name,
"group_desc": group_desc,
"owner_uids": ['number']
},
addMember: {
"*id": id,
"role": role,
"*member_uids": member_uids
},
changeMemberRole: {
"*member_uid": "number",
"*id": id,
role: role
},
getMemberList: {
"*id": id
},
delMember: {
"*id": id,
"*member_uid": "number"
},
del: {
"*id": id
},
up: {
"*id": id,
"*group_name": group_name,
"group_desc": group_desc,
"custom_field1": {
name: 'string',
enable: 'boolen'
},
"custom_field2": {
name: 'string',
enable: 'boolen'
},
"custom_field3": {
name: 'string',
enable: 'boolen'
}
}
}
}
/**
* 查询项目分组
* @interface /group/get
* @method GET
* @category group
* @foldnumber 10
* @param {String} id 项目分组ID
* @returns {Object}
* @example
*/
async get(ctx) {
let params = ctx.params;
let groupInst = yapi.getInst(groupModel);
let result = await groupInst.getGroupById(params.id);
result = result.toObject();
result.role = await this.getProjectRole(params.id, 'group');
if (result.type === 'private') {
result.group_name = '个人空间';
}
ctx.body = yapi.commons.resReturn(result);
}
/**
* 添加项目分组
* @interface /group/add
* @method POST
* @category group
* @foldnumber 10
* @param {String} group_name 项目分组名称,不能为空
* @param {String} [group_desc] 项目分组描述
* @param {String} [owner_uids] 组长[uid]
* @returns {Object}
* @example ./api/group/add.json
*/
async add(ctx) {
let params = ctx.params;
if (this.getRole() !== 'admin') {
return ctx.body = yapi.commons.resReturn(null, 401, '没有权限');
}
let owners = [];
if (params.owner_uids) {
for (let i = 0, len = params.owner_uids.length; i < len; i++) {
let id = params.owner_uids[i]
let groupUserdata = await this.getUserdata(id, 'owner');
if (groupUserdata) {
owners.push(groupUserdata)
}
}
}
let groupInst = yapi.getInst(groupModel);
let checkRepeat = await groupInst.checkRepeat(params.group_name);
if (checkRepeat > 0) {
return ctx.body = yapi.commons.resReturn(null, 401, '项目分组名已存在');
}
let data = {
group_name: params.group_name,
group_desc: params.group_desc,
uid: this.getUid(),
add_time: yapi.commons.time(),
up_time: yapi.commons.time(),
members: owners
};
let result = await groupInst.save(data);
result = yapi.commons.fieldSelect(result, ['_id', 'group_name', 'group_desc', 'uid', 'members', 'type']);
let username = this.getUsername();
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 新增了分组 <a href="/group/${result._id}">${params.group_name}</a>`,
type: 'group',
uid: this.getUid(),
username: username,
typeid: result._id
});
ctx.body = yapi.commons.resReturn(result);
}
/**
* 获取用户数据
* @param uid
* @param role
* @returns {Promise.<*>}
*/
async getUserdata(uid, role) {
role = role || 'dev';
let userInst = yapi.getInst(userModel);
let userData = await userInst.findById(uid);
if (!userData) {
return null;
}
return {
_role: userData.role,
role: role,
uid: userData._id,
username: userData.username,
email: userData.email
}
}
/**
* 添加项目分组成员
* @interface /group/add_member
* @method POST
* @category group
* @foldnumber 10
* @param {String} id 项目分组id
* @param {String} member_uids 项目分组成员[uid]
* @param {String} role 成员角色owner or dev or guest
* @returns {Object}
* @example
*/
async addMember(ctx) {
let params = ctx.params;
let groupInst = yapi.getInst(groupModel);
params.role = ['owner', 'dev', 'guest'].find(v => v === params.role) || 'dev';
let add_members = [];
let exist_members = [];
let no_members = []
for (let i = 0, len = params.member_uids.length; i < len; i++) {
let id = params.member_uids[i];
let check = await groupInst.checkMemberRepeat(params.id, id);
let userdata = await this.getUserdata(id, params.role);
if (check > 0) {
exist_members.push(userdata)
} else if (!userdata) {
no_members.push(id)
} else {
userdata.role !== 'admin' && add_members.push(userdata);
delete userdata._role;
}
}
let result = await groupInst.addMember(params.id, add_members);
let username = this.getUsername();
if (add_members.length) {
let members = add_members.map((item) => {
return `<a href = "/user/profile/${item.uid}">${item.username}</a>`
})
members = members.join("、");
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 新增了分组成员 ${members} 为 ${rolename[params.role]}`,
type: 'group',
uid: this.getUid(),
username: username,
typeid: params.id
});
}
ctx.body = yapi.commons.resReturn({
result,
add_members,
exist_members,
no_members
});
}
/**
* 修改项目分组成员角色
* @interface /group/change_member_role
* @method POST
* @category group
* @foldnumber 10
* @param {String} id 项目分组id
* @param {String} member_uid 项目分组成员uid
* @param {String} role 权限 ['owner'|'dev']
* @returns {Object}
* @example
*/
async changeMemberRole(ctx) {
let params = ctx.request.body;
let groupInst = yapi.getInst(groupModel);
var check = await groupInst.checkMemberRepeat(params.id, params.member_uid);
if (check === 0) {
return ctx.body = yapi.commons.resReturn(null, 400, '分组成员不存在');
}
if (await this.checkAuth(params.id, 'group', 'danger') !== true) {
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
}
params.role = ['owner', 'dev', 'guest'].find(v => v === params.role) || 'dev';
let result = await groupInst.changeMemberRole(params.id, params.member_uid, params.role);
let username = this.getUsername();
let groupUserdata = await this.getUserdata(params.member_uid, params.role);
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 更改了分组成员 <a href="/user/profile/${params.member_uid}">${groupUserdata.username}</a> 的权限为 "${rolename[params.role]}"`,
type: 'group',
uid: this.getUid(),
username: username,
typeid: params.id
});
ctx.body = yapi.commons.resReturn(result);
}
/**
* 获取所有项目成员
* @interface /group/get_member_list
* @method GET
* @category group
* @foldnumber 10
* @param {String} id 项目分组id
* @returns {Object}
* @example
*/
async getMemberList(ctx) {
let params = ctx.params;
let groupInst = yapi.getInst(groupModel);
let group = await groupInst.get(params.id);
ctx.body = yapi.commons.resReturn(group.members);
}
/**
* 删除项目成员
* @interface /group/del_member
* @method POST
* @category group
* @foldnumber 10
* @param {String} id 项目分组id
* @param {String} member_uid 项目分组成员uid
* @returns {Object}
* @example
*/
async delMember(ctx) {
let params = ctx.params;
let groupInst = yapi.getInst(groupModel);
var check = await groupInst.checkMemberRepeat(params.id, params.member_uid);
if (check === 0) {
return ctx.body = yapi.commons.resReturn(null, 400, '分组成员不存在');
}
if (await this.checkAuth(params.id, 'group', 'danger') !== true) {
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
}
let result = await groupInst.delMember(params.id, params.member_uid);
let username = this.getUsername();
let groupUserdata = await this.getUserdata(params.member_uid, params.role);
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 删除了分组成员 <a href="/user/profile/${params.member_uid}">${groupUserdata.username}</a>`,
type: 'group',
uid: this.getUid(),
username: username,
typeid: params.id
});
ctx.body = yapi.commons.resReturn(result);
}
/**
* 获取项目分组列表
* @interface /group/list
* @method get
* @category group
* @foldnumber 10
* @returns {Object}
* @example ./api/group/list.json
*/
async list(ctx) {
var groupInst = yapi.getInst(groupModel);
let projectInst = yapi.getInst(projectModel);
let result = await groupInst.list();
let privateGroup = await groupInst.getByPrivateUid(this.getUid());
let newResult = [];
if (!privateGroup) {
privateGroup = await groupInst.save({
uid: this.getUid(),
group_name: 'User-' + this.getUid(),
add_time: yapi.commons.time(),
up_time: yapi.commons.time(),
type: 'private'
})
}
if (result && result.length > 0) {
for (let i = 0; i < result.length; i++) {
result[i] = result[i].toObject();
result[i].role = await this.getProjectRole(result[i]._id, 'group');
if (result[i].role !== 'member') {
newResult.unshift(result[i]);
} else {
let publicCount = await projectInst.countWithPublic(result[i]._id);
if (publicCount > 0) {
newResult.push(result[i]);
} else {
let projectCountWithAuth = await projectInst.getProjectWithAuth(result[i]._id, this.getUid());
if (projectCountWithAuth > 0) {
newResult.push(result[i]);
}
}
}
}
}
if (privateGroup) {
privateGroup = privateGroup.toObject();
privateGroup.group_name = '个人空间';
privateGroup.role = 'owner';
newResult.unshift(privateGroup);
}
ctx.body = yapi.commons.resReturn(newResult);
}
/**
* 删除项目分组
* @interface /group/del
* @method post
* @param {String} id 项目分组id
* @category group
* @foldnumber 10
* @returns {Object}
* @example ./api/group/del.json
*/
async del(ctx) {
if (this.getRole() !== 'admin') {
return ctx.body = yapi.commons.resReturn(null, 401, '没有权限');
}
let groupInst = yapi.getInst(groupModel);
let projectInst = yapi.getInst(projectModel);
let interfaceInst = yapi.getInst(interfaceModel);
let interfaceColInst = yapi.getInst(interfaceColModel);
let interfaceCaseInst = yapi.getInst(interfaceCaseModel);
let id = ctx.params.id;
let projectList = await projectInst.list(id, true);
projectList.forEach(async (p) => {
await interfaceInst.delByProjectId(p._id)
await interfaceCaseInst.delByProjectId(p._id)
await interfaceColInst.delByProjectId(p._id)
})
if (projectList.length > 0) {
await projectInst.delByGroupid(id);
}
let result = await groupInst.del(id);
ctx.body = yapi.commons.resReturn(result);
}
/**
* 更新项目分组
* @interface /group/up
* @method post
* @param {String} id 项目分组id
* @param {String} group_name 项目分组名称
* @param {String} group_desc 项目分组描述
* @category group
* @foldnumber 10
* @returns {Object}
* @example ./api/group/up.json
*/
async up(ctx) {
let groupInst = yapi.getInst(groupModel);
let params = ctx.params;
if (await this.checkAuth(params.id, 'group', 'danger') !== true) {
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
}
let result = await groupInst.up(params.id, params);
let username = this.getUsername();
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 更新了 <a href="/group/${params.id}">${params.group_name}</a> 分组`,
type: 'group',
uid: this.getUid(),
username: username,
typeid: params.id
});
ctx.body = yapi.commons.resReturn(result);
}
}
module.exports = groupController;
</pre>
</div>
</div>
</div>
</div>
<!-- <div class="docs-header" id="content" tabindex="-1">
<div class="container">
<h1>YApi : ./server/controllers/group.js</h1>
<p>源代码</p>
</div>
</div> -->
<footer class="docs-footer" role="contentinfo">
<div class="container">
<p></p>
</div>
</footer>
</div>
<script type="text/javascript">
SyntaxHighlighter.all();
function getTop(node){
return node.offsetTop + (node.offsetParent ? getTop(node.offsetParent) : 0);
}
document.addEventListener('DOMContentLoaded', function() {
setTimeout(function() {
try {
var lineNum = (parseInt(location.hash.replace(/#/g, '')) - 1) || 0,
node = document.querySelectorAll('div.line')[lineNum];
document.body.scrollTop = getTop(node);
node.className += ' highlight';
} catch(e) {}
}, 500);
}, false);
</script>
</body>
</html>

View File

@ -0,0 +1,971 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no" />
<title>YApi : ./server/controllers/interface.js</title>
<link type="text/css" rel="stylesheet" href="../../../source/code.css"/>
<script type="text/javascript" src="../../../source/shCore.js"></script>
<script type="text/javascript" src="../../../source/shBrush-js.js"></script>
<style>
.syntaxhighlighter .number1 .spaces,.syntaxhighlighter .toolbar{ display: none;}
.syntaxhighlighter table td.gutter .line.highlight { background-color: #6ce26c !important; color: white; }
</style>
</head>
<body>
<div class="ydoc">
<div class="ydoc-banner-bg">
<div class="ydoc-banner" id="content" tabindex="-1">
<div class="ydoc-banner-area">
<h1>YApi : ./server/controllers/interface.js</h1>
<p>源代码</p>
</div>
</div>
<div class="ydoc-container">
<div class="ydoc-container-content">
<div class="static-code-content" role="main">
<pre class="brush: js;">
const interfaceModel = require('../models/interface.js');
const interfaceCatModel = require('../models/interfaceCat.js');
const interfaceCaseModel = require('../models/interfaceCase.js');
const followModel = require('../models/follow.js');
const groupModel = require('../models/group.js')
const _ = require('underscore');
const url = require('url');
const baseController = require('./base.js');
const yapi = require('../yapi.js');
const userModel = require('../models/user.js');
const projectModel = require('../models/project.js');
const jsondiffpatch = require('jsondiffpatch')
const formattersHtml = jsondiffpatch.formatters.html;
const showDiffMsg = require('../../common/diff-view.js');
const fs = require('fs-extra')
const path = require('path');
// const annotatedCss = require("jsondiffpatch/public/formatters-styles/annotated.css");
// const htmlCss = require("jsondiffpatch/public/formatters-styles/html.css");
class interfaceController extends baseController {
constructor(ctx) {
super(ctx);
this.Model = yapi.getInst(interfaceModel);
this.catModel = yapi.getInst(interfaceCatModel);
this.projectModel = yapi.getInst(projectModel);
this.caseModel = yapi.getInst(interfaceCaseModel);
this.followModel = yapi.getInst(followModel);
this.userModel = yapi.getInst(userModel);
this.groupModel = yapi.getInst(groupModel);
const minLengthStringField = {
type: 'string',
minLength: 1
}
const addAndUpCommonField = {
'desc': 'string',
'status': 'string',
req_query: [{
name: 'string',
value: 'string',
example: 'string',
desc: 'string',
required: 'string'
}],
req_headers: [{
name: 'string',
value: 'string',
example: 'string',
desc: 'string',
required: 'string'
}],
req_body_type: 'string',
req_params: [{
name: 'string',
example: 'string',
desc: 'string'
}],
req_body_form: [{
name: 'string',
type: {
type: 'string'
},
example: 'string',
desc: 'string',
required: 'string'
}],
'req_body_other': 'string',
res_body_type: 'string',
res_body: 'string',
custom_field_value: 'string'
}
this.schemaMap = {
add: Object.assign({
'*project_id': 'number',
'*path': minLengthStringField,
'*title': minLengthStringField,
'*method': minLengthStringField,
'*catid': 'number'
}, addAndUpCommonField),
up: Object.assign({
'*id': 'number',
'project_id': 'number',
'path': minLengthStringField,
'title': minLengthStringField,
'method': minLengthStringField,
'catid': 'number',
'switch_notice': 'boolean',
'message': minLengthStringField
}, addAndUpCommonField),
save: Object.assign({
'project_id': 'number',
'catid': 'number',
'title': minLengthStringField,
'path': minLengthStringField,
'method': minLengthStringField,
'message': minLengthStringField
}, addAndUpCommonField)
}
}
/**
* 添加项目分组
* @interface /interface/add
* @method POST
* @category interface
* @foldnumber 10
* @param {Number} project_id 项目id不能为空
* @param {String} title 接口标题,不能为空
* @param {String} path 接口请求路径,不能为空
* @param {String} method 请求方式
* @param {Array} [req_headers] 请求的header信息
* @param {String} [req_headers[].name] 请求的header信息名
* @param {String} [req_headers[].value] 请求的header信息值
* @param {Boolean} [req_headers[].required] 是否是必须,默认为否
* @param {String} [req_headers[].desc] header描述
* @param {String} [req_body_type] 请求参数方式,有["form", "json", "text", "xml"]四种
* @param {Array} [req_params] name, desc两个参数
* @param {Mixed} [req_body_form] 请求参数,如果请求方式是form参数是Array数组其他格式请求参数是字符串
* @param {String} [req_body_form[].name] 请求参数名
* @param {String} [req_body_form[].value] 请求参数值可填写生成规则mock。如@email随机生成一条email
* @param {String} [req_body_form[].type] 请求参数类型,有["text", "file"]两种
* @param {String} [req_body_other] 非form类型的请求参数可保存到此字段
* @param {String} [res_body_type] 相应信息的数据格式,有["json", "text", "xml"]三种
* @param {String} [res_body] 响应信息可填写任意字符串如果res_body_type是json,则会调用mock功能
* @param {String} [desc] 接口描述
* @returns {Object}
* @example ./api/interface/add.json
*/
async add(ctx) {
let params = ctx.params;
let auth = await this.checkAuth(params.project_id, 'project', 'edit')
if (!auth) {
return ctx.body = yapi.commons.resReturn(null, 40033, '没有权限');
}
params.method = params.method || 'GET';
params.method = params.method.toUpperCase();
params.req_params = params.req_params || [];
params.res_body_type = params.res_body_type ? params.res_body_type.toLowerCase() : 'json';
let http_path = url.parse(params.path, true);
if (!yapi.commons.verifyPath(http_path.pathname)) {
return ctx.body = yapi.commons.resReturn(null, 400, 'path第一位必需为 /, 只允许由 字母数字-/_:.! 组成');
}
params.query_path = {};
params.query_path.path = http_path.pathname;
params.query_path.params = [];
Object.keys(http_path.query).forEach((item) => {
params.query_path.params.push({
name: item,
value: http_path.query[item]
})
})
let checkRepeat = await this.Model.checkRepeat(params.project_id, params.path, params.method);
if (checkRepeat > 0) {
return ctx.body = yapi.commons.resReturn(null, 40022, '已存在的接口:' + params.path + '[' + params.method + ']');
}
let data = Object.assign(params, {
uid: this.getUid(),
add_time: yapi.commons.time(),
up_time: yapi.commons.time()
});
yapi.commons.handleVarPath(params.path, params.req_params);
if (params.req_params.length > 0) {
data.type = 'var'
data.req_params = params.req_params;
} else {
data.type = 'static'
}
let result = await this.Model.save(data);
yapi.emitHook('interface_add', result._id).then();
this.catModel.get(params.catid).then((cate) => {
let username = this.getUsername();
let title = `<a href="/user/profile/${this.getUid()}">${username}</a> 为分类 <a href="/project/${params.project_id}/interface/api/cat_${params.catid}">${cate.name}</a> 添加了接口 <a href="/project/${params.project_id}/interface/api/${result._id}">${data.title}</a> `
yapi.commons.saveLog({
content: title,
type: 'project',
uid: this.getUid(),
username: username,
typeid: params.project_id
});
this.projectModel.up(params.project_id, { up_time: new Date().getTime() }).then();
});
ctx.body = yapi.commons.resReturn(result);
}
/**
* 保存接口数据,如果接口存在则更新数据,如果接口不存在则添加数据
* @interface /interface/save
* @method post
* @category interface
* @foldnumber 10
* @param {Number} project_id 项目id不能为空
* @param {String} title 接口标题,不能为空
* @param {String} path 接口请求路径,不能为空
* @param {String} method 请求方式
* @param {Array} [req_headers] 请求的header信息
* @param {String} [req_headers[].name] 请求的header信息名
* @param {String} [req_headers[].value] 请求的header信息值
* @param {Boolean} [req_headers[].required] 是否是必须,默认为否
* @param {String} [req_headers[].desc] header描述
* @param {String} [req_body_type] 请求参数方式,有["form", "json", "text", "xml"]四种
* @param {Array} [req_params] name, desc两个参数
* @param {Mixed} [req_body_form] 请求参数,如果请求方式是form参数是Array数组其他格式请求参数是字符串
* @param {String} [req_body_form[].name] 请求参数名
* @param {String} [req_body_form[].value] 请求参数值可填写生成规则mock。如@email随机生成一条email
* @param {String} [req_body_form[].type] 请求参数类型,有["text", "file"]两种
* @param {String} [req_body_other] 非form类型的请求参数可保存到此字段
* @param {String} [res_body_type] 相应信息的数据格式,有["json", "text", "xml"]三种
* @param {String} [res_body] 响应信息可填写任意字符串如果res_body_type是json,则会调用mock功能
* @param {String} [desc] 接口描述
* @returns {Object}
*/
async save(ctx) {
let params = ctx.params;
let auth = await this.checkAuth(params.project_id, 'project', 'edit')
if (!auth) {
return ctx.body = yapi.commons.resReturn(null, 40033, '没有权限');
}
params.method = params.method || 'GET';
params.method = params.method.toUpperCase();
let http_path = url.parse(params.path, true);
if (!yapi.commons.verifyPath(http_path.pathname)) {
return ctx.body = yapi.commons.resReturn(null, 400, 'path第一位必需为 /, 只允许由 字母数字-/_:.! 组成');
}
let result = await this.Model.getByPath(params.project_id, params.path, params.method, '_id');
if (result.length > 0) {
result.forEach(async item => {
params.id = item._id;
// console.log(this.schemaMap['up'])
let validResult = yapi.commons.validateParams(this.schemaMap['up'], params);
if (validResult.valid) {
let data = {};
data.params = params
await this.up(data)
} else {
return ctx.body = yapi.commons.resReturn(null, 400, validResult.message);
}
})
} else {
let validResult = yapi.commons.validateParams(this.schemaMap['add'], params);
if (validResult.valid) {
let data = {};
data.params = params
await this.add(data)
} else {
return ctx.body = yapi.commons.resReturn(null, 400, validResult.message);
}
}
ctx.body = yapi.commons.resReturn(result);
// return ctx.body = yapi.commons.resReturn(null, 400, 'path第一位必需为 /, 只允许由 字母数字-/_:.! 组成');
}
/**
* 获取项目分组
* @interface /interface/get
* @method GET
* @category interface
* @foldnumber 10
* @param {Number} id 接口id不能为空
* @returns {Object}
* @example ./api/interface/get.json
*/
async get(ctx) {
let params = ctx.request.query;
if (!params.id) {
return ctx.body = yapi.commons.resReturn(null, 400, '接口id不能为空');
}
try {
let result = await this.Model.get(params.id);
// console.log('result', result);
if (!result) {
return ctx.body = yapi.commons.resReturn(null, 490, '不存在的');
}
let userinfo = await this.userModel.findById(result.uid);
let project = await this.projectModel.getBaseInfo(result.project_id);
if (project.project_type === 'private') {
if (await this.checkAuth(project._id, 'project', 'view') !== true) {
return ctx.body = yapi.commons.resReturn(null, 406, '没有权限');
}
}
yapi.emitHook('interface_get', params.id).then();
result = result.toObject();
if (userinfo) {
result.username = userinfo.username;
}
ctx.body = yapi.commons.resReturn(result);
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}
}
/**
* 接口列表
* @interface /interface/list
* @method GET
* @category interface
* @foldnumber 10
* @param {Number} project_id 项目id不能为空
* @returns {Object}
* @example ./api/interface/list.json
*/
async list(ctx) {
let project_id = ctx.request.query.project_id;
let project = await this.projectModel.getBaseInfo(project_id);
if (!project) {
return ctx.body = yapi.commons.resReturn(null, 407, '不存在的项目');
}
if (project.project_type === 'private') {
if (await this.checkAuth(project._id, 'project', 'view') !== true) {
return ctx.body = yapi.commons.resReturn(null, 406, '没有权限');
}
}
if (!project_id) {
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
}
try {
let result = await this.Model.list(project_id);
ctx.body = yapi.commons.resReturn(result);
yapi.emitHook('interface_list', project_id).then();
} catch (err) {
ctx.body = yapi.commons.resReturn(null, 402, err.message);
}
}
async downloadCrx(ctx) {
let filename = 'crossRequest.zip';
let dataBuffer = yapi.fs.readFileSync(yapi.path.join(yapi.WEBROOT, 'static/attachment/cross-request.zip'));
ctx.set('Content-disposition', 'attachment; filename=' + filename);
ctx.set('Content-Type', 'application/zip');
ctx.body = dataBuffer;
}
async listByCat(ctx) {
let catid = ctx.request.query.catid;
if (!catid) {
return ctx.body = yapi.commons.resReturn(null, 400, 'catid不能为空');
}
try {
let catdata = await this.catModel.get(catid);
let project = await this.projectModel.getBaseInfo(catdata.project_id);
if (project.project_type === 'private') {
if (await this.checkAuth(project._id, 'project', 'view') !== true) {
return ctx.body = yapi.commons.resReturn(null, 406, '没有权限');
}
}
let result = await this.Model.listByCatid(catid)
ctx.body = yapi.commons.resReturn(result);
} catch (err) {
ctx.body = yapi.commons.resReturn(null, 402, err.message);
}
}
async listByMenu(ctx) {
let project_id = ctx.request.query.project_id;
if (!project_id) {
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
}
let project = await this.projectModel.getBaseInfo(project_id);
if (!project) {
return ctx.body = yapi.commons.resReturn(null, 406, '不存在的项目');
}
if (project.project_type === 'private') {
if (await this.checkAuth(project._id, 'project', 'view') !== true) {
return ctx.body = yapi.commons.resReturn(null, 406, '没有权限');
}
}
try {
let result = await this.catModel.list(project_id), newResult = [];
for (let i = 0, item, list; i < result.length; i++) {
item = result[i].toObject()
list = await this.Model.listByCatid(item._id)
for (let j = 0; j < list.length; j++) {
list[j] = list[j].toObject()
}
item.list = list;
newResult[i] = item
}
ctx.body = yapi.commons.resReturn(newResult);
} catch (err) {
ctx.body = yapi.commons.resReturn(null, 402, err.message);
}
}
/**
* 编辑接口
* @interface /interface/up
* @method POST
* @category interface
* @foldnumber 10
* @param {Number} id 接口id不能为空
* @param {String} [path] 接口请求路径
* @param {String} [method] 请求方式
* @param {Array} [req_headers] 请求的header信息
* @param {String} [req_headers[].name] 请求的header信息名
* @param {String} [req_headers[].value] 请求的header信息值
* @param {Boolean} [req_headers[].required] 是否是必须,默认为否
* @param {String} [req_headers[].desc] header描述
* @param {String} [req_body_type] 请求参数方式,有["form", "json", "text", "xml"]四种
* @param {Mixed} [req_body_form] 请求参数,如果请求方式是form参数是Array数组其他格式请求参数是字符串
* @param {String} [req_body_form[].name] 请求参数名
* @param {String} [req_body_form[].value] 请求参数值可填写生成规则mock。如@email随机生成一条email
* @param {String} [req_body_form[].type] 请求参数类型,有["text", "file"]两种
* @param {String} [req_body_other] 非form类型的请求参数可保存到此字段
* @param {String} [res_body_type] 相应信息的数据格式,有["json", "text", "xml"]三种
* @param {String} [res_body] 响应信息可填写任意字符串如果res_body_type是json,则会调用mock功能
* @param {String} [desc] 接口描述
* @returns {Object}
* @example ./api/interface/up.json
*/
async up(ctx) {
let params = ctx.params;
if (!_.isUndefined(params.method)) {
params.method = params.method || 'GET';
params.method = params.method.toUpperCase();
}
let id = params.id;
params.message = params.message || '';
params.message = params.message.replace(/\n/g, "<br>")
let interfaceData = await this.Model.get(id);
if (!interfaceData) {
return ctx.body = yapi.commons.resReturn(null, 400, '不存在的接口');
}
let auth = await this.checkAuth(interfaceData.project_id, 'project', 'edit')
if (!auth) {
return ctx.body = yapi.commons.resReturn(null, 400, '没有权限');
}
let data = Object.assign({
up_time: yapi.commons.time()
}, params);
if (params.path) {
let http_path = url.parse(params.path, true);
if (!yapi.commons.verifyPath(http_path.pathname)) {
return ctx.body = yapi.commons.resReturn(null, 400, 'path第一位必需为 /, 只允许由 字母数字-/_:.! 组成');
}
params.query_path = {};
params.query_path.path = http_path.pathname;
params.query_path.params = [];
Object.keys(http_path.query).forEach((item) => {
params.query_path.params.push({
name: item,
value: http_path.query[item]
})
})
data.query_path = params.query_path
}
if (params.path && (params.path !== interfaceData.path || params.method !== interfaceData.method)) {
let checkRepeat = await this.Model.checkRepeat(interfaceData.project_id, params.path, params.method);
if (checkRepeat > 0) {
return ctx.body = yapi.commons.resReturn(null, 401, '已存在的接口:' + params.path + '[' + params.method + ']');
}
}
if (!_.isUndefined(data.req_params)) {
if (Array.isArray(data.req_params) && data.req_params.length > 0) {
data.type = 'var'
} else {
data.type = 'static'
data.req_params = [];
}
}
let result = await this.Model.up(id, data);
let username = this.getUsername();
let CurrentInterfaceData = await this.Model.get(id);
let logData = {
interface_id: id,
cat_id: data.catid,
current: CurrentInterfaceData.toObject(),
old: interfaceData.toObject()
}
this.catModel.get(interfaceData.catid).then((cate) => {
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a>
更新了分类 <a href="/project/${cate.project_id}/interface/api/cat_${data.catid}">${cate.name}</a>
下的接口 <a href="/project/${cate.project_id}/interface/api/${id}">${interfaceData.title}</a><p>${params.message}</p>`,
type: 'project',
uid: this.getUid(),
username: username,
typeid: cate.project_id,
data: logData
});
});
this.projectModel.up(interfaceData.project_id, { up_time: new Date().getTime() }).then();
if (params.switch_notice === true) {
let diffView = showDiffMsg(jsondiffpatch, formattersHtml, logData);
let annotatedCss = fs.readFileSync(path.resolve(yapi.WEBROOT, 'node_modules/jsondiffpatch/public/formatters-styles/annotated.css'), 'utf8');
let htmlCss = fs.readFileSync(path.resolve(yapi.WEBROOT, 'node_modules/jsondiffpatch/public/formatters-styles/html.css'), 'utf8');
let project = await this.projectModel.getBaseInfo(interfaceData.project_id);
let interfaceUrl = `http://${ctx.request.host}/project/${interfaceData.project_id}/interface/api/${id}`
this.sendNotice(interfaceData.project_id, {
title: `${username} 更新了接口`,
content: `<html>
<head>
<style>
${annotatedCss}
${htmlCss}
</style>
</head>
<body>
<div><h3>${username}更新了接口(${data.title})</h3>
<p>项目名:${project.name} </p>
<p>修改用户: ${username}</p>
<p>接口名: <a href="${interfaceUrl}">${data.title}</a></p>
<p>接口路径: [${data.method}]${data.path}</p>
<p>详细改动日志: ${this.diffHTML(diffView)}</p></div>
</body>
</html>`
})
}
yapi.emitHook('interface_update', id).then();
ctx.body = yapi.commons.resReturn(result);
return 1;
}
diffHTML(html) {
if (html.length === 0) {
return `<span style="color: #555">没有改动该操作未改动Api数据</span>`
}
return html.map(item => {
return (`<div>
<h4 class="title">${item.title}</h4>
<div>${item.content}</div>
</div>`)
})
}
/**
* 删除接口
* @interface /interface/del
* @method GET
* @category interface
* @foldnumber 10
* @param {Number} id 接口id不能为空
* @returns {Object}
* @example ./api/interface/del.json
*/
async del(ctx) {
try {
let id = ctx.request.body.id;
if (!id) {
return ctx.body = yapi.commons.resReturn(null, 400, '接口id不能为空');
}
let data = await this.Model.get(ctx.request.body.id);
if (data.uid != this.getUid()) {
let auth = await this.checkAuth(data.project_id, 'project', 'danger')
if (!auth) {
return ctx.body = yapi.commons.resReturn(null, 400, '没有权限');
}
}
let inter = await this.Model.get(id);
let result = await this.Model.del(id);
yapi.emitHook('interface_del', id).then();
await this.caseModel.delByInterfaceId(id);
let username = this.getUsername();
this.catModel.get(inter.catid).then((cate) => {
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 删除了分类 <a href="/project/${cate.project_id}/interface/api/cat_${inter.catid}">${cate.name}</a> 下的接口 "${inter.title}"`,
type: 'project',
uid: this.getUid(),
username: username,
typeid: cate.project_id
});
})
this.projectModel.up(data.project_id, { up_time: new Date().getTime() }).then();
ctx.body = yapi.commons.resReturn(result);
} catch (err) {
ctx.body = yapi.commons.resReturn(null, 402, err.message);
}
}
async solveConflict(ctx) {
try {
let id = parseInt(ctx.query.id, 10), result, userInst, userinfo, data;
if (!id) return ctx.websocket.send("id 参数有误");
result = await this.Model.get(id);
if (result.edit_uid !== 0 && result.edit_uid !== this.getUid()) {
userInst = yapi.getInst(userModel);
userinfo = await userInst.findById(result.edit_uid);
data = {
errno: result.edit_uid,
data: { uid: result.edit_uid, username: userinfo.username }
}
} else {
this.Model.upEditUid(id, this.getUid()).then()
data = {
errno: 0,
data: result
}
}
ctx.websocket.send(JSON.stringify(data));
ctx.websocket.on('close', () => {
this.Model.upEditUid(id, 0).then()
})
} catch (err) {
yapi.commons.log(err, 'error')
}
}
async addCat(ctx) {
try {
let params = ctx.request.body;
params = yapi.commons.handleParams(params, {
name: 'string',
project_id: 'number',
desc: 'string'
});
if (!params.project_id) {
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
}
let auth = await this.checkAuth(params.project_id, 'project', 'edit')
if (!auth) {
return ctx.body = yapi.commons.resReturn(null, 400, '没有权限');
}
if (!params.name) {
return ctx.body = yapi.commons.resReturn(null, 400, '名称不能为空');
}
let result = await this.catModel.save({
name: params.name,
project_id: params.project_id,
desc: params.desc,
uid: this.getUid(),
add_time: yapi.commons.time(),
up_time: yapi.commons.time()
})
let username = this.getUsername();
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 添加了分类 <a href="/project/${params.project_id}/interface/api/cat_${result._id}">${params.name}</a>`,
type: 'project',
uid: this.getUid(),
username: username,
typeid: params.project_id
});
ctx.body = yapi.commons.resReturn(result);
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}
}
async upCat(ctx) {
try {
let params = ctx.request.body;
let result = await this.catModel.up(params.catid, {
name: params.name,
desc: params.desc,
up_time: yapi.commons.time()
});
let username = this.getUsername();
let cate = await this.catModel.get(params.catid);
let auth = await this.checkAuth(cate.project_id, 'project', 'edit')
if (!auth) {
return ctx.body = yapi.commons.resReturn(null, 400, '没有权限');
}
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 更新了分类 <a href="/project/${cate.project_id}/interface/api/cat_${params.catid}">${cate.name}</a>`,
type: 'project',
uid: this.getUid(),
username: username,
typeid: cate.project_id
});
ctx.body = yapi.commons.resReturn(result)
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 400, e.message)
}
}
async delCat(ctx) {
try {
let id = ctx.request.body.catid;
let catData = await this.catModel.get(id);
if (!catData) {
ctx.body = yapi.commons.resReturn(null, 400, "不存在的分类")
}
if (catData.uid !== this.getUid()) {
let auth = await this.checkAuth(catData.project_id, 'project', 'danger')
if (!auth) {
return ctx.body = yapi.commons.resReturn(null, 400, '没有权限');
}
}
let username = this.getUsername();
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 删除了分类 "${catData.name}" 及该分类下的接口`,
type: 'project',
uid: this.getUid(),
username: username,
typeid: catData.project_id
});
let interfaceData = await this.Model.listByCatid(id);
interfaceData.forEach(async item => {
try {
yapi.emitHook('interface_del', item._id).then();
await this.caseModel.delByInterfaceId(item._id);
} catch (e) {
yapi.commons.log(e.message, 'error');
}
})
await this.catModel.del(id);
let r = await this.Model.delByCatid(id);
return ctx.body = yapi.commons.resReturn(r);
} catch (e) {
yapi.commons.resReturn(null, 400, e.message)
}
}
/**
* 获取分类列表
* @interface /interface/getCatMenu
* @method GET
* @category interface
* @foldnumber 10
* @param {Number} project_id 项目id不能为空
* @returns {Object}
* @example ./api/interface/getCatMenu
*/
async getCatMenu(ctx) {
let project_id = ctx.request.query.project_id;
if (!project_id || isNaN(project_id)) {
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
}
try {
let project = await this.projectModel.getBaseInfo(project_id);
if (project.project_type === 'private') {
if (await this.checkAuth(project._id, 'project', 'edit') !== true) {
return ctx.body = yapi.commons.resReturn(null, 406, '没有权限');
}
}
let res = await this.catModel.list(project_id);
return ctx.body = yapi.commons.resReturn(res);
} catch (e) {
yapi.commons.resReturn(null, 400, e.message);
}
}
/**
* 获取自定义接口字段数据
* @interface /interface/get_custom_field
* @method GET
* @category interface
* @foldnumber 10
* @param {String} app_code = '111'
* @returns {Object}
*
*/
async getCustomField(ctx) {
let params = ctx.request.query
if (Object.keys(params).length !== 1) {
return ctx.body = yapi.commons.resReturn(null, 400, '参数数量错误');
}
let customFieldName = Object.keys(params)[0];
let customFieldValue = params[customFieldName];
try {
// 查找有customFieldName的分组group
let groups = await this.groupModel.getcustomFieldName(customFieldName)
if (groups.length === 0) {
return ctx.body = yapi.commons.resReturn(null, 404, '没有找到对应自定义接口');
}
// 在每个分组group下查找对应project的id值
let interfaces = [];
for (let i = 0; i < groups.length; i++) {
let projects = await this.projectModel.list(groups[i]._id);
// 在每个项目project中查找interface下的custom_field_value
for (let j = 0; j < projects.length; j++) {
let data = {}
let inter = await this.Model.getcustomFieldValue(projects[j]._id, customFieldValue)
if (inter.length > 0) {
data.project_name = projects[j].name
inter = inter.map((item, i) => {
item = inter[i] = inter[i].toObject();
item.res_body = yapi.commons.json_parse(item.res_body)
item.req_body_other = yapi.commons.json_parse(item.req_body_other)
return item
})
data.list = inter;
interfaces.push(data);
}
}
}
return ctx.body = yapi.commons.resReturn(interfaces);
} catch (e) {
yapi.commons.resReturn(null, 400, e.message);
}
}
async sendNotice(projectId, data) {
const list = await this.followModel.listByProjectId(projectId);
const starUsers = list.map(item => item.uid);
const projectList = await this.projectModel.get(projectId);
const projectMenbers = projectList.members.map(item => item.uid);
const users = this.arrUnique(projectMenbers, starUsers);
const usersInfo = await this.userModel.findByUids(users)
const emails = usersInfo.map(item => item.email).join(',');
try {
yapi.commons.sendMail({
to: emails,
contents: data.content,
subject: data.title
})
} catch (e) {
yapi.commons.log('邮件发送失败:' + e, 'error')
}
}
arrUnique(arr1, arr2) {
let arr = arr1.concat(arr2);
let res = arr.filter(function (item, index, arr) {
return arr.indexOf(item) === index;
})
return res;
}
requiredSort(params) {
return params.sort((item1, item2) => {
return item2.required - item1.required;
})
}
}
module.exports = interfaceController;
</pre>
</div>
</div>
</div>
</div>
<!-- <div class="docs-header" id="content" tabindex="-1">
<div class="container">
<h1>YApi : ./server/controllers/interface.js</h1>
<p>源代码</p>
</div>
</div> -->
<footer class="docs-footer" role="contentinfo">
<div class="container">
<p></p>
</div>
</footer>
</div>
<script type="text/javascript">
SyntaxHighlighter.all();
function getTop(node){
return node.offsetTop + (node.offsetParent ? getTop(node.offsetParent) : 0);
}
document.addEventListener('DOMContentLoaded', function() {
setTimeout(function() {
try {
var lineNum = (parseInt(location.hash.replace(/#/g, '')) - 1) || 0,
node = document.querySelectorAll('div.line')[lineNum];
document.body.scrollTop = getTop(node);
node.className += ' highlight';
} catch(e) {}
}, 500);
}, false);
</script>
</body>
</html>

View File

@ -0,0 +1,889 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no" />
<title>YApi : ./server/controllers/interfaceCol.js</title>
<link type="text/css" rel="stylesheet" href="../../../source/code.css"/>
<script type="text/javascript" src="../../../source/shCore.js"></script>
<script type="text/javascript" src="../../../source/shBrush-js.js"></script>
<style>
.syntaxhighlighter .number1 .spaces,.syntaxhighlighter .toolbar{ display: none;}
.syntaxhighlighter table td.gutter .line.highlight { background-color: #6ce26c !important; color: white; }
</style>
</head>
<body>
<div class="ydoc">
<div class="ydoc-banner-bg">
<div class="ydoc-banner" id="content" tabindex="-1">
<div class="ydoc-banner-area">
<h1>YApi : ./server/controllers/interfaceCol.js</h1>
<p>源代码</p>
</div>
</div>
<div class="ydoc-container">
<div class="ydoc-container-content">
<div class="static-code-content" role="main">
<pre class="brush: js;">
const interfaceColModel = require('../models/interfaceCol.js');
const interfaceCaseModel = require('../models/interfaceCase.js');
const interfaceModel = require('../models/interface.js');
const projectModel = require('../models/project.js');
const baseController = require('./base.js');
const yapi = require('../yapi.js');
const _ = require('underscore');
class interfaceColController extends baseController {
constructor(ctx) {
super(ctx);
this.colModel = yapi.getInst(interfaceColModel);
this.caseModel = yapi.getInst(interfaceCaseModel);
this.interfaceModel = yapi.getInst(interfaceModel);
this.projectModel = yapi.getInst(projectModel);
}
/**
* 获取所有接口集
* @interface /col/list
* @method GET
* @category col
* @foldnumber 10
* @param {String} project_id email名称不能为空
* @returns {Object}
* @example
*/
async list(ctx) {
try {
let id = ctx.query.project_id;
let project = await this.projectModel.getBaseInfo(id);
if (project.project_type === 'private') {
if (await this.checkAuth(project._id, 'project', 'view') !== true) {
return ctx.body = yapi.commons.resReturn(null, 406, '没有权限');
}
}
let result = await this.colModel.list(id);
for (let i = 0; i < result.length; i++) {
result[i] = result[i].toObject();
let caseList = await this.caseModel.list(result[i]._id)
caseList = caseList.sort((a, b) => {
return a.index - b.index;
});
result[i].caseList = caseList
}
ctx.body = yapi.commons.resReturn(result);
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}
}
/**
* 增加接口集
* @interface /col/add_col
* @method POST
* @category col
* @foldnumber 10
* @param {Number} project_id
* @param {String} name
* @param {String} desc
* @returns {Object}
* @example
*/
async addCol(ctx) {
try {
let params = ctx.request.body;
params = yapi.commons.handleParams(params, {
name: 'string',
project_id: 'number',
desc: 'string'
});
if (!params.project_id) {
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
}
if (!params.name) {
return ctx.body = yapi.commons.resReturn(null, 400, '名称不能为空');
}
let auth = await this.checkAuth(params.project_id, 'project', 'edit')
if (!auth) {
return ctx.body = yapi.commons.resReturn(null, 400, '没有权限');
}
let result = await this.colModel.save({
name: params.name,
project_id: params.project_id,
desc: params.desc,
uid: this.getUid(),
add_time: yapi.commons.time(),
up_time: yapi.commons.time()
});
let username = this.getUsername();
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 添加了接口集 <a href="/project/${params.project_id}/interface/col/${result._id}">${params.name}</a>`,
type: 'project',
uid: this.getUid(),
username: username,
typeid: params.project_id
});
// this.projectModel.up(params.project_id,{up_time: new Date().getTime()}).then();
ctx.body = yapi.commons.resReturn(result);
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}
}
/**
* 获取一个接口集下的所有的接口用例
* @interface /col/case_list
* @method GET
* @category col
* @foldnumber 10
* @param {String} col_id 接口集id
* @returns {Object}
* @example
*/
async getCaseList(ctx) {
try {
let id = ctx.query.col_id;
if (!id || id == 0) {
return ctx.body = yapi.commons.resReturn(null, 407, 'col_id不能为空')
}
let resultList = await this.caseModel.list(id, 'all');
let colData = await this.colModel.get(id);
let project = await this.projectModel.getBaseInfo(colData.project_id);
if (project.project_type === 'private') {
if (await this.checkAuth(project._id, 'project', 'view') !== true) {
return ctx.body = yapi.commons.resReturn(null, 406, '没有权限');
}
}
for (let index = 0; index < resultList.length; index++) {
let result = resultList[index].toObject();
let data = await this.interfaceModel.get(result.interface_id);
if (!data) {
await this.caseModel.del(result._id);
continue;
}
let projectData = await this.projectModel.getBaseInfo(data.project_id);
result.path = projectData.basepath + data.path;
result.method = data.method;
result.req_body_type = data.req_body_type;
result.req_headers = this.handleParamsValue(data.req_headers, result.req_headers);
result.res_body_type = data.res_body_type;
result.req_body_form = this.handleParamsValue(data.req_body_form, result.req_body_form)
result.req_query = this.handleParamsValue(data.req_query, result.req_query)
result.req_params = this.handleParamsValue(data.req_params, result.req_params)
resultList[index] = result;
}
resultList = resultList.sort((a, b) => {
return a.index - b.index;
});
let ctxBody = yapi.commons.resReturn(resultList);
ctxBody.colData = colData;
ctx.body = ctxBody;
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}
}
requestParamsToObj(arr) {
if (!arr || !Array.isArray(arr) || arr.length === 0) {
return {}
}
let obj = {};
arr.forEach(item => {
obj[item.name] = ''
})
return obj;
}
/**
* 获取一个接口集下的所有的接口用例
* @interface /col/case_list_by_var_params
* @method GET
* @category col
* @foldnumber 10
* @param {String} col_id 接口集id
* @returns {Object}
* @example
*/
async getCaseListByVariableParams(ctx) {
try {
let id = ctx.query.col_id;
if (!id || id == 0) {
return ctx.body = yapi.commons.resReturn(null, 407, 'col_id不能为空')
}
let resultList = await this.caseModel.list(id, 'all');
if (resultList.length === 0) {
return ctx.body = yapi.commons.resReturn([])
}
let project = await this.projectModel.getBaseInfo(resultList[0].project_id);
if (project.project_type === 'private') {
if (await this.checkAuth(project._id, 'project', 'view') !== true) {
return ctx.body = yapi.commons.resReturn(null, 406, '没有权限');
}
}
for (let index = 0; index < resultList.length; index++) {
let result = resultList[index].toObject();
let item = {}, body, query, bodyParams, pathParams;
let data = await this.interfaceModel.get(result.interface_id);
if (!data) {
await this.caseModel.del(result._id);
continue;
}
item._id = result._id;
item.casename = result.casename;
body = yapi.commons.json_parse(data.res_body);
body = typeof body === 'object' ? body : {};
item.body = Object.assign({}, body);
query = this.requestParamsToObj(data.req_query);
pathParams = this.requestParamsToObj(data.req_params);
if (data.req_body_type === 'form') {
bodyParams = this.requestParamsToObj(data.req_body_form);
} else {
bodyParams = yapi.commons.json_parse(data.req_body_other);
bodyParams = typeof bodyParams === 'object' ? bodyParams : {}
}
item.params = Object.assign(pathParams, query, bodyParams)
item.index = result.index;
resultList[index] = item;
}
ctx.body = yapi.commons.resReturn(resultList);
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}
}
/**
* 增加一个接口用例
* @interface /col/add_case
* @method POST
* @category col
* @foldnumber 10
* @param {String} casename
* @param {Number} col_id
* @param {Number} project_id
* @param {String} domain
* @param {String} path
* @param {String} method
* @param {Object} req_query
* @param {Object} req_headers
* @param {String} req_body_type
* @param {Array} req_body_form
* @param {String} req_body_other
* @returns {Object}
* @example
*/
async addCase(ctx) {
try {
let params = ctx.request.body;
params = yapi.commons.handleParams(params, {
casename: 'string',
project_id: 'number',
col_id: 'number',
interface_id: 'number',
case_env: 'string'
});
if (!params.project_id) {
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
}
if (!params.interface_id) {
return ctx.body = yapi.commons.resReturn(null, 400, '接口id不能为空');
}
let auth = await this.checkAuth(params.project_id, 'project', 'edit');
if (!auth) {
return ctx.body = yapi.commons.resReturn(null, 400, '没有权限');
}
if (!params.col_id) {
return ctx.body = yapi.commons.resReturn(null, 400, '接口集id不能为空');
}
if (!params.casename) {
return ctx.body = yapi.commons.resReturn(null, 400, '用例名称不能为空');
}
params.uid = this.getUid();
params.index = 0;
params.add_time = yapi.commons.time();
params.up_time = yapi.commons.time();
let result = await this.caseModel.save(params);
let username = this.getUsername();
this.colModel.get(params.col_id).then((col) => {
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 在接口集 <a href="/project/${params.project_id}/interface/col/${params.col_id}">${col.name}</a> 下添加了接口用例 <a href="/project/${params.project_id}/interface/case/${result._id}">${params.casename}</a>`,
type: 'project',
uid: this.getUid(),
username: username,
typeid: params.project_id
});
});
this.projectModel.up(params.project_id, { up_time: new Date().getTime() }).then();
ctx.body = yapi.commons.resReturn(result);
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}
}
async addCaseList(ctx) {
try {
let params = ctx.request.body;
params = yapi.commons.handleParams(params, {
project_id: 'number',
col_id: 'number'
});
if (!params.interface_list || !Array.isArray(params.interface_list)) {
return ctx.body = yapi.commons.resReturn(null, 400, 'interface_list 参数有误');
}
if (!params.project_id) {
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
}
let auth = await this.checkAuth(params.project_id, 'project', 'edit');
if (!auth) {
return ctx.body = yapi.commons.resReturn(null, 400, '没有权限');
}
if (!params.col_id) {
return ctx.body = yapi.commons.resReturn(null, 400, '接口集id不能为空');
}
let data = {
uid: this.getUid(),
index: 0,
add_time: yapi.commons.time(),
up_time: yapi.commons.time(),
project_id: params.project_id,
col_id: params.col_id
}
for (let i = 0; i < params.interface_list.length; i++) {
let interfaceData = await this.interfaceModel.get(params.interface_list[i]);
data.interface_id = params.interface_list[i];
data.casename = interfaceData.title;
data.req_body_other = interfaceData.req_body_other;
data.req_body_type = interfaceData.req_body_type;
await this.caseModel.save(data);
let username = this.getUsername();
this.colModel.get(params.col_id).then((col) => {
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 在接口集 <a href="/project/${params.project_id}/interface/col/${params.col_id}">${col.name}</a> 下导入了接口 <a href="/project/${params.project_id}/interface/case/${data.interface_id}">${data.casename}</a>`,
type: 'project',
uid: this.getUid(),
username: username,
typeid: params.project_id
});
});
}
this.projectModel.up(params.project_id, { up_time: new Date().getTime() }).then();
ctx.body = yapi.commons.resReturn('ok');
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}
}
async cloneCaseList(ctx) {
try {
let params = ctx.request.body;
params = yapi.commons.handleParams(params, {
project_id: 'number',
col_id: 'number',
new_col_id: 'number'
});
const { project_id, col_id, new_col_id } = params;
if (!project_id) {
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
}
let auth = await this.checkAuth(params.project_id, 'project', 'edit');
if (!auth) {
return ctx.body = yapi.commons.resReturn(null, 400, '没有权限');
}
if (!col_id) {
return ctx.body = yapi.commons.resReturn(null, 400, '被克隆的接口集id不能为空');
}
if (!new_col_id) {
return ctx.body = yapi.commons.resReturn(null, 400, '克隆的接口集id不能为空');
}
let oldColCaselistData = await this.caseModel.list(col_id, 'all');
oldColCaselistData = oldColCaselistData.sort((a, b) => {
return a.index - b.index;
});
const newCaseList = [];
const oldCaseObj = {};
let obj = {};
const handleTypeParams = (data, name) => {
let res = data[name];
const type = Object.prototype.toString.call(res);
switch (type) {
case "[object Array]":
if (res.length) {
res = JSON.stringify(res);
try {
res = JSON.parse(handleReplaceStr(res));
} catch (e) {
console.log('e ->', e);
}
}
break;
case "[object String]":
if (data[name]) {
res = handleReplaceStr(res);
}
break;
}
return res;
}
const handleReplaceStr = (str) => {
if (str.indexOf("$") !== -1) {
str = str.replace(/\$\.([0-9]+)\./g, function (match, p1) {
p1 = p1.toString();
return `$.${newCaseList[oldCaseObj[p1]]}.` || "";
})
}
return str;
}
// 处理数据里面的$id;
const handleParams = (data) => {
data.col_id = new_col_id;
delete data._id;
delete data.add_time;
delete data.up_time;
delete data.__v;
data.req_body_other = handleTypeParams(data, "req_body_other");
data.req_query = handleTypeParams(data, "req_query");
data.req_params = handleTypeParams(data, "req_params");
data.req_body_form = handleTypeParams(data, "req_body_form");
return data;
}
for (let i = 0; i < oldColCaselistData.length; i++) {
obj = oldColCaselistData[i].toObject();
// 将被克隆的id和位置绑定
oldCaseObj[obj._id] = i;
let caseData = handleParams(obj);
let newCase = await this.caseModel.save(caseData);
newCaseList.push(newCase._id);
}
this.projectModel.up(params.project_id, { up_time: new Date().getTime() }).then();
ctx.body = yapi.commons.resReturn('ok');
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}
}
/**
* 更新一个接口用例
* @interface /col/up_case
* @method POST
* @category col
* @foldnumber 10
* @param {number} id
* @param {String} casename
* @param {String} domain
* @param {String} path
* @param {String} method
* @param {Object} req_query
* @param {Object} req_headers
* @param {String} req_body_type
* @param {Array} req_body_form
* @param {String} req_body_other
* @returns {Object}
* @example
*/
async upCase(ctx) {
try {
let params = ctx.request.body;
params = yapi.commons.handleParams(params, {
id: 'number',
casename: 'string'
});
if (!params.id) {
return ctx.body = yapi.commons.resReturn(null, 400, '用例id不能为空');
}
let caseData = await this.caseModel.get(params.id);
let auth = await this.checkAuth(caseData.project_id, 'project', 'edit');
if (!auth) {
return ctx.body = yapi.commons.resReturn(null, 400, '没有权限');
}
params.uid = this.getUid();
//不允许修改接口id和项目id
delete params.interface_id;
delete params.project_id;
let result = await this.caseModel.up(params.id, params);
let username = this.getUsername();
this.colModel.get(caseData.col_id).then((col) => {
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 在接口集 <a href="/project/${caseData.project_id}/interface/col/${caseData.col_id}">${col.name}</a> 更新了接口用例 <a href="/project/${caseData.project_id}/interface/case/${params.id}">${params.casename || caseData.casename}</a>`,
type: 'project',
uid: this.getUid(),
username: username,
typeid: caseData.project_id
});
});
this.projectModel.up(caseData.project_id, { up_time: new Date().getTime() }).then();
ctx.body = yapi.commons.resReturn(result);
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}
}
/**
* 获取一个接口用例详情
* @interface /col/case
* @method GET
* @category col
* @foldnumber 10
* @param {String} caseid
* @returns {Object}
* @example
*/
async getCase(ctx) {
try {
let id = ctx.query.caseid;
let result = await this.caseModel.get(id);
if (!result) {
return ctx.body = yapi.commons.resReturn(null, 400, '不存在的case');
}
result = result.toObject();
let data = await this.interfaceModel.get(result.interface_id);
if (!data) {
return ctx.body = yapi.commons.resReturn(null, 400, '找不到对应的接口,请联系管理员')
}
data = data.toObject();
let projectData = await this.projectModel.getBaseInfo(data.project_id);
result.path = projectData.basepath + data.path;
result.method = data.method;
result.req_body_type = data.req_body_type;
result.req_headers = this.handleParamsValue(data.req_headers, result.req_headers);
result.res_body = data.res_body;
result.res_body_type = data.res_body_type;
result.req_body_form = this.handleParamsValue(data.req_body_form, result.req_body_form)
result.req_query = this.handleParamsValue(data.req_query, result.req_query)
result.req_params = this.handleParamsValue(data.req_params, result.req_params)
result.interface_up_time = data.up_time;
ctx.body = yapi.commons.resReturn(result);
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 400, e.message)
}
}
/**
*
* @param {*} params 接口定义的参数
* @param {*} val 接口case 定义的参数值
*/
handleParamsValue(params, val) {
let value = {};
try {
params = params.toObject();
} catch (e) { }
if (params.length === 0 || val.length === 0) {
return params;
}
val.forEach((item, index) => {
value[item.name] = item;
})
params.forEach((item, index) => {
if (!value[item.name] || typeof value[item.name] !== 'object') return null;
params[index].value = value[item.name].value;
if (!_.isUndefined(value[item.name].enable)) {
params[index].enable = value[item.name].enable
}
})
return params;
}
/**
* 更新一个接口集name或描述
* @interface /col/up_col
* @method POST
* @category col
* @foldnumber 10
* @param {String} name
* @param {String} desc
* @returns {Object}
* @example
*/
async upCol(ctx) {
try {
let params = ctx.request.body;
let id = params.col_id;
if (!id) {
return ctx.body = yapi.commons.resReturn(null, 400, '缺少 col_id 参数');
}
let colData = await this.colModel.get(id);
if (!colData) {
return ctx.body = yapi.commons.resReturn(null, 400, '不存在');
}
let auth = await this.checkAuth(colData.project_id, 'project', 'edit')
if (!auth) {
return ctx.body = yapi.commons.resReturn(null, 400, '没有权限');
}
delete params.col_id;
let result = await this.colModel.up(id, params);
let username = this.getUsername();
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 更新了接口集 <a href="/project/${colData.project_id}/interface/col/${id}">${colData.name}</a> 的信息`,
type: 'project',
uid: this.getUid(),
username: username,
typeid: colData.project_id
});
ctx.body = yapi.commons.resReturn(result)
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 400, e.message)
}
}
/**
* 更新多个接口case index
* @interface /col/up_col_index
* @method POST
* @category col
* @foldnumber 10
* @param {Array} [id, index]
* @returns {Object}
* @example
*/
async upCaseIndex(ctx) {
try {
let params = ctx.request.body;
if (!params || !Array.isArray(params)) {
ctx.body = yapi.commons.resReturn(null, 400, "请求参数必须是数组")
}
params.forEach((item) => {
if (item.id) {
this.caseModel.upCaseIndex(item.id, item.index).then((res) => { }, (err) => {
yapi.commons.log(err.message, 'error')
})
}
});
return ctx.body = yapi.commons.resReturn('成功!')
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 400, e.message)
}
}
/**
* 删除一个接口集
* @interface /col/del_col
* @method GET
* @category col
* @foldnumber 10
* @param {String}
* @returns {Object}
* @example
*/
async delCol(ctx) {
try {
let id = ctx.query.col_id;
let colData = await this.colModel.get(id);
if (!colData) {
ctx.body = yapi.commons.resReturn(null, 400, "不存在的id")
}
if (colData.uid !== this.getUid()) {
let auth = await this.checkAuth(colData.project_id, 'project', 'danger')
if (!auth) {
return ctx.body = yapi.commons.resReturn(null, 400, '没有权限');
}
}
let result = await this.colModel.del(id);
await this.caseModel.delByCol(id);
let username = this.getUsername();
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 删除了接口集 ${colData.name} 及其下面的接口`,
type: 'project',
uid: this.getUid(),
username: username,
typeid: colData.project_id
});
return ctx.body = yapi.commons.resReturn(result);
} catch (e) {
yapi.commons.resReturn(null, 400, e.message)
}
}
/**
*
* @param {*} ctx
*/
async delCase(ctx) {
try {
let caseid = ctx.query.caseid;
let caseData = await this.caseModel.get(caseid);
if (!caseData) {
ctx.body = yapi.commons.resReturn(null, 400, "不存在的caseid")
}
if (caseData.uid !== this.getUid()) {
let auth = await this.checkAuth(caseData.project_id, 'project', 'danger')
if (!auth) {
return ctx.body = yapi.commons.resReturn(null, 400, '没有权限');
}
}
let result = await this.caseModel.del(caseid);
let username = this.getUsername();
this.colModel.get(caseData.col_id).then((col) => {
yapi.commons.saveLog({
content: `<a href="/user/profile/${this.getUid()}">${username}</a> 删除了接口集 <a href="/project/${caseData.project_id}/interface/col/${caseData.col_id}">${col.name}</a> 下的接口 ${caseData.casename}`,
type: 'project',
uid: this.getUid(),
username: username,
typeid: caseData.project_id
});
});
this.projectModel.up(caseData.project_id, { up_time: new Date().getTime() }).then();
return ctx.body = yapi.commons.resReturn(result);
} catch (e) {
yapi.commons.resReturn(null, 400, e.message)
}
}
convertString(variable) {
if (variable instanceof Error) {
return variable.name + ': ' + variable.message;
}
try {
return JSON.stringify(variable, null, ' ');
} catch (err) {
return variable || '';
}
}
async runCaseScript(ctx) {
let params = ctx.request.body;
let script = params.script;
if (!script) {
return ctx.body = yapi.commons.resReturn('ok');
}
let logs = [];
let result = {
assert: require('assert'),
status: params.response.status,
body: params.response.body,
header: params.response.header,
records: params.records,
params: params.params,
log: (msg) => {
logs.push('log: ' + this.convertString(msg))
}
}
try {
result = yapi.commons.sandbox(result, script);
result.logs = logs;
return ctx.body = yapi.commons.resReturn(result);
} catch (err) {
logs.push(this.convertString(err));
result.logs = logs;
return ctx.body = yapi.commons.resReturn(result, 400, err.name + ": " + err.message)
}
}
}
module.exports = interfaceColController
</pre>
</div>
</div>
</div>
</div>
<!-- <div class="docs-header" id="content" tabindex="-1">
<div class="container">
<h1>YApi : ./server/controllers/interfaceCol.js</h1>
<p>源代码</p>
</div>
</div> -->
<footer class="docs-footer" role="contentinfo">
<div class="container">
<p></p>
</div>
</footer>
</div>
<script type="text/javascript">
SyntaxHighlighter.all();
function getTop(node){
return node.offsetTop + (node.offsetParent ? getTop(node.offsetParent) : 0);
}
document.addEventListener('DOMContentLoaded', function() {
setTimeout(function() {
try {
var lineNum = (parseInt(location.hash.replace(/#/g, '')) - 1) || 0,
node = document.querySelectorAll('div.line')[lineNum];
document.body.scrollTop = getTop(node);
node.className += ' highlight';
} catch(e) {}
}, 500);
}, false);
</script>
</body>
</html>

210
static/doc/usage 2.html Normal file
View File

@ -0,0 +1,210 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta name="format-detection" content="telephone=no,email=no" />
<meta http-equiv="X-UA-Compatible" content="ie=edge, chrome=1">
<meta name="description" content="description of your site">
<meta name="author" content="author of the site">
<title>YApi 接口管理平台 使用手册</title>
<link rel="shortcut icon" href="./favicon.ico" />
<link rel="stylesheet" href="source/main.css" />
<link rel="stylesheet" href="styles/theme.css" />
</head>
<body>
<div class="ydoc">
<header class="ydoc-header">
<div class="ydoc-header-area">
<a href="./index.html" class="navbar-brand"><img src="./images/logo_header@2x.png" /> &nbsp;YAPI</a>
<button class="ydocIcon navbar-toggle">&#xf020;</button>
<nav class="ydoc-nav">
<ul class="navbar-left">
<li class="">
<a href="index.html"></a>
</li>
<li class="active">
<a href="usage.html">使用手册</a>
</li>
<li class="">
<a href="devops.html">内网部署</a>
</li>
<li class="">
<a href="plugin.html">插件 Wiki</a>
</li>
<li class="">
<a href="qa.html">常见问题</a>
</li>
<li class="">
<a href="releases.html">版本记录</a>
</li>
<li class="">
<a href="http://yapi.demo.qunar.com/" target="_blank">demo 站点</a>
</li>
<li class="">
<a href="api.html"></a>
</li>
</ul>
</nav>
</div>
</header>
<!-- <header style="height:20px"></header> -->
<!-- Docs page layout -->
<div class="ydoc-banner-bg">
<div class="ydoc-banner ">
<div class="ydoc-banner-area">
<h1 >YApi</h1>
<p class="desc ">高效、易用、功能强大的api管理平台旨在为开发、产品、测试人员提供更优雅的接口管理服务。</p>
</div>
</div>
<div class="ydoc-container">
<div class="ydoc-container-content ">
<div class="content-left staticsidenav" role="complementary">
<nav class="docs-sidebar hidden-print hidden-xs hidden-sm">
<ul class="nav docs-sidenav">
<!-- <li > -->
<li >
<a href="getfamiliar.html">认识 YApi</a>
</li>
<!-- <li > -->
<li >
<a href="quickstart.html">创建第一个API</a>
</li>
<!-- <li > -->
<li >
<a href="manage.html">管理分组与项目</a>
</li>
<!-- <li > -->
<li >
<a href="project.html">项目操作</a>
</li>
<!-- <li > -->
<li >
<a href="interface.html">接口操作</a>
</li>
<!-- <li > -->
<li >
<a href="mock.html">普通 Mock</a>
</li>
<!-- <li > -->
<li >
<a href="adv_mock.html">高级 Mock</a>
</li>
<!-- <li > -->
<li >
<a href="case.html">使用测试集</a>
</li>
<!-- <li > -->
<li >
<a href="data.html">数据导入</a>
</li>
</ul>
</nav>
</div>
<div class="content-right markdown-body use-sidebar" role="main">
<p>YApi 是高效、易用、功能强大的api管理平台。
<!-- 它有扁平化的管理结构(`超管`-`组长`-`组员`),有清晰的接口组织方式(`分组`-`项目`-`接口`)有更方便的mock方案。 --></p>
<p>在开始使用 YApi 之前,我们先来熟悉一下 YApi 的网站结构这将让你快速了解YApi。</p>
<h2 class="subject" id="登录与注册">登录与注册 <a class="hashlink" href="#登录与注册">#</a></h2><p>想要使用 YApi ,首先要注册账号。</p>
<p><img src="./images/usage/login.png" /></p>
<h2 class="subject" id="首页">首页 <a class="hashlink" href="#首页">#</a></h2><p>登录后进入首页,首页展示了分组与项目。</p>
<p>此时你作为新用户,没有任何分组与项目的权限,因此只能搜索、浏览 “公开项目” 的接口,如果在首页找不到任何项目,请联系管理员将你加入对应项目。</p>
<p><span class="list-index">1</span>首页头部展示了当前所在的位置、搜索框、新建项目、查看文档和用户信息。</p>
<p><span class="list-index">2</span>首页左侧展示分组信息,“分组”是“项目”的集合,只有超级管理员可以管理分组。</p>
<p><span class="list-index">3</span>首页右侧是分组下的项目和成员列表,点击左侧的某个分组,右侧会出现该分组下的项目和成员信息。</p>
<p><span class="list-index">4</span>点击项目右上角的星星即可关注项目,关注的项目可以在“我的关注”页面查看。</p>
<p><img src="./images/usage/index.png" /></p>
<h2 class="subject" id="项目页">项目页 <a class="hashlink" href="#项目页">#</a></h2><p>点击一个项目,进入项目页,项目页展示了属于该项目的全部接口,并提供项目、接口的全部操作。</p>
<p>此时你作为新用户,只能浏览接口信息,不可以编辑项目或接口,如果需要编辑,请联系管理员将你加入该项目。</p>
<p><span class="list-index">1</span>项目页左侧的 “接口列表” 展示了该项目下的所有接口,右侧默认显示该项目下所有接口的列表。</p>
<p><span class="list-index">2</span>点击左侧的某个接口,右侧会出现“预览”、“编辑”和“运行”。</p>
<p><span class="list-index">3</span>点击左侧的 “测试集合” 使用<a href="./case.html">测试集</a>功能。</p>
<p><span class="list-index">4</span>点击二级导航的“设置”,项目组长即可编辑项目信息和管理成员列表。</p>
<p><span class="list-index">5</span>点击二级导航的“动态”,即可查看项目的操作日志。</p>
<p><img src="./images/usage/project.png" /></p>
<h2 class="subject" id="个人中心">个人中心 <a class="hashlink" href="#个人中心">#</a></h2><p>鼠标移动到右上角的用户头像或用户名上,即可点击“个人中心”查看个人信息。</p>
<p><img src="./images/usage/hover.png" /></p>
<p>在个人信息页面可以查看并修改自己的用户名、密码等信息。</p>
<p><img src="./images/usage/user.png" /></p>
</div>
</div>
</div>
</div>
<footer class="footer">
<div class="copyright">
&copy; 2017 <a href="https://ymfe.org">YMFE</a> Team. Build by <a href="http://ued.qunar.com/ydoc/">ydoc</a>&nbsp;
</div>
</footer>
</div>
<div class="open-panel"></div>
<div class="mask"></div>
<script src="source/main.js"></script>
<script src="source/app.js"></script>
</body>
</html>