fork from bc4552c5a8
This commit is contained in:
159
common/HandleImportData.js
Normal file
159
common/HandleImportData.js
Normal file
@@ -0,0 +1,159 @@
|
||||
const _ = require('underscore');
|
||||
const axios = require('axios');
|
||||
|
||||
|
||||
const isNode = typeof global == 'object' && global.global === global;
|
||||
|
||||
async function handle(
|
||||
res,
|
||||
projectId,
|
||||
selectCatid,
|
||||
menuList,
|
||||
basePath,
|
||||
dataSync,
|
||||
messageError,
|
||||
messageSuccess,
|
||||
callback,
|
||||
token,
|
||||
port
|
||||
) {
|
||||
|
||||
const taskNotice = _.throttle((index, len)=>{
|
||||
messageSuccess(`正在导入,已执行任务 ${index+1} 个,共 ${len} 个`)
|
||||
}, 3000)
|
||||
|
||||
const handleAddCat = async cats => {
|
||||
let catsObj = {};
|
||||
if (cats && Array.isArray(cats)) {
|
||||
for (let i = 0; i < cats.length; i++) {
|
||||
let cat = cats[i];
|
||||
let findCat = _.find(menuList, menu => menu.name === cat.name);
|
||||
catsObj[cat.name] = cat;
|
||||
if (findCat) {
|
||||
cat.id = findCat._id;
|
||||
} else {
|
||||
let apipath = '/api/interface/add_cat';
|
||||
if (isNode) {
|
||||
apipath = 'http://127.0.0.1:' + port + apipath;
|
||||
}
|
||||
|
||||
let data = {
|
||||
name: cat.name,
|
||||
project_id: projectId,
|
||||
desc: cat.desc,
|
||||
token
|
||||
};
|
||||
let result = await axios.post(apipath, data);
|
||||
|
||||
if (result.data.errcode) {
|
||||
messageError(result.data.errmsg);
|
||||
callback({ showLoading: false });
|
||||
return false;
|
||||
}
|
||||
cat.id = result.data.data._id;
|
||||
}
|
||||
}
|
||||
}
|
||||
return catsObj;
|
||||
};
|
||||
|
||||
const handleAddInterface = async info => {
|
||||
const cats = await handleAddCat(info.cats);
|
||||
if (cats === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
const res = info.apis;
|
||||
let len = res.length;
|
||||
let count = 0;
|
||||
let successNum = len;
|
||||
let existNum = 0;
|
||||
if (len === 0) {
|
||||
messageError(`解析数据为空`);
|
||||
callback({ showLoading: false });
|
||||
return;
|
||||
}
|
||||
|
||||
if(info.basePath){
|
||||
let projectApiPath = '/api/project/up';
|
||||
if (isNode) {
|
||||
projectApiPath = 'http://127.0.0.1:' + port + projectApiPath;
|
||||
}
|
||||
|
||||
await axios.post(projectApiPath, {
|
||||
id: projectId,
|
||||
basepath: info.basePath,
|
||||
token
|
||||
})
|
||||
}
|
||||
|
||||
for (let index = 0; index < res.length; index++) {
|
||||
let item = res[index];
|
||||
let data = Object.assign(item, {
|
||||
project_id: projectId,
|
||||
catid: selectCatid
|
||||
});
|
||||
if (basePath) {
|
||||
data.path =
|
||||
data.path.indexOf(basePath) === 0 ? data.path.substr(basePath.length) : data.path;
|
||||
}
|
||||
if (
|
||||
data.catname &&
|
||||
cats[data.catname] &&
|
||||
typeof cats[data.catname] === 'object' &&
|
||||
cats[data.catname].id
|
||||
) {
|
||||
data.catid = cats[data.catname].id;
|
||||
}
|
||||
data.token = token;
|
||||
|
||||
if (dataSync !== 'normal') {
|
||||
// 开启同步功能
|
||||
count++;
|
||||
let apipath = '/api/interface/save';
|
||||
if (isNode) {
|
||||
apipath = 'http://127.0.0.1:' + port + apipath;
|
||||
}
|
||||
data.dataSync = dataSync;
|
||||
let result = await axios.post(apipath, data);
|
||||
if (result.data.errcode) {
|
||||
successNum--;
|
||||
callback({ showLoading: false });
|
||||
messageError(result.data.errmsg);
|
||||
} else {
|
||||
existNum = existNum + result.data.data.length;
|
||||
}
|
||||
} else {
|
||||
// 未开启同步功能
|
||||
count++;
|
||||
let apipath = '/api/interface/add';
|
||||
if (isNode) {
|
||||
apipath = 'http://127.0.0.1:' + port + apipath;
|
||||
}
|
||||
let result = await axios.post(apipath, data);
|
||||
if (result.data.errcode) {
|
||||
successNum--;
|
||||
if (result.data.errcode == 40022) {
|
||||
existNum++;
|
||||
}
|
||||
if (result.data.errcode == 40033) {
|
||||
callback({ showLoading: false });
|
||||
messageError('没有权限');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (count === len) {
|
||||
callback({ showLoading: false });
|
||||
messageSuccess(`成功导入接口 ${successNum} 个, 已存在的接口 ${existNum} 个`);
|
||||
return;
|
||||
}
|
||||
|
||||
taskNotice(index, res.length)
|
||||
}
|
||||
};
|
||||
|
||||
return await handleAddInterface(res);
|
||||
}
|
||||
|
||||
module.exports = handle;
|
||||
29
common/config.js
Normal file
29
common/config.js
Normal file
@@ -0,0 +1,29 @@
|
||||
module.exports = {
|
||||
exts: [{
|
||||
name: 'import-postman'
|
||||
},{
|
||||
name: 'import-har'
|
||||
},{
|
||||
name: 'advanced-mock'
|
||||
},{
|
||||
name: 'import-swagger'
|
||||
},{
|
||||
name: 'statistics'
|
||||
},{
|
||||
name: 'export-data'
|
||||
},{
|
||||
name: 'gen-services'
|
||||
},{
|
||||
name: 'export-swagger2-data'
|
||||
},{
|
||||
name: 'import-yapi-json'
|
||||
},{
|
||||
name: 'wiki'
|
||||
}, {
|
||||
name: 'swagger-auto-sync'
|
||||
}
|
||||
// {
|
||||
// name: 'test'
|
||||
// }
|
||||
]
|
||||
}
|
||||
14
common/createContext.js
Normal file
14
common/createContext.js
Normal file
@@ -0,0 +1,14 @@
|
||||
module.exports = function (uid, projectId,interfaceId) {
|
||||
if(!uid || !projectId || !interfaceId){
|
||||
console.error('uid projectId interfaceId 不能为空', uid, projectId,interfaceId)
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一转换为number
|
||||
*/
|
||||
return {
|
||||
uid: +uid,
|
||||
projectId: +projectId,
|
||||
interfaceId: +interfaceId
|
||||
}
|
||||
}
|
||||
190
common/diff-view.js
Normal file
190
common/diff-view.js
Normal file
@@ -0,0 +1,190 @@
|
||||
// const json5_parse = require('../client/common.js').json5_parse;
|
||||
|
||||
const json5 = require('json5');
|
||||
|
||||
module.exports = function(jsondiffpatch, formattersHtml, curDiffData) {
|
||||
const json5_parse = json => {
|
||||
if (typeof json === 'object' && json) return json;
|
||||
try {
|
||||
return json5.parse(json);
|
||||
} catch (err) {
|
||||
return json;
|
||||
}
|
||||
};
|
||||
|
||||
const diffText = (left, right) => {
|
||||
left = left || '';
|
||||
right = right || '';
|
||||
if (left == right) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var delta = jsondiffpatch.diff(left, right);
|
||||
|
||||
let result = formattersHtml.format(delta, left);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const diffJson = (left, right) => {
|
||||
left = json5_parse(left);
|
||||
right = json5_parse(right);
|
||||
let delta = jsondiffpatch.diff(left, right);
|
||||
return formattersHtml.format(delta, left);
|
||||
// return '';
|
||||
};
|
||||
|
||||
const valueMaps = {
|
||||
'1': '必需',
|
||||
'0': '非必需',
|
||||
text: '文本',
|
||||
file: '文件',
|
||||
undone: '未完成',
|
||||
done: '已完成'
|
||||
};
|
||||
|
||||
const handleParams = item => {
|
||||
let newItem = Object.assign({}, item);
|
||||
newItem._id = undefined;
|
||||
|
||||
Object.keys(newItem).forEach(key => {
|
||||
switch (key) {
|
||||
case 'required':
|
||||
newItem[key] = valueMaps[newItem[key]];
|
||||
break;
|
||||
case 'type':
|
||||
newItem[key] = valueMaps[newItem[key]];
|
||||
break;
|
||||
}
|
||||
});
|
||||
return newItem;
|
||||
};
|
||||
|
||||
const diffArray = (arr1, arr2) => {
|
||||
arr1 = arr1 || [];
|
||||
arr2 = arr2 || [];
|
||||
arr1 = arr1.map(handleParams);
|
||||
arr2 = arr2.map(handleParams);
|
||||
return diffJson(arr1, arr2);
|
||||
};
|
||||
|
||||
let diffView = [];
|
||||
|
||||
if (curDiffData && typeof curDiffData === 'object' && curDiffData.current) {
|
||||
const { current, old, type } = curDiffData;
|
||||
// wiki 信息的diff 输出
|
||||
if (type === 'wiki') {
|
||||
if (current != old) {
|
||||
diffView.push({
|
||||
title: 'wiki更新',
|
||||
content: diffText(old, current)
|
||||
});
|
||||
}
|
||||
return (diffView = diffView.filter(item => item.content));
|
||||
}
|
||||
if (current.path != old.path) {
|
||||
diffView.push({
|
||||
title: 'Api 路径',
|
||||
content: diffText(old.path, current.path)
|
||||
});
|
||||
}
|
||||
if (current.title != old.title) {
|
||||
diffView.push({
|
||||
title: 'Api 名称',
|
||||
content: diffText(old.title, current.title)
|
||||
});
|
||||
}
|
||||
|
||||
if (current.method != old.method) {
|
||||
diffView.push({
|
||||
title: 'Method',
|
||||
content: diffText(old.method, current.method)
|
||||
});
|
||||
}
|
||||
|
||||
if (current.catid != old.catid) {
|
||||
diffView.push({
|
||||
title: '分类 id',
|
||||
content: diffText(old.catid, current.catid)
|
||||
});
|
||||
}
|
||||
|
||||
if (current.status != old.status) {
|
||||
diffView.push({
|
||||
title: '接口状态',
|
||||
content: diffText(valueMaps[old.status], valueMaps[current.status])
|
||||
});
|
||||
}
|
||||
|
||||
if (current.tag !== old.tag) {
|
||||
diffView.push({
|
||||
title: '接口tag',
|
||||
content: diffText(old.tag, current.tag)
|
||||
});
|
||||
}
|
||||
|
||||
diffView.push({
|
||||
title: 'Request Path Params',
|
||||
content: diffArray(old.req_params, current.req_params)
|
||||
});
|
||||
|
||||
diffView.push({
|
||||
title: 'Request Query',
|
||||
content: diffArray(old.req_query, current.req_query)
|
||||
});
|
||||
|
||||
diffView.push({
|
||||
title: 'Request Header',
|
||||
content: diffArray(old.req_headers, current.req_headers)
|
||||
});
|
||||
|
||||
let oldValue = current.req_body_type === 'form' ? old.req_body_form : old.req_body_other;
|
||||
if (current.req_body_type !== old.req_body_type) {
|
||||
diffView.push({
|
||||
title: 'Request Type',
|
||||
content: diffText(old.req_body_type, current.req_body_type)
|
||||
});
|
||||
oldValue = null;
|
||||
}
|
||||
|
||||
if (current.req_body_type === 'json') {
|
||||
diffView.push({
|
||||
title: 'Request Body',
|
||||
content: diffJson(oldValue, current.req_body_other)
|
||||
});
|
||||
} else if (current.req_body_type === 'form') {
|
||||
diffView.push({
|
||||
title: 'Request Form Body',
|
||||
content: diffArray(oldValue, current.req_body_form)
|
||||
});
|
||||
} else {
|
||||
diffView.push({
|
||||
title: 'Request Raw Body',
|
||||
content: diffText(oldValue, current.req_body_other)
|
||||
});
|
||||
}
|
||||
|
||||
let oldResValue = old.res_body;
|
||||
if (current.res_body_type !== old.res_body_type) {
|
||||
diffView.push({
|
||||
title: 'Response Type',
|
||||
content: diffText(old.res_body_type, current.res_body_type)
|
||||
});
|
||||
oldResValue = '';
|
||||
}
|
||||
|
||||
if (current.res_body_type === 'json') {
|
||||
diffView.push({
|
||||
title: 'Response Body',
|
||||
content: diffJson(oldResValue, current.res_body)
|
||||
});
|
||||
} else {
|
||||
diffView.push({
|
||||
title: 'Response Body',
|
||||
content: diffText(oldResValue, current.res_body)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return (diffView = diffView.filter(item => item.content));
|
||||
};
|
||||
101
common/formats.js
Normal file
101
common/formats.js
Normal file
@@ -0,0 +1,101 @@
|
||||
const formats = [
|
||||
{
|
||||
name: 'url',
|
||||
title: 'url'
|
||||
},
|
||||
{
|
||||
name: 'domain',
|
||||
title: '域名'
|
||||
},
|
||||
{
|
||||
name: 'ip',
|
||||
title: 'ipv4 地址'
|
||||
},
|
||||
{
|
||||
name: 'id'
|
||||
},
|
||||
{
|
||||
name: 'guid'
|
||||
},
|
||||
{
|
||||
name: 'now'
|
||||
},
|
||||
{
|
||||
name: 'timestamp'
|
||||
},
|
||||
{
|
||||
name: 'date'
|
||||
},
|
||||
{
|
||||
name: 'time'
|
||||
},
|
||||
{
|
||||
name: 'datetime'
|
||||
},
|
||||
{
|
||||
name: 'image',
|
||||
title: '图片链接'
|
||||
},
|
||||
{
|
||||
name: 'imageData',
|
||||
title: '图片'
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
title: '邮箱'
|
||||
},
|
||||
{
|
||||
name: 'paragraph',
|
||||
title: '段落'
|
||||
},
|
||||
{
|
||||
name: 'sentence',
|
||||
title: '句子'
|
||||
},
|
||||
{
|
||||
name: 'word',
|
||||
title: '单词'
|
||||
},
|
||||
{
|
||||
name: 'title',
|
||||
title: '标题'
|
||||
},
|
||||
{
|
||||
name: 'name',
|
||||
title: '姓名'
|
||||
},
|
||||
{
|
||||
name: 'region',
|
||||
title: '地区'
|
||||
},
|
||||
{
|
||||
name: 'province',
|
||||
title: '省份'
|
||||
},
|
||||
{
|
||||
name: 'city',
|
||||
title: '城市名'
|
||||
},
|
||||
{
|
||||
name: 'county',
|
||||
title: '国家'
|
||||
},
|
||||
{
|
||||
name: 'mobile',
|
||||
title: '手机号'
|
||||
},
|
||||
{
|
||||
name: 'cparagraph',
|
||||
title: '中文本'
|
||||
},
|
||||
{
|
||||
name: 'cname',
|
||||
title: '中文姓名'
|
||||
},
|
||||
{
|
||||
title: '中文标题',
|
||||
name: 'ctitle'
|
||||
}
|
||||
];
|
||||
|
||||
module.exports = formats;
|
||||
97
common/lib.js
Normal file
97
common/lib.js
Normal file
@@ -0,0 +1,97 @@
|
||||
const _ = require('underscore');
|
||||
|
||||
function isObj(object) {
|
||||
return (
|
||||
object &&
|
||||
typeof object == 'object' &&
|
||||
Object.prototype.toString.call(object).toLowerCase() == '[object object]'
|
||||
);
|
||||
}
|
||||
|
||||
function isArray(object) {
|
||||
return object && typeof object == 'object' && object.constructor == Array;
|
||||
}
|
||||
|
||||
function getLength(object) {
|
||||
return Object.keys(object).length;
|
||||
}
|
||||
|
||||
function Compare(objA, objB) {
|
||||
if (!isObj(objA) && !isObj(objB)) {
|
||||
if (isArray(objA) && isArray(objB)) {
|
||||
return CompareArray(objA, objB, true);
|
||||
}
|
||||
return objA == objB;
|
||||
}
|
||||
if (!isObj(objA) || !isObj(objB)) return false;
|
||||
if (getLength(objA) != getLength(objB)) return false;
|
||||
return CompareObj(objA, objB, true);
|
||||
}
|
||||
|
||||
function CompareArray(objA, objB, flag) {
|
||||
if (objA.length != objB.length) return false;
|
||||
for (let i in objB) {
|
||||
if (!Compare(objA[i], objB[i])) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
function CompareObj(objA, objB, flag) {
|
||||
for (var key in objA) {
|
||||
if (!flag) break;
|
||||
if (!objB.hasOwnProperty(key)) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
if (!isArray(objA[key])) {
|
||||
if (objB[key] != objA[key]) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (!isArray(objB[key])) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
var oA = objA[key],
|
||||
oB = objB[key];
|
||||
if (oA.length != oB.length) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
for (var k in oA) {
|
||||
if (!flag) break;
|
||||
flag = CompareObj(oA[k], oB[k], flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
exports.jsonEqual = Compare;
|
||||
|
||||
exports.isDeepMatch = function(obj, properties) {
|
||||
|
||||
if (!properties || typeof properties !== 'object' || Object.keys(properties).length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!obj || typeof obj !== 'object' || Object.keys(obj).length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let match = true;
|
||||
let keys = Object.keys(properties)
|
||||
for (let index=0; index< keys.length; index++) {
|
||||
let i = keys[index];
|
||||
if (!Compare(obj[i], properties[i])) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return match;
|
||||
};
|
||||
325
common/markdown.js
Normal file
325
common/markdown.js
Normal file
@@ -0,0 +1,325 @@
|
||||
const schema = require('./schema-transformTo-table.js');
|
||||
const _ = require('underscore');
|
||||
|
||||
const json_parse = function(json) {
|
||||
try {
|
||||
return JSON.parse(json);
|
||||
} catch (err) {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
// 处理字符串换行
|
||||
const handleWrap = str => {
|
||||
return _.isString(str) ? str.replace(/\n/gi, '<br/>') : str;
|
||||
};
|
||||
const messageMap = {
|
||||
desc: '备注',
|
||||
default: '实例',
|
||||
maximum: '最大值',
|
||||
minimum: '最小值',
|
||||
maxItems: '最大数量',
|
||||
minItems: '最小数量',
|
||||
maxLength: '最大长度',
|
||||
minLength: '最小长度',
|
||||
uniqueItems: '元素是否都不同',
|
||||
itemType: 'item 类型',
|
||||
format: 'format',
|
||||
enum: '枚举',
|
||||
enumDesc: '枚举备注',
|
||||
mock: 'mock'
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name'
|
||||
},
|
||||
{
|
||||
title: '类型',
|
||||
dataIndex: 'type',
|
||||
key: 'type'
|
||||
},
|
||||
{
|
||||
title: '是否必须',
|
||||
dataIndex: 'required',
|
||||
key: 'required'
|
||||
},
|
||||
{
|
||||
title: '默认值',
|
||||
dataIndex: 'default',
|
||||
key: 'default'
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'desc',
|
||||
key: 'desc'
|
||||
},
|
||||
{
|
||||
title: '其他信息',
|
||||
dataIndex: 'sub',
|
||||
key: 'sub'
|
||||
}
|
||||
];
|
||||
|
||||
function escapeStr(str, isToc) {
|
||||
return isToc ? escape(str) : str;
|
||||
}
|
||||
|
||||
function createBaseMessage(basepath, inter) {
|
||||
// 基本信息
|
||||
let baseMessage = `### 基本信息\n\n**Path:** ${basepath + inter.path}\n\n**Method:** ${
|
||||
inter.method
|
||||
}\n\n**接口描述:**\n${_.isUndefined(inter.desc) ? '' : inter.desc}\n`;
|
||||
return baseMessage;
|
||||
}
|
||||
|
||||
function createReqHeaders(req_headers) {
|
||||
// Request-headers
|
||||
if (req_headers && req_headers.length) {
|
||||
let headersTable = `**Headers**\n\n`;
|
||||
headersTable += `| 参数名称 | 参数值 | 是否必须 | 示例 | 备注 |\n| ------------ | ------------ | ------------ | ------------ | ------------ |\n`;
|
||||
for (let j = 0; j < req_headers.length; j++) {
|
||||
headersTable += `| ${req_headers[j].name || ''} | ${req_headers[j].value || ''} | ${
|
||||
req_headers[j].required == 1 ? '是' : '否'
|
||||
} | ${handleWrap(req_headers[j].example) || ''} | ${handleWrap(req_headers[j].desc) ||
|
||||
''} |\n`;
|
||||
}
|
||||
return headersTable;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function createPathParams(req_params) {
|
||||
if (req_params && req_params.length) {
|
||||
let paramsTable = `**路径参数**\n\n`;
|
||||
paramsTable += `| 参数名称 | 示例 | 备注 |\n| ------------ | ------------ | ------------ |\n`;
|
||||
for (let j = 0; j < req_params.length; j++) {
|
||||
paramsTable += `| ${req_params[j].name || ''} | ${handleWrap(req_params[j].example) ||
|
||||
''} | ${handleWrap(req_params[j].desc) || ''} |\n`;
|
||||
}
|
||||
return paramsTable;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function createReqQuery(req_query) {
|
||||
if (req_query && req_query.length) {
|
||||
let headersTable = `**Query**\n\n`;
|
||||
headersTable += `| 参数名称 | 是否必须 | 示例 | 备注 |\n| ------------ | ------------ | ------------ | ------------ |\n`;
|
||||
for (let j = 0; j < req_query.length; j++) {
|
||||
headersTable += `| ${req_query[j].name || ''} | ${
|
||||
req_query[j].required == 1 ? '是' : '否'
|
||||
} | ${handleWrap(req_query[j].example) || ''} | ${handleWrap(req_query[j].desc) ||
|
||||
''} |\n`;
|
||||
}
|
||||
return headersTable;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function createReqBody(req_body_type, req_body_form, req_body_other, req_body_is_json_schema) {
|
||||
if (req_body_type === 'form' && req_body_form.length) {
|
||||
let bodyTable = `**Body**\n\n`;
|
||||
bodyTable += `| 参数名称 | 参数类型 | 是否必须 | 示例 | 备注 |\n| ------------ | ------------ | ------------ | ------------ | ------------ |\n`;
|
||||
let req_body = req_body_form;
|
||||
for (let j = 0; j < req_body.length; j++) {
|
||||
bodyTable += `| ${req_body[j].name || ''} | ${req_body[j].type || ''} | ${
|
||||
req_body[j].required == 1 ? '是' : '否'
|
||||
} | ${req_body[j].example || ''} | ${req_body[j].desc || ''} |\n`;
|
||||
}
|
||||
return `${bodyTable}\n\n`;
|
||||
} else if (req_body_other) {
|
||||
if (req_body_is_json_schema) {
|
||||
let reqBody = createSchemaTable(req_body_other);
|
||||
return `**Body**\n\n` + reqBody;
|
||||
} else {
|
||||
//other
|
||||
return `**Body**\n\n` + '```javascript' + `\n${req_body_other || ''}` + '\n```';
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function tableHeader(columns) {
|
||||
let header = ``;
|
||||
columns.map(item => {
|
||||
header += `<th key=${item.key}>${item.title}</th>`;
|
||||
});
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
function handleObject(text) {
|
||||
if (!_.isObject(text)) {
|
||||
return text;
|
||||
}
|
||||
let tpl = ``;
|
||||
Object.keys(text || {}).map((item, index) => {
|
||||
let name = messageMap[item];
|
||||
let value = text[item];
|
||||
tpl += _.isUndefined(text[item])
|
||||
? ''
|
||||
: `<p key=${index}><span style="font-weight: '700'">${name}: </span><span>${value.toString()}</span></p>`;
|
||||
});
|
||||
|
||||
return tpl;
|
||||
}
|
||||
|
||||
function tableCol(col, columns, level) {
|
||||
let tpl = ``;
|
||||
columns.map((item, index) => {
|
||||
let dataIndex = item.dataIndex;
|
||||
let value = col[dataIndex];
|
||||
value = _.isUndefined(value) ? '' : value;
|
||||
let text = ``;
|
||||
|
||||
switch (dataIndex) {
|
||||
case 'sub':
|
||||
text = handleObject(value);
|
||||
break;
|
||||
case 'type':
|
||||
text =
|
||||
value === 'array'
|
||||
? `<span>${col.sub ? col.sub.itemType || '' : 'array'} []</span>`
|
||||
: `<span>${value}</span>`;
|
||||
break;
|
||||
case 'required':
|
||||
text = value ? '必须' : '非必须';
|
||||
break;
|
||||
case 'desc':
|
||||
text = _.isUndefined(col.childrenDesc)
|
||||
? `<span style="white-space: pre-wrap">${value}</span>`
|
||||
: `<span style="white-space: pre-wrap">${col.childrenDesc}</span>`;
|
||||
break;
|
||||
case 'name':
|
||||
text = `<span style="padding-left: ${20 * level}px"><span style="color: #8c8a8a">${
|
||||
level > 0 ? '├─' : ''
|
||||
}</span> ${value}</span>`;
|
||||
break;
|
||||
default:
|
||||
text = value;
|
||||
}
|
||||
tpl += `<td key=${index}>${text}</td>`;
|
||||
});
|
||||
|
||||
return tpl;
|
||||
}
|
||||
|
||||
function tableBody(dataSource, columns, level) {
|
||||
// 按照columns的顺序排列数据
|
||||
let tpl = ``;
|
||||
dataSource.map(col => {
|
||||
let child = null;
|
||||
tpl += `<tr key=${col.key}>${tableCol(col, columns, level)}</tr>`;
|
||||
if (!_.isUndefined(col.children) && _.isArray(col.children)) {
|
||||
let index = level + 1;
|
||||
child = tableBody(col.children, columns, index);
|
||||
}
|
||||
tpl += child ? `${child}` : ``;
|
||||
});
|
||||
|
||||
return tpl;
|
||||
}
|
||||
|
||||
function createSchemaTable(body) {
|
||||
let template = ``;
|
||||
let dataSource = schema.schemaTransformToTable(json_parse(body));
|
||||
template += `<table>
|
||||
<thead class="ant-table-thead">
|
||||
<tr>
|
||||
${tableHeader(columns)}
|
||||
</tr>
|
||||
</thead>`;
|
||||
|
||||
template += `<tbody className="ant-table-tbody">${tableBody(dataSource, columns, 0)}
|
||||
</tbody>
|
||||
</table>
|
||||
`;
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
function createResponse(res_body, res_body_is_json_schema, res_body_type) {
|
||||
let resTitle = `\n### 返回数据\n\n`;
|
||||
if (res_body) {
|
||||
if (res_body_is_json_schema && res_body_type === 'json') {
|
||||
let resBody = createSchemaTable(res_body);
|
||||
return resTitle + resBody;
|
||||
} else {
|
||||
let resBody = '```javascript' + `\n${res_body || ''}\n` + '```';
|
||||
return resTitle + resBody;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function createInterMarkdown(basepath, listItem, isToc) {
|
||||
let mdTemplate = ``;
|
||||
const toc = `[TOC]\n\n`;
|
||||
// 接口名称
|
||||
mdTemplate += `\n## ${escapeStr(`${listItem.title}\n<a id=${listItem.title + listItem.catid}> </a>`, isToc)}\n`;
|
||||
isToc && (mdTemplate += toc);
|
||||
// 基本信息
|
||||
mdTemplate += createBaseMessage(basepath, listItem);
|
||||
// Request
|
||||
mdTemplate += `\n### 请求参数\n`;
|
||||
// Request-headers
|
||||
mdTemplate += createReqHeaders(listItem.req_headers);
|
||||
// Request-params
|
||||
mdTemplate += createPathParams(listItem.req_params);
|
||||
// Request-query
|
||||
mdTemplate += createReqQuery(listItem.req_query);
|
||||
// Request-body
|
||||
mdTemplate += createReqBody(
|
||||
listItem.req_body_type,
|
||||
listItem.req_body_form,
|
||||
listItem.req_body_other,
|
||||
listItem.req_body_is_json_schema
|
||||
);
|
||||
// Response
|
||||
// Response-body
|
||||
mdTemplate += createResponse(
|
||||
listItem.res_body,
|
||||
listItem.res_body_is_json_schema,
|
||||
listItem.res_body_type
|
||||
);
|
||||
|
||||
return mdTemplate;
|
||||
}
|
||||
|
||||
function createProjectMarkdown(curProject, wikiData) {
|
||||
let mdTemplate = ``;
|
||||
// 项目名、项目描述
|
||||
let title = `<h1 class="curproject-name"> ${curProject.name} </h1>`;
|
||||
|
||||
mdTemplate += `\n ${title} \n ${curProject.desc || ''}\n\n`;
|
||||
|
||||
// 增加公共wiki信息展示
|
||||
mdTemplate += wikiData ? `\n### 公共信息\n${wikiData.desc || ''}\n` : '';
|
||||
return mdTemplate;
|
||||
}
|
||||
|
||||
function createClassMarkdown(curProject, list, isToc) {
|
||||
let mdTemplate = ``;
|
||||
const toc = `[TOC]\n\n`;
|
||||
list.map(item => {
|
||||
// 分类名称
|
||||
mdTemplate += `\n# ${escapeStr(item.name, isToc)}\n`;
|
||||
isToc && (mdTemplate += toc);
|
||||
for (let i = 0; i < item.list.length; i++) {
|
||||
//循环拼接 接口
|
||||
// 接口内容
|
||||
mdTemplate += createInterMarkdown(curProject.basepath, item.list[i], isToc);
|
||||
}
|
||||
});
|
||||
return mdTemplate;
|
||||
}
|
||||
|
||||
let r = {
|
||||
createInterMarkdown,
|
||||
createProjectMarkdown,
|
||||
createClassMarkdown
|
||||
};
|
||||
|
||||
module.exports = r;
|
||||
34
common/mergeJsonSchema.js
Normal file
34
common/mergeJsonSchema.js
Normal file
@@ -0,0 +1,34 @@
|
||||
function isPlainObject(obj) {
|
||||
return obj ? typeof obj === 'object' && Object.getPrototypeOf(obj) === Object.prototype : false;
|
||||
}
|
||||
|
||||
function handleProperties(sourceProperties, mergeProperties){
|
||||
if(!isPlainObject(mergeProperties)){
|
||||
return mergeProperties
|
||||
}
|
||||
if(! isPlainObject(sourceProperties)){
|
||||
return mergeProperties
|
||||
}
|
||||
Object.keys(mergeProperties).forEach(key=>{
|
||||
mergeProperties[key]= handleSchema(sourceProperties[key], mergeProperties[key])
|
||||
})
|
||||
return mergeProperties;
|
||||
}
|
||||
|
||||
|
||||
function handleSchema(source, merge){
|
||||
if(!isPlainObject(source)) return merge;
|
||||
if(!isPlainObject(merge)) return merge;
|
||||
let result = {}
|
||||
Object.assign(result, source, merge)
|
||||
if(merge.type === 'object'){
|
||||
result.properties = handleProperties(source.properties, merge.properties);
|
||||
}else if(merge.type === 'array'){
|
||||
result.items = handleSchema(source.items, merge.items);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = function(sourceJsonSchema, mergeJsonSchema){
|
||||
return handleSchema(sourceJsonSchema, mergeJsonSchema)
|
||||
}
|
||||
95
common/mock-extra.js
Normal file
95
common/mock-extra.js
Normal file
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* @author suxiaoxin
|
||||
* @info mockJs 功能增强脚本
|
||||
*/
|
||||
var strRegex = /\${([a-zA-Z]+)\.?([a-zA-Z0-9_\.]*)\}/i;
|
||||
var varSplit = '.';
|
||||
var mockSplit = '|';
|
||||
var Mock = require('mockjs');
|
||||
Mock.Random.extend({
|
||||
timestamp: function(){
|
||||
var time = new Date().getTime() + '';
|
||||
return +time.substr(0, time.length - 3)
|
||||
}
|
||||
})
|
||||
|
||||
function mock(mockJSON, context) {
|
||||
context = context || {};
|
||||
var filtersMap = {
|
||||
regexp: handleRegexp
|
||||
};
|
||||
if(!mockJSON || typeof mockJSON !== 'object'){
|
||||
return mockJSON;
|
||||
}
|
||||
|
||||
return parse(mockJSON);
|
||||
|
||||
function parse(p, c) {
|
||||
if(!c){
|
||||
c = Array.isArray(p) ? [] : {}
|
||||
}
|
||||
|
||||
for (var i in p) {
|
||||
if (!p.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
if (p[i] && typeof p[i] === 'object') {
|
||||
c[i] = (p[i].constructor === Array) ? [] : {};
|
||||
parse(p[i], c[i]);
|
||||
} else if(p[i] && typeof p[i] === 'string'){
|
||||
p[i] = handleStr(p[i]);
|
||||
var filters = i.split(mockSplit), newFilters = [].concat(filters);
|
||||
c[i] = p[i];
|
||||
if (filters.length > 1) {
|
||||
for (var f = 1, l = filters.length, index; f < l; f++) {
|
||||
filters[f] = filters[f].toLowerCase();
|
||||
if (filters[f] in filtersMap) {
|
||||
if ((index = newFilters.indexOf(filters[f])) !== -1) {
|
||||
newFilters.splice(index, 1);
|
||||
}
|
||||
delete c[i];
|
||||
c[newFilters.join(mockSplit)] = filtersMap[filters[f]].call(p, p[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
c[i] = p[i];
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
function handleRegexp(item) {
|
||||
return new RegExp(item);
|
||||
}
|
||||
|
||||
function handleStr(str) {
|
||||
if (typeof str !== 'string' || str.indexOf('{') === -1 || str.indexOf('}') === -1 || str.indexOf('$') === -1) {
|
||||
return str;
|
||||
}
|
||||
|
||||
let matchs = str.match(strRegex);
|
||||
if(matchs){
|
||||
let name = matchs[1] + (matchs[2]? '.' + matchs[2] : '');
|
||||
if(!name) return str;
|
||||
var names = name.split(varSplit);
|
||||
var data = context;
|
||||
|
||||
if(typeof context[names[0]] === undefined){
|
||||
return str;
|
||||
}
|
||||
names.forEach(function (n) {
|
||||
if (data === '') return '';
|
||||
if (n in data) {
|
||||
data = data[n];
|
||||
} else {
|
||||
data = '';
|
||||
}
|
||||
});
|
||||
return data;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = mock;
|
||||
54
common/plugin.js
Normal file
54
common/plugin.js
Normal file
@@ -0,0 +1,54 @@
|
||||
const _ = require('underscore');
|
||||
|
||||
function getPluginConfig(name, type) {
|
||||
let pluginConfig;
|
||||
if (type === 'ext') {
|
||||
pluginConfig = require('../exts/yapi-plugin-' + name);
|
||||
} else {
|
||||
pluginConfig = require('yapi-plugin-' + name);
|
||||
}
|
||||
|
||||
if (!pluginConfig || typeof pluginConfig !== 'object') {
|
||||
throw new Error(`Plugin ${name} Config 配置错误,请检查 yapi-plugin-${name}/index.js`);
|
||||
}
|
||||
|
||||
return {
|
||||
server: pluginConfig.server,
|
||||
client: pluginConfig.client
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* type @string enum[plugin, ext] plugin是外部插件,ext是内部插件
|
||||
*/
|
||||
exports.initPlugins = function (plugins, type) {
|
||||
if (!plugins) {
|
||||
return [];
|
||||
}
|
||||
if (typeof plugins !== 'object' || !Array.isArray(plugins)) {
|
||||
throw new Error('插件配置有误,请检查', plugins);
|
||||
}
|
||||
|
||||
plugins = plugins.map(item => {
|
||||
let pluginConfig;
|
||||
if (item && typeof item === 'string') {
|
||||
pluginConfig = getPluginConfig(item, type);
|
||||
return Object.assign({}, pluginConfig, { name: item, enable: true })
|
||||
} else if (item && typeof item === 'object') {
|
||||
pluginConfig = getPluginConfig(item.name, type);
|
||||
return Object.assign({},
|
||||
pluginConfig,
|
||||
{
|
||||
name: item.name,
|
||||
options: item.options,
|
||||
enable: item.enable === false ? false : true
|
||||
})
|
||||
}
|
||||
})
|
||||
plugins = plugins.filter(item => {
|
||||
return item.enable === true && (item.server || item.client)
|
||||
})
|
||||
|
||||
return _.uniq(plugins, item => item.name)
|
||||
}
|
||||
484
common/postmanLib.js
Normal file
484
common/postmanLib.js
Normal file
@@ -0,0 +1,484 @@
|
||||
const { isJson5, json_parse, handleJson, joinPath, safeArray } = require('./utils');
|
||||
const constants = require('../client/constants/variable.js');
|
||||
const _ = require('underscore');
|
||||
const URL = require('url');
|
||||
const utils = require('./power-string.js').utils;
|
||||
const HTTP_METHOD = constants.HTTP_METHOD;
|
||||
const axios = require('axios');
|
||||
const qs = require('qs');
|
||||
const CryptoJS = require('crypto-js');
|
||||
const jsrsasign = require('jsrsasign');
|
||||
const https = require('https');
|
||||
|
||||
const isNode = typeof global == 'object' && global.global === global;
|
||||
const ContentTypeMap = {
|
||||
'application/json': 'json',
|
||||
'application/xml': 'xml',
|
||||
'text/xml': 'xml',
|
||||
'application/html': 'html',
|
||||
'text/html': 'html',
|
||||
other: 'text'
|
||||
};
|
||||
|
||||
const getStorage = async (id)=>{
|
||||
try{
|
||||
if(isNode){
|
||||
let storage = global.storageCreator(id);
|
||||
let data = await storage.getItem();
|
||||
return {
|
||||
getItem: (name)=> data[name],
|
||||
setItem: (name, value)=>{
|
||||
data[name] = value;
|
||||
storage.setItem(name, value)
|
||||
}
|
||||
}
|
||||
}else{
|
||||
return {
|
||||
getItem: (name)=> window.localStorage.getItem(name),
|
||||
setItem: (name, value)=> window.localStorage.setItem(name, value)
|
||||
}
|
||||
}
|
||||
}catch(e){
|
||||
console.error(e)
|
||||
return {
|
||||
getItem: (name)=>{
|
||||
console.error(name, e)
|
||||
},
|
||||
setItem: (name, value)=>{
|
||||
console.error(name, value, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function httpRequestByNode(options) {
|
||||
function handleRes(response) {
|
||||
if (!response || typeof response !== 'object') {
|
||||
return {
|
||||
res: {
|
||||
status: 500,
|
||||
body: isNode
|
||||
? '请求出错, 内网服务器自动化测试无法访问到,请检查是否为内网服务器!'
|
||||
: '请求出错'
|
||||
}
|
||||
};
|
||||
}
|
||||
return {
|
||||
res: {
|
||||
header: response.headers,
|
||||
status: response.status,
|
||||
body: response.data
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function handleData() {
|
||||
let contentTypeItem;
|
||||
if (!options) return;
|
||||
if (typeof options.headers === 'object' && options.headers) {
|
||||
Object.keys(options.headers).forEach(key => {
|
||||
if (/content-type/i.test(key)) {
|
||||
if (options.headers[key]) {
|
||||
contentTypeItem = options.headers[key]
|
||||
.split(';')[0]
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
}
|
||||
}
|
||||
if (!options.headers[key]) delete options.headers[key];
|
||||
});
|
||||
|
||||
if (
|
||||
contentTypeItem === 'application/x-www-form-urlencoded' &&
|
||||
typeof options.data === 'object' &&
|
||||
options.data
|
||||
) {
|
||||
options.data = qs.stringify(options.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
handleData(options);
|
||||
let response = await axios({
|
||||
method: options.method,
|
||||
url: options.url,
|
||||
headers: options.headers,
|
||||
timeout: 10000,
|
||||
maxRedirects: 0,
|
||||
httpsAgent: new https.Agent({
|
||||
rejectUnauthorized: false
|
||||
}),
|
||||
data: options.data
|
||||
});
|
||||
return handleRes(response);
|
||||
} catch (err) {
|
||||
if (err.response === undefined) {
|
||||
return handleRes({
|
||||
headers: {},
|
||||
status: null,
|
||||
data: err.message
|
||||
});
|
||||
}
|
||||
return handleRes(err.response);
|
||||
}
|
||||
}
|
||||
|
||||
function handleContentType(headers) {
|
||||
if (!headers || typeof headers !== 'object') return ContentTypeMap.other;
|
||||
let contentTypeItem = 'other';
|
||||
try {
|
||||
Object.keys(headers).forEach(key => {
|
||||
if (/content-type/i.test(key)) {
|
||||
contentTypeItem = headers[key]
|
||||
.split(';')[0]
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
}
|
||||
});
|
||||
return ContentTypeMap[contentTypeItem] ? ContentTypeMap[contentTypeItem] : ContentTypeMap.other;
|
||||
} catch (err) {
|
||||
return ContentTypeMap.other;
|
||||
}
|
||||
}
|
||||
|
||||
function checkRequestBodyIsRaw(method, reqBodyType) {
|
||||
if (
|
||||
reqBodyType &&
|
||||
reqBodyType !== 'file' &&
|
||||
reqBodyType !== 'form' &&
|
||||
HTTP_METHOD[method].request_body
|
||||
) {
|
||||
return reqBodyType;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkNameIsExistInArray(name, arr) {
|
||||
let isRepeat = false;
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
let item = arr[i];
|
||||
if (item.name === name) {
|
||||
isRepeat = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isRepeat;
|
||||
}
|
||||
|
||||
function handleCurrDomain(domains, case_env) {
|
||||
let currDomain = _.find(domains, item => item.name === case_env);
|
||||
|
||||
if (!currDomain) {
|
||||
currDomain = domains[0];
|
||||
}
|
||||
return currDomain;
|
||||
}
|
||||
|
||||
function sandboxByNode(sandbox = {}, script) {
|
||||
const vm = require('vm');
|
||||
script = new vm.Script(script);
|
||||
const context = new vm.createContext(sandbox);
|
||||
script.runInContext(context, {
|
||||
timeout: 10000
|
||||
});
|
||||
return sandbox;
|
||||
}
|
||||
|
||||
async function sandbox(context = {}, script) {
|
||||
if (isNode) {
|
||||
try {
|
||||
context.context = context;
|
||||
context.console = console;
|
||||
context.Promise = Promise;
|
||||
context.setTimeout = setTimeout;
|
||||
context = sandboxByNode(context, script);
|
||||
} catch (err) {
|
||||
err.message = `Script: ${script}
|
||||
message: ${err.message}`;
|
||||
throw err;
|
||||
}
|
||||
} else {
|
||||
context = sandboxByBrowser(context, script);
|
||||
}
|
||||
if (context.promise && typeof context.promise === 'object' && context.promise.then) {
|
||||
try {
|
||||
await context.promise;
|
||||
} catch (err) {
|
||||
err.message = `Script: ${script}
|
||||
message: ${err.message}`;
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
function sandboxByBrowser(context = {}, script) {
|
||||
if (!script || typeof script !== 'string') {
|
||||
return context;
|
||||
}
|
||||
let beginScript = '';
|
||||
for (var i in context) {
|
||||
beginScript += `var ${i} = context.${i};`;
|
||||
}
|
||||
try {
|
||||
eval(beginScript + script);
|
||||
} catch (err) {
|
||||
let message = `Script:
|
||||
----CodeBegin----:
|
||||
${beginScript}
|
||||
${script}
|
||||
----CodeEnd----
|
||||
`;
|
||||
err.message = `Script: ${message}
|
||||
message: ${err.message}`;
|
||||
|
||||
throw err;
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} defaultOptions
|
||||
* @param {*} preScript
|
||||
* @param {*} afterScript
|
||||
* @param {*} commonContext 负责传递一些业务信息,crossRequest 不关注具体传什么,只负责当中间人
|
||||
*/
|
||||
async function crossRequest(defaultOptions, preScript, afterScript, commonContext = {}) {
|
||||
let options = Object.assign({}, defaultOptions);
|
||||
const taskId = options.taskId || Math.random() + '';
|
||||
let urlObj = URL.parse(options.url, true),
|
||||
query = {};
|
||||
query = Object.assign(query, urlObj.query);
|
||||
let context = {
|
||||
isNode,
|
||||
get href() {
|
||||
return urlObj.href;
|
||||
},
|
||||
set href(val) {
|
||||
throw new Error('context.href 不能被赋值');
|
||||
},
|
||||
get hostname() {
|
||||
return urlObj.hostname;
|
||||
},
|
||||
set hostname(val) {
|
||||
throw new Error('context.hostname 不能被赋值');
|
||||
},
|
||||
|
||||
get caseId() {
|
||||
return options.caseId;
|
||||
},
|
||||
|
||||
set caseId(val) {
|
||||
throw new Error('context.caseId 不能被赋值');
|
||||
},
|
||||
|
||||
method: options.method,
|
||||
pathname: urlObj.pathname,
|
||||
query: query,
|
||||
requestHeader: options.headers || {},
|
||||
requestBody: options.data,
|
||||
promise: false,
|
||||
storage: await getStorage(taskId)
|
||||
};
|
||||
|
||||
Object.assign(context, commonContext)
|
||||
|
||||
context.utils = Object.freeze({
|
||||
_: _,
|
||||
CryptoJS: CryptoJS,
|
||||
jsrsasign: jsrsasign,
|
||||
base64: utils.base64,
|
||||
md5: utils.md5,
|
||||
sha1: utils.sha1,
|
||||
sha224: utils.sha224,
|
||||
sha256: utils.sha256,
|
||||
sha384: utils.sha384,
|
||||
sha512: utils.sha512,
|
||||
unbase64: utils.unbase64,
|
||||
axios: axios
|
||||
});
|
||||
|
||||
let scriptEnable = true;
|
||||
if (preScript && scriptEnable) {
|
||||
context = await sandbox(context, preScript);
|
||||
defaultOptions.url = options.url = URL.format({
|
||||
protocol: urlObj.protocol,
|
||||
host: urlObj.host,
|
||||
query: context.query,
|
||||
pathname: context.pathname
|
||||
});
|
||||
defaultOptions.headers = options.headers = context.requestHeader;
|
||||
defaultOptions.data = options.data = context.requestBody;
|
||||
}
|
||||
|
||||
let data;
|
||||
|
||||
if (isNode) {
|
||||
data = await httpRequestByNode(options);
|
||||
data.req = options;
|
||||
} else {
|
||||
data = await new Promise((resolve, reject) => {
|
||||
options.error = options.success = function(res, header, data) {
|
||||
let message = '';
|
||||
if (res && typeof res === 'string') {
|
||||
res = json_parse(data.res.body);
|
||||
data.res.body = res;
|
||||
}
|
||||
if (!isNode) message = '请求异常,请检查 chrome network 错误信息... https://juejin.im/post/5c888a3e5188257dee0322af 通过该链接查看教程")';
|
||||
if (isNaN(data.res.status)) {
|
||||
reject({
|
||||
body: res || message,
|
||||
header,
|
||||
message
|
||||
});
|
||||
}
|
||||
resolve(data);
|
||||
};
|
||||
|
||||
window.crossRequest(options);
|
||||
});
|
||||
}
|
||||
|
||||
if (afterScript && scriptEnable) {
|
||||
context.responseData = data.res.body;
|
||||
context.responseHeader = data.res.header;
|
||||
context.responseStatus = data.res.status;
|
||||
context.runTime = data.runTime;
|
||||
context = await sandbox(context, afterScript);
|
||||
data.res.body = context.responseData;
|
||||
data.res.header = context.responseHeader;
|
||||
data.res.status = context.responseStatus;
|
||||
data.runTime = context.runTime;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function handleParams(interfaceData, handleValue, requestParams) {
|
||||
let interfaceRunData = Object.assign({}, interfaceData);
|
||||
function paramsToObjectWithEnable(arr) {
|
||||
const obj = {};
|
||||
safeArray(arr).forEach(item => {
|
||||
if (item && item.name && (item.enable || item.required === '1')) {
|
||||
obj[item.name] = handleValue(item.value, currDomain.global);
|
||||
if (requestParams) {
|
||||
requestParams[item.name] = obj[item.name];
|
||||
}
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
}
|
||||
|
||||
function paramsToObjectUnWithEnable(arr) {
|
||||
const obj = {};
|
||||
safeArray(arr).forEach(item => {
|
||||
if (item && item.name) {
|
||||
obj[item.name] = handleValue(item.value, currDomain.global);
|
||||
if (requestParams) {
|
||||
requestParams[item.name] = obj[item.name];
|
||||
}
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
}
|
||||
|
||||
let { case_env, path, env, _id } = interfaceRunData;
|
||||
let currDomain,
|
||||
requestBody,
|
||||
requestOptions = {};
|
||||
currDomain = handleCurrDomain(env, case_env);
|
||||
interfaceRunData.req_params = interfaceRunData.req_params || [];
|
||||
interfaceRunData.req_params.forEach(item => {
|
||||
let val = handleValue(item.value, currDomain.global);
|
||||
if (requestParams) {
|
||||
requestParams[item.name] = val;
|
||||
}
|
||||
path = path.replace(`:${item.name}`, val || `:${item.name}`);
|
||||
path = path.replace(`{${item.name}}`, val || `{${item.name}}`);
|
||||
});
|
||||
|
||||
const urlObj = URL.parse(joinPath(currDomain.domain, path), true);
|
||||
const url = URL.format({
|
||||
protocol: urlObj.protocol || 'http',
|
||||
host: urlObj.host,
|
||||
pathname: urlObj.pathname,
|
||||
query: Object.assign(urlObj.query, paramsToObjectWithEnable(interfaceRunData.req_query))
|
||||
});
|
||||
|
||||
let headers = paramsToObjectUnWithEnable(interfaceRunData.req_headers);
|
||||
requestOptions = {
|
||||
url,
|
||||
caseId: _id,
|
||||
method: interfaceRunData.method,
|
||||
headers,
|
||||
timeout: 82400000
|
||||
};
|
||||
|
||||
// 对 raw 类型的 form 处理
|
||||
try {
|
||||
if (interfaceRunData.req_body_type === 'raw') {
|
||||
if (headers && headers['Content-Type']) {
|
||||
if (headers['Content-Type'].indexOf('application/x-www-form-urlencoded') >= 0) {
|
||||
interfaceRunData.req_body_type = 'form';
|
||||
let reqData = json_parse(interfaceRunData.req_body_other);
|
||||
if (reqData && typeof reqData === 'object') {
|
||||
interfaceRunData.req_body_form = [];
|
||||
Object.keys(reqData).forEach(key => {
|
||||
interfaceRunData.req_body_form.push({
|
||||
name: key,
|
||||
type: 'text',
|
||||
value: JSON.stringify(reqData[key]),
|
||||
enable: true
|
||||
});
|
||||
});
|
||||
}
|
||||
} else if (headers['Content-Type'].indexOf('application/json') >= 0) {
|
||||
interfaceRunData.req_body_type = 'json';
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('err', e);
|
||||
}
|
||||
|
||||
if (HTTP_METHOD[interfaceRunData.method].request_body) {
|
||||
if (interfaceRunData.req_body_type === 'form') {
|
||||
requestBody = paramsToObjectWithEnable(
|
||||
safeArray(interfaceRunData.req_body_form).filter(item => {
|
||||
return item.type == 'text';
|
||||
})
|
||||
);
|
||||
} else if (interfaceRunData.req_body_type === 'json') {
|
||||
let reqBody = isJson5(interfaceRunData.req_body_other);
|
||||
if (reqBody === false) {
|
||||
requestBody = interfaceRunData.req_body_other;
|
||||
} else {
|
||||
if (requestParams) {
|
||||
requestParams = Object.assign(requestParams, reqBody);
|
||||
}
|
||||
requestBody = handleJson(reqBody, val => handleValue(val, currDomain.global));
|
||||
}
|
||||
} else {
|
||||
requestBody = interfaceRunData.req_body_other;
|
||||
}
|
||||
requestOptions.data = requestBody;
|
||||
if (interfaceRunData.req_body_type === 'form') {
|
||||
requestOptions.files = paramsToObjectWithEnable(
|
||||
safeArray(interfaceRunData.req_body_form).filter(item => {
|
||||
return item.type == 'file';
|
||||
})
|
||||
);
|
||||
} else if (interfaceRunData.req_body_type === 'file') {
|
||||
requestOptions.file = 'single-file';
|
||||
}
|
||||
}
|
||||
return requestOptions;
|
||||
}
|
||||
|
||||
exports.checkRequestBodyIsRaw = checkRequestBodyIsRaw;
|
||||
exports.handleParams = handleParams;
|
||||
exports.handleContentType = handleContentType;
|
||||
exports.crossRequest = crossRequest;
|
||||
exports.handleCurrDomain = handleCurrDomain;
|
||||
exports.checkNameIsExistInArray = checkNameIsExistInArray;
|
||||
202
common/power-string.js
Normal file
202
common/power-string.js
Normal file
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* @author suxiaoxin
|
||||
*/
|
||||
|
||||
const aUniqueVerticalStringNotFoundInData = '___UNIQUE_VERTICAL___';
|
||||
const aUniqueCommaStringNotFoundInData = '___UNIQUE_COMMA___';
|
||||
const segmentSeparateChar = '|';
|
||||
const methodAndArgsSeparateChar = ':';
|
||||
const argsSeparateChar = ',';
|
||||
|
||||
const md5 = require('md5');
|
||||
const sha = require('sha.js');
|
||||
const Base64 = require('js-base64').Base64;
|
||||
|
||||
const stringHandles = {
|
||||
md5: function(str) {
|
||||
return md5(str);
|
||||
},
|
||||
|
||||
sha: function(str, arg) {
|
||||
return sha(arg)
|
||||
.update(str)
|
||||
.digest('hex');
|
||||
},
|
||||
|
||||
/**
|
||||
* type: sha1 sha224 sha256 sha384 sha512
|
||||
*/
|
||||
sha1: function(str) {
|
||||
return sha('sha1')
|
||||
.update(str)
|
||||
.digest('hex');
|
||||
},
|
||||
|
||||
sha224: function(str) {
|
||||
return sha('sha224')
|
||||
.update(str)
|
||||
.digest('hex');
|
||||
},
|
||||
|
||||
sha256: function(str) {
|
||||
return sha('sha256')
|
||||
.update(str)
|
||||
.digest('hex');
|
||||
},
|
||||
|
||||
sha384: function(str) {
|
||||
return sha('sha384')
|
||||
.update(str)
|
||||
.digest('hex');
|
||||
},
|
||||
|
||||
sha512: function(str) {
|
||||
return sha('sha512')
|
||||
.update(str)
|
||||
.digest('hex');
|
||||
},
|
||||
|
||||
base64: function(str) {
|
||||
return Base64.encode(str);
|
||||
},
|
||||
|
||||
unbase64: function(str) {
|
||||
return Base64.decode(str);
|
||||
},
|
||||
|
||||
substr: function(str, ...args) {
|
||||
return str.substr(...args);
|
||||
},
|
||||
|
||||
concat: function(str, ...args) {
|
||||
args.forEach(item => {
|
||||
str += item;
|
||||
});
|
||||
return str;
|
||||
},
|
||||
|
||||
lconcat: function(str, ...args) {
|
||||
args.forEach(item => {
|
||||
str = item + this._string;
|
||||
});
|
||||
return str;
|
||||
},
|
||||
|
||||
lower: function(str) {
|
||||
return str.toLowerCase();
|
||||
},
|
||||
|
||||
upper: function(str) {
|
||||
return str.toUpperCase();
|
||||
},
|
||||
|
||||
length: function(str) {
|
||||
return str.length;
|
||||
},
|
||||
|
||||
number: function(str) {
|
||||
return !isNaN(str) ? +str : str;
|
||||
}
|
||||
};
|
||||
|
||||
let handleValue = function(str) {
|
||||
return str;
|
||||
};
|
||||
|
||||
const _handleValue = function(str) {
|
||||
if (str[0] === str[str.length - 1] && (str[0] === '"' || str[0] === "'")) {
|
||||
str = str.substr(1, str.length - 2);
|
||||
}
|
||||
return handleValue(
|
||||
str
|
||||
.replace(new RegExp(aUniqueVerticalStringNotFoundInData, 'g'), segmentSeparateChar)
|
||||
.replace(new RegExp(aUniqueCommaStringNotFoundInData, 'g'), argsSeparateChar)
|
||||
);
|
||||
};
|
||||
|
||||
class PowerString {
|
||||
constructor(str) {
|
||||
this._string = str;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this._string;
|
||||
}
|
||||
}
|
||||
|
||||
function addMethod(method, fn) {
|
||||
PowerString.prototype[method] = function(...args) {
|
||||
args.unshift(this._string + '');
|
||||
this._string = fn.apply(this, args);
|
||||
return this;
|
||||
};
|
||||
}
|
||||
|
||||
function importMethods(handles) {
|
||||
for (let method in handles) {
|
||||
addMethod(method, handles[method]);
|
||||
}
|
||||
}
|
||||
|
||||
importMethods(stringHandles);
|
||||
|
||||
function handleOriginStr(str, handleValueFn) {
|
||||
if (!str) return str;
|
||||
if (typeof handleValueFn === 'function') {
|
||||
handleValue = handleValueFn;
|
||||
}
|
||||
str = str
|
||||
.replace('\\' + segmentSeparateChar, aUniqueVerticalStringNotFoundInData)
|
||||
.replace('\\' + argsSeparateChar, aUniqueCommaStringNotFoundInData)
|
||||
.split(segmentSeparateChar)
|
||||
.map(handleSegment)
|
||||
.reduce(execute, null)
|
||||
.toString();
|
||||
return str;
|
||||
}
|
||||
|
||||
function execute(str, curItem, index) {
|
||||
if (index === 0) {
|
||||
return new PowerString(curItem);
|
||||
}
|
||||
return str[curItem.method].apply(str, curItem.args);
|
||||
}
|
||||
|
||||
function handleSegment(str, index) {
|
||||
str = str.trim();
|
||||
if (index === 0) {
|
||||
return _handleValue(str);
|
||||
}
|
||||
|
||||
let method,
|
||||
args = [];
|
||||
if (str.indexOf(methodAndArgsSeparateChar) > 0) {
|
||||
str = str.split(methodAndArgsSeparateChar);
|
||||
method = str[0].trim();
|
||||
args = str[1].split(argsSeparateChar).map(item => _handleValue(item.trim()));
|
||||
} else {
|
||||
method = str;
|
||||
}
|
||||
if (typeof stringHandles[method] !== 'function') {
|
||||
throw new Error(`This method name(${method}) is not exist.`);
|
||||
}
|
||||
|
||||
return {
|
||||
method,
|
||||
args
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
utils: stringHandles,
|
||||
PowerString,
|
||||
/**
|
||||
* 类似于 angularJs的 filter 功能
|
||||
* @params string
|
||||
* @params fn 处理参数值函数,默认是一个返回原有参数值函数
|
||||
*
|
||||
* @expamle
|
||||
* filter('string | substr: 1, 10 | md5 | concat: hello ')
|
||||
*/
|
||||
filter: handleOriginStr
|
||||
};
|
||||
197
common/schema-transformTo-table.js
Normal file
197
common/schema-transformTo-table.js
Normal file
@@ -0,0 +1,197 @@
|
||||
const _ = require('underscore');
|
||||
let fieldNum = 1;
|
||||
|
||||
exports.schemaTransformToTable = schema => {
|
||||
try {
|
||||
schema = checkJsonSchema(schema);
|
||||
let result = Schema(schema, 0);
|
||||
result = _.isArray(result) ? result : [result];
|
||||
return result;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
};
|
||||
|
||||
// 自动添加type
|
||||
|
||||
function checkJsonSchema(json) {
|
||||
let newJson = Object.assign({}, json);
|
||||
if (_.isUndefined(json.type) && _.isObject(json.properties)) {
|
||||
newJson.type = 'object';
|
||||
}
|
||||
|
||||
return newJson;
|
||||
}
|
||||
|
||||
const mapping = function(data, index) {
|
||||
switch (data.type) {
|
||||
case 'string':
|
||||
return SchemaString(data);
|
||||
|
||||
case 'number':
|
||||
return SchemaNumber(data);
|
||||
|
||||
case 'array':
|
||||
return SchemaArray(data, index);
|
||||
|
||||
case 'object':
|
||||
return SchemaObject(data, index);
|
||||
|
||||
case 'boolean':
|
||||
return SchemaBoolean(data);
|
||||
|
||||
case 'integer':
|
||||
return SchemaInt(data);
|
||||
default:
|
||||
return SchemaOther(data);
|
||||
}
|
||||
};
|
||||
|
||||
const ConcatDesc = (title, desc) => {
|
||||
return [title, desc].join('\n').trim();
|
||||
};
|
||||
|
||||
const Schema = (data, key) => {
|
||||
let result = mapping(data, key);
|
||||
if (data.type !== 'object') {
|
||||
let desc = result.desc;
|
||||
let d = result.default;
|
||||
let children = result.children;
|
||||
|
||||
delete result.desc;
|
||||
delete result.default;
|
||||
delete result.children;
|
||||
let item = {
|
||||
type: data.type,
|
||||
key,
|
||||
desc,
|
||||
default: d,
|
||||
sub: result
|
||||
};
|
||||
|
||||
if (_.isArray(children)) {
|
||||
item = Object.assign({}, item, { children });
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const SchemaObject = (data, key) => {
|
||||
let { properties, required } = data;
|
||||
properties = properties || {};
|
||||
required = required || [];
|
||||
let result = [];
|
||||
Object.keys(properties).map((name, index) => {
|
||||
let value = properties[name];
|
||||
let copiedState = checkJsonSchema(JSON.parse(JSON.stringify(value)));
|
||||
|
||||
let optionForm = Schema(copiedState, key + '-' + index);
|
||||
let item = {
|
||||
name,
|
||||
key: key + '-' + index,
|
||||
desc: ConcatDesc(copiedState.title, copiedState.description),
|
||||
required: required.indexOf(name) != -1
|
||||
};
|
||||
|
||||
if (value.type === 'object' || (_.isUndefined(value.type) && _.isArray(optionForm))) {
|
||||
item = Object.assign({}, item, { type: 'object', children: optionForm });
|
||||
delete item.sub;
|
||||
} else {
|
||||
item = Object.assign({}, item, optionForm);
|
||||
}
|
||||
|
||||
result.push(item);
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const SchemaString = data => {
|
||||
let item = {
|
||||
desc: ConcatDesc(data.title, data.description),
|
||||
default: data.default,
|
||||
maxLength: data.maxLength,
|
||||
minLength: data.minLength,
|
||||
enum: data.enum,
|
||||
enumDesc: data.enumDesc,
|
||||
format: data.format,
|
||||
mock: data.mock && data.mock.mock
|
||||
};
|
||||
return item;
|
||||
};
|
||||
|
||||
const SchemaArray = (data, index) => {
|
||||
data.items = data.items || { type: 'string' };
|
||||
let items = checkJsonSchema(data.items);
|
||||
let optionForm = mapping(items, index);
|
||||
// 处理array嵌套array的问题
|
||||
let children =optionForm ;
|
||||
if (!_.isArray(optionForm) && !_.isUndefined(optionForm)) {
|
||||
optionForm.key = 'array-' + fieldNum++;
|
||||
children = [optionForm];
|
||||
}
|
||||
|
||||
let item = {
|
||||
desc: ConcatDesc(data.title, data.description),
|
||||
default: data.default,
|
||||
minItems: data.minItems,
|
||||
uniqueItems: data.uniqueItems,
|
||||
maxItems: data.maxItems,
|
||||
itemType: items.type,
|
||||
children
|
||||
};
|
||||
if (items.type === 'string') {
|
||||
item = Object.assign({}, item, { itemFormat: items.format });
|
||||
}
|
||||
return item;
|
||||
};
|
||||
|
||||
const SchemaNumber = data => {
|
||||
let item = {
|
||||
desc: ConcatDesc(data.title, data.description),
|
||||
maximum: data.maximum,
|
||||
minimum: data.minimum,
|
||||
default: data.default,
|
||||
format: data.format,
|
||||
enum: data.enum,
|
||||
enumDesc: data.enumDesc,
|
||||
mock: data.mock && data.mock.mock
|
||||
};
|
||||
return item;
|
||||
};
|
||||
|
||||
const SchemaInt = data => {
|
||||
let item = {
|
||||
desc: ConcatDesc(data.title, data.description),
|
||||
maximum: data.maximum,
|
||||
minimum: data.minimum,
|
||||
default: data.default,
|
||||
format: data.format,
|
||||
enum: data.enum,
|
||||
enumDesc: data.enumDesc,
|
||||
mock: data.mock && data.mock.mock
|
||||
};
|
||||
return item;
|
||||
};
|
||||
|
||||
const SchemaBoolean = data => {
|
||||
let item = {
|
||||
desc: ConcatDesc(data.title, data.description),
|
||||
default: data.default,
|
||||
enum: data.enum,
|
||||
mock: data.mock && data.mock.mock
|
||||
};
|
||||
return item;
|
||||
};
|
||||
|
||||
const SchemaOther = data => {
|
||||
let item = {
|
||||
desc: ConcatDesc(data.title, data.description),
|
||||
default: data.default,
|
||||
mock: data.mock && data.mock.mock
|
||||
};
|
||||
return item;
|
||||
};
|
||||
BIN
common/tui-editor/dist/tui-editor-2x.png
vendored
Normal file
BIN
common/tui-editor/dist/tui-editor-2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
61
common/tui-editor/dist/tui-editor-Editor-all.min.js
vendored
Normal file
61
common/tui-editor/dist/tui-editor-Editor-all.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
36
common/tui-editor/dist/tui-editor-Editor.min.js
vendored
Normal file
36
common/tui-editor/dist/tui-editor-Editor.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
61
common/tui-editor/dist/tui-editor-Viewer-all.min.js
vendored
Normal file
61
common/tui-editor/dist/tui-editor-Viewer-all.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
36
common/tui-editor/dist/tui-editor-Viewer.min.js
vendored
Normal file
36
common/tui-editor/dist/tui-editor-Viewer.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
common/tui-editor/dist/tui-editor-contents.min.css
vendored
Normal file
1
common/tui-editor/dist/tui-editor-contents.min.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
@charset "UTF-8";.CodeMirror{font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif}.tui-editor-contents :not(table){line-height:160%;box-sizing:content-box}.tui-editor-contents address,.tui-editor-contents cite,.tui-editor-contents dfn,.tui-editor-contents em,.tui-editor-contents i,.tui-editor-contents var{font-style:italic}.tui-editor-contents strong{font-weight:700}.tui-editor-contents p{margin:10px 0;color:#555}.tui-editor-contents>div>div:first-of-type h1,.tui-editor-contents>h1:first-of-type{margin-top:14px}.tui-editor-contents h1,.tui-editor-contents h2,.tui-editor-contents h3,.tui-editor-contents h5{font-weight:700}.tui-editor-contents h1{font-size:1.6rem;line-height:28px;border-bottom:3px double #999;margin:52px 0 15px 0;padding-bottom:7px;color:#000}.tui-editor-contents h2{font-size:1.3rem;line-height:23px;border-bottom:1px solid #dbdbdb;margin:30px 0 13px 0;padding-bottom:7px;color:#333}.tui-editor-contents h3,.tui-editor-contents h4{font-size:1.2rem;line-height:18px;margin:20px 0 2px;color:#333}.tui-editor-contents h5,.tui-editor-contents h6{font-size:1rem;line-height:17px;margin:10px 0 -4px;color:#333}.tui-editor-contents blockquote{margin:15px 0}.tui-editor-contents blockquote{border-left:4px solid #ddd;padding:0 15px;color:#777}.tui-editor-contents blockquote>:first-child{margin-top:0}.tui-editor-contents blockquote>:last-child{margin-bottom:0}.tui-editor-contents code,.tui-editor-contents pre{font-family:Consolas,Courier,"Apple SD 산돌고딕 Neo",-apple-system,"Lucida Grande","Apple SD Gothic Neo","맑은 고딕","Malgun Gothic","Segoe UI","돋움",dotum,sans-serif;border:0;border-radius:0}.tui-editor-contents pre{margin:2px 0 8px;padding:18px;background-color:#f5f7f8}.tui-editor-contents code{color:#c1788b;padding:4px 4px 2px 0;letter-spacing:-.3px}.tui-editor-contents pre code{padding:0;color:inherit;white-space:pre-wrap;background-color:transparent}.tui-editor-contents pre.addon{border:1px solid #e8ebed;background-color:#fff}.tui-editor-contents img{margin:4px 0 10px;box-sizing:border-box;vertical-align:top;max-width:100%}.tui-editor-contents table{margin:2px 0 14px;color:#555;width:auto;border-collapse:collapse;box-sizing:border-box}.tui-editor-contents table td,.tui-editor-contents table th{height:32px;padding:5px 14px 5px 12px}.tui-editor-contents table td{border:1px solid #eaeaea}.tui-editor-contents table th{border:1px solid #72777b;border-top:0;background-color:#7b8184;font-weight:300;color:#fff;padding-top:6px}.tui-editor-contents dir,.tui-editor-contents menu,.tui-editor-contents ol,.tui-editor-contents ul{display:block;list-style-type:disc;padding-left:17px;margin:6px 0 10px;color:#555}.tui-editor-contents ol{list-style-type:decimal}.tui-editor-contents ol ol,.tui-editor-contents ol ul,.tui-editor-contents ul ol,.tui-editor-contents ul ul{margin-top:0!important;margin-bottom:0!important}.tui-editor-contents ul li{position:relative}.tui-editor-contents ul p,ol p{margin:0}.tui-editor-contents pre ul li:before,.tui-editor-contents ul li.task-list-item:before{content:""}.tui-editor-contents hr{border-top:1px solid #eee;margin:16px 0}.tui-editor-contents a{text-decoration:underline;color:#5286bc}.tui-editor-contents a:hover{color:#007cff}.tui-editor-contents{font-size:13px;margin:0;padding:0}.tui-editor-contents .task-list-item{border:0;list-style:none;padding-left:22px;margin-left:-22px;background-repeat:no-repeat;background-size:16px 16px;background-position:0 2px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAADdJREFUKBVjvHv37n8GMgALSI+SkhJJWu/du8fARJIOJMWjGpECA505GjjoIYLEB6dVUNojFQAA/1MJUFWet/4AAAAASUVORK5CYII=)}.tui-editor-contents .task-list-item.checked{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAMpJREFUKBVjjJ/64D8DGYCJDD1gLbTVyM3OxJDiJMzAxcYIdyALnIWDAdJU7i/OICfCxsDMxMgwc88bwk5F1vTs/W+GFUffwY2H+1FBlI2hLliCQYCbGSyJrqlzwwuGj9//YWoMtRBgUBJnZ6gMEGeQFWaFOw9kE7omkG5GWDyCPF7mJ86gIMbO8P//fwZGRkYGXJpAGuFO/fbrP0PXppcMD179JKgJRSOIA9N8/NZXrM4DqYEBjOgAaYYFOUwRNhruVGyS+MTI1ggAx8NTGcUtFVQAAAAASUVORK5CYII=)}.tui-editor-contents .task-list-item .task-list-item-checkbox,.tui-editor-contents .task-list-item input[type=checkbox]{margin-left:-17px;margin-right:3.8px;margin-top:3px}
|
||||
53
common/tui-editor/dist/tui-editor-extChart.min.js
vendored
Normal file
53
common/tui-editor/dist/tui-editor-extChart.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
44
common/tui-editor/dist/tui-editor-extColorSyntax.min.js
vendored
Normal file
44
common/tui-editor/dist/tui-editor-extColorSyntax.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
36
common/tui-editor/dist/tui-editor-extScrollSync.min.js
vendored
Normal file
36
common/tui-editor/dist/tui-editor-extScrollSync.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
36
common/tui-editor/dist/tui-editor-extTable.min.js
vendored
Normal file
36
common/tui-editor/dist/tui-editor-extTable.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
36
common/tui-editor/dist/tui-editor-extUML.min.js
vendored
Normal file
36
common/tui-editor/dist/tui-editor-extUML.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
common/tui-editor/dist/tui-editor.min.css
vendored
Normal file
1
common/tui-editor/dist/tui-editor.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
common/tui-editor/dist/tui-editor.png
vendored
Normal file
BIN
common/tui-editor/dist/tui-editor.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
288
common/utils.js
Normal file
288
common/utils.js
Normal file
@@ -0,0 +1,288 @@
|
||||
const Mock = require('mockjs');
|
||||
const filter = require('./power-string.js').filter;
|
||||
const stringUtils = require('./power-string.js').utils;
|
||||
const json5 = require('json5');
|
||||
const Ajv = require('ajv');
|
||||
/**
|
||||
* 作用:解析规则串 key ,然后根据规则串的规则以及路径找到在 json 中对应的数据
|
||||
* 规则串:$.{key}.{body||params}.{dataPath} 其中 body 为返回数据,params 为请求数据,datapath 为数据的路径
|
||||
* 数组:$.key.body.data.arr[0]._id (获取 key 所指向请求的返回数据的 arr 数组的第 0 项元素的 _id 属性)
|
||||
* 对象:$.key.body.data.obj._id ((获取 key 所指向请求的返回数据的 obj 对象的 _id 属性))
|
||||
*
|
||||
* @param String key 规则串
|
||||
* @param Object json 数据
|
||||
* @returns
|
||||
*/
|
||||
function simpleJsonPathParse(key, json) {
|
||||
if (!key || typeof key !== 'string' || key.indexOf('$.') !== 0 || key.length <= 2) {
|
||||
return null;
|
||||
}
|
||||
let keys = key.substr(2).split('.');
|
||||
keys = keys.filter(item => {
|
||||
return item;
|
||||
});
|
||||
for (let i = 0, l = keys.length; i < l; i++) {
|
||||
try {
|
||||
let m = keys[i].match(/(.*?)\[([0-9]+)\]/);
|
||||
if (m) {
|
||||
json = json[m[1]][m[2]];
|
||||
} else {
|
||||
json = json[keys[i]];
|
||||
}
|
||||
} catch (e) {
|
||||
json = '';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
// 全局变量 {{ global.value }}
|
||||
// value 是在环境变量中定义的字段
|
||||
function handleGlobalWord(word, json) {
|
||||
if (!word || typeof word !== 'string' || word.indexOf('global.') !== 0) return word;
|
||||
let keys = word.split('.');
|
||||
keys = keys.filter(item => {
|
||||
return item;
|
||||
});
|
||||
return json[keys[0]][keys[1]] || word;
|
||||
}
|
||||
|
||||
function handleMockWord(word) {
|
||||
if (!word || typeof word !== 'string' || word[0] !== '@') return word;
|
||||
return Mock.mock(word);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} data
|
||||
* @param {*} handleValueFn 处理参数值函数
|
||||
*/
|
||||
function handleJson(data, handleValueFn) {
|
||||
if (!data) {
|
||||
return data;
|
||||
}
|
||||
if (typeof data === 'string') {
|
||||
return handleValueFn(data);
|
||||
} else if (typeof data === 'object') {
|
||||
for (let i in data) {
|
||||
data[i] = handleJson(data[i], handleValueFn);
|
||||
}
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function handleValueWithFilter(context) {
|
||||
return function(match) {
|
||||
if (match[0] === '@') {
|
||||
return handleMockWord(match);
|
||||
} else if (match.indexOf('$.') === 0) {
|
||||
return simpleJsonPathParse(match, context);
|
||||
} else if (match.indexOf('global.') === 0) {
|
||||
return handleGlobalWord(match, context);
|
||||
} else {
|
||||
return match;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function handleFilter(str, match, context) {
|
||||
match = match.trim();
|
||||
try {
|
||||
let a = filter(match, handleValueWithFilter(context));
|
||||
|
||||
return a;
|
||||
} catch (err) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
function handleParamsValue(val, context = {}) {
|
||||
const variableRegexp = /\{\{\s*([^}]+?)\}\}/g;
|
||||
if (!val || typeof val !== 'string') {
|
||||
return val;
|
||||
}
|
||||
val = val.trim();
|
||||
|
||||
let match = val.match(/^\{\{([^\}]+)\}\}$/);
|
||||
if (!match) {
|
||||
// val ==> @name 或者 $.body
|
||||
if (val[0] === '@' || val[0] === '$') {
|
||||
return handleFilter(val, val, context);
|
||||
}
|
||||
} else {
|
||||
return handleFilter(val, match[1], context);
|
||||
}
|
||||
|
||||
return val.replace(variableRegexp, (str, match) => {
|
||||
return handleFilter(str, match, context);
|
||||
});
|
||||
}
|
||||
|
||||
exports.handleJson = handleJson;
|
||||
exports.handleParamsValue = handleParamsValue;
|
||||
|
||||
exports.simpleJsonPathParse = simpleJsonPathParse;
|
||||
exports.handleMockWord = handleMockWord;
|
||||
|
||||
exports.joinPath = (domain, joinPath) => {
|
||||
let l = domain.length;
|
||||
if (domain[l - 1] === '/') {
|
||||
domain = domain.substr(0, l - 1);
|
||||
}
|
||||
if (joinPath[0] !== '/') {
|
||||
joinPath = joinPath.substr(1);
|
||||
}
|
||||
return domain + joinPath;
|
||||
};
|
||||
|
||||
// exports.safeArray = arr => {
|
||||
// return Array.isArray(arr) ? arr : [];
|
||||
// };
|
||||
function safeArray(arr) {
|
||||
return Array.isArray(arr) ? arr : [];
|
||||
}
|
||||
exports.safeArray = safeArray;
|
||||
|
||||
exports.isJson5 = function isJson5(json) {
|
||||
if (!json) return false;
|
||||
try {
|
||||
json = json5.parse(json);
|
||||
return json;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
function isJson(json) {
|
||||
if (!json) return false;
|
||||
try {
|
||||
json = JSON.parse(json);
|
||||
return json;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
exports.isJson = isJson;
|
||||
|
||||
exports.unbase64 = function(base64Str) {
|
||||
try {
|
||||
return stringUtils.unbase64(base64Str);
|
||||
} catch (err) {
|
||||
return base64Str;
|
||||
}
|
||||
};
|
||||
|
||||
exports.json_parse = function(json) {
|
||||
try {
|
||||
return JSON.parse(json);
|
||||
} catch (err) {
|
||||
return json;
|
||||
}
|
||||
};
|
||||
|
||||
exports.json_format = function(json) {
|
||||
try {
|
||||
return JSON.stringify(JSON.parse(json), null, ' ');
|
||||
} catch (e) {
|
||||
return json;
|
||||
}
|
||||
};
|
||||
|
||||
exports.ArrayToObject = function(arr) {
|
||||
let obj = {};
|
||||
safeArray(arr).forEach(item => {
|
||||
obj[item.name] = item.value;
|
||||
});
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
exports.timeago = function(timestamp) {
|
||||
let minutes, hours, days, seconds, mouth, year;
|
||||
const timeNow = parseInt(new Date().getTime() / 1000);
|
||||
seconds = timeNow - timestamp;
|
||||
if (seconds > 86400 * 30 * 12) {
|
||||
year = parseInt(seconds / (86400 * 30 * 12));
|
||||
} else {
|
||||
year = 0;
|
||||
}
|
||||
if (seconds > 86400 * 30) {
|
||||
mouth = parseInt(seconds / (86400 * 30));
|
||||
} else {
|
||||
mouth = 0;
|
||||
}
|
||||
if (seconds > 86400) {
|
||||
days = parseInt(seconds / 86400);
|
||||
} else {
|
||||
days = 0;
|
||||
}
|
||||
if (seconds > 3600) {
|
||||
hours = parseInt(seconds / 3600);
|
||||
} else {
|
||||
hours = 0;
|
||||
}
|
||||
minutes = parseInt(seconds / 60);
|
||||
if (year > 0) {
|
||||
return year + '年前';
|
||||
} else if (mouth > 0 && year <= 0) {
|
||||
return mouth + '月前';
|
||||
} else if (days > 0 && mouth <= 0) {
|
||||
return days + '天前';
|
||||
} else if (days <= 0 && hours > 0) {
|
||||
return hours + '小时前';
|
||||
} else if (hours <= 0 && minutes > 0) {
|
||||
return minutes + '分钟前';
|
||||
} else if (minutes <= 0 && seconds > 0) {
|
||||
if (seconds < 30) {
|
||||
return '刚刚';
|
||||
} else {
|
||||
return seconds + '秒前';
|
||||
}
|
||||
} else {
|
||||
return '刚刚';
|
||||
}
|
||||
};
|
||||
|
||||
// json schema 验证器
|
||||
exports.schemaValidator = function(schema, params) {
|
||||
try {
|
||||
const ajv = new Ajv({
|
||||
format: false,
|
||||
meta: false
|
||||
});
|
||||
let metaSchema = require('ajv/lib/refs/json-schema-draft-04.json');
|
||||
ajv.addMetaSchema(metaSchema);
|
||||
ajv._opts.defaultMeta = metaSchema.id;
|
||||
ajv._refs['http://json-schema.org/schema'] = 'http://json-schema.org/draft-04/schema';
|
||||
var localize = require('ajv-i18n');
|
||||
|
||||
schema = schema || {
|
||||
type: 'object',
|
||||
title: 'empty object',
|
||||
properties: {}
|
||||
};
|
||||
const validate = ajv.compile(schema);
|
||||
let valid = validate(params);
|
||||
|
||||
let message = '';
|
||||
if (!valid) {
|
||||
localize.zh(validate.errors);
|
||||
message += ajv.errorsText(validate.errors, { separator: '\n' });
|
||||
}
|
||||
|
||||
return {
|
||||
valid: valid,
|
||||
message: message
|
||||
};
|
||||
} catch (e) {
|
||||
return {
|
||||
valid: false,
|
||||
message: e.message
|
||||
};
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user