mirror of
https://github.com/YMFE/yapi.git
synced 2025-02-23 13:59:28 +08:00
feat: req_body json 支持指针位置可视化插入表达式
This commit is contained in:
parent
e5aff7a41c
commit
0dc6c7fb64
@ -3,13 +3,14 @@
|
||||
* 支持自定义域名邮箱登录
|
||||
* 测试用例支持导入不同项目接口
|
||||
* 完善可视化表达式,可根据焦点编辑表达式
|
||||
* req_body json 支持指针位置可视化插入表达式
|
||||
|
||||
|
||||
#### Bug Fixed
|
||||
|
||||
* postman headers 为 null 时报错
|
||||
* 导入postman headers 为 null 时报错
|
||||
* format-data 数据解析不成功
|
||||
* 导出的接口顺序希望按照api的接口顺序
|
||||
* 导出的接口顺序按照api的接口顺序
|
||||
|
||||
|
||||
|
||||
|
@ -1,22 +1,24 @@
|
||||
import React from 'react'
|
||||
import mockEditor from './mockEditor'
|
||||
import PropTypes from 'prop-types'
|
||||
import './AceEditor.scss'
|
||||
import React from 'react';
|
||||
import mockEditor from './mockEditor';
|
||||
import PropTypes from 'prop-types';
|
||||
import './AceEditor.scss';
|
||||
|
||||
const ModeMap = {
|
||||
'javascript' : 'ace/mode/javascript',
|
||||
'json' : 'ace/mode/json',
|
||||
'text' : 'ace/mode/text',
|
||||
'xml' : 'ace/mode/xml',
|
||||
'html' : 'ace/mode/html'
|
||||
}
|
||||
javascript: 'ace/mode/javascript',
|
||||
json: 'ace/mode/json',
|
||||
text: 'ace/mode/text',
|
||||
xml: 'ace/mode/xml',
|
||||
html: 'ace/mode/html'
|
||||
};
|
||||
|
||||
function getMode(mode){
|
||||
return ModeMap[mode] || ModeMap.text
|
||||
const defaultStyle = { width: '100%', height: '200px' }
|
||||
|
||||
function getMode(mode) {
|
||||
return ModeMap[mode] || ModeMap.text;
|
||||
}
|
||||
|
||||
class AceEditor extends React.PureComponent {
|
||||
constructor(props){
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
@ -30,40 +32,49 @@ class AceEditor extends React.PureComponent {
|
||||
style: PropTypes.object,
|
||||
fullScreen: PropTypes.bool,
|
||||
insertCode: PropTypes.func
|
||||
}
|
||||
};
|
||||
|
||||
componentDidMount(){
|
||||
componentDidMount() {
|
||||
this.editor = mockEditor({
|
||||
container: this.editorElement,
|
||||
data: this.props.data,
|
||||
onChange: this.props.onChange,
|
||||
readOnly: this.props.readOnly,
|
||||
fullScreen: this.props.fullScreen
|
||||
})
|
||||
});
|
||||
|
||||
let mode = this.props.mode || 'javascript';
|
||||
this.editor.editor.getSession().setMode(getMode(mode));
|
||||
if(typeof this.props.callback === 'function'){
|
||||
this.props.callback(this.editor.editor)
|
||||
if (typeof this.props.callback === 'function') {
|
||||
this.props.callback(this.editor.editor);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (!this.editor) return;
|
||||
if (nextProps.data !== this.props.data && this.editor.getValue() !== nextProps.data) {
|
||||
this.editor.setValue(nextProps.data);
|
||||
let mode = nextProps.mode || 'javascript';
|
||||
this.editor.editor.getSession().setMode(getMode(mode));
|
||||
this.editor.editor.clearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps){
|
||||
|
||||
if(!this.editor) return;
|
||||
if(nextProps.data !== this.props.data && this.editor.getValue() !== nextProps.data){
|
||||
this.editor.setValue(nextProps.data);
|
||||
let mode = nextProps.mode || 'javascript';
|
||||
this.editor.editor.getSession().setMode(getMode(mode));
|
||||
this.editor.editor.clearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className={this.props.className} style={this.props.className ? undefined : this.props.style || {width: '100%', height: '200px'}} ref={editor=>{
|
||||
this.editorElement=editor
|
||||
}} ></div>
|
||||
return (
|
||||
<div
|
||||
className={this.props.className}
|
||||
style={
|
||||
this.props.className ? undefined : this.props.style || defaultStyle
|
||||
}
|
||||
ref={editor => {
|
||||
this.editorElement = editor;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default AceEditor;
|
||||
export default AceEditor;
|
||||
|
@ -175,6 +175,7 @@ function run(options) {
|
||||
editor.clearSelection();
|
||||
|
||||
});
|
||||
|
||||
|
||||
return mockEditor;
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ export default class Run extends Component {
|
||||
test_script: '',
|
||||
hasPlugin: true,
|
||||
inputValue: '',
|
||||
cursurPosition: -1,
|
||||
cursurPosition: { row: 1, column: -1 },
|
||||
envModalVisible: false,
|
||||
test_res_header: null,
|
||||
test_res_body: null,
|
||||
@ -178,19 +178,16 @@ export default class Run extends Component {
|
||||
}
|
||||
|
||||
initEnvState(case_env, env) {
|
||||
|
||||
let headers = this.handleReqHeader(case_env, env);
|
||||
|
||||
|
||||
this.setState(
|
||||
{
|
||||
req_headers: headers,
|
||||
env: env
|
||||
},
|
||||
() => {
|
||||
|
||||
let s = !_.find(env, item => item.name === this.state.case_env);
|
||||
if (!this.state.case_env || s) {
|
||||
|
||||
this.setState({
|
||||
case_env: this.state.env[0].name
|
||||
});
|
||||
@ -220,7 +217,7 @@ export default class Run extends Component {
|
||||
this.initState(nextProps.data);
|
||||
}
|
||||
if (nextProps.data.env !== this.props.data.env) {
|
||||
this.initEnvState(this.state.case_env,nextProps.data.env);
|
||||
this.initEnvState(this.state.case_env, nextProps.data.env);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -331,10 +328,22 @@ export default class Run extends Component {
|
||||
|
||||
// 模态框的相关操作
|
||||
showModal = (val, index, type) => {
|
||||
let oTxt1 = document.getElementById(`${type}_${index}`);
|
||||
let cursurPosition = oTxt1.selectionStart;
|
||||
|
||||
let inputValue = this.getInstallValue(val || '', cursurPosition).val
|
||||
let inputValue = '';
|
||||
let cursurPosition;
|
||||
if (type === 'req_body_other') {
|
||||
// req_body
|
||||
let editor = this.aceEditor.editor.editor;
|
||||
cursurPosition = editor.session.doc.positionToIndex(editor.selection.getCursor());
|
||||
// 获取选中的数据
|
||||
inputValue = this.getInstallValue(val || '', cursurPosition).val;
|
||||
} else {
|
||||
// 其他input 输入
|
||||
let oTxt1 = document.getElementById(`${type}_${index}`);
|
||||
cursurPosition = oTxt1.selectionStart;
|
||||
inputValue = this.getInstallValue(val || '', cursurPosition).val;
|
||||
// cursurPosition = {row: 1, column: position}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
modalVisible: true,
|
||||
inputIndex: index,
|
||||
@ -347,45 +356,57 @@ export default class Run extends Component {
|
||||
// 点击插入
|
||||
handleModalOk = val => {
|
||||
const { inputIndex, modalType } = this.state;
|
||||
this.changeInstallParam(modalType, val, inputIndex);
|
||||
if (modalType === 'req_body_other') {
|
||||
this.changeInstallBody(modalType, val);
|
||||
} else {
|
||||
this.changeInstallParam(modalType, val, inputIndex);
|
||||
}
|
||||
|
||||
this.setState({ modalVisible: false });
|
||||
};
|
||||
|
||||
handleModalCancel = () => {
|
||||
this.setState({ modalVisible: false, cursurPosition: -1 });
|
||||
// 根据鼠标位置往req_body中动态插入数据
|
||||
changeInstallBody = (type, value) => {
|
||||
const pathParam = deepCopyJson(this.state[type]);
|
||||
// console.log(pathParam)
|
||||
let oldValue = pathParam || '';
|
||||
let newValue = this.getInstallValue(oldValue, this.state.cursurPosition);
|
||||
let left = newValue.left;
|
||||
let right = newValue.right;
|
||||
this.setState({
|
||||
[type]: `${left}${value}${right}`
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 获取截取的字符串
|
||||
getInstallValue = (oldValue, cursurPosition) => {
|
||||
let left = oldValue.substr(0, cursurPosition);
|
||||
let right = oldValue.substr(cursurPosition);
|
||||
|
||||
|
||||
let leftPostion = left.lastIndexOf('{{');
|
||||
let leftPostion2 = left.lastIndexOf('}}');
|
||||
let rightPostion = right.indexOf('}}');
|
||||
// console.log(leftPostion, leftPostion2,rightPostion, rightPostion2);
|
||||
let val = '';
|
||||
// 需要切除原来的变量
|
||||
if (leftPostion !== -1 && rightPostion !==-1 && leftPostion > leftPostion2) {
|
||||
if (leftPostion !== -1 && rightPostion !== -1 && leftPostion > leftPostion2) {
|
||||
left = left.substr(0, leftPostion);
|
||||
right = right.substr(rightPostion + 2);
|
||||
val = oldValue.substring(leftPostion, cursurPosition+rightPostion+2)
|
||||
val = oldValue.substring(leftPostion, cursurPosition + rightPostion + 2);
|
||||
}
|
||||
return {
|
||||
left,
|
||||
right,
|
||||
val
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// 根据鼠标位置动态插入数据
|
||||
changeInstallParam = (name, v, index, key) => {
|
||||
key = key || 'value';
|
||||
const pathParam = deepCopyJson(this.state[name]);
|
||||
let oldValue = pathParam[index][key] || '';
|
||||
let newValue = this.getInstallValue(oldValue, this.state.cursurPosition)
|
||||
let newValue = this.getInstallValue(oldValue, this.state.cursurPosition);
|
||||
let left = newValue.left;
|
||||
let right = newValue.right;
|
||||
pathParam[index][key] = `${left}${v}${right}`;
|
||||
@ -394,6 +415,11 @@ export default class Run extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
// 取消参数插入
|
||||
handleModalCancel = () => {
|
||||
this.setState({ modalVisible: false, cursurPosition: -1 });
|
||||
};
|
||||
|
||||
// 环境变量模态框相关操作
|
||||
showEnvModal = () => {
|
||||
this.setState({
|
||||
@ -648,8 +674,22 @@ export default class Run extends Component {
|
||||
<div
|
||||
style={{ display: checkRequestBodyIsRaw(method, req_body_type) ? 'block' : 'none' }}
|
||||
>
|
||||
{req_body_type === 'json' && (
|
||||
<div className="adv-button">
|
||||
<Button
|
||||
onClick={() => this.showModal(this.state.req_body_other, 0, 'req_body_other')}
|
||||
>
|
||||
高级参数设置
|
||||
</Button>
|
||||
<Tooltip title="高级参数设置只在json字段中生效">
|
||||
{' '}<Icon type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<AceEditor
|
||||
className="pretty-editor"
|
||||
ref={editor => (this.aceEditor = editor)}
|
||||
data={this.state.req_body_other}
|
||||
mode={req_body_type === 'json' ? null : 'text'}
|
||||
onChange={this.handleRequestBody}
|
||||
|
@ -3,7 +3,9 @@
|
||||
|
||||
|
||||
|
||||
|
||||
.adv-button {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.pretty-editor {
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
|
BIN
docs/documents/images/project-remove.png
Normal file
BIN
docs/documents/images/project-remove.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 109 KiB |
@ -32,11 +32,14 @@
|
||||
|
||||
YApi中支持项目迁移到不同的分组中。
|
||||
|
||||
<img src="./images/project-remove.png" />
|
||||
|
||||
迁移权限: 只有管理员和该项目的owner有权限对位置进行修改。项目owner主要有创建该项目的人、项目中的组长、创建分组的人、分组中的组长。
|
||||
|
||||
> Tips: owner权限判断的优先级是 项目权限 > 分组权限
|
||||
|
||||
## 项目拷贝
|
||||
该功能在 v1.3.12 版本上线,项目克隆功能可复制项目全部接口到一个新项目,如下图所示,点击红色框里面的 icon 使用。
|
||||
|
||||
YApi支持项目复制功能,但是无法复制项目中的测试集合list。
|
||||
|
||||
@ -177,8 +180,3 @@ context.promise = new Promise(function(resolve){
|
||||
## token配置
|
||||
|
||||
每个项目都有唯一的标识token,用户可以使用这个token值来请求项目的所有资源数据。目前用到的地方是接口的<a href="./case.md">自动化测试</a>,用户不需要登录就可以访问接口测试结果信息。
|
||||
|
||||
## 项目克隆
|
||||
该功能在 v1.3.12 版本上线,项目克隆功能可复制项目全部接口到一个新项目,如下图所示,点击红色框里面的 icon 使用。
|
||||
|
||||

|
@ -10,10 +10,14 @@
|
||||
</div></div><nav class="m-header-nav js-nav"><ul class="m-header-items"><li class="item active"><a class="href" href="index.html">教程</a></li><li class="item "><a class="href" href="../devops/index.html">内网部署</a></li></ul></nav><div id="js-nav-btn" class="m-header-btn ui-font-ydoc"></div></header><div class="m-content" id="js-content"><div id="markdown-body" class="m-content-container markdown-body"><h3 id="v1.3.16">v1.3.16</h3>
|
||||
<ul>
|
||||
<li>支持自定义域名邮箱登录</li>
|
||||
<li>测试用例支持导入不同项目接口</li>
|
||||
<li>完善可视化表达式,可根据焦点编辑表达式</li>
|
||||
</ul>
|
||||
<h4>Bug Fixed</h4>
|
||||
<ul>
|
||||
<li>postman headers 为 null 时报错</li>
|
||||
<li>format-data 数据解析不成功</li>
|
||||
<li>导出的接口顺序希望按照api的接口顺序</li>
|
||||
</ul>
|
||||
<h3 id="v1.3.15">v1.3.15</h3>
|
||||
<ul>
|
||||
|
BIN
static/doc/documents/images/project-remove.png
Normal file
BIN
static/doc/documents/images/project-remove.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 109 KiB |
@ -38,7 +38,7 @@
|
||||
<pre><code>{
|
||||
"name": "${query.name}", //请求的url是/path?name=xiaoming, 返回的name字段是xiaoming
|
||||
"type": "${body.type}", //请求的requestBody type=1,返回的type字段是1
|
||||
"value": "${body.fields.value}" // 当header是Content-Type: multipart/form-data 时获取body中的值 (v1.3.16+支持)
|
||||
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
|
@ -29,11 +29,13 @@
|
||||
<img src="./images/usage/project_setting_logo.png">
|
||||
<h2 id="项目迁移">项目迁移</h2>
|
||||
<p>YApi中支持项目迁移到不同的分组中。</p>
|
||||
<img src="./images/project-remove.png">
|
||||
<p>迁移权限: 只有管理员和该项目的owner有权限对位置进行修改。项目owner主要有创建该项目的人、项目中的组长、创建分组的人、分组中的组长。</p>
|
||||
<blockquote>
|
||||
<p>Tips: owner权限判断的优先级是 项目权限 > 分组权限</p>
|
||||
</blockquote>
|
||||
<h2 id="项目拷贝">项目拷贝</h2>
|
||||
<p>该功能在 v1.3.12 版本上线,项目克隆功能可复制项目全部接口到一个新项目,如下图所示,点击红色框里面的 icon 使用。</p>
|
||||
<p>YApi支持项目复制功能,但是无法复制项目中的测试集合list。</p>
|
||||
<p>操作: 点击下图左上角的复制按钮,在弹窗中写入复制项目名称点击确定就可以完成项目复制</p>
|
||||
<img src="./images/usage/projectCopy.png">
|
||||
@ -110,6 +112,9 @@
|
||||
<pre><code>context.responseBody.a = 2;
|
||||
|
||||
</code></pre>
|
||||
<blockquote>
|
||||
<p>(v1.3.16+新增)context.href和context.hostname</p>
|
||||
</blockquote>
|
||||
<h3 id="请求配置-工具函数">工具函数</h3>
|
||||
<pre><code>context.utils = {
|
||||
_ //underscore 函数,详细 API 查看官网 http://underscorejs.org/
|
||||
@ -142,9 +147,6 @@
|
||||
</blockquote>
|
||||
<h2 id="token配置">token配置</h2>
|
||||
<p>每个项目都有唯一的标识token,用户可以使用这个token值来请求项目的所有资源数据。目前用到的地方是接口的<a href="./case.html">自动化测试</a>,用户不需要登录就可以访问接口测试结果信息。</p>
|
||||
<h2 id="项目克隆">项目克隆</h2>
|
||||
<p>该功能在 v1.3.12 版本上线,项目克隆功能可复制项目全部接口到一个新项目,如下图所示,点击红色框里面的 icon 使用。</p>
|
||||
<p><img src="clone-project.png.png" alt=""></p>
|
||||
</div><div class="m-content-container m-paging"><div class="m-paging-prev m-paging-item"><a href="manage.html" class="href"><span class="ui-font-ydoc"></span>权限</a></div><div class="m-paging-next m-paging-item"><a href="api.html" class="href">接口操作<span class="ui-font-ydoc"></span></a></div></div></div></div></div><div><div class="m-mask js-mask">
|
||||
<div class="container">
|
||||
<img src="" alt="" class="img js-mask-img" />
|
||||
|
@ -200,7 +200,7 @@ window.ydoc_plugin_search_json = {
|
||||
{
|
||||
"title": "项目拷贝",
|
||||
"url": "/documents/project.html#项目拷贝",
|
||||
"content": "项目拷贝YApi支持项目复制功能,但是无法复制项目中的测试集合list。操作: 点击下图左上角的复制按钮,在弹窗中写入复制项目名称点击确定就可以完成项目复制Tips: 如果你在该分组下有新建项目的权限,那你也同时拥有复制项目的权限\n"
|
||||
"content": "项目拷贝该功能在 v1.3.12 版本上线,项目克隆功能可复制项目全部接口到一个新项目,如下图所示,点击红色框里面的 icon 使用。YApi支持项目复制功能,但是无法复制项目中的测试集合list。操作: 点击下图左上角的复制按钮,在弹窗中写入复制项目名称点击确定就可以完成项目复制Tips: 如果你在该分组下有新建项目的权限,那你也同时拥有复制项目的权限\n"
|
||||
},
|
||||
{
|
||||
"title": "删除项目",
|
||||
@ -225,7 +225,7 @@ window.ydoc_plugin_search_json = {
|
||||
{
|
||||
"title": "返回数据示例",
|
||||
"url": "/documents/project.html#请求配置-返回数据示例",
|
||||
"content": "返回数据示例在上面的示例请求完成后,假设返回 responseBody={a:1},公共变量 context 包含以下属性:context = { pathname: '/api/user',\n query: {\n id: 1\n },\n requestHeader: {\n xxx: 'xxx'\n },\n method: 'POST',\n requestBody: {\n type:1\n },\n responseData: {\n a:1\n },\n responseHeader: {\n content-type: 'application/json'\n ...\n }\n}\n假设我们需要修改响应数据 responseBody a 的值为 2,可以填写如下自定义脚本:context.responseBody.a = 2;\n"
|
||||
"content": "返回数据示例在上面的示例请求完成后,假设返回 responseBody={a:1},公共变量 context 包含以下属性:context = { pathname: '/api/user',\n query: {\n id: 1\n },\n requestHeader: {\n xxx: 'xxx'\n },\n method: 'POST',\n requestBody: {\n type:1\n },\n responseData: {\n a:1\n },\n responseHeader: {\n content-type: 'application/json'\n ...\n }\n}\n假设我们需要修改响应数据 responseBody a 的值为 2,可以填写如下自定义脚本:context.responseBody.a = 2;\n(v1.3.16+新增)context.href和context.hostname\n"
|
||||
},
|
||||
{
|
||||
"title": "工具函数",
|
||||
@ -241,11 +241,6 @@ window.ydoc_plugin_search_json = {
|
||||
"title": "token配置",
|
||||
"url": "/documents/project.html#token配置",
|
||||
"content": "token配置每个项目都有唯一的标识token,用户可以使用这个token值来请求项目的所有资源数据。目前用到的地方是接口的自动化测试,用户不需要登录就可以访问接口测试结果信息。"
|
||||
},
|
||||
{
|
||||
"title": "项目克隆",
|
||||
"url": "/documents/project.html#项目克隆",
|
||||
"content": "项目克隆该功能在 v1.3.12 版本上线,项目克隆功能可复制项目全部接口到一个新项目,如下图所示,点击红色框里面的 icon 使用。"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -277,7 +272,7 @@ window.ydoc_plugin_search_json = {
|
||||
{
|
||||
"title": "项目拷贝",
|
||||
"url": "/documents/project.html#项目拷贝",
|
||||
"content": "项目拷贝YApi支持项目复制功能,但是无法复制项目中的测试集合list。操作: 点击下图左上角的复制按钮,在弹窗中写入复制项目名称点击确定就可以完成项目复制Tips: 如果你在该分组下有新建项目的权限,那你也同时拥有复制项目的权限\n"
|
||||
"content": "项目拷贝该功能在 v1.3.12 版本上线,项目克隆功能可复制项目全部接口到一个新项目,如下图所示,点击红色框里面的 icon 使用。YApi支持项目复制功能,但是无法复制项目中的测试集合list。操作: 点击下图左上角的复制按钮,在弹窗中写入复制项目名称点击确定就可以完成项目复制Tips: 如果你在该分组下有新建项目的权限,那你也同时拥有复制项目的权限\n"
|
||||
},
|
||||
{
|
||||
"title": "删除项目",
|
||||
@ -302,7 +297,7 @@ window.ydoc_plugin_search_json = {
|
||||
{
|
||||
"title": "返回数据示例",
|
||||
"url": "/documents/project.html#请求配置-返回数据示例",
|
||||
"content": "返回数据示例在上面的示例请求完成后,假设返回 responseBody={a:1},公共变量 context 包含以下属性:context = { pathname: '/api/user',\n query: {\n id: 1\n },\n requestHeader: {\n xxx: 'xxx'\n },\n method: 'POST',\n requestBody: {\n type:1\n },\n responseData: {\n a:1\n },\n responseHeader: {\n content-type: 'application/json'\n ...\n }\n}\n假设我们需要修改响应数据 responseBody a 的值为 2,可以填写如下自定义脚本:context.responseBody.a = 2;\n"
|
||||
"content": "返回数据示例在上面的示例请求完成后,假设返回 responseBody={a:1},公共变量 context 包含以下属性:context = { pathname: '/api/user',\n query: {\n id: 1\n },\n requestHeader: {\n xxx: 'xxx'\n },\n method: 'POST',\n requestBody: {\n type:1\n },\n responseData: {\n a:1\n },\n responseHeader: {\n content-type: 'application/json'\n ...\n }\n}\n假设我们需要修改响应数据 responseBody a 的值为 2,可以填写如下自定义脚本:context.responseBody.a = 2;\n(v1.3.16+新增)context.href和context.hostname\n"
|
||||
},
|
||||
{
|
||||
"title": "工具函数",
|
||||
@ -318,11 +313,6 @@ window.ydoc_plugin_search_json = {
|
||||
"title": "token配置",
|
||||
"url": "/documents/project.html#token配置",
|
||||
"content": "token配置每个项目都有唯一的标识token,用户可以使用这个token值来请求项目的所有资源数据。目前用到的地方是接口的自动化测试,用户不需要登录就可以访问接口测试结果信息。"
|
||||
},
|
||||
{
|
||||
"title": "项目克隆",
|
||||
"url": "/documents/project.html#项目克隆",
|
||||
"content": "项目克隆该功能在 v1.3.12 版本上线,项目克隆功能可复制项目全部接口到一个新项目,如下图所示,点击红色框里面的 icon 使用。"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -418,7 +408,7 @@ window.ydoc_plugin_search_json = {
|
||||
{
|
||||
"title": "原理",
|
||||
"url": "/documents/mock.html#方式1.-mockjs-原理",
|
||||
"content": "原理基于 mockjs,跟 Mockjs 区别是 yapi 基于 json + 注释 定义 mock 数据,无法使用 mockjs 原有的函数功能。正则表达式需要基于 rule 书写,示例如下:\n{ \"name|regexp\": \"[a-z0-9_]+?\",\n \"type|regexp\": \"json|text|xml\"\n}\n\n支持替换请求的 query, body 参数\n{ \"name\": \"${query.name}\", //请求的url是/path?name=xiaoming, 返回的name字段是xiaoming\n \"type\": \"${body.type}\", //请求的requestBody type=1,返回的type字段是1\n \"value\": \"${body.fields.value}\" // 当header是Content-Type: multipart/form-data 时获取body中的值 (v1.3.16+支持)\n}\n\n示例\n/** * 这是一个接口返回数据示例\n */\n\n{\n \"errcode\": 0,\n \"errmsg\": \"@word\",\n \"data\": {\n \"id\": \"@id\", //@id 随机生成 id\n \"name\": \"@name\" //@name 随机生成用户名\n }\n}\n\n详细使用文档请查看:Mockjs 官网"
|
||||
"content": "原理基于 mockjs,跟 Mockjs 区别是 yapi 基于 json + 注释 定义 mock 数据,无法使用 mockjs 原有的函数功能。正则表达式需要基于 rule 书写,示例如下:\n{ \"name|regexp\": \"[a-z0-9_]+?\",\n \"type|regexp\": \"json|text|xml\"\n}\n\n支持替换请求的 query, body 参数\n{ \"name\": \"${query.name}\", //请求的url是/path?name=xiaoming, 返回的name字段是xiaoming\n \"type\": \"${body.type}\", //请求的requestBody type=1,返回的type字段是1\n \n}\n\n示例\n/** * 这是一个接口返回数据示例\n */\n\n{\n \"errcode\": 0,\n \"errmsg\": \"@word\",\n \"data\": {\n \"id\": \"@id\", //@id 随机生成 id\n \"name\": \"@name\" //@name 随机生成用户名\n }\n}\n\n详细使用文档请查看:Mockjs 官网"
|
||||
},
|
||||
{
|
||||
"title": "方式2. json-schema",
|
||||
@ -465,7 +455,7 @@ window.ydoc_plugin_search_json = {
|
||||
{
|
||||
"title": "原理",
|
||||
"url": "/documents/mock.html#方式1.-mockjs-原理",
|
||||
"content": "原理基于 mockjs,跟 Mockjs 区别是 yapi 基于 json + 注释 定义 mock 数据,无法使用 mockjs 原有的函数功能。正则表达式需要基于 rule 书写,示例如下:\n{ \"name|regexp\": \"[a-z0-9_]+?\",\n \"type|regexp\": \"json|text|xml\"\n}\n\n支持替换请求的 query, body 参数\n{ \"name\": \"${query.name}\", //请求的url是/path?name=xiaoming, 返回的name字段是xiaoming\n \"type\": \"${body.type}\", //请求的requestBody type=1,返回的type字段是1\n \"value\": \"${body.fields.value}\" // 当header是Content-Type: multipart/form-data 时获取body中的值 (v1.3.16+支持)\n}\n\n示例\n/** * 这是一个接口返回数据示例\n */\n\n{\n \"errcode\": 0,\n \"errmsg\": \"@word\",\n \"data\": {\n \"id\": \"@id\", //@id 随机生成 id\n \"name\": \"@name\" //@name 随机生成用户名\n }\n}\n\n详细使用文档请查看:Mockjs 官网"
|
||||
"content": "原理基于 mockjs,跟 Mockjs 区别是 yapi 基于 json + 注释 定义 mock 数据,无法使用 mockjs 原有的函数功能。正则表达式需要基于 rule 书写,示例如下:\n{ \"name|regexp\": \"[a-z0-9_]+?\",\n \"type|regexp\": \"json|text|xml\"\n}\n\n支持替换请求的 query, body 参数\n{ \"name\": \"${query.name}\", //请求的url是/path?name=xiaoming, 返回的name字段是xiaoming\n \"type\": \"${body.type}\", //请求的requestBody type=1,返回的type字段是1\n \n}\n\n示例\n/** * 这是一个接口返回数据示例\n */\n\n{\n \"errcode\": 0,\n \"errmsg\": \"@word\",\n \"data\": {\n \"id\": \"@id\", //@id 随机生成 id\n \"name\": \"@name\" //@name 随机生成用户名\n }\n}\n\n详细使用文档请查看:Mockjs 官网"
|
||||
},
|
||||
{
|
||||
"title": "方式2. json-schema",
|
||||
@ -1162,7 +1152,7 @@ window.ydoc_plugin_search_json = {
|
||||
{
|
||||
"title": "v1.3.16",
|
||||
"url": "/documents/CHANGELOG.html#v1.3.16",
|
||||
"content": "v1.3.16支持自定义域名邮箱登录\nBug Fixedpostman headers 为 null 时报错\n"
|
||||
"content": "v1.3.16支持自定义域名邮箱登录\n测试用例支持导入不同项目接口\n完善可视化表达式,可根据焦点编辑表达式\nBug Fixedpostman headers 为 null 时报错\nformat-data 数据解析不成功\n导出的接口顺序希望按照api的接口顺序\n"
|
||||
},
|
||||
{
|
||||
"title": "v1.3.15",
|
||||
@ -1309,7 +1299,7 @@ window.ydoc_plugin_search_json = {
|
||||
{
|
||||
"title": "v1.3.16",
|
||||
"url": "/documents/CHANGELOG.html#v1.3.16",
|
||||
"content": "v1.3.16支持自定义域名邮箱登录\nBug Fixedpostman headers 为 null 时报错\n"
|
||||
"content": "v1.3.16支持自定义域名邮箱登录\n测试用例支持导入不同项目接口\n完善可视化表达式,可根据焦点编辑表达式\nBug Fixedpostman headers 为 null 时报错\nformat-data 数据解析不成功\n导出的接口顺序希望按照api的接口顺序\n"
|
||||
},
|
||||
{
|
||||
"title": "v1.3.15",
|
||||
|
Loading…
Reference in New Issue
Block a user