mirror of
https://github.com/YMFE/yapi.git
synced 2025-03-13 14:26:50 +08:00
Merge branch 'dev' of gitlab.corp.qunar.com:mfe/yapi into dev
This commit is contained in:
commit
07900bc947
1
.gitignore
vendored
1
.gitignore
vendored
@ -41,3 +41,4 @@ dev/
|
||||
.tags
|
||||
.tags1
|
||||
tsconfig.json
|
||||
client/plugin-module.js
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React, { Component } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Route, BrowserRouter as Router } from 'react-router-dom';
|
||||
@ -7,6 +8,7 @@ import User from './containers/User/User.js';
|
||||
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 { checkLoginState } from './reducer/modules/user';
|
||||
import { requireAuthentication } from './components/AuthenticatedComponent';
|
||||
|
||||
@ -46,7 +48,13 @@ export default class App extends Component {
|
||||
return <Loading visible />;
|
||||
} else {
|
||||
r = (
|
||||
<Router >
|
||||
<Router getUserConfirmation={(msg, callback) => {
|
||||
let container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
ReactDOM.render((
|
||||
<MyPopConfirm msg={msg} callback={callback} />
|
||||
), container);
|
||||
}}>
|
||||
<div className="g-main">
|
||||
<div className="router-main">
|
||||
{this.props.loginState !== 1 ? <Header /> : null}
|
||||
|
48
client/components/GuideBtns/GuideBtns.js
Normal file
48
client/components/GuideBtns/GuideBtns.js
Normal file
@ -0,0 +1,48 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button } from 'antd';
|
||||
import { connect } from 'react-redux'
|
||||
import { changeStudyTip, finishStudy } from '../../reducer/modules/user.js';
|
||||
|
||||
@connect(
|
||||
null,
|
||||
{
|
||||
changeStudyTip,
|
||||
finishStudy
|
||||
}
|
||||
)
|
||||
class GuideBtns extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
changeStudyTip: PropTypes.func,
|
||||
finishStudy: PropTypes.func,
|
||||
isLast: PropTypes.bool
|
||||
}
|
||||
|
||||
// 点击下一步
|
||||
nextStep = () => {
|
||||
this.props.changeStudyTip();
|
||||
if (this.props.isLast) {
|
||||
this.props.finishStudy();
|
||||
}
|
||||
}
|
||||
|
||||
// 点击退出指引
|
||||
exitGuide = () => {
|
||||
this.props.finishStudy();
|
||||
}
|
||||
|
||||
render () {
|
||||
console.log(this.props);
|
||||
return (
|
||||
<div className="btn-container">
|
||||
<Button className="btn" type="primary" onClick={this.nextStep}>{this.props.isLast ? '完 成' : '下一步'}</Button>
|
||||
<Button className="btn" type="dashed" onClick={this.exitGuide}>退出指引</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default GuideBtns;
|
@ -3,7 +3,7 @@ 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 } from 'antd'
|
||||
import { Icon, Layout, Menu, Dropdown, message, Tooltip, Avatar, Popover } from 'antd'
|
||||
import { checkLoginState, logoutActions, loginTypeAction} from '../../reducer/modules/user'
|
||||
import { changeMenuItem } from '../../reducer/modules/menu'
|
||||
import { withRouter } from 'react-router';
|
||||
@ -11,6 +11,7 @@ import Srch from './Search/Search'
|
||||
const { Header } = Layout;
|
||||
import { logoSVG } from '../../common.js';
|
||||
import Breadcrumb from '../Breadcrumb/Breadcrumb.js'
|
||||
import GuideBtns from '../GuideBtns/GuideBtns.js';
|
||||
|
||||
const MenuUser = (props) => (
|
||||
<Menu theme="dark" className="user-menu" >
|
||||
@ -23,6 +24,15 @@ const MenuUser = (props) => (
|
||||
</Menu>
|
||||
);
|
||||
|
||||
const tip = (<div className="title-container">
|
||||
<h3 className="title">工具栏</h3>
|
||||
<p><Icon type="search" /> 搜索功能: 搜索分组与项目;</p>
|
||||
<p><Icon type="heart" /> 关注功能: 属于自己的收藏夹;</p>
|
||||
<p><Icon type="plus-circle" /> 新建项目: 在任何页面都可以快速新建项目;</p>
|
||||
<p><Icon type="question-circle" /> 使用文档: 遇到问题的时候随时可以查看文档;</p>
|
||||
<p>你还可以更换头像,便于同事在 YApi 里找到你 ~</p>
|
||||
</div>);
|
||||
|
||||
MenuUser.propTypes={
|
||||
user: PropTypes.string,
|
||||
msg: PropTypes.string,
|
||||
@ -96,7 +106,9 @@ ToolUser.propTypes={
|
||||
user: state.user.userName,
|
||||
uid: state.user.uid,
|
||||
msg: null,
|
||||
login:state.user.isLogin
|
||||
login:state.user.isLogin,
|
||||
studyTip: state.user.studyTip,
|
||||
study: state.user.study
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -123,7 +135,9 @@ export default class HeaderCom extends Component {
|
||||
loginTypeAction:PropTypes.func,
|
||||
changeMenuItem:PropTypes.func,
|
||||
history: PropTypes.object,
|
||||
location: PropTypes.object
|
||||
location: PropTypes.object,
|
||||
study: PropTypes.bool,
|
||||
studyTip: PropTypes.number
|
||||
}
|
||||
linkTo = (e) =>{
|
||||
if(e.key != '/doc'){
|
||||
@ -184,13 +198,21 @@ export default class HeaderCom extends Component {
|
||||
<Breadcrumb />
|
||||
<div className="user-toolbar">
|
||||
{login?
|
||||
<ToolUser
|
||||
user = { user }
|
||||
msg = { msg }
|
||||
uid = { uid }
|
||||
relieveLink = { this.relieveLink }
|
||||
logout = { this.logout }
|
||||
/>
|
||||
<Popover
|
||||
overlayClassName="popover-index"
|
||||
content={<GuideBtns/>}
|
||||
title={tip}
|
||||
placement="bottomRight"
|
||||
visible={(this.props.studyTip === 1 && !this.props.study) ? true : false}
|
||||
>
|
||||
<ToolUser
|
||||
user = { user }
|
||||
msg = { msg }
|
||||
uid = { uid }
|
||||
relieveLink = { this.relieveLink }
|
||||
logout = { this.logout }
|
||||
/>
|
||||
</Popover>
|
||||
:""}
|
||||
</div>
|
||||
</div>
|
||||
|
50
client/components/MyPopConfirm/MyPopConfirm.js
Normal file
50
client/components/MyPopConfirm/MyPopConfirm.js
Normal file
@ -0,0 +1,50 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Modal, Button } from 'antd';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
// 嵌入到 BrowserRouter 内部,覆盖掉默认的 window.confirm
|
||||
// http://reacttraining.cn/web/api/BrowserRouter/getUserConfirmation-func
|
||||
class MyPopConfirm extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
visible: true
|
||||
};
|
||||
}
|
||||
static propTypes = {
|
||||
msg: PropTypes.string,
|
||||
callback: PropTypes.func
|
||||
};
|
||||
|
||||
yes = () => {
|
||||
this.props.callback(true);
|
||||
this.setState({ visible: false });
|
||||
}
|
||||
|
||||
no = () => {
|
||||
this.props.callback(false);
|
||||
this.setState({ visible: false });
|
||||
}
|
||||
|
||||
componentWillReceiveProps() {
|
||||
this.setState({ visible: true });
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.state.visible) {
|
||||
return null;
|
||||
}
|
||||
return (<Modal
|
||||
title="你即将离开编辑页面"
|
||||
visible={this.state.visible}
|
||||
footer={[
|
||||
<Button key="back" onClick={this.no}>取 消</Button>,
|
||||
<Button key="submit" onClick={this.yes}>确 定</Button>
|
||||
]}
|
||||
>
|
||||
<p>{this.props.msg}</p>
|
||||
</Modal>);
|
||||
}
|
||||
}
|
||||
|
||||
export default MyPopConfirm;
|
@ -72,7 +72,7 @@ export default class Run extends Component {
|
||||
validRes: [],
|
||||
hasPlugin: true,
|
||||
test_status: null,
|
||||
resTest: false,
|
||||
resTest: true,
|
||||
resStatusCode: null,
|
||||
resStatusText: ''
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ class UsernameAutoComplete extends Component {
|
||||
|
||||
return (
|
||||
<Select
|
||||
mode="multiple"
|
||||
mode="multiple"
|
||||
style={{ width: '100%' }}
|
||||
placeholder="请输入用户名"
|
||||
filterOption={false}
|
||||
@ -109,7 +109,7 @@ class UsernameAutoComplete extends Component {
|
||||
onChange={this.handleChange}
|
||||
size="large"
|
||||
>
|
||||
{children}
|
||||
{children}
|
||||
</Select>
|
||||
)
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { connect } from 'react-redux'
|
||||
import { Icon, Modal, Alert, Input, message, Menu, Row, Col, Dropdown } from 'antd'
|
||||
import { Icon, Modal, Alert, Input, message, Menu, Row, Col, Dropdown, Popover } from 'antd'
|
||||
import { autobind } from 'core-decorators';
|
||||
import axios from 'axios';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
@ -10,6 +10,7 @@ const Search = Input.Search;
|
||||
const TYPE_EDIT = 'edit';
|
||||
const confirm = Modal.confirm;
|
||||
import UsernameAutoComplete from '../../../components/UsernameAutoComplete/UsernameAutoComplete.js';
|
||||
import GuideBtns from '../../../components/GuideBtns/GuideBtns.js';
|
||||
import { fetchNewsData } from '../../../reducer/modules/news.js';
|
||||
import {
|
||||
fetchGroupList,
|
||||
@ -17,13 +18,20 @@ import {
|
||||
setGroupList
|
||||
} from '../../../reducer/modules/group.js'
|
||||
|
||||
import './GroupList.scss'
|
||||
import './GroupList.scss';
|
||||
|
||||
const tip = (<div className="title-container">
|
||||
<h3 className="title">欢迎使用 YApi ~</h3>
|
||||
<p>这里的 <b>“个人空间”</b> 是你自己才能看到的分组,你拥有这个分组的全部权限,可以在这个分组里尝试 YApi 的功能。</p>
|
||||
</div>);
|
||||
|
||||
@connect(
|
||||
state => ({
|
||||
groupList: state.group.groupList,
|
||||
currGroup: state.group.currGroup,
|
||||
curUserRole: state.user.role
|
||||
curUserRole: state.user.role,
|
||||
studyTip: state.user.studyTip,
|
||||
study: state.user.study
|
||||
}),
|
||||
{
|
||||
fetchGroupList,
|
||||
@ -44,6 +52,8 @@ export default class GroupList extends Component {
|
||||
match: PropTypes.object,
|
||||
history: PropTypes.object,
|
||||
curUserRole: PropTypes.string,
|
||||
studyTip: PropTypes.number,
|
||||
study: PropTypes.bool,
|
||||
fetchNewsData: PropTypes.func
|
||||
}
|
||||
|
||||
@ -242,7 +252,7 @@ export default class GroupList extends Component {
|
||||
</Menu.Item>
|
||||
const editmark = <Menu.Item>
|
||||
<span onClick={() => { this.showConfirm() }}>删除分组</span>
|
||||
</Menu.Item>
|
||||
</Menu.Item>
|
||||
const addmark = <Menu.Item>
|
||||
<span onClick={this.showModal}>添加分组</span>
|
||||
</Menu.Item>
|
||||
@ -291,16 +301,27 @@ export default class GroupList extends Component {
|
||||
onClick={this.selectGroup}
|
||||
selectedKeys={[`${currGroup._id}`]}
|
||||
>
|
||||
{
|
||||
this.state.groupList.map((group) => (
|
||||
<Menu.Item key={`${group._id}`} className="group-item">
|
||||
{group.type === 'private' ?
|
||||
<Icon type="user" /> :
|
||||
<Icon type="folder-open" />
|
||||
}{group.group_name}
|
||||
{this.state.groupList.map((group) => {
|
||||
if(group.type === 'private') {
|
||||
return <Menu.Item key={`${group._id}`} className="group-item">
|
||||
<Icon type="user" />
|
||||
<Popover
|
||||
overlayClassName="popover-index"
|
||||
content={<GuideBtns/>}
|
||||
title={tip}
|
||||
placement="right"
|
||||
visible={(this.props.studyTip === 0 && !this.props.study) ? true : false}
|
||||
>
|
||||
{group.group_name}
|
||||
</Popover>
|
||||
</Menu.Item>
|
||||
))
|
||||
}
|
||||
} else {
|
||||
return <Menu.Item key={`${group._id}`} className="group-item">
|
||||
<Icon type="folder-open" />
|
||||
{group.group_name}
|
||||
</Menu.Item>
|
||||
}
|
||||
})}
|
||||
</Menu>
|
||||
</div>
|
||||
{
|
||||
|
@ -1,15 +1,23 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { Row, Col, Button, Tooltip } from 'antd';
|
||||
import { Row, Col, Button, Tooltip, Popover } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { addProject, fetchProjectList, delProject, changeUpdateModal } from '../../../reducer/modules/project';
|
||||
import ProjectCard from '../../../components/ProjectCard/ProjectCard.js';
|
||||
import ErrMsg from '../../../components/ErrMsg/ErrMsg.js';
|
||||
import { autobind } from 'core-decorators';
|
||||
import { setBreadcrumb } from '../../../reducer/modules/user';
|
||||
import GuideBtns from '../../../components/GuideBtns/GuideBtns.js';
|
||||
|
||||
import './ProjectList.scss'
|
||||
import './ProjectList.scss';
|
||||
|
||||
const tip = (<div className="title-container">
|
||||
<h3 className="title">项目列表</h3>
|
||||
<p>这里列出了分组下的所有项目。</p>
|
||||
<p>成为分组成员即可在该分组下添加项目。</p>
|
||||
<p>赶快创建属于你的第一个项目把 ~</p>
|
||||
</div>);
|
||||
|
||||
@connect(
|
||||
state => {
|
||||
@ -18,7 +26,9 @@ import './ProjectList.scss'
|
||||
userInfo: state.project.userInfo,
|
||||
tableLoading: state.project.tableLoading,
|
||||
currGroup: state.group.currGroup,
|
||||
currPage: state.project.currPage
|
||||
currPage: state.project.currPage,
|
||||
studyTip: state.user.studyTip,
|
||||
study: state.user.study
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -49,7 +59,9 @@ class ProjectList extends Component {
|
||||
tableLoading: PropTypes.bool,
|
||||
currGroup: PropTypes.object,
|
||||
setBreadcrumb: PropTypes.func,
|
||||
currPage: PropTypes.number
|
||||
currPage: PropTypes.number,
|
||||
studyTip: PropTypes.number,
|
||||
study: PropTypes.bool
|
||||
}
|
||||
|
||||
// 取消修改
|
||||
@ -113,7 +125,15 @@ class ProjectList extends Component {
|
||||
|
||||
|
||||
{/(admin)|(owner)|(dev)/.test(this.props.currGroup.role) ?
|
||||
<Button type="primary" ><Link to="/add-project">添加项目</Link></Button> :
|
||||
<Popover
|
||||
overlayClassName="popover-index"
|
||||
content={<GuideBtns isLast={true}/>}
|
||||
title={tip}
|
||||
placement="right"
|
||||
visible={(this.props.studyTip === 2 && !this.props.study) ? true : false}
|
||||
>
|
||||
<Button type="primary" ><Link to="/add-project">添加项目</Link></Button>
|
||||
</Popover> :
|
||||
<Tooltip title="您没有权限,请联系该分组组长或管理员">
|
||||
<Button type="primary" disabled >添加项目</Button>
|
||||
</Tooltip>}
|
||||
|
@ -135,7 +135,8 @@ class Content extends Component {
|
||||
<Prompt
|
||||
when={this.state.curtab === 'edit' && this.props.editStatus ? true : false}
|
||||
message={() => {
|
||||
this.showModal();
|
||||
// this.showModal();
|
||||
console.log('e');
|
||||
return '离开页面会丢失当前编辑的内容,确定要离开吗?';
|
||||
}}
|
||||
/>
|
||||
|
1
client/plugin-module.js
Normal file
1
client/plugin-module.js
Normal file
@ -0,0 +1 @@
|
||||
module.exports = {}
|
@ -79,21 +79,25 @@ pluginModule = {
|
||||
bindHook: bindHook,
|
||||
emitHook: emitHook
|
||||
}
|
||||
let pluginModuleList;
|
||||
try{
|
||||
pluginModuleList = require('./plugin-module.js');
|
||||
}catch(err){pluginModuleList = {}}
|
||||
|
||||
config.plugins.forEach(plugin => {
|
||||
|
||||
config.plugins.forEach(plugin=>{
|
||||
if (!plugin) return null;
|
||||
if (!plugin.enable) return null;
|
||||
if (plugin.client) {
|
||||
let p = require(`plugins/yapi-plugin-${plugin.name}/client.js`);
|
||||
p.call(pluginModule, plugin);
|
||||
if(plugin.client){
|
||||
if(pluginModuleList[plugin.name] && typeof pluginModuleList[plugin.name] === 'function'){
|
||||
pluginModuleList[plugin.name].call(pluginModule, plugin)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
|
||||
systemPlugins.forEach(plugin => {
|
||||
if (!plugin) return null;
|
||||
if (!plugin.enable) return null;
|
||||
|
||||
if (plugin.client) {
|
||||
let p = require(`exts/yapi-plugin-${plugin.name}/client.js`);
|
||||
p.call(pluginModule, plugin);
|
||||
|
@ -7,6 +7,8 @@ const LOGIN_TYPE = 'yapi/user/LOGIN_TYPE';
|
||||
const GET_LOGIN_STATE = 'yapi/user/GET_LOGIN_STATE';
|
||||
const REGISTER = 'yapi/user/REGISTER';
|
||||
const SET_BREADCRUMB = 'yapi/user/SET_BREADCRUMB';
|
||||
const CHANGE_STUDY_TIP = 'yapi/user/CHANGE_STUDY_TIP';
|
||||
const FINISH_STUDY = 'yapi/user/FINISH_STUDY';
|
||||
|
||||
// Reducer
|
||||
const LOADING_STATUS = 0;
|
||||
@ -28,7 +30,8 @@ const initialState = {
|
||||
// }, {
|
||||
// name: '当前页面'
|
||||
// }]
|
||||
breadcrumb: []
|
||||
breadcrumb: [],
|
||||
studyTip: 0
|
||||
};
|
||||
|
||||
export default (state = initialState, action) => {
|
||||
@ -41,7 +44,8 @@ export default (state = initialState, action) => {
|
||||
loginState: (action.payload.data.errcode == 0)?MEMBER_STATUS:GUEST_STATUS,
|
||||
userName: action.payload.data.data ? action.payload.data.data.username : null,
|
||||
uid: action.payload.data.data ? action.payload.data.data._id : null,
|
||||
type: action.payload.data.data ? action.payload.data.data.type : null
|
||||
type: action.payload.data.data ? action.payload.data.data.type : null,
|
||||
study: action.payload.data.data ? action.payload.data.data.study : false
|
||||
};
|
||||
}
|
||||
case LOGIN: {
|
||||
@ -53,7 +57,8 @@ export default (state = initialState, action) => {
|
||||
uid: action.payload.data.data.uid,
|
||||
userName: action.payload.data.data.username,
|
||||
role: action.payload.data.data.role,
|
||||
type: action.payload.data.data.type
|
||||
type: action.payload.data.data.type,
|
||||
study: action.payload.data.data.study
|
||||
};
|
||||
} else {
|
||||
return state;
|
||||
@ -92,6 +97,18 @@ export default (state = initialState, action) => {
|
||||
breadcrumb: action.data
|
||||
};
|
||||
}
|
||||
case CHANGE_STUDY_TIP: {
|
||||
return {
|
||||
...state,
|
||||
studyTip: state.studyTip + 1
|
||||
}
|
||||
}
|
||||
case FINISH_STUDY: {
|
||||
return {
|
||||
...state,
|
||||
study: true
|
||||
};
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
@ -149,3 +166,16 @@ export function setBreadcrumb(data) {
|
||||
data
|
||||
}
|
||||
}
|
||||
|
||||
export function changeStudyTip() {
|
||||
return {
|
||||
type: CHANGE_STUDY_TIP
|
||||
}
|
||||
}
|
||||
|
||||
export function finishStudy() {
|
||||
return {
|
||||
type: FINISH_STUDY,
|
||||
payload: axios.get('/api/user/up_study')
|
||||
}
|
||||
}
|
||||
|
@ -171,3 +171,22 @@ em {
|
||||
.has-affix-footer {
|
||||
padding-bottom: .92rem;
|
||||
}
|
||||
|
||||
.popover-index {
|
||||
max-width: 3.2rem;
|
||||
.ant-popover-title {
|
||||
height: auto;
|
||||
}
|
||||
.title-container {
|
||||
padding: .16rem 0;
|
||||
.title {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.btn-container {
|
||||
text-align: center;
|
||||
.btn {
|
||||
margin: 0 .04rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
module.exports = function(){
|
||||
return null;
|
||||
};
|
@ -69,8 +69,7 @@ class baseController {
|
||||
|
||||
async getLoginStatus(ctx) {
|
||||
if (await this.checkLogin(ctx) === true) {
|
||||
let result = yapi.commons.fieldSelect(this.$user, ['_id', 'username', 'email', 'up_time', 'add_time', 'role', 'type']);
|
||||
result.server_ip = yapi.WEBCONFIG.server_ip;
|
||||
let result = yapi.commons.fieldSelect(this.$user, ['_id', 'username', 'email', 'up_time', 'add_time', 'role', 'type', 'study']);
|
||||
return ctx.body = yapi.commons.resReturn(result);
|
||||
}
|
||||
return ctx.body = yapi.commons.resReturn(null, 40011, '请登录...');
|
||||
|
@ -55,7 +55,8 @@ class userController extends baseController {
|
||||
add_time: result.add_time,
|
||||
up_time: result.up_time,
|
||||
server_ip: yapi.WEBCONFIG.server_ip,
|
||||
type: 'site'
|
||||
type: 'site',
|
||||
study: result.study
|
||||
}, 0, 'logout success...');
|
||||
} else {
|
||||
return ctx.body = yapi.commons.resReturn(null, 405, '密码错误');
|
||||
@ -78,6 +79,30 @@ class userController extends baseController {
|
||||
ctx.body = yapi.commons.resReturn('ok');
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录接口
|
||||
* @interface /user/up_study
|
||||
* @method GET
|
||||
* @category user
|
||||
* @foldnumber 10
|
||||
* @returns {Object}
|
||||
* @example
|
||||
*/
|
||||
|
||||
async upStudy(ctx) {
|
||||
let userInst = yapi.getInst(userModel); //创建user实体
|
||||
let data = {
|
||||
up_time: yapi.commons.time(),
|
||||
study: true
|
||||
};
|
||||
try {
|
||||
let result = await userInst.update(this.getUid(), data);
|
||||
ctx.body = yapi.commons.resReturn(result);
|
||||
} catch (e) {
|
||||
ctx.body = yapi.commons.resReturn(null, 401, e.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 第三方登录需要提供一个request方法和 token字段,暂时只支持qunar第三方
|
||||
@ -281,7 +306,8 @@ class userController extends baseController {
|
||||
role: 'member',
|
||||
add_time: yapi.commons.time(),
|
||||
up_time: yapi.commons.time(),
|
||||
type: "site"
|
||||
type: "site",
|
||||
study: false
|
||||
};
|
||||
|
||||
if (!data.username) {
|
||||
|
@ -20,6 +20,7 @@ class userModel extends baseModel {
|
||||
required: true
|
||||
},
|
||||
passsalt: String,
|
||||
study: {type: Boolean, default: false},
|
||||
role: String,
|
||||
add_time: Number,
|
||||
up_time: Number,
|
||||
@ -39,19 +40,19 @@ class userModel extends baseModel {
|
||||
}
|
||||
|
||||
list() {
|
||||
return this.model.find().select('_id username email role type add_time up_time').exec(); //显示id name email role
|
||||
return this.model.find().select('_id username email role type add_time up_time study').exec(); //显示id name email role
|
||||
}
|
||||
|
||||
findByUids(uids) {
|
||||
return this.model.find({
|
||||
_id: { $in: uids }
|
||||
}).select('_id username email role type add_time up_time').exec();
|
||||
}).select('_id username email role type add_time up_time study').exec();
|
||||
}
|
||||
|
||||
listWithPaging(page, limit) {
|
||||
page = parseInt(page);
|
||||
limit = parseInt(limit);
|
||||
return this.model.find().sort({ _id: -1 }).skip((page - 1) * limit).limit(limit).select('_id username email role type add_time up_time').exec();
|
||||
return this.model.find().sort({ _id: -1 }).skip((page - 1) * limit).limit(limit).select('_id username email role type add_time up_time study').exec();
|
||||
}
|
||||
|
||||
listCount() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
const yapi = require('./yapi.js');
|
||||
const plugin_path = yapi.path.join(yapi.WEBROOT, 'plugins');
|
||||
const plugin_path = yapi.path.join(yapi.WEBROOT, 'node_modules');
|
||||
const plugin_system_path = yapi.path.join(yapi.WEBROOT, 'exts');
|
||||
const initPlugins = require('../common/lib.js').initPlugins;
|
||||
var extConfig = require('../common/config.js').exts;
|
||||
|
@ -148,6 +148,11 @@ let routerConfig = {
|
||||
"path": "login_by_token",
|
||||
"method": "post"
|
||||
},
|
||||
{
|
||||
action: 'upStudy',
|
||||
path: 'up_study',
|
||||
method: 'get'
|
||||
},
|
||||
{
|
||||
"action": "changePassword",
|
||||
"path": "change_password",
|
||||
|
@ -79,7 +79,7 @@ exports.fieldSelect = (data, field) => {
|
||||
var arr = {};
|
||||
|
||||
field.forEach((f) => {
|
||||
data[f] && (arr[f] = data[f]);
|
||||
(typeof data[f] !== 'undefined') && (arr[f] = data[f]);
|
||||
});
|
||||
|
||||
return arr;
|
||||
|
39
service.sh
39
service.sh
@ -1,39 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
prog="/var/soft/node-v6.11.1-linux-x64/bin/pm2"
|
||||
app="/home/q/www/yapi.beta.corp.qunar.com/webapp/server_dist/app.js"
|
||||
|
||||
|
||||
|
||||
start() {
|
||||
echo "Starting Server..."
|
||||
eval "$prog start $app --name=yapi"
|
||||
}
|
||||
|
||||
stop() {
|
||||
echo "Stopping Server..."
|
||||
eval "$prog stop yapi"
|
||||
}
|
||||
|
||||
restart() {
|
||||
echo "Restart Server..."
|
||||
eval "$prog restart yapi"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start && exit 0
|
||||
;;
|
||||
stop)
|
||||
stop || exit 0
|
||||
;;
|
||||
restart)
|
||||
restart || exit 0
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|restart}"
|
||||
exit 2
|
||||
esac
|
@ -1 +1 @@
|
||||
window.WEBPACK_ASSETS = {"index.js":{"js":"index@726f0c05be8ee7a1b257.js","css":"index@726f0c05be8ee7a1b257.css"},"lib":{"js":"lib@70933cf119a409aca1f2.js"},"lib2":{"js":"lib2@2536ef5c4b4711cf085a.js"},"manifest":{"js":"manifest@b67af9f8b578904e66c5.js"}}
|
||||
window.WEBPACK_ASSETS = {"index.js":{"js":"index@86c2b0ce829f6e441377.js","css":"index@86c2b0ce829f6e441377.css"},"lib":{"js":"lib@0fe1d0abd11fbb8ef3d6.js"},"lib2":{"js":"lib2@980bff89a8e0841fa293.js"},"manifest":{"js":"manifest@b67af9f8b578904e66c5.js"}}
|
18928
static/prd/index.css
18928
static/prd/index.css
File diff suppressed because it is too large
Load Diff
5331
static/prd/index.js
5331
static/prd/index.js
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
1
static/prd/index@86c2b0ce829f6e441377.css
Normal file
1
static/prd/index@86c2b0ce829f6e441377.css
Normal file
File diff suppressed because one or more lines are too long
BIN
static/prd/index@86c2b0ce829f6e441377.css.gz
Normal file
BIN
static/prd/index@86c2b0ce829f6e441377.css.gz
Normal file
Binary file not shown.
1
static/prd/index@86c2b0ce829f6e441377.js
Normal file
1
static/prd/index@86c2b0ce829f6e441377.js
Normal file
File diff suppressed because one or more lines are too long
BIN
static/prd/index@86c2b0ce829f6e441377.js.gz
Normal file
BIN
static/prd/index@86c2b0ce829f6e441377.js.gz
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3019
static/prd/lib.js
3019
static/prd/lib.js
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
static/prd/lib2@980bff89a8e0841fa293.js.gz
Normal file
BIN
static/prd/lib2@980bff89a8e0841fa293.js.gz
Normal file
Binary file not shown.
1
static/prd/lib@0fe1d0abd11fbb8ef3d6.js
Normal file
1
static/prd/lib@0fe1d0abd11fbb8ef3d6.js
Normal file
File diff suppressed because one or more lines are too long
BIN
static/prd/lib@0fe1d0abd11fbb8ef3d6.js.gz
Normal file
BIN
static/prd/lib@0fe1d0abd11fbb8ef3d6.js.gz
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -1,94 +0,0 @@
|
||||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // install a JSONP callback for chunk loading
|
||||
/******/ var parentJsonpFunction = window["webpackJsonp"];
|
||||
/******/ window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules) {
|
||||
/******/ // add "moreModules" to the modules object,
|
||||
/******/ // then flag all "chunkIds" as loaded and fire callback
|
||||
/******/ var moduleId, chunkId, i = 0, callbacks = [];
|
||||
/******/ for(;i < chunkIds.length; i++) {
|
||||
/******/ chunkId = chunkIds[i];
|
||||
/******/ if(installedChunks[chunkId])
|
||||
/******/ callbacks.push.apply(callbacks, installedChunks[chunkId]);
|
||||
/******/ installedChunks[chunkId] = 0;
|
||||
/******/ }
|
||||
/******/ for(moduleId in moreModules) {
|
||||
/******/ modules[moduleId] = moreModules[moduleId];
|
||||
/******/ }
|
||||
/******/ if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules);
|
||||
/******/ while(callbacks.length)
|
||||
/******/ callbacks.shift().call(null, __webpack_require__);
|
||||
/******/ if(moreModules[0]) {
|
||||
/******/ installedModules[0] = 0;
|
||||
/******/ return __webpack_require__(0);
|
||||
/******/ }
|
||||
/******/ };
|
||||
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
|
||||
/******/ // object to store loaded and loading chunks
|
||||
/******/ // "0" means "already loaded"
|
||||
/******/ // Array means "loading", array contains callbacks
|
||||
/******/ var installedChunks = {
|
||||
/******/ 3:0
|
||||
/******/ };
|
||||
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId])
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ exports: {},
|
||||
/******/ id: moduleId,
|
||||
/******/ loaded: false
|
||||
/******/ };
|
||||
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.loaded = true;
|
||||
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
|
||||
/******/ // This file contains only the entry chunk.
|
||||
/******/ // The chunk loading function for additional chunks
|
||||
/******/ __webpack_require__.e = function requireEnsure(chunkId, callback) {
|
||||
/******/ // "0" is the signal for "already loaded"
|
||||
/******/ if(installedChunks[chunkId] === 0)
|
||||
/******/ return callback.call(null, __webpack_require__);
|
||||
|
||||
/******/ // an array means "currently loading".
|
||||
/******/ if(installedChunks[chunkId] !== undefined) {
|
||||
/******/ installedChunks[chunkId].push(callback);
|
||||
/******/ } else {
|
||||
/******/ // start chunk loading
|
||||
/******/ installedChunks[chunkId] = [callback];
|
||||
/******/ var head = document.getElementsByTagName('head')[0];
|
||||
/******/ var script = document.createElement('script');
|
||||
/******/ script.type = 'text/javascript';
|
||||
/******/ script.charset = 'utf-8';
|
||||
/******/ script.async = true;
|
||||
|
||||
/******/ script.src = __webpack_require__.p + "" + chunkId + ".chunk.js";
|
||||
/******/ head.appendChild(script);
|
||||
/******/ }
|
||||
/******/ };
|
||||
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([]);
|
20
ykit.js
20
ykit.js
@ -26,10 +26,18 @@ function fileExist (filePath){
|
||||
};
|
||||
|
||||
function initPlugins(){
|
||||
if(config.plugins && Array.isArray(config.plugins)){
|
||||
var scripts = [] ;
|
||||
if(config.plugins && Array.isArray(config.plugins) && config.plugins.length){
|
||||
config.plugins = config.plugins.filter(item=>{
|
||||
return fileExist(path.resolve(__dirname, 'plugins/yapi-plugin-' + item + '/client.js'))
|
||||
return fileExist(path.resolve(__dirname, 'node_modules/yapi-plugin-' + item + '/client.js'))
|
||||
})
|
||||
config.plugins.forEach((plugin)=>{
|
||||
scripts.push(`${plugin} : require('plugins/yapi-plugin-${plugin}/client.js')`)
|
||||
})
|
||||
scripts = "module.exports = {" + scripts.join(",") + "}";
|
||||
fs.writeFileSync('client/plugin-module.js', scripts);
|
||||
}else{
|
||||
fs.writeFileSync('client/plugin-module.js', 'module.exports = {}');
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,13 +58,13 @@ module.exports = {
|
||||
defaultQuery.plugins.push(["import", { libraryName: "antd"}])
|
||||
return defaultQuery;
|
||||
},
|
||||
exclude: /node_modules/
|
||||
}
|
||||
exclude: /node_modules\/(?!yapi-plugin)/
|
||||
}
|
||||
}],
|
||||
// devtool: 'cheap-source-map',
|
||||
config: function (ykit) {
|
||||
return {
|
||||
exports: [
|
||||
exports: [
|
||||
'./index.js'
|
||||
],
|
||||
commonsChunk: {
|
||||
@ -110,7 +118,7 @@ module.exports = {
|
||||
baseConfig.context = path.resolve(__dirname, './client');
|
||||
baseConfig.resolve.alias.client = '/client';
|
||||
baseConfig.resolve.alias.common = '/common';
|
||||
baseConfig.resolve.alias.plugins = '/plugins';
|
||||
baseConfig.resolve.alias.plugins = '/node_modules';
|
||||
baseConfig.resolve.alias.exts = '/exts';
|
||||
baseConfig.output.prd.path = 'static/prd';
|
||||
baseConfig.output.prd.publicPath = '';
|
||||
|
Loading…
x
Reference in New Issue
Block a user