Merge branch 'dev' of gitlab.corp.qunar.com:mfe/yapi into dev

This commit is contained in:
zwjamnsss 2017-09-29 14:29:06 +08:00
commit 07900bc947
46 changed files with 328 additions and 27548 deletions

1
.gitignore vendored
View File

@ -41,3 +41,4 @@ dev/
.tags
.tags1
tsconfig.json
client/plugin-module.js

View File

@ -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}

View 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;

View File

@ -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>

View 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;

View File

@ -72,7 +72,7 @@ export default class Run extends Component {
validRes: [],
hasPlugin: true,
test_status: null,
resTest: false,
resTest: true,
resStatusCode: null,
resStatusText: ''
}

View File

@ -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>
)
}

View File

@ -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>
{

View File

@ -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>}

View File

@ -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
View File

@ -0,0 +1 @@
module.exports = {}

View File

@ -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);

View File

@ -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')
}
}

View File

@ -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;
}
}
}

View File

@ -1,3 +0,0 @@
module.exports = function(){
return null;
};

View File

@ -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, '请登录...');

View File

@ -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) {

View File

@ -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() {

View File

@ -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;

View File

@ -148,6 +148,11 @@ let routerConfig = {
"path": "login_by_token",
"method": "post"
},
{
action: 'upStudy',
path: 'up_study',
method: 'get'
},
{
"action": "changePassword",
"path": "change_password",

View File

@ -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;

View File

@ -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

View File

@ -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"}}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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.

File diff suppressed because one or more lines are too long

View File

@ -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
View File

@ -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 = '';