fix: modify

This commit is contained in:
qitmac000249 2017-08-11 10:16:50 +08:00
commit ad72fd9b38
14 changed files with 8 additions and 1422 deletions

View File

@ -4,7 +4,7 @@ import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
import { Icon, Layout, Menu, Dropdown, message, Tooltip } from 'antd'
import { checkLoginState, logoutActions, loginTypeAction} from '../../reducer/modules/login'
import { checkLoginState, logoutActions, loginTypeAction} from '../../reducer/modules/user'
import { changeMenuItem } from '../../reducer/modules/menu'
import { withRouter } from 'react-router';
import Srch from './Search/Search'
@ -44,7 +44,7 @@ const ToolUser = (props)=> (
<li className="toolbar-li item-search">
<Srch groupList={props.groupList}/>
</li>
<Link to="/">
<Link to="/add-project">
<Tooltip placement="bottom" title={'新建项目'}>
<li className="toolbar-li">
<Icon className="dropdown-link" style={{ fontSize: 16 }} type="plus-circle" />
@ -89,11 +89,16 @@ ToolUser.propTypes={
@connect(
(state) => {
return{
<<<<<<< HEAD
avatar: state.login.avatar,
user: state.login.userName,
uid: state.login.uid,
=======
user: state.user.userName,
uid: state.user.uid,
>>>>>>> 8c04198eb2dd2e6ddae9b815cc9a21b6436d8c76
msg: null,
login:state.login.isLogin
login:state.user.isLogin
}
},
{

View File

@ -1,276 +0,0 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { Button, Icon, Popconfirm, Modal, Input, message, Menu, Row, Col } from 'antd'
import { autobind } from 'core-decorators';
import axios from 'axios';
import { withRouter } from 'react-router';
const { TextArea } = Input;
const Search = Input.Search;
const TYPE_EDIT = 'edit';
import {
fetchGroupList,
setCurrGroup,
setGroupList
} from '../../../reducer/modules/group.js'
import './GroupList.scss'
@connect(
state => ({
groupList: state.group.groupList,
currGroup: state.group.currGroup,
curUserRole: state.login.role
}),
{
fetchGroupList,
setCurrGroup,
setGroupList
}
)
@withRouter
export default class GroupList extends Component {
static propTypes = {
groupList: PropTypes.array,
currGroup: PropTypes.object,
fetchGroupList: PropTypes.func,
setCurrGroup: PropTypes.func,
setGroupList: PropTypes.func,
match: PropTypes.object,
history: PropTypes.object,
curUserRole: PropTypes.string
}
state = {
addGroupModalVisible: false,
editGroupModalVisible: false,
newGroupName: '',
newGroupDesc: '',
currGroupName: '',
currGroupDesc: '',
groupList: []
}
constructor(props) {
super(props)
}
async componentWillMount() {
const groupName = this.props.match.params.groupName;
await this.props.fetchGroupList();
let currGroup = this.props.groupList[0] || { group_name: '', group_desc: '' };
if(this.props.groupList.length && groupName){
for(let i = 0;i<this.props.groupList.length;i++){
if(this.props.groupList[i].group_name === groupName){
currGroup = this.props.groupList[i];
}else{
this.props.history.replace(`${currGroup._id}`);
}
}
}else if(!groupName && this.props.groupList.length){
this.props.history.push(`/group/${this.props.groupList[0]._id}`);
}
this.setState({groupList: this.props.groupList});
this.props.setCurrGroup(currGroup)
}
@autobind
showModal(type) {
if (type === 'edit') {
const { currGroup } = this.props;
this.setState({
currGroupName: currGroup.group_name,
currGroupDesc: currGroup.group_desc,
editGroupModalVisible: true
});
} else {
this.setState({
addGroupModalVisible: true
});
}
}
@autobind
hideModal(type) {
if (type === TYPE_EDIT) {
this.setState({
editGroupModalVisible: false
});
} else {
this.setState({
addGroupModalVisible: false
});
}
}
@autobind
async addGroup() {
const { newGroupName: group_name, newGroupDesc: group_desc } = this.state;
const res = await axios.post('/group/add', { group_name, group_desc })
if (!res.data.errcode) {
this.setState({
addGroupModalVisible: false
});
await this.props.fetchGroupList();
this.setState({groupList: this.props.groupList});
this.props.setCurrGroup(res.data.data)
}
}
@autobind
async editGroup() {
const { currGroupName: group_name, currGroupDesc: group_desc } = this.state;
const id = this.props.currGroup._id;
const res = axios.post('/group/up', { group_name, group_desc, id });
if (res.data.errcode) {
message.error(res.data.errmsg);
} else {
this.setState({
editGroupModalVisible: false
});
this.props.setCurrGroup({ group_name, group_desc, _id: id });
}
}
@autobind
inputNewGroupName(e, type) {
if (type === TYPE_EDIT) {
this.setState({ currGroupName: e.target.value})
} else {
this.setState({newGroupName: e.target.value});
}
}
@autobind
inputNewGroupDesc(e, type) {
if (type === TYPE_EDIT) {
this.setState({ currGroupDesc: e.target.value})
} else {
this.setState({newGroupDesc: e.target.value});
}
}
@autobind
selectGroup(e) {
const groupId = e.key;
const currGroup = this.props.groupList.find((group) => { return +group._id === +groupId });
this.props.setCurrGroup(currGroup);
this.props.history.replace(`${currGroup._id}`);
}
@autobind
async deleteGroup() {
const self = this;
const { currGroup } = self.props;
const res = await axios.post('/group/del', {id: currGroup._id})
if (res.data.errcode) {
message.error(res.data.errmsg);
} else {
message.success('删除成功');
await self.props.fetchGroupList()
const currGroup = self.props.groupList[0] || { group_name: '', group_desc: '' };
self.setState({groupList: self.props.groupList});
self.props.setCurrGroup(currGroup)
}
}
@autobind
searchGroup(e, value) {
const v = value || e.target.value;
const { groupList } = this.props;
if (v === '') {
this.setState({groupList})
} else {
this.setState({groupList: groupList.filter(group => new RegExp(v, 'i').test(group.group_name))})
}
}
render () {
const { currGroup } = this.props;
const delmark = <Icon className="edit-group" type="edit" title="编辑分组" onClick={() => this.showModal(TYPE_EDIT)}/>
const editmark = (<Popconfirm title={`你确定要删除分组 ${currGroup.group_name}`} onConfirm={this.deleteGroup}>
<Icon className="delete-group" type="delete" title="删除分组"/>
</Popconfirm>)
return (
<div className="m-group">
<div className="group-bar">
<div className="curr-group">
<div className="curr-group-name">
<div className="text" title={currGroup.group_name}>{currGroup.group_name}</div>
{
this.props.curUserRole === "admin"?(editmark):''
}
{
this.props.curUserRole === "admin"?(delmark):''
}
</div>
<div className="curr-group-desc" title={currGroup.group_desc}>简介{currGroup.group_desc}</div>
</div>
<div className="group-operate">
<div className="search">
<Search onChange={this.searchGroup} onSearch={(v) => this.searchGroup(null, v)}/>
</div>
{
this.props.curUserRole === "admin"?(<Button type="primary" onClick={this.showModal}>添加分组</Button>):''
}
</div>
<Menu
className="group-list"
mode="inline"
onClick={this.selectGroup}
selectedKeys={[`${currGroup._id}`]}
>
{
this.state.groupList.map((group) => (
<Menu.Item key={`${group._id}`} className="group-item">
<Icon type="folder-open" />{group.group_name}
</Menu.Item>
))
}
</Menu>
</div>
<Modal
title="添加分组"
visible={this.state.addGroupModalVisible}
onOk={this.addGroup}
onCancel={this.hideModal}
className="add-group-modal"
>
<Row gutter={6} className="modal-input">
<Col span="5"><div className="label">分组名</div></Col>
<Col span="15">
<Input placeholder="请输入分组名称" onChange={this.inputNewGroupName}></Input>
</Col>
</Row>
<Row gutter={6} className="modal-input">
<Col span="5"><div className="label">简介</div></Col>
<Col span="15">
<TextArea rows = {3} placeholder="请输入分组描述" onChange={this.inputNewGroupDesc}></TextArea>
</Col>
</Row>
</Modal>
<Modal
title="编辑分组"
visible={this.state.editGroupModalVisible}
onOk={this.editGroup}
onCancel={() => this.hideModal(TYPE_EDIT)}
className="add-group-modal"
>
<Row gutter={6} className="modal-input">
<Col span="5"><div className="label">分组名</div></Col>
<Col span="15">
<Input placeholder="请输入分组名称" value={this.state.currGroupName} onChange={(e) => this.inputNewGroupName(e, TYPE_EDIT)}></Input>
</Col>
</Row>
<Row gutter={6} className="modal-input">
<Col span="5"><div className="label">简介</div></Col>
<Col span="15">
<TextArea rows={3} placeholder="请输入分组描述" value={this.state.currGroupDesc} onChange={(e) => this.inputNewGroupDesc(e, TYPE_EDIT)}></TextArea>
</Col>
</Row>
</Modal>
</div>
)
}
}

View File

@ -1,92 +0,0 @@
.group-bar {
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.20);
border-radius: 4px;
background-color: #fff;
min-height: 5rem;
.curr-group {
background: #34495E;
border-radius: 4px 4px 0 0;
padding: 32px 24px;
.curr-group-name {
.text {
display: inline-block;
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
max-width: 150px;
vertical-align: bottom;
}
color: #fff;
font-size: 24px;
}
.curr-group-desc {
color: #fff;
font-size: 12px;
max-height: 54px;
text-overflow:ellipsis;
overflow:hidden;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
display: -webkit-box;
}
.delete-group, .edit-group {
font-size: 18px;
margin-left: 12px;
cursor: pointer;
}
.delete-group:hover, .edit-group:hover {
color: #ccc;
}
}
.group-operate {
height: 48px;
padding: 10px 6px;
background: #eee;
display: flex;
justify-content: space-around;
.search {
margin-right: 6px;
flex-grow: 1;
}
}
.group-list {
max-height: 650px;
overflow-y: scroll;
overflow-x: hidden;
border-bottom: 1px solid #e9e9e9;
padding-bottom: 24px;
border-radius: 0 0 4px 4px;
border: none;
.group-item {
// height: 48px;
// line-height: 48px;
// padding: 0 24px;
font-size: 14px;
}
.group-item:hover {
// background: #34495E;
// color: #fff;
}
.group-item.selected {
// background: #34495E;
}
.group-name {
float: left;
}
.group-edit {
float: right;
font-size: 18px;
}
}
}
.add-group-modal {
.modal-input {
margin: 24px;
}
.label {
text-align: right;
line-height: 28px;
}
}

View File

@ -1,39 +0,0 @@
import React, { Component } from 'react';
import GroupList from './GroupList/GroupList.js';
import ProjectList from './ProjectList/ProjectList.js';
import Subnav from '../../components/Subnav/Subnav.js';
import { Row, Col } from 'antd';
import './ProjectGroups.scss'
export default class ProjectGroups extends Component {
constructor(props) {
super(props)
}
render () {
return (
<div>
<Subnav
default={'项目广场'}
data={[{
name: '项目广场',
path: '/group'
}, {
name: '我的关注',
path: '/follow'
}]}/>
<div className="g-row">
<Row gutter={16}>
<Col span={6}>
<GroupList></GroupList>
</Col>
<Col span={18}>
<ProjectList/>
</Col>
</Row>
</div>
</div>
)
}
}

View File

@ -1,6 +0,0 @@
@import '../../styles/mixin.scss';
.g-doc {
@include row-width-limit;
margin: 0 auto .24rem;
}

View File

@ -1,343 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Table, Button, Modal, Form, Input, Icon, Tooltip, Select, Popconfirm, message } from 'antd';
import { addProject, fetchProjectList, delProject, changeUpdateModal, changeTableLoading } from '../../../reducer/modules/project';
import UpDateModal from './UpDateModal';
import { Link } from 'react-router-dom'
import variable from '../../../constants/variable';
import common from '../../../common';
import { autobind } from 'core-decorators';
const { TextArea } = Input;
const FormItem = Form.Item;
const Option = Select.Option;
import './ProjectList.scss'
// 确认删除项目 handleDelete, currGroup._id, fetchProjectList
const deleteConfirm = (id, props) => {
const { delProject, currGroup, fetchProjectList } = props;
const handle = () => {
delProject(id).then((res) => {
if (res.payload.data.errcode == 0) {
message.success('删除成功!')
fetchProjectList(currGroup._id).then(() => {
});
} else {
message.error(res.payload.data.errmsg);
}
});
}
return handle;
};
const getColumns = (data, props) => {
const { changeUpdateModal, userInfo } = props;
return [{
title: '项目名称',
dataIndex: 'name',
key: 'name',
render: (text, record) => {
return <Link to={`/project/${record._id}`}>{text}</Link>
}
},{
title: 'Mock基本URL',
key: 'domain',
render: (item) => {
return 'http://'+ item.prd_host + item.basepath;
}
}, {
title: '创建人',
dataIndex: 'owner',
key: 'owner',
render: (text, record, index) => {
// data是projectList的列表值
// 根据序号找到对应项的uid根据uid获取对应项目的创建人
return <span>{userInfo[data[index].uid] ? userInfo[data[index].uid].username : ''}</span>;
}
}, {
title: '创建时间',
dataIndex: 'add_time',
key: 'add_time',
render: time => <span>{common.formatTime(time)}</span>
}, {
title: '操作',
key: 'action',
render: (text, record, index) => {
const id = record._id;
return (
<span>
<a onClick={() => changeUpdateModal(true, index)}>修改</a>
<span className="ant-divider" />
<Popconfirm title="你确定要删除项目吗?" onConfirm={deleteConfirm(id, props)} okText="确定" cancelText="取消">
<a href="#">删除</a>
</Popconfirm>
</span>
)}
}];
}
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 6 }
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 14 }
}
};
@connect(
state => {
return {
projectList: state.project.projectList,
userInfo: state.project.userInfo,
tableLoading: state.project.tableLoading,
currGroup: state.group.currGroup,
total: state.project.total,
currPage: state.project.currPage
}
},
{
fetchProjectList,
addProject,
delProject,
changeUpdateModal,
changeTableLoading
}
)
class ProjectList extends Component {
constructor(props) {
super(props);
this.state = {
visible: false,
protocol: 'http:\/\/',
projectData: []
}
}
static propTypes = {
form: PropTypes.object,
fetchProjectList: PropTypes.func,
addProject: PropTypes.func,
delProject: PropTypes.func,
changeUpdateModal: PropTypes.func,
changeTableLoading: PropTypes.func,
projectList: PropTypes.array,
userInfo: PropTypes.object,
tableLoading: PropTypes.bool,
currGroup: PropTypes.object,
total: PropTypes.number,
currPage: PropTypes.number
}
// 显示模态框 - 创建项目
@autobind
showAddProjectModal() {
this.setState({
visible: true
});
}
// 确认添加项目
@autobind
handleOk(e) {
const { form, currGroup, changeTableLoading, addProject, fetchProjectList } = this.props;
const that = this;
e.preventDefault();
form.validateFields((err, values) => {
if (!err) {
values.protocol = this.state.protocol.split(':')[0];
// 获取当前分组id传入values
values.group_id = currGroup._id;
changeTableLoading(true);
addProject(values).then((res) => {
// 添加项目成功后再次请求列表
if (res.payload.data.errcode == 0) {
that.setState({
visible: false
});
form.resetFields();
message.success('创建成功! ');
fetchProjectList(currGroup._id, this.props.currPage).then(() => {
changeTableLoading(false);
});
} else {
changeTableLoading(false);
message.error(res.payload.data.errmsg);
}
}).catch(() => {
changeTableLoading(false);
});
}
});
}
// 取消修改
@autobind
handleCancel() {
this.props.form.resetFields();
this.setState({
visible: false
});
}
// 修改线上域名的协议类型 (http/https)
@autobind
protocolChange(value) {
this.setState({
protocol: value
})
}
// 分页逻辑
@autobind
paginationChange(pageNum) {
this.props.fetchProjectList(this.props.currGroup._id, pageNum).then((res) => {
if (res.payload.data.errcode) {
message.error(res.payload.data.errmsg);
} else {
this.props.changeTableLoading(false);
}
});
}
componentWillReceiveProps(nextProps) {
// 切换分组
if (this.props.currGroup !== nextProps.currGroup) {
if (nextProps.currGroup._id) {
this.props.fetchProjectList(nextProps.currGroup._id, this.props.currPage).then((res) => {
if (res.payload.data.errcode) {
message.error(res.payload.data.errmsg);
} else {
this.props.changeTableLoading(false);
}
});
} else {
// 无分组的时候停止loading状态
this.props.changeTableLoading(false);
}
}
// 切换项目列表
if (this.props.projectList !== nextProps.projectList) {
// console.log(nextProps.projectList);
const data = nextProps.projectList.map((item, index) => {
item.key = index;
return item;
});
this.setState({
projectData: data
});
}
}
render() {
const { getFieldDecorator } = this.props.form;
return (
<div className="m-container">
<Modal
title="创建项目"
visible={this.state.visible}
onOk={this.handleOk}
onCancel={this.handleCancel}
>
<Form>
<FormItem
{...formItemLayout}
label="项目名称"
>
{getFieldDecorator('name', {
rules: [{
required: true, message: '请输入项目名称!'
}]
})(
<Input />
)}
</FormItem>
<FormItem
{...formItemLayout}
label={(
<span>
线上域名&nbsp;
<Tooltip title="将根据配置的线上域名访问mock数据">
<Icon type="question-circle-o" />
</Tooltip>
</span>
)}
>
{getFieldDecorator('prd_host', {
rules: [{
required: true,
message: '请输入项目线上域名!'
}]
})(
<Input addonBefore={(
<Select defaultValue="http://" onChange={this.protocolChange}>
<Option value="http://">{'http:\/\/'}</Option>
<Option value="https://">{'https:\/\/'}</Option>
</Select>)} />
)}
</FormItem>
<FormItem
{...formItemLayout}
label={(
<span>
基本路径&nbsp;
<Tooltip title="基本路径为空是根路径">
<Icon type="question-circle-o" />
</Tooltip>
</span>
)}
>
{getFieldDecorator('basepath', {
rules: [{
required: false, message: '请输入项目基本路径'
}]
})(
<Input />
)}
</FormItem>
<FormItem
{...formItemLayout}
label="描述"
>
{getFieldDecorator('desc', {
rules: [{
required: false, message: '请输入描述!'
}]
})(
<TextArea rows={4} />
)}
</FormItem>
</Form>
</Modal>
<UpDateModal/>
<Button className="m-btn" icon="plus" type="primary"
onClick={this.showAddProjectModal}
disabled={this.props.currGroup._id ? false : true}>创建项目</Button>
<Table
className="m-table"
bordered={true}
loading={this.props.tableLoading}
columns={getColumns(this.state.projectData, this.props)}
dataSource={this.state.projectData}
pagination={{
total: this.props.total * variable.PAGE_LIMIT,
defaultPageSize: variable.PAGE_LIMIT,
onChange: this.paginationChange
}}
/>
</div>
);
}
}
export default Form.create()(ProjectList);

View File

@ -1,32 +0,0 @@
.m-container{
background-color: #fff;
padding: 24px;
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.20);
border-radius: 4px;
min-height: 5rem;
}
.m-table {
text-align: left;
margin-top: .16rem;
}
.ant-input-group-wrapper {
width: 100%;
}
.dynamic-delete-button {
cursor: pointer;
position: relative;
top: 4px;
font-size: 24px;
color: #999;
transition: all .3s;
}
.dynamic-delete-button:hover {
color: #777;
}
.dynamic-delete-button[disabled] {
cursor: not-allowed;
opacity: 0.5;
}

View File

@ -1,365 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Modal, Form, Input, Icon, Tooltip, Select, message, Button, Row, Col } from 'antd';
import { updateProject, fetchProjectList, delProject, changeUpdateModal, changeTableLoading } from '../../../reducer/modules/project';
const { TextArea } = Input;
const FormItem = Form.Item;
const Option = Select.Option;
import './ProjectList.scss'
// layout
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 6 }
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 14 }
}
};
const formItemLayoutWithOutLabel = {
wrapperCol: {
xs: { span: 24, offset: 0 },
sm: { span: 20, offset: 6 }
}
};
let uuid = 0;
@connect(
state => {
return {
projectList: state.project.projectList,
isUpdateModalShow: state.project.isUpdateModalShow,
handleUpdateIndex: state.project.handleUpdateIndex,
tableLoading: state.project.tableLoading,
currGroup: state.group.currGroup
}
},
{
fetchProjectList,
updateProject,
delProject,
changeUpdateModal,
changeTableLoading
}
)
class UpDateModal extends Component {
constructor(props) {
super(props);
this.state = {
protocol: 'http:\/\/',
envProtocolChange: 'http:\/\/'
}
}
static propTypes = {
form: PropTypes.object,
fetchProjectList: PropTypes.func,
updateProject: PropTypes.func,
delProject: PropTypes.func,
changeUpdateModal: PropTypes.func,
changeTableLoading: PropTypes.func,
projectList: PropTypes.array,
currGroup: PropTypes.object,
isUpdateModalShow: PropTypes.bool,
handleUpdateIndex: PropTypes.number
}
// 修改线上域名的协议类型 (http/https)
protocolChange = (value) => {
this.setState({
protocol: value
})
}
handleCancel = () => {
this.props.form.resetFields();
this.props.changeUpdateModal(false, -1);
}
// 确认修改
handleOk = (e) => {
e.preventDefault();
const { form, updateProject, changeUpdateModal, currGroup, projectList, handleUpdateIndex, fetchProjectList, changeTableLoading } = this.props;
form.validateFields((err, values) => {
if (!err) {
// console.log(projectList[handleUpdateIndex]);
let assignValue = Object.assign(projectList[handleUpdateIndex], values);
values.protocol = this.state.protocol.split(':')[0];
assignValue.env = assignValue.envs.map((item, index) => {
return {
name: values['envs-name-' + index],
domain: values['envs-protocol-' + index] + values['envs-domain-' + index]
}
});
// console.log(assignValue);
changeTableLoading(true);
updateProject(assignValue).then((res) => {
if (res.payload.data.errcode == 0) {
changeUpdateModal(false, -1);
message.success('修改成功! ');
fetchProjectList(currGroup._id).then(() => {
changeTableLoading(false);
});
} else {
changeTableLoading(false);
message.error(res.payload.data.errmsg);
}
}).catch(() => {
changeTableLoading(false);
});
form.resetFields();
}
});
}
// 项目的修改操作 - 删除一项环境配置
remove = (id) => {
const { form } = this.props;
// can use data-binding to get
const envs = form.getFieldValue('envs');
// We need at least one passenger
if (envs.length === 0) {
return;
}
// can use data-binding to set
form.setFieldsValue({
envs: envs.filter(key => {
const realKey = key._id ? key._id : key
return realKey !== id;
})
});
}
// 项目的修改操作 - 添加一项环境配置
add = () => {
uuid++;
const { form } = this.props;
// can use data-binding to get
const envs = form.getFieldValue('envs');
const nextKeys = envs.concat(uuid);
// can use data-binding to set
// important! notify form to detect changes
form.setFieldsValue({
envs: nextKeys
});
}
render() {
const { getFieldDecorator, getFieldValue } = this.props.form;
// const that = this;
const { isUpdateModalShow, projectList, handleUpdateIndex } = this.props;
let initFormValues = {};
let envMessage = [];
// 如果列表存在且用户点击修改按钮时,设置表单默认值
if (projectList.length !== 0 && handleUpdateIndex !== -1) {
// console.log(projectList[handleUpdateIndex]);
const { name, basepath, desc, env } = projectList[handleUpdateIndex];
initFormValues = { name, basepath, desc, env };
if (env.length !== 0) {
envMessage = env;
}
initFormValues.prd_host = projectList[handleUpdateIndex].prd_host;
initFormValues.prd_protocol = projectList[handleUpdateIndex].protocol + '\:\/\/';
}
getFieldDecorator('envs', { initialValue: envMessage });
const envs = getFieldValue('envs');
const formItems = envs.map((k, index) => {
const secondIndex = 'next' + index; // 为保证key的唯一性
return (
<Row key={index} type="flex" justify="space-between" align={index === 0 ? 'middle' : 'top'}>
<Col span={10} offset={2}>
<FormItem
label={index === 0 ? (
<span>环境名称</span>) : ''}
required={false}
key={index}
>
{getFieldDecorator(`envs-name-${index}`, {
validateTrigger: ['onChange', 'onBlur'],
initialValue: envMessage.length !== 0 ? k.name : '',
rules: [{
required: false,
whitespace: true,
validator(rule, value, callback) {
if (value) {
if (value.length === 0) {
callback('请输入环境域名');
} else if (!/\S/.test(value)) {
callback('请输入环境域名');
} else if (/prd/.test(value)) {
callback('环境域名不能是"prd"');
} else {
return callback();
}
} else {
callback('请输入环境域名');
}
}
}]
})(
<Input placeholder="请输入环境名称" style={{ width: '90%', marginRight: 8 }} />
)}
</FormItem>
</Col>
<Col span={10}>
<FormItem
label={index === 0 ? (
<span>环境域名</span>) : ''}
required={false}
key={secondIndex}
>
{getFieldDecorator(`envs-domain-${index}`, {
validateTrigger: ['onChange', 'onBlur'],
initialValue: envMessage.length !== 0 && k.domain ? k.domain.split('\/\/')[1] : '',
rules: [{
required: false,
whitespace: true,
message: "请输入环境域名",
validator(rule, value, callback) {
if (value) {
if (value.length === 0) {
callback('请输入环境域名');
} else if (!/\S/.test(value)) {
callback('请输入环境域名');
} else {
return callback();
}
} else {
callback('请输入环境域名');
}
}
}]
})(
<Input placeholder="请输入环境域名" style={{ width: '90%', marginRight: 8 }} addonBefore={
getFieldDecorator(`envs-protocol-${index}`, {
initialValue: envMessage.length !== 0 && k.domain ? k.domain.split('\/\/')[0] + '\/\/' : 'http\:\/\/',
rules: [{
required: true
}]
})(
<Select>
<Option value="http://">{'http:\/\/'}</Option>
<Option value="https://">{'https:\/\/'}</Option>
</Select>
)} />
)}
</FormItem>
</Col>
<Col span={2}>
{/* 新增的项中,只有最后一项有删除按钮 */}
{(envs.length > 0 && k._id) || (envs.length == index + 1) ? (
<Icon
className="dynamic-delete-button"
type="minus-circle-o"
onClick={() => {
return this.remove(k._id ? k._id : k);
}}
/>
) : null}
</Col>
</Row>
);
});
return (
<Modal
title="修改项目"
visible={isUpdateModalShow}
onOk={this.handleOk}
onCancel={this.handleCancel}
>
<Form>
<FormItem
{...formItemLayout}
label="项目名称"
>
{getFieldDecorator('name', {
initialValue: initFormValues.name,
rules: [{
required: true, message: '请输入项目名称!'
}]
})(
<Input />
)}
</FormItem>
<FormItem
{...formItemLayout}
label={(
<span>
线上域名&nbsp;
<Tooltip title="将根据配置的线上域名访问mock数据">
<Icon type="question-circle-o" />
</Tooltip>
</span>
)}
>
{getFieldDecorator('prd_host', {
initialValue: initFormValues.prd_host,
rules: [{
required: true, message: '请输入项目线上域名!'
}]
})(
<Input addonBefore={(
<Select defaultValue={initFormValues.prd_protocol} onChange={this.protocolChange}>
<Option value="http://">{'http:\/\/'}</Option>
<Option value="https://">{'https:\/\/'}</Option>
</Select>)} />
)}
</FormItem>
<FormItem
{...formItemLayout}
label={(
<span>
基本路径&nbsp;
<Tooltip title="基本路径为空表示根路径">
<Icon type="question-circle-o" />
</Tooltip>
</span>
)}
>
{getFieldDecorator('basepath', {
initialValue: initFormValues.basepath,
rules: [{
required: false, message: '请输入项目基本路径! '
}]
})(
<Input />
)}
</FormItem>
<FormItem
{...formItemLayout}
label="描述"
>
{getFieldDecorator('desc', {
initialValue: initFormValues.desc,
rules: [{
required: false, message: '请输入描述!'
}]
})(
<TextArea rows={4} />
)}
</FormItem>
{formItems}
<FormItem {...formItemLayoutWithOutLabel}>
<Button type="dashed" onClick={this.add} style={{ width: '60%' }}>
<Icon type="plus" /> 添加环境配置
</Button>
</FormItem>
</Form>
</Modal>
);
}
}
export default Form.create()(UpDateModal);

View File

@ -1,139 +0,0 @@
import axios from 'axios';
// Actions
const LOGIN = 'yapi/login/LOGIN';
const LOGIN_OUT = 'yapi/login/LOGIN_OUT';
const LOGIN_TYPE = 'yapi/login/LOGIN_TYPE';
const GET_LOGIN_STATE = 'yapi/login/GET_LOGIN_STATE';
const REGISTER = 'yapi/login/REGISTER';
const GET_AVATAR = 'yapi/login/AVATAR';
// Reducer
const LOADING_STATUS = 0;
const GUEST_STATUS = 1;
const MEMBER_STATUS = 2;
const initialState = {
isLogin: false,
userName: null,
uid: null,
loginState: LOADING_STATUS,
loginWrapActiveKey: "1"
};
export default (state = initialState, action) => {
switch (action.type) {
case GET_LOGIN_STATE: {
console.log(action.payload.data);
return {
...state,
isLogin: (action.payload.data.errcode == 0),
role: action.payload.data.data ? action.payload.data.data.role:null,
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,
server_ip: action.payload.data.data ? action.payload.data.data.server_ip:null
};
}
case LOGIN: {
if (action.payload.data.errcode === 0) {
return {
...state,
isLogin: true,
loginState: MEMBER_STATUS,
uid: action.payload.data.data.uid,
userName: action.payload.data.data.username,
server_ip: action.payload.data.data.server_ip
};
} else {
return state;
}
}
case LOGIN_OUT: {
return{
...state,
isLogin: false,
loginState: GUEST_STATUS,
userName: null,
uid: null
}
}
case LOGIN_TYPE: {
return {
...state,
loginWrapActiveKey: action.index
};
}
case REGISTER: {
return {
...state,
isLogin: true,
loginState: MEMBER_STATUS,
uid: action.payload.data.data.uid,
userName: action.payload.data.data.username
};
}
case GET_AVATAR: {
return {
...state
}
}
default:
return state;
}
};
// Action Creators
export function checkLoginState() {
return(dispatch)=> {
axios.get('/user/status').then((res) => {
dispatch({
type: GET_LOGIN_STATE,
payload: res
});
}).catch((err) => {
console.log(err);
})
}
}
export function loginActions(data) {
return {
type: LOGIN,
payload: axios.post('/user/login', data)
};
}
export function regActions(data) {
const { email, password, userName } = data;
const param = {
email,
password,
username: userName
};
return {
type: REGISTER,
payload: axios.post('/user/reg', param)
};
}
export function logoutActions() {
return {
type: LOGIN_OUT,
payload: axios.get('./user/logout')
}
}
export function loginTypeAction(index) {
return{
type: LOGIN_TYPE,
index
}
}
export function getAvatar(){
return {
type: GET_AVATAR,
payload: axios.get("/user/avatar")
}
}

View File

@ -1,24 +0,0 @@
import React from 'react'
import { Route, HashRouter } from 'react-router-dom'
import { Header, Home, ProjectGroups, Interface, News, AddInterface, Follows } from './containers/index'
import User from './containers/User/User.js'
export default () => {
return (
<HashRouter>
<div className="router-main">
<Header/>
<Route path="/" component={ Home } exact />
<Route path="/group" component={ ProjectGroups } >
<Route exact={false} path="/group/:groupName" component={ ProjectGroups } />
</Route>
<Route path="/project" component={ Interface } />
<Route path="/user" component={User} />
<Route path="/news" component={ News } />
<Route path="/add-interface" component={ AddInterface } />
<Route path="/follow" component={ Follows } />
</div>
</HashRouter>
)
}

View File

@ -1,17 +0,0 @@
// const jwt = require('jsonwebtoken');
//检查token是否过期
module.exports = async ( ctx, next ) => {
// const authorization = ctx.get('Authorization');
// if (authorization === '') {
// ctx.throw(401, 'no token detected in http header ');
// }
// const token = authorization.split(' ')[1];
// let tokenContent;
// try {
// tokenContent = await jwt.verify(token, 'qunar'); //如果token过期或验证失败将抛出错误
// } catch (err) {
// ctx.throw(401, 'invalid token');
// }
await next();
};

View File

@ -1,6 +0,0 @@
module.exports = async (ctx, next) => {
let path = ctx.path;
console.log(path); // eslint-disable-line
console.log(ctx.hostname); // eslint-disable-line
if (next) await next();
};

View File

@ -1,36 +0,0 @@
"use strict";
var _regenerator = require("babel-runtime/regenerator");
var _regenerator2 = _interopRequireDefault(_regenerator);
var _asyncToGenerator2 = require("babel-runtime/helpers/asyncToGenerator");
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// const jwt = require('jsonwebtoken');
//检查token是否过期
module.exports = function () {
var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(ctx, next) {
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return next();
case 2:
case "end":
return _context.stop();
}
}
}, _callee, undefined);
}));
return function (_x, _x2) {
return _ref.apply(this, arguments);
};
}();

View File

@ -1,44 +0,0 @@
"use strict";
var _regenerator = require("babel-runtime/regenerator");
var _regenerator2 = _interopRequireDefault(_regenerator);
var _asyncToGenerator2 = require("babel-runtime/helpers/asyncToGenerator");
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
module.exports = function () {
var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(ctx, next) {
var path;
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
path = ctx.path;
console.log(path); // eslint-disable-line
console.log(ctx.hostname); // eslint-disable-line
if (!next) {
_context.next = 6;
break;
}
_context.next = 6;
return next();
case 6:
case "end":
return _context.stop();
}
}
}, _callee, undefined);
}));
return function (_x, _x2) {
return _ref.apply(this, arguments);
};
}();