fix: 增加mock点击数据查询

This commit is contained in:
gaoxiaolin.gao 2017-10-27 12:13:59 +08:00
parent 3b9d249280
commit ef79b8be77
14 changed files with 512 additions and 87 deletions

View File

@ -10,20 +10,54 @@ import Header from './components/Header/Header';
import Footer from './components/Footer/Footer';
import Loading from './components/Loading/Loading';
import MyPopConfirm from './components/MyPopConfirm/MyPopConfirm';
import statisticsPage from '../exts/yapi-plugin-statistics/statisticsClientPage/index';
// import statisticsPage from '../exts/yapi-plugin-statistics/statisticsClientPage/index';
import { checkLoginState } from './reducer/modules/user';
import { requireAuthentication } from './components/AuthenticatedComponent';
const plugin = require('client/plugin.js');
const LOADING_STATUS = 0;
const alertContent = () => {
const ua = window.navigator.userAgent,
isChrome = ua.indexOf("Chrome") && window.chrome;
isChrome = ua.indexOf("Chrome") && window.chrome;
if (!isChrome) {
return <Alert style={{zIndex: 99}} message={'YApi 的接口测试等功能仅支持 Chrome 浏览器,请使用 Chrome 浏览器获得完整功能。'} banner closable />
return <Alert style={{ zIndex: 99 }} message={'YApi 的接口测试等功能仅支持 Chrome 浏览器,请使用 Chrome 浏览器获得完整功能。'} banner closable />
}
}
let AppRoute = {
home: {
path: '/',
component: Home
},
group: {
path: '/group',
component: Group
},
project: {
path: '/project/:id',
component: Project
},
user: {
path: '/user',
component: User
},
follow: {
path: '/follow',
component: Follows
},
addProject: {
path: '/add-project',
component: AddProject
},
login: {
path: '/login',
component: Login
}
};
// 增加路由钩子
plugin.emitHook('app_route', AppRoute);
@connect(
state => {
return {
@ -72,6 +106,18 @@ export default class App extends Component {
{alertContent()}
{this.props.loginState !== 1 ? <Header /> : null}
<div className="router-container">
{Object.keys(AppRoute).map(key => {
let item = AppRoute[key];
return (
key === 'login' ?
<Route key={key} path={item.path} component={item.component} />
: key === 'home' ? <Route key={key} exact path={item.path} component={item.component} />
: <Route key={key} path={item.path} component={requireAuthentication(item.component)} />
)
})
}
</div>
{/* <div className="router-container">
<Route exact path="/" component={Home} />
<Route path="/group" component={requireAuthentication(Group)} />
<Route path="/project/:id" component={requireAuthentication(Project)} />
@ -79,12 +125,12 @@ export default class App extends Component {
<Route path="/follow" component={requireAuthentication(Follows)} />
<Route path="/add-project" component={requireAuthentication(AddProject)} />
<Route path="/login" component={Login} />
<Route path="/statistic" component={statisticsPage} />
</div>
{/* <Route path="/statistic" component={statisticsPage} /> */}
{/* </div> */}
</div>
<Footer/>
<Footer />
</div>
</Router>
</Router >
)
}

View File

@ -1,15 +1,15 @@
import './Header.scss'
import React, {Component} from 'react'
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {Link} from 'react-router-dom'
import {Icon, Layout, Menu, Dropdown, message, Tooltip, Avatar, Popover, Tag} from 'antd'
import {checkLoginState, logoutActions, loginTypeAction} from '../../reducer/modules/user'
import {changeMenuItem} from '../../reducer/modules/menu'
import {withRouter} from 'react-router';
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
import { Icon, Layout, Menu, Dropdown, message, Tooltip, Avatar, Popover, Tag } from 'antd'
import { checkLoginState, logoutActions, loginTypeAction } from '../../reducer/modules/user'
import { changeMenuItem } from '../../reducer/modules/menu'
import { withRouter } from 'react-router';
import Srch from './Search/Search'
const {Header} = Layout;
import {logoSVG} from '../../common.js';
const { Header } = Layout;
import { logoSVG } from '../../common.js';
import Breadcrumb from '../Breadcrumb/Breadcrumb.js'
import GuideBtns from '../GuideBtns/GuideBtns.js';
const plugin = require('client/plugin.js');
@ -49,11 +49,11 @@ const MenuUser = (props) => (
<Menu.Item key={key}>
{
item.name === '个人中心' ? <Link to={item.path + `/${props.uid}`}>
<Icon type={item.icon}/>
<Icon type={item.icon} />
{item.name}
</Link> : !item.adminFlag ? <Link to={item.path}><Icon type={item.icon}/>
</Link> : !item.adminFlag ? <Link to={item.path}><Icon type={item.icon} />
{item.name}
</Link> : <Link to={item.path}><Icon type={item.icon}/>
</Link> : <Link to={item.path}><Icon type={item.icon} />
{item.name}
</Link>
}
@ -73,17 +73,17 @@ const MenuUser = (props) => (
{/*}*/}
<Menu.Item key="9">
<a onClick={props.logout}><Icon type="logout"/>退出</a>
<a onClick={props.logout}><Icon type="logout" />退出</a>
</Menu.Item>
</Menu>
);
const tipFollow = (<div className="title-container">
<h3 className="title"><Icon type="star"/> 关注</h3>
<h3 className="title"><Icon type="star" /> 关注</h3>
<p>这里是你的专属收藏夹便于你找到自己的项目</p>
</div>);
const tipAdd = (<div className="title-container">
<h3 className="title"><Icon type="plus-circle"/> 新建项目</h3>
<h3 className="title"><Icon type="plus-circle" /> 新建项目</h3>
<p>在任何页面都可以快速新建项目</p>
</div>);
const tipDoc = (<div className="title-container">
@ -105,11 +105,11 @@ const ToolUser = (props) => {
return (
<ul>
<li className="toolbar-li item-search">
<Srch groupList={props.groupList}/>
<Srch groupList={props.groupList} />
</li>
<Popover
overlayClassName="popover-index"
content={<GuideBtns/>}
content={<GuideBtns />}
title={tipFollow}
placement="bottomRight"
arrowPointAtCenter
@ -118,14 +118,14 @@ const ToolUser = (props) => {
<Tooltip placement="bottom" title={'我的关注'}>
<li className="toolbar-li">
<Link to="/follow">
<Icon className="dropdown-link" style={{fontSize: 16}} type="star"/>
<Icon className="dropdown-link" style={{ fontSize: 16 }} type="star" />
</Link>
</li>
</Tooltip>
</Popover>
<Popover
overlayClassName="popover-index"
content={<GuideBtns/>}
content={<GuideBtns />}
title={tipAdd}
placement="bottomRight"
arrowPointAtCenter
@ -134,14 +134,14 @@ const ToolUser = (props) => {
<Tooltip placement="bottom" title={'新建项目'}>
<li className="toolbar-li">
<Link to="/add-project">
<Icon className="dropdown-link" style={{fontSize: 16}} type="plus-circle"/>
<Icon className="dropdown-link" style={{ fontSize: 16 }} type="plus-circle" />
</Link>
</li>
</Tooltip>
</Popover>
<Popover
overlayClassName="popover-index"
content={<GuideBtns isLast={true}/>}
content={<GuideBtns isLast={true} />}
title={tipDoc}
placement="bottomRight"
arrowPointAtCenter
@ -150,7 +150,7 @@ const ToolUser = (props) => {
<Tooltip placement="bottom" title={'使用文档'}>
<li className="toolbar-li">
<a target="_blank" href="https://yapi.ymfe.org/" rel="noopener noreferrer"><Icon
className="dropdown-link" style={{fontSize: 16}} type="question-circle"/></a>
className="dropdown-link" style={{ fontSize: 16 }} type="question-circle" /></a>
</li>
</Tooltip>
</Popover>
@ -170,10 +170,10 @@ const ToolUser = (props) => {
/>
}>
<a className="dropdown-link">
<Avatar src={`/api/user/avatar?uid=${props.uid}`}/>
<Avatar src={`/api/user/avatar?uid=${props.uid}`} />
{/*<img style={{width:24,height:24}} src={`/api/user/avatar?uid=${props.uid}`} />*/}
{/*<span className="name">{props.user}</span>*/}
<span className="name"><Icon type="down"/></span>
<span className="name"><Icon type="down" /></span>
</a>
</Dropdown>
@ -281,7 +281,7 @@ export default class HeaderCom extends Component {
render() {
const {login, user, msg, uid, role, studyTip, study} = this.props;
const { login, user, msg, uid, role, studyTip, study } = this.props;
return (
<Header className="header-box m-header">
<div className="content g-row">
@ -293,12 +293,12 @@ export default class HeaderCom extends Component {
</Link>
<Breadcrumb />
<div className="user-toolbar"
style={{position: 'relative', zIndex: this.props.studyTip > 0 ? 3 : 1}}>
style={{ position: 'relative', zIndex: this.props.studyTip > 0 ? 3 : 1 }}>
{login ?
<ToolUser
{...{studyTip, study, user, msg, uid, role}}
relieveLink={ this.relieveLink }
logout={ this.logout }
{...{ studyTip, study, user, msg, uid, role }}
relieveLink={this.relieveLink}
logout={this.logout}
/>
: ""}
</div>

View File

@ -112,6 +112,50 @@ hooks = {
type: 'listener',
mulit: true,
listener: []
},
/**
* Route路由列表钩子
* @param AppRoute
*
* @info
* 可参考 vendors/exts/yapi-plugin-statistics
* 添加位置在Application.js
* let AppRoute = {
home: {
path: '/',
component: Home
},
group: {
path: '/group',
component: Group
},
project: {
path: '/project/:id',
component: Project
},
user: {
path: '/user',
component: User
},
follow: {
path: '/follow',
component: Follows
},
addProject: {
path: '/add-project',
component: AddProject
},
login: {
path: '/login',
component: Login
}
};
};
*/
app_route: {
type: 'listener',
mulit: true,
listener: []
}
};

View File

@ -1,7 +1,7 @@
/**
* Created by gxl.gao on 2017/10/24.
*/
// import statisticsPage from './statisticsClientPage'
import StatisticsPage from './statisticsClientPage/index'
module.exports = function () {
this.bindHook('header_menu', function (menu) {
@ -12,4 +12,12 @@ module.exports = function () {
adminFlag: true
}
})
this.bindHook('app_route', function (app) {
app.statisticsPage = {
path: '/statistic',
component: StatisticsPage
}
})
}

View File

@ -6,9 +6,11 @@ const statisMockModel = require('./statisMockModel.js');
const groupModel = require('models/group.js');
const projectModel = require('models/project.js');
const interfaceModel = require('models/interface.js');
const interfaceCaseModel = require('models/interfaceCase.js')
const yapi = require('yapi.js');
const config = require('./index.js');
const commons = require('./util.js');
class statisMockController extends baseController {
constructor(ctx) {
@ -17,20 +19,55 @@ class statisMockController extends baseController {
this.groupModel = yapi.getInst(groupModel);
this.projectModel = yapi.getInst(projectModel);
this.interfaceModel = yapi.getInst(interfaceModel);
this.interfaceCaseModel = yapi.getInst(interfaceCaseModel);
}
async getStatisMock(ctx) {
/**
* 获取所有统计总数
* @interface statismock/count
* @method get
* @category statistics
* @foldnumber 10
* @returns {Object}
*/
async getStatisCount(ctx) {
// let id = ctx.query.interface_id;
// let mockData = await this.Model.get(id);
let groupCount = await this.groupModel.getGroupListCount();
let projectCount = await this.projectModel.getProjectListCount();
let interfaceCount = await this.interfaceModel.getInterfaceListCount();
let interfaceCaseCount = await this.interfaceCaseModel.getInterfaceCaseListCount();
// if(!mockData){
// return ctx.body = yapi.commons.resReturn(null, 408, 'mock脚本不存在');
// }
return ctx.body = yapi.commons.resReturn({groupCount, projectCount, interfaceCount});
return ctx.body = yapi.commons.resReturn({ groupCount, projectCount, interfaceCount, interfaceCaseCount });
}
/**
* 获取所有mock接口数据信息
* @interface statismock/get
* @method get
* @category statistics
* @foldnumber 10
* @returns {Object}
*/
async getMockDateList(ctx) {
let mockCount = await this.Model.getTotalCount();
// let list = await this.Model.list();
let mockDateList = [];
if (!this.getRole() === 'admin') {
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
}
// 默认时间是30 天为一周期
let dateInterval = commons.getDateRange();
// console.log('interval', dateInterval);
mockDateList = await this.Model.getDayCount(dateInterval);
return ctx.body = yapi.commons.resReturn({ mockCount, mockDateList });
}
}
module.exports = statisMockController;

View File

@ -4,8 +4,10 @@
const yapi = require('yapi.js')
const mongoose = require('mongoose');
const controller = require('./controller');
const statisModel = require('./statisMockModel.js');
const commons = require('./util.js');
module.exports = function(){
module.exports = function () {
yapi.connect.then(function () {
let Col = mongoose.connection.db.collection('statis_mock');
@ -15,16 +17,57 @@ module.exports = function(){
Col.createIndex({
project_id: 1
})
Col.createIndex({
group_id: 1
})
Col.createIndex({
time: 1
})
});
this.bindHook('add_router', function(addRouter) {
this.bindHook('add_router', function (addRouter) {
addRouter({
controller: controller,
method: 'get',
path: 'statismock/count',
action: 'getStatisCount'
})
addRouter({
controller: controller,
method: 'get',
path: 'statismock/get',
action: 'getStatisMock'
action: 'getMockDateList'
})
})
// MockServer生成mock数据后触发
this.bindHook('mock_after', async function (context) {
// console.log('context', context);
let interfaceId = context.interfaceData._id;
let projectId = context.projectData._id;
let groupId = context.projectData.group_id;
let ip = context.ctx.originalUrl;
// let date = commons.formatYMD(new Date());
let data = {
interface_id: interfaceId,
project_id: projectId,
group_id: groupId,
time: yapi.commons.time(),
ip: ip,
date: commons.formatYMD(new Date())
};
let inst = yapi.getInst(statisModel);
try {
let result = await inst.save(data);
result = yapi.commons.fieldSelect(result, ['interface_id', 'project_id', 'group_id', 'time', 'ip', 'date']);
console.log('result', result);
} catch (e) {
console.log('mockStatisError', e);
}
})
};

View File

@ -8,6 +8,56 @@ class statisMockModel extends baseModel {
getName() {
return 'statis_mock';
}
getSchema() {
return {
interface_id: { type: Number, required: true },
project_id: { type: Number, required: true },
group_id: { type: Number, required: true },
time: Number, //'时间戳'
ip: String,
date: String
};
}
save(data) {
let m = new this.model(data);
return m.save();
}
getTotalCount() {
return this.model.count({});
}
getDayCount(timeInterval) {
// console.log(this.model.count({}));
let end = timeInterval[1];
let start = timeInterval[0];
return this.model.aggregate([
{
$match: {
date: { $gt: start, $lte: end }
}
},
{
$group: {
_id: '$date', //$region is the column name in collection
count: { $sum: 1 }
}
}
]);
}
list() {
return this.model.find({}).select('date').exec();
}
up(id, data) {
data.up_time = yapi.commons.time();
return this.model.update({
_id: id
}, data, { runValidators: true });
}
}
module.exports = statisMockModel;

View File

@ -0,0 +1,44 @@
/**
* Created by gxl.gao on 2017/10/25.
*/
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend } from 'recharts'
// const data = [
// { name: 'Page A', pv: 2400 },
// { name: 'Page B', pv: 1398 },
// { name: 'Page C', pv: 9800 },
// { name: 'Page D', pv: 3908 },
// { name: 'Page E', pv: 4800 },
// { name: 'Page F', pv: 3800 },
// { name: 'Page G', pv: 4300 }
// ];
class StatisChart extends Component {
static propTypes = {
data: PropTypes.object
}
render() {
// console.log('date', this.props.date);
const { data } = this.props;
return (
<div className="statis-select">
我是一个图表
<LineChart width={600} height={300} data={data.mockDateList}
margin={{ top: 5, right: 30, left: 20, bottom: 5 }}>
<XAxis dataKey="_id" />
<YAxis />
<CartesianGrid strokeDasharray="3 3" />
<Tooltip />
<Legend />
<Line type="monotone" dataKey="count" stroke="#8884d8" activeDot={{ r: 8 }} />
{/* <Line type="monotone" dataKey="uv" stroke="#82ca9d" /> */}
</LineChart>
</div>
);
}
}
export default StatisChart;

View File

@ -1,18 +0,0 @@
/**
* Created by gxl.gao on 2017/10/25.
*/
import React, {Component} from 'react'
class StatisSelect extends Component {
render() {
return (
<div className="statis-select">
我是一个select
</div>
);
}
}
export default StatisSelect;

View File

@ -1,47 +1,57 @@
/**
* Created by gxl.gao on 2017/10/25.
*/
import React, {Component} from 'react'
import {connect} from 'react-redux'
import React, { Component } from 'react'
import { connect } from 'react-redux'
import axios from 'axios'
import PropTypes from 'prop-types'
import './index.scss'
// import { withRouter } from 'react-router-dom';
import {Row, Col, Tooltip, Icon} from 'antd';
import {setBreadcrumb} from '../../../client/reducer/modules/user';
import StatisSelect from './StatisSelect';
import { Row, Col, Tooltip, Icon } from 'antd';
import { setBreadcrumb } from 'client/reducer/modules/user';
import StatisChart from './StatisChart';
const CountOverview = (props) => (
<Row type="flex" justify="space-start" className="m-row">
<Col className="gutter-row" span={8}>
<Col className="gutter-row" span={6}>
<span>
分组总数
<Tooltip placement="rightTop" title="统计yapi中一共开启了多少可见的公共分组">
<Icon className="m-help" type="question-circle"/>
<Icon className="m-help" type="question-circle" />
</Tooltip>
</span>
<h2 className="gutter-box">{props.date.groupCount}</h2>
</Col>
<Col className="gutter-row" span={8}>
<Col className="gutter-row" span={6}>
<span>
项目总数
<Tooltip placement="rightTop" title="统计yapi中建立的所有项目总数">
<Icon className="m-help" type="question-circle"/>
<Icon className="m-help" type="question-circle" />
</Tooltip>
</span>
<h2 className="gutter-box">{props.date.projectCount}</h2>
</Col>
<Col className="gutter-row" span={8}>
<Col className="gutter-row" span={6}>
<span>
接口总数
<Tooltip placement="rightTop" title="统计yapi所有项目中的所有接口总数">
{/*<a href="javascript:void(0)" className="m-a-help">?</a>*/}
<Icon className="m-help" type="question-circle"/>
<Icon className="m-help" type="question-circle" />
</Tooltip>
</span>
<h2 className="gutter-box">{props.date.interfaceCount}</h2>
</Col>
<Col className="gutter-row" span={6}>
<span>
测试接口总数
<Tooltip placement="rightTop" title="统计yapi所有项目中的所有测试接口总数">
{/*<a href="javascript:void(0)" className="m-a-help">?</a>*/}
<Icon className="m-help" type="question-circle" />
</Tooltip>
</span>
<h2 className="gutter-box">{props.date.interfaceCaseCount}</h2>
</Col>
</Row>
);
@ -68,37 +78,53 @@ class statisticsPage extends Component {
count: {
groupCount: 0,
projectCount: 0,
interfaceCount: 0
interfaceCount: 0,
interfactCaseCount: 0
},
chartDate: {
mockCount: 0,
mockDateList: []
}
}
}
async componentWillMount() {
this.props.setBreadcrumb([{name: '数据统计'}]);
this.props.setBreadcrumb([{ name: '数据统计' }]);
this.getStatisData();
this.getMockData();
}
// 获取统计数据
async getStatisData() {
let result = await axios.get('/api/plugin/statismock/get');
let result = await axios.get('/api/plugin/statismock/count');
if (result.data.errcode === 0) {
let statisData = result.data.data;
this.setState({
count: {...statisData}
count: { ...statisData }
});
}
}
// 获取mock 请求次数信息
async getMockData() {
let result = await axios.get('/api/plugin/statismock/get');
if (result.data.errcode === 0) {
let mockStatisData = result.data.data;
this.setState({
chartDate: { ...mockStatisData }
});
console.log('state', this.state);
}
}
render() {
const {count} = this.state;
const { count, chartDate } = this.state;
// console.log('state', this.state)
return (
<div className="g-statistic">
<div className="statis-content">
<CountOverview date={count}></CountOverview>
<StatisSelect/>
<StatisChart data={chartDate} />
</div>
</div>

View File

@ -0,0 +1,139 @@
/**
* 获取所需要的日期区间点
* @param time {Number} Number是ele日期区间选择组件返回的结果
* Number是之前时刻距离今天的间隔天数默认是3天
* @param start {String} 日期对象日期区间的开始点 '2017-01-17 00:00:00'
* @param withToday {Boolean} 是否包含今天
* @return {Array} ['2017-01-17 00:00:00', '2017-01-20 23:59:59']
*/
exports.getDateRange = (time = 30, start = false, withToday = true) => {
const gapTime = time * 24 * 3600 * 1000;
if (!start) {
// 没有规定start时间
let endTime = getNowMidnightDate().getTime();
if (!withToday) {
endTime -= 86400000;
}
return [this.formatYMD(endTime - gapTime), this.formatYMD(endTime - 1000)];
}
const startTime = dateSpacialWithSafari(start);
const endTime = startTime + (gapTime - 1000);
return [start, this.formatYMD(endTime)];
}
// 时间
const convert2Decimal = num => (num > 9 ? num : `0${num}`)
/**
* 获取距今天之前多少天的所有时间
* @param time {Number} Number是ele日期区间选择组件返回的结果
* Number是之前时刻距离今天的间隔天数默认是30天
* @return {Array} ['2017-01-17', '2017-01-28', '2017-10-29',...]
*/
exports.getDateInterval = (time = 30) => {
// const gapTime = time * 24 * 3600 * 1000;
// 今天
let endTime = new Date().getTime();
let timeList = []
for (let i = 0; i < time; i++) {
const gapTime = i * 24 * 3600 * 1000;
const time = this.formatYMD(endTime - gapTime);
timeList.push(time);
}
return timeList;
}
/**2017-10-27 00:00:00 2017-10-27 23:59:59
* @param date {String} "2017-10-27"
* @return {Array} [ 1509033600000, 1509119999000 ]
*/
exports.getTimeInterval = (date) => {
const startTime = (getNowMidnightDate(date).getTime()-86400000)/1000;
const endTime =(getNowMidnightDate(date).getTime()-1000)/1000;
// console.log('start',formatDate(startTime))
return [startTime, endTime];
}
/**
* 获取当前时间午夜0点的日期对象
*/
const getNowMidnightDate = (time) => {
let date;
if (time) {
date = new Date(time);
} else {
date = new Date();
}
return new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1);
}
/**
* 格式化
* @param val {Object or String or Number} 日期对象 或是可new Date的对象或时间戳
* @return {String} 2017-01-20 20:00:00
*/
const formatDate = val => {
let date = val;
if (typeof val !== 'object') {
date = new Date(val);
}
return `${[
date.getFullYear(),
convert2Decimal(date.getMonth() + 1),
convert2Decimal(date.getDate())
].join('-')} ${[
convert2Decimal(date.getHours()),
convert2Decimal(date.getMinutes()),
convert2Decimal(date.getSeconds())
].join(':')}`;
}
/**
* 格式化年
* @param val {Object or String or Number} 日期对象 或是可new Date的对象或时间戳
* @return {String} 2017-01-20
*/
exports.formatYMD = (val, joinStr = '-') => {
let date = val;
if (typeof val !== 'object') {
date = new Date(val);
}
return `${[
date.getFullYear(),
convert2Decimal(date.getMonth() + 1),
convert2Decimal(date.getDate())
].join(joinStr)}`;
}
/**
* 获取所需的时间差值,
* tipnew Date('2017-01-17 00:00:00')在safari下不可用需进行替换
* @param Array ['2017-01-17 00:00:00', '2017-01-20 23:59:59']
* @return {Number} 3
*/
exports.getDayGapFromRange = dateRange => {
const startTime = dateSpacialWithSafari(dateRange[0]);
const endTime = dateSpacialWithSafari(dateRange[1]);
return Math.ceil((endTime - startTime) / 86400000);
}
/**
* dateSpacialWithSafari 格式话safari下通用的格式
* @param str {String} 2017-04-19T11:01:19.074+0800 or 2017-10-10 10:10:10
* @return {number} date.getTime()
*/
const dateSpacialWithSafari = str => {
if (str.indexOf('T') > -1) {
let date;
str.replace(/(\d{4})-(\d{2})-(\d{2})\w(\d{2}):(\d{2}):(\d{2})/, (match, p1, p2, p3, p4, p5, p6) => {
date = new Date(p1, +p2 - 1, p3, p4, p5, p6);
return;
})
return date.getTime();
}
return new Date(str.replace(/-/g, '/')).getTime();
}

View File

@ -97,6 +97,7 @@
"react-scripts": "1.0.10",
"reactabular-dnd": "^8.9.0",
"reactabular-table": "^8.9.0",
"recharts": "^1.0.0-beta.0",
"redux": "^3.7.1",
"redux-devtools": "^3.4.0",
"redux-devtools-dock-monitor": "^1.1.2",

View File

@ -44,6 +44,11 @@ class interfaceCase extends baseModel {
return m.save();
}
//获取全部测试接口信息
getInterfaceCaseListCount() {
return this.model.count({});
}
get(id) {
return this.model.findOne({
_id: id

View File

@ -37,7 +37,7 @@ var hooks = {
* 客户端更新接口成功后触发
* @param id 接口id
*/
'interface_update':{
'interface_update': {
type: 'multi',
listener: []
},
@ -45,7 +45,7 @@ var hooks = {
* 客户端获取接口数据列表
* @param id project_id
*/
'interface_list':{
'interface_list': {
type: 'multi',
listener: []
},
@ -53,7 +53,7 @@ var hooks = {
* 客户端获取一条接口信息触发
* @param id 接口id
*/
'interface_get':{
'interface_get': {
type: 'multi',
listener: []
},
@ -61,7 +61,7 @@ var hooks = {
* 客户端增加一个新项目
* @param id 项目id
*/
'project_add':{
'project_add': {
type: 'multi',
listener: []
},
@ -69,7 +69,7 @@ var hooks = {
* 客户端删除删除一个项目
* @param id 项目id
*/
'project_del':{
'project_del': {
type: 'multi',
listener: []
},
@ -131,12 +131,12 @@ function emitHook(name) {
if (hooks[name] && typeof hooks[name] === 'object') {
let args = Array.prototype.slice.call(arguments, 1);
if (hooks[name].type === 'single' && typeof hooks[name].listener === 'function') {
return Promise.resolve(hooks[name].listener.apply(yapi, args));
return Promise.resolve(hooks[name].listener.apply(yapi, args));
}
let promiseAll = [];
if (Array.isArray(hooks[name].listener)) {
let listenerList = hooks[name].listener;
for(let i=0, l = listenerList.length; i< l; i++){
for (let i = 0, l = listenerList.length; i < l; i++) {
promiseAll.push(Promise.resolve(listenerList[i].apply(yapi, args)));
}
}