diff --git a/client/ReduxContainer.js b/client/ReduxContainer.js index 92ace258..a0c8263e 100644 --- a/client/ReduxContainer.js +++ b/client/ReduxContainer.js @@ -2,10 +2,12 @@ import LoginRedux from './reducer/Login/Login_redux.js' import login from './reducer/Login/login.js' import group from './reducer/group/group.js' import Interface from './reducer/Interface/InterfaceReducer.js' +import news from './reducer/news/news.js' export default { group, login, LoginRedux, - Interface + Interface, + news } diff --git a/client/actions/news.js b/client/actions/news.js new file mode 100644 index 00000000..31b34382 --- /dev/null +++ b/client/actions/news.js @@ -0,0 +1,66 @@ +import { + FETCH_NEWS_DATA +} from '../constants/action-types.js'; + +export function fetchNewsData () { + const data = [{ + name: 'John Brown', + date: '2015-11-11 13:00:15', + desc: '创建服务现场' + }, { + name: 'John Brown1', + date: '2015-11-11 13:00:15', + desc: '技术测试异常' + }, { + name: 'John Brown2', + date: '2015-11-11 13:00:15', + desc: '网络异常正在修复' + }] + + return { + type: FETCH_NEWS_DATA, + payload: data + }; +} + +export function fetchViewedNews () { + const data = [{ + name: 'John Brown21', + date: '2015-11-11 13:00:15', + desc: '创建服务现场' + }, { + name: 'John Brown12', + date: '2015-11-11 13:00:15', + desc: '技术测试异常' + }, { + name: 'John Brown22', + date: '2015-11-11 13:00:15', + desc: '网络异常正在修复' + }] + + return { + type: FETCH_NEWS_DATA, + payload: data + } +} + +export function fetchNotVieweNews () { + const data = [{ + name: 'John Brown22', + date: '2015-11-11 13:00:15', + desc: '创建服务现场' + }, { + name: 'John Brown12', + date: '2015-11-11 13:00:15', + desc: '技术测试异常' + }, { + name: 'John Brown22', + date: '2015-11-11 13:00:15', + desc: '网络异常正在修复' + }] + + return { + type: FETCH_NEWS_DATA, + payload: data + } +} diff --git a/client/constants/action-types.js b/client/constants/action-types.js index dd3f4970..0965f35e 100644 --- a/client/constants/action-types.js +++ b/client/constants/action-types.js @@ -16,3 +16,7 @@ export const REGISTER = 'REGISTER'; //header export const LOGIN_TYPE = 'LOGIN_TYPE'; + +// News +export const FETCH_NEWS_DATA = 'FETCH_NEWS_DATA' + diff --git a/client/containers/News/News.js b/client/containers/News/News.js new file mode 100644 index 00000000..b3808597 --- /dev/null +++ b/client/containers/News/News.js @@ -0,0 +1,43 @@ +import './News.scss' +import React, { Component } from 'react' +import NewsTimeline from './NewsTimeline/NewsTimeline' +import { connect } from 'react-redux' +import PropTypes from 'prop-types' +import NewsList from './NewsList/NewsList.js' +import { fetchNewsData } from '../../actions/news.js' + + +@connect( + state => { + return { + newsData: state.news.newsData?state.news.newsData:[] + } + }, + { + fetchNewsData: fetchNewsData + } +) + +class News extends Component { + constructor(props) { + super(props) + } + static propTypes = { + newsData: PropTypes.array, + fetchNewsData: PropTypes.func + } + componentWillMount(){ + this.props.fetchNewsData() + } + render () { + const data = this.props.newsData; + return ( +
+ + +
+ ) + } +} + +export default News diff --git a/client/containers/News/News.scss b/client/containers/News/News.scss new file mode 100644 index 00000000..e5f8224e --- /dev/null +++ b/client/containers/News/News.scss @@ -0,0 +1,31 @@ +/* .interface-box.css */ +.news-box { + max-width: 11rem; + display: -webkit-box; + -webkit-box-flex: 1; + margin: 15px auto 0 auto; + font-size: 0.14rem; + background: #FFF; + + .news-list { + width: 216px; + line-height: 45px; + background: #f9fafe; + + li { + padding: 0 0 0 30px; + color: #344562; + cursor: pointer; + + &:hover, &.active { + background: #657289; + color: #FFF; + } + } + } + +} +.news-timeline{ + margin-left: 30px; + margin-top: 30px; +} \ No newline at end of file diff --git a/client/containers/News/NewsList/NewsList.js b/client/containers/News/NewsList/NewsList.js new file mode 100644 index 00000000..0b33508f --- /dev/null +++ b/client/containers/News/NewsList/NewsList.js @@ -0,0 +1,77 @@ +import React, { Component } from 'react' +import { connect } from 'react-redux' +import PropTypes from 'prop-types' +import { + fetchNewsData, + fetchViewedNews, + fetchNotVieweNews } from '../../../actions/news.js' + + +@connect( + state => { + return { + newsData: state.news.newsData + } + }, + { + fetchNewsData, + fetchViewedNews, + fetchNotVieweNews + } +) + +class NewsList extends Component { + + static propTypes = { + fetchNewsData: PropTypes.func, + fetchViewedNews: PropTypes.func, + fetchNotVieweNews: PropTypes.func + } + + constructor(props) { + super(props) + } + + + + fetchData(e){ + const mark = e.target.className; + if(mark.indexOf('allnews')>-1){ + this.props.fetchNewsData() + this.switchColor(mark.indexOf('allnews'),e.target) + }else if(mark.indexOf('viewednews')>-1){ + this.props.fetchViewedNews(); + this.switchColor(mark.indexOf('viewednews'),e.target) + }else if(mark.indexOf('notview')>-1){ + this.props.fetchNotVieweNews(); + this.switchColor(mark.indexOf('notview'),e.target) + } + + } + switchColor(index,e){ + let childNodes = e.parentNode.childNodes; + if(e.className.indexOf('active')> -1) return; + for(let j = 0;j -1){ + // console.log( childNodes[i].className.splice); + let className = childNodes[j].className; + className = className.split(''); + className.splice(i,6); + childNodes[j].className = className.join(''); + } + } + e.className = e.className + ' active'; + } + render () { + return ( + + ) + } +} + +export default NewsList \ No newline at end of file diff --git a/client/containers/News/NewsTimeline/NewsTimeline.js b/client/containers/News/NewsTimeline/NewsTimeline.js new file mode 100644 index 00000000..23dc9bfc --- /dev/null +++ b/client/containers/News/NewsTimeline/NewsTimeline.js @@ -0,0 +1,32 @@ +import React, { Component } from 'react' +import { Timeline } from 'antd' +import PropTypes from 'prop-types' + +class NewsTimeline extends Component { + static propTypes = { + data: PropTypes.array + } + + constructor(props) { + super(props) + } + + render () { + const data = this.props.data; + return ( +
+ See more}> + { + data.map(function(item,i){ + return ( + { item.date + item.desc + item.name } + ) + }) + } + +
+ ) + } +} + +export default NewsTimeline diff --git a/client/containers/User/userTable/InterfaceTable.js b/client/containers/User/InterfaceTable/InterfaceTable.js similarity index 68% rename from client/containers/User/userTable/InterfaceTable.js rename to client/containers/User/InterfaceTable/InterfaceTable.js index c2e73fd2..6288fe03 100644 --- a/client/containers/User/userTable/InterfaceTable.js +++ b/client/containers/User/InterfaceTable/InterfaceTable.js @@ -13,21 +13,21 @@ class InterfaceTable extends Component { render () { const columns = [{ - title: 'Uid', - dataIndex: 'uid', - key: 'uid' + title: '接口名称', + dataIndex: 'name', + key: 'name' }, { - title: '用户名', - dataIndex: 'username', - key: 'username' + title: '接口URL', + dataIndex: 'age', + key: 'age' }, { - title: 'email', - dataIndex: 'email', - key: 'email' + title: '操作者', + dataIndex: 'address', + key: 'address' }, { title: '更新日期', - dataIndex: 'up_time', - key: 'up_time' + dataIndex: 'date', + key: 'date' }, { title: '功能', 'key': 'action', @@ -41,9 +41,7 @@ class InterfaceTable extends Component { } }] - const data = [ - {uid: 1, username: 'admin', email: 'admin@admin.com', up_time: '2017.07.01'} - ]; + const data = this.props.data; return (
diff --git a/client/containers/User/LeftMenu.js b/client/containers/User/LeftMenu.js new file mode 100644 index 00000000..e7de34c3 --- /dev/null +++ b/client/containers/User/LeftMenu.js @@ -0,0 +1,62 @@ +import React, { Component } from 'react' +import { Link } from 'react-router-dom' +import {Input, Row, Col} from 'antd' + +class LeftMenu extends Component { + + + constructor(props) { + super(props) + this.state = { + curitem: 'profile' + } + console.log(this.props) + } + + handleCurItem(curitem) { + return () => { + this.setState({ + curitem: curitem + }) + } + } + + render() { + const menus = [{ + title: '个人资料', + path: '/user/profile' + }, { + title: '用户管理', + path: '/user/list' + } + ] + + let content = menus.map((menu, index) => { + return ( +
  • + {menu.title} +
  • + ) + }) + + const Search = Input.Search; + + return (
    + + + console.log(value)} + /> + + + +
      + {content} +
    +
    + ) + } +} + +export default LeftMenu \ No newline at end of file diff --git a/client/containers/User/List.js b/client/containers/User/List.js new file mode 100755 index 00000000..7cffd611 --- /dev/null +++ b/client/containers/User/List.js @@ -0,0 +1,64 @@ +import React, { Component } from 'react' +//import PropTypes from 'prop-types' +import { + Table, + Button +} from 'antd' + + + +class List extends Component { + + constructor(props) { + super(props) + + } + + render() { + + const columns = [{ + title: 'UID', + dataIndex: 'uid', + key: 'uid' + }, { + title: '用户名', + dataIndex: 'username', + key: 'username' + }, { + title: 'email', + dataIndex: 'email', + key: 'email' + }, { + title: '更新日期', + dataIndex: 'up_time', + key: 'up_time' + }, { + title: '功能', + key: 'action', + render: () => { + return ( + + + + + ) + } + }] + + + const data = [ + { uid: 1, username: 'admin', email: 'admin@admin.com', up_time: '2017.07.01', key: 1 }, + { uid: 2, username: 'admin2', email: 'admin21113qq3ß@admin311.com', up_time: '2017.07.21', key: 2 } + ]; + + return ( +
    + + + + + ) + } +} + +export default List diff --git a/client/containers/User/Profile.js b/client/containers/User/Profile.js new file mode 100644 index 00000000..864f05ae --- /dev/null +++ b/client/containers/User/Profile.js @@ -0,0 +1,113 @@ +import React, { Component } from 'react' +import { Row, Col, Icon , Input, Button, Select} from 'antd' + +class Profile extends Component { + + constructor(props) { + super(props) + this.state = { + usernameEdit: false, + emailEdit: false, + secureEdit: false, + roleEdit: false + } + } + + handleEdit = (key, val) =>{ + var s = {}; + s[key] = val ; + this.setState(s) + } + + render() { + let ButtonGroup = Button.Group; + let userNameEditHtml, emailEditHtml,secureEditHtml, roleEditHtml; + const Option = Select.Option; + if(this.state.usernameEdit === false){ + userNameEditHtml =
    + xiaoming   + {this.handleEdit( 'usernameEdit', true)}}>修改 +
    + }else{ + userNameEditHtml =
    + + + + + +
    + } + + if(this.state.emailEdit === false){ + emailEditHtml =
    + abc@qq.com   + {this.handleEdit( 'emailEdit', true)}} >修改 +
    + }else{ + emailEditHtml =
    + + + + + +
    + } + + if(this.state.roleEdit === true){ + roleEditHtml =
    + 管理员   + {this.handleEdit( 'roleEdit', true)}} >修改 +
    + }else{ + roleEditHtml = + } + + if(this.state.secureEdit === false){ + secureEditHtml = + }else{ + secureEditHtml =
    + + + + + + +
    + } + + + return
    + +
    用户名 + + {userNameEditHtml} + + + + + Email + + {emailEditHtml} + + + + 角色 + + {roleEditHtml} + + + + 安全 + + {secureEditHtml} + + + + } +} + +export default Profile diff --git a/client/containers/User/User.js b/client/containers/User/User.js new file mode 100755 index 00000000..51739a9f --- /dev/null +++ b/client/containers/User/User.js @@ -0,0 +1,42 @@ +import './index.scss' +import React, { Component } from 'react' +import { connect } from 'react-redux' +import { Route} from 'react-router-dom' +import LeftMenu from './LeftMenu.js' +import List from './List.js' +import PropTypes from 'prop-types' +import Profile from './Profile.js' + +@connect() +class User extends Component { + static propTypes = { + match: PropTypes.object + } + + constructor(props) { + super(props) + } + + componentDidMount () { + console.log(this.props.match) + } + + render () { + + + return ( +
    +
    + + + + + +
    +
    + ) + } +} + +export default User \ No newline at end of file diff --git a/client/containers/User/index.scss b/client/containers/User/index.scss index e5733c85..64e61f6e 100644 --- a/client/containers/User/index.scss +++ b/client/containers/User/index.scss @@ -6,6 +6,30 @@ margin: 15px auto 0 auto; font-size: 0.14rem; background: #FFF; + min-height:500px; + + .search{ + height: 40px; + padding: 5px; + background: #f9f9f9; + + input{ + background: #f9f9f9; + line-height: 40px; + height: 40px; + border: 0; + font-size: 14px; + } + + input:focus{ + outline:0; + border-color:0; + box-shadow: none + } + + + + } .user-list { width: 216px; @@ -14,13 +38,16 @@ li { padding: 0 0 0 30px; - color: #344562; - cursor: pointer; + a{ + color: #344562; + } - &:hover, &.active { + &.active,&.active a { background: #657289; color: #FFF; + text-decoration: none; } + } } @@ -36,4 +63,33 @@ } } } + + .user-profile { + -webkit-box-flex: 1; + margin-top: 15px; + margin-left: 15px; + + .user-item { + min-height:35px; + line-height:35px; + margin: 5px; + margin-bottom:10px; + + .text-button{ + font-size: 12px; + color: #657289; + cursor: pointer + } + + .edit-buttons{ + margin:10px; + } + + .edit-button{ + margin: 5px; + } + } + } + + } \ No newline at end of file diff --git a/client/containers/User/userList/userList.js b/client/containers/User/userList/userList.js deleted file mode 100644 index 9c6a689f..00000000 --- a/client/containers/User/userList/userList.js +++ /dev/null @@ -1,25 +0,0 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' - -class InterfaceList extends Component { - static propTypes = { - projectMember: PropTypes.func - } - - constructor(props) { - super(props) - } - - render () { - const { projectMember } = this.props - - return ( -
      -
    • 个人资料
    • -
    • 用户管理
    • -
    - ) - } -} - -export default InterfaceList \ No newline at end of file diff --git a/client/containers/index.js b/client/containers/index.js index e5014aa6..d92b4ae3 100644 --- a/client/containers/index.js +++ b/client/containers/index.js @@ -2,10 +2,12 @@ import Home from './Home/Home.js' import Login from './Login/login-wrap.js' import ProjectGroups from './ProjectGroups/ProjectGroups.js' import Interface from './Interface/Interface.js' +import News from './News/News.js' export { Home, Login, ProjectGroups, - Interface + Interface, + News } diff --git a/client/reducer/news/news.js b/client/reducer/news/news.js new file mode 100644 index 00000000..374e5410 --- /dev/null +++ b/client/reducer/news/news.js @@ -0,0 +1,20 @@ +import { + FETCH_NEWS_DATA +} from '../../constants/action-types.js' + +const initialState = { + newsData: [] +} + +export default (state = initialState, action) => { + switch (action.type) { + case FETCH_NEWS_DATA: { + return { + ...state, + newsData: action.payload + }; + } + default: + return state; + } +} diff --git a/client/routes.js b/client/routes.js index 552e9a9b..67069a00 100644 --- a/client/routes.js +++ b/client/routes.js @@ -1,6 +1,9 @@ import React from 'react' + import { Route, HashRouter } from 'react-router-dom' -import { Home, ProjectGroups, Interface } from './containers/index' +import { Home, ProjectGroups, Interface, News } from './containers/index' +import User from './containers/User/User.js' + import Header from './components/Header/Header' export default () => { @@ -11,7 +14,11 @@ export default () => { + + + ) } + \ No newline at end of file diff --git a/client/styles/common.scss b/client/styles/common.scss index a9e067c1..069d979c 100644 --- a/client/styles/common.scss +++ b/client/styles/common.scss @@ -26,6 +26,9 @@ ul { a { text-decoration: none; + &:active, &:hover, &:visited{ + text-decoration: none + } } a:hover { diff --git a/runtime/config.dev.json b/runtime/config.dev.json index bc831657..df132f3f 100644 --- a/runtime/config.dev.json +++ b/runtime/config.dev.json @@ -3,9 +3,11 @@ "webhost": "127.0.0.1", "adminAccount": "admin@admin.com", "db": { - "servername": "192.168.237.71", + "servername": "10.86.40.194", "DATABASE": "yapi", - "port": 27017 + "port": 27017, + "user": "yapi", + "pass": "yapi" }, "mail": { "host": "smtp.163.com", diff --git a/server/install.js b/server/install.js index 7f7b6268..5fafdf4d 100644 --- a/server/install.js +++ b/server/install.js @@ -22,6 +22,7 @@ function setupSql(){ let userInst = yapi.getInst(userModel); let passsalt = yapi.commons.randStr(); let result = userInst.save({ + username: yapi.WEBCONFIG.adminAccount.substr(0, yapi.WEBCONFIG.adminAccount.indexOf('@')), email: yapi.WEBCONFIG.adminAccount, password: yapi.commons.generatePassword('qunar.com', passsalt), passsalt: passsalt, diff --git a/server/middleware/mockServer.js b/server/middleware/mockServer.js index 6cb58768..61382f27 100644 --- a/server/middleware/mockServer.js +++ b/server/middleware/mockServer.js @@ -18,24 +18,23 @@ module.exports = async (ctx, next) => { return ctx.body = yapi.commons.resReturn(null, 403, e.message); } - let matchProject = []; + let matchProject = false, maxBasepath = 0; for(let i=0, l = projects.length; i< l; i++){ let project = projects[i]; if(ctx.path && ctx.path.indexOf(project.basepath) === 0 && project.basepath[project.basepath.length -1] === '/'){ - matchProject.push(project); + matchProject.push(project); + if(project.basepath.length > maxBasepath){ + maxBasepath = project.basepath.length; + matchProject = project; + } } } - - if(matchProject.length === 0){ + if(matchProject === false){ return ctx.body = yapi.commons.resReturn(null, 400, '不存在的domain'); } - if(matchProject.length > 1){ - return ctx.body = yapi.commons.resReturn(null, 401, '存在多个project,请检查数据库'); - } - - let project = matchProject[0], interfaceData; + let project = matchProject, interfaceData; let interfaceInst = yapi.getInst(interfaceModel); try{ interfaceData = await interfaceInst.getByPath(project._id, ctx.path.substr(project.basepath.length)); diff --git a/server/utils/db.js b/server/utils/db.js index 1aab20af..ff9f8728 100644 --- a/server/utils/db.js +++ b/server/utils/db.js @@ -16,7 +16,10 @@ function connect(){ mongoose.Promise = global.Promise; let config = yapi.WEBCONFIG; - let db = mongoose.connect(`mongodb://${config.db.servername}:${config.db.port}/${config.db.DATABASE}`); + let db = mongoose.connect(`mongodb://${config.db.servername}:${config.db.port}/${config.db.DATABASE}`, { + user: config.db.user, + pass: config.db.pass + }); db.then(function (res) { yapi.commons.log('mongodb load success...')