Commit e4e9ed07 by bert

init

parent f174aa72
import * as types from '../constants/actionTypes'
export function addTodo(text) {
return { type: types.ADD_TODO, text }
}
export function completeTodo(id) {
return { type: types.COMPLETE_TODO, id }
}
import superagent from 'superagent';
const methods = [
'get',
'head',
'post',
'put',
'del',
'options',
'patch'
];
class _Api {
constructor(opts) {
this.opts = opts || {};
if (!this.opts.baseURI)
throw new Error('baseURI option is required');
methods.forEach(method =>
this[method] = (path, { params, data } = {}) => new Promise((resolve, reject) => {
const request = superagent[method](this.opts.baseURI + path);
if (params) {
request.query(params);
}
if (this.opts.headers) {
request.set(this.opts.headers);
}
if (data) {
request.send(data);
}
request.end((err, { body } = {}) => err ? reject(body || err) : resolve(body));
})
);
}
}
const Api = _Api;
export default Api;
import Api from './api';
const api = new Api({
baseURI: '/',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
export default api
import React, { Component, PropTypes } from 'react';
import Todos from './Todos/Todos';
import MainLayout from '../layouts/MainLayout/MainLayout';
const App = ({ location }) => {
return (
<MainLayout>
<Todos location={location} />
</MainLayout>
);
};
App.propTypes = {
};
export default App;
import React from 'react'
import { bindActionCreators } from 'redux'
import reqwest from 'reqwest'
import md5 from 'md5'
import { connect } from 'react-redux'
import { Button, Modal, Form, Input, Row, Col, DatePicker, Radio, Select, Cascader } from 'antd';
import * as Util from '../../util';
const FormItem = Form.Item;
const RangePicker = DatePicker.RangePicker;
const RadioButton = Radio.Button;
const RadioGroup = Radio.Group;
const Option = Select.Option;
const appID = window.globalConfig.appid;
const token = window.globalConfig.token;
const ts = new Date().getTime().toString().substring(0,10);
const sign = md5(appID+ts+token+'false');
const agUrl = window.globalConfig.url;
import './index.less'
let ExportExcel = React.createClass({
getInitialState() {
return { visible: false };
},
componentDidMount() {
},
showModal() {
this.setState({
visible: true,
});
reqwest({
url: agUrl + 'case2/type',
method: 'get',
type: 'json',
data: [
{ name: 'sign', value: sign },
{ name: 'ts', value: ts },
{ name: 'appID', value: appID } ]
}).then (function(data) {
console.log('this.state', this.state);
if (this.isMounted()) {
this.setState(Object.assign({}, this.state, {typeList: data.content}));
}
}.bind(this))
},
reset() {
this.props.form.resetFields();
},
handleOk(e) {
let subResult = this.props.form.getFieldsValue();
// subResult.startTime = subResult.endTime? this.dataFormat(subResult.startTime) : subResult.endTime;
// subResult.endTime = subResult.endTime? this.dataFormat(subResult.endTime) : subResult.endTime;
subResult.startTime = subResult.startTime && Util.dateFormat(subResult.startTime, 'yyyy-MM-dd hh:mm:ss')
subResult.endTime = subResult.endTime && Util.dateFormat(subResult.endTime, 'yyyy-MM-dd hh:mm:ss')
console.log('getFormatter', subResult.endTime);
const url = "/download?"
+ 'keyword='+ encodeURI(subResult.keyword)
+ '&taskType=' + subResult.taskType
+ '&status=' + subResult.status
+ '&searchType=' + subResult.searchType
+ '&startTime=' + subResult.startTime
+ '&endTime=' + subResult.endTime
// + '&sortType=' + subResult.sortType
+ '&sourceType=' + subResult.sourceType
+ '&sourceUser=' + encodeURI(subResult.sourceUser)
+ '&isTimeout=' + subResult.isTimeout;
console.log('url', url);
window.open(url)
this.setState({
visible: false,
});
},
dataFormat(strTime) {
var date = new Date(strTime);
// return date.getFullYear()+"-"+(date.getMonth()+1)+"-"+date.getDate()+" "+date.getHours()+":"+date.getMinutes()+":"+date.getSeconds();
return Util.dateFormat(date, 'yyyy-MM-dd hh:mm:ss')
},
handleCancel() {
this.setState({
visible: false,
});
},
timeChange(value, dateString) {
console.log('From: ', value[0], ', to: ', value[1]);
console.log('From: ', dateString[0], ', to: ', dateString[1]);
},
userTypeChange(e) {
console.log(`userTypeChange checked:${e.target.value}`);
},
statusChange(e) {
console.log(`statusChange checked:${e.target.value}`);
},
render() {
const { getFieldProps } = this.props.form;
const taskType = this.state.typeList?this.state.typeList.map( (type) => {
return (<RadioButton value={type.id}>{type.case_type}</RadioButton>)
}) : "";
const selectBefore = (
<Select {...getFieldProps('sourceType',{initialValue: 'createUser'})} defaultValue="createUser" style={{ width: 80 }}>
<Option value="createUser">发布人</Option>
<Option value="executorUser">执行人</Option>
<Option value="focusUser">关注人</Option>
</Select>
);
return (
<div>
<Button type="primary" onClick={this.showModal}>Excel导出</Button>
<Modal title="Excel导出" visible={this.state.visible}
width={800}
onOk={this.handleOk} onCancel={this.handleCancel}
okText="确定导出" cancelText="取消"
>
<div>
<Form horizontal className="ant-advanced-search-form">
<Row>
<Col span={24}>
<FormItem
label="关键字"
labelCol={{ span: 3 }}
wrapperCol={{ span: 8 }}
>
<Input {...getFieldProps('keyword', {initialValue: ''})} placeholder="请输入关键字" size="default" />
</FormItem>
</Col>
<Col span={24}>
<FormItem
label="创建时间区间"
labelCol={{ span: 3 }}
>
<Col span="4">
<Select {...getFieldProps('searchType',{initialValue: 'createTime'})} defaultValue="createTime" style={{ width: 110, marginRight: 10 }}>
<Option value="createTime">创建时间区间</Option>
<Option value="finishTime">完成时间区间</Option>
<Option value="confirmFinishTime">确认完成时间区间</Option>
<Option value="closeTime">关闭时间区间</Option>
</Select>
</Col>
<Col span="6">
<FormItem>
<DatePicker format="yyyy-MM-dd HH:mm:ss" showTime {...getFieldProps('startTime', {initialValue: ''})} placeholder="开始时间" />
</FormItem>
</Col>
<Col span="1">
<p className="ant-form-split">-</p>
</Col>
<Col span="6">
<FormItem>
<DatePicker format="yyyy-MM-dd HH:mm:ss" showTime {...getFieldProps('endTime', {initialValue: ''})} placeholder="结束时间" />
</FormItem>
</Col>
</FormItem>
</Col>
<Col span={24}>
<FormItem
label="人员类型"
labelCol={{ span: 3 }}
wrapperCol={{ span: 8 }}
>
<Input {...getFieldProps('sourceUser',{initialValue: ''})} addonBefore={selectBefore} placeholder="请输入人员姓名" />
</FormItem>
</Col>
<Col span={24}>
<FormItem
label="任务进度"
labelCol={{ span: 3 }}
wrapperCol={{ span: 14 }}
>
<RadioGroup {...getFieldProps('isTimeout',{initialValue: ''})}>
<RadioButton value="">全部</RadioButton>
<RadioButton value="0">已超时</RadioButton>
<RadioButton value="1">未超时</RadioButton>
</RadioGroup>
</FormItem>
</Col>
<Col span={24}>
<FormItem
label="请选择状态"
labelCol={{ span: 3 }}
wrapperCol={{ span: 14 }}
>
<RadioGroup {...getFieldProps('status',{initialValue: ''})}>
<RadioButton value="">全部</RadioButton>
<RadioButton value="1">进行中</RadioButton>
<RadioButton value="2">已完成</RadioButton>
<RadioButton value="3">确认完成</RadioButton>
<RadioButton value="4">已关闭</RadioButton>
</RadioGroup>
</FormItem>
</Col>
<Col span={24}>
<FormItem
label="选择case类型"
labelCol={{ span: 3 }}
wrapperCol={{ span: 14 }}
>
<RadioGroup {...getFieldProps('taskType',{initialValue: ''})} >
<RadioButton value="">全部</RadioButton>
{taskType}
</RadioGroup>
</FormItem>
</Col>
</Row>
<Row>
<Col span={12} offset={12} style={{ textAlign: 'right' }}>
<Button onClick={this.reset}>请除条件</Button>
</Col>
</Row>
</Form>
</div>
</Modal>
</div>
);
}
});
ExportExcel = Form.create()(ExportExcel);
function mapStateToProps(state) {
return {
}
}
function mapDispatchToProps(dispatch) {
return {
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ExportExcel);
.ant-advanced-search-form {
padding: 16px 8px;
background: #f8f8f8;
border: 1px solid #d9d9d9;
border-radius: 6px;
}
/* 由于输入标签长度不确定,所以需要微调使之看上去居中 */
.ant-advanced-search-form > .ant-row {
position: relative;
left: -6px;
}
.ant-advanced-search-form .ant-btn + .ant-btn {
margin-left: 8px;
}
import React from 'react'
import styles from './index.less'
export default class Footer extends React.Component {
constructor () {
super()
}
render () {
return (
<div className={styles["ant-layout-footer"]}>
xxxx 版权所有 © 2015 xxxxxx.com
</div>
)
}
}
.ant-layout-footer {
height: 64px;
line-height: 64px;
text-align: center;
font-size: 12px;
color: #999;
background: #fff;
border-top: 1px solid #e9e9e9;
width: 100%;
}
import React, { PropTypes } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { Row, Col, Icon, Menu, Dropdown } from 'antd'
import styles from './index.less'
// import styles from './index.less';
import { Link } from 'react-router'
// import * as menu from '../../store/modules/menu/menu_action'
import logo from './logo.png'
const SubMenu = Menu.SubMenu;
const MenuItemGroup = Menu.ItemGroup;
const DropdownButton = Dropdown.Button;
const defaultProps = {
topMenu: [],
currentIndex: 0
}
const propTypes = {
topMenu: PropTypes.array,
currentIndex: PropTypes.number
}
class Header extends React.Component {
constructor () {
super()
this.onCollapseChange = this.onCollapseChange.bind(this);
this.menuClickHandle = this.menuClickHandle.bind(this);
}
componentDidMount () {
/**
* 初始化头部菜单,通过服务端获取。
*/
// this.props.menu.getTopMenu()
}
menuClickHandle (item) {
/**
* 加入二级导航时,可以通过判断字符串头标记来定位是住导航还是子导航
*
*/
// if (item.key.indexOf('sub') != -1) {
// console.log('是主导航')
// } else {
// console.log('是副级导航');
// }
/**
* 特定功能:返回旧版
*
* 判断 `key = index.html` 则跳转旧版
* 因为在导航前加入了标记,所以这里判断时也需要加入 `sub` 标记
*
*/
switch (item.key) {
case 'myMain':
// 获取我的发布数据
// 获取边栏菜单数据
break;
case 'submanage':
// 获取case管理数据
// 获取边栏菜单数据
break;
case 'sub' + 'index.html':
window.open("/index.html");
break;
}
/**
* 默认情况更改 `面包屑` 信息
*/
// this.props.menu.updateNavPath(item.keyPath, item.key)
}
onCollapseChange(collapse) {
/**
* 侧栏切换功能
*
* 点击特定按钮更改侧栏状态,实现侧栏切换功能
* 通过判断侧栏状态,显示不同的class
* 该 `class` 在 `View/App` 下: `<div className={collapse ? "ant-layout-aside ant-layout-aside-collapse" : "ant-layout-aside"}>`
* 该功能可以放在任意位置,目前放在顶部实现
*
*/
// this.props.menu.updateCollapse(this.props.collapse)
}
render () {
// const { topMenu, user, collapse, routing } = this.props
// const basename = '/newIndex.html/';
// let selectKey = routing.locationBeforeTransitions && routing.locationBeforeTransitions.pathname.split('/')[1]
// console.log('selectKey', selectKey);
// console.log('routing', routing);
// console.log('THIS.PROPS', this.props);
const topMenu = [
{
key: 'add_task',
name: '发起任务',
icon: 'edit'
},
{
key: 'my_case',
name: '我的发布',
icon: 'book'
},
{
key: 'my_task',
name: '我的任务',
icon: 'user'
},
{
key: 'my_focus',
name: '我的关注',
icon: 'eye-o'
},
{
key: 'case_manage',
name: 'case管理',
icon: 'setting'
}, {
key: 'case_group',
name: '分组管理',
icon: 'tags-o'
}, {
key: 'case_rank',
name: '统计排名',
icon: 'line-chart'
}, {
key: 'index.html',
name: '返回旧版',
icon: 'retweet'
}
];
const menu = topMenu.map((item) => {
/**
* 遍历 `topMenu` 显示顶部信息
*
* `sub` 标记为是主导航
* `key` 用于页面跳转与记录唯一
* `name` 标签显示内容
*
*/
return (
<Menu.Item key={'sub'+ item.key}>
<Link to={'' + item.key}>
<Icon type={item.icon} />
<span>{item.name}</span>
</Link>
</Menu.Item>
)
});
/**
* `selectKey` 用于默认显示
*
* 优化:
* 根据路由规则显示导航状态
* 需要在 `state` 中加入 `router` 这样就方便了对全局的管理了
* 学习下 `redux-simple-router` 来实现该功能
*
*/
// return (
// <div className='ant-layout-header'>
// <div className="ant-layout-wrapper">
// <div className="collapse-icon" onClick={this.onCollapseChange}><Icon type="bars" /></div>
// <Menu
// theme="light"
// mode="horizontal"
// onClick={this.menuClickHandle}
// defaultSelectedKeys={'sub' + selectKey} style={{lineHeight: '64px'}}>
// { menu }
// </Menu>
// </div>
// </div>
// )
return (
<div className={styles['ant-layout-header']}>
<div className={styles["ant-layout-wrapper"]}>
<Menu
theme="light"
mode="horizontal"
onClick={this.menuClickHandle}
style={{lineHeight: '64px'}}>
{ menu }
</Menu>
</div>
</div>
)
}
}
Header.propTypes = propTypes;
Header.defaultProps = defaultProps;
const mapStateToProps = (state) => {
// console.log('state.router', state.router);
// console.log('state.routing', state.routing);
return {
// topMenu : state.menu.topMenu,
// currentIndex : state.menu.currentIndex,
// collapse : state.menu.collapse,
// selectKey : state.menu.selectKey,
// router : state.router,
// routing : state.routing,
};
};
function mapDispatchToProps(dispatch) {
return {
// menu: bindActionCreators(menu, dispatch),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Header);
// handleClick(e) {
// /**
// * 旧版头部功能
// *
// * 目前已经停用,留着以后用到时方便
// *
// */
// console.log('click ', e);
// this.setState({
// current: e.key,
// });
// }
// render () {
// const {user} = this.props
// return (
// <div className='ant-layout-header'>
// <div className="ant-layout-wrapper">
// <Menu className="header-menu" onClick={this.handleClick} style={{lineHeight: '64px'}}
// mode="horizontal">
// <SubMenu title={<span><Icon type="user" />{user.user}</span>}>
// <Menu.Item key="setting:1">选项1</Menu.Item>
// <Menu.Item key="setting:2">选项2</Menu.Item>
// <Menu.Divider />
// <Menu.Item key="setting:3">注销</Menu.Item>
// </SubMenu>
// <Menu.Item key="mail">
// <Icon type="question" />帮助
// </Menu.Item>
// </Menu>
// </div>
// </div>
// )
// }
\ No newline at end of file
.ant-layout-header {
background: #fff;
.header-menu {
> li {
float: right;
}
}
}
// .ant-layout-wrapper {
// padding: 0 0 0 50px;
// }
// .ant-layout-wrapper .ant-layout-header {
// background: #404040;
// height: 64px;
// }
// .ant-layout-wrapper .ant-layout-logo {
// position: relative;
// width: 200px;
// height: 32px;
// border-radius: 6px;
// margin: 16px 28px 16px 0;
// padding: 6px 0px 0 55px;
// float: left;
// }
// .ant-layout-wrapper .ant-layout-logo img {
// position: absolute;
// top: 0;
// left: 0;
// height: 100%;
// }
.top-nav-img {
width: 20px;
margin-right: 3px;
position: relative;
top: 5px;
left: 0;
}
// 顶部导航因为Link表单导致激活颜色问题,这里强制设置激活颜色
.ant-menu-item-selected > a, .ant-menu-item-selected > a:hover {
color: #2db7f5 !important;
}
// 菜单
.ant-layout-header .ant-layout-wrapper .collapse-icon {
line-height: 64px;
padding-top: 20px;
float: left;
margin: 0 20px 0 20px;
font-size: 20px;
cursor: pointer;
}
\ No newline at end of file
import React, {PropTypes} from 'react'
import { bindActionCreators } from 'redux'
import { Breadcrumb } from 'antd'
import { connect } from 'react-redux'
import './index.less'
const defaultProps = {
navpath: []
}
const propTypes = {
navpath: PropTypes.array
}
class NavPath extends React.Component {
constructor (props) {
super(props)
}
render () {
const { navpath } = this.props
const bread = navpath.map((item)=>{
return (
<Breadcrumb.Item key={'bc-'+item.key}>{item.name}</Breadcrumb.Item>
)
})
const breadInit = <Breadcrumb.Item key={'bc-myMain'}>我的发布</Breadcrumb.Item>
return (
<div className="ant-layout-breadcrumb">
<Breadcrumb>
<Breadcrumb.Item key='bc-0'>首页</Breadcrumb.Item>
{bread.length == 0? breadInit: bread}
</Breadcrumb>
</div>
)
}
}
NavPath.propTypes = propTypes;
NavPath.defaultProps = defaultProps;
function mapStateToProps(state) {
return {
// navpath: state.menu.navpath
}
}
export default connect(mapStateToProps)(NavPath)
.ant-layout-breadcrumb {
margin: 7px 0 -17px 24px;
}
import React from 'react';
import { Button } from 'antd';
import styles from './NotFound.less';
const NotFound = () => {
return (
<div className={styles.normal}>
<div className={styles.container}>
<h1 className={styles.title}>404</h1>
<p className={styles.desc}>未找到该页面</p>
<a href="/"><Button type="primary" style={{ marginTop: 5 }}>返回首页</Button></a>
</div>
</div>
);
};
export default NotFound;
.normal {
width: 100%;
height: 100%;
min-height: 100vh;
padding-top: 120px;
}
.container {
padding: 0;
margin: 0 auto;
width: 620px;
height: 300px;
text-align: center;
}
.title {
font-size: 80px;
color: #666;
margin-top: 20px;
margin-bottom: 10px;
}
.desc {
font-size: 14px;
}
import React from 'react'
import './index.less'
export default class PanelBox extends React.Component {
constructor () {
super()
}
render () {
return (
<div className="panel-box ant-collapse">
<div className="ant-collapse-item">
<div className="ant-collapse-header">
<span>{this.props.title}</span>
</div>
<div className="ant-collapse-content ant-collapse-content-active">
<div className="ant-collapse-content-box">
{this.props.children}
</div>
</div>
</div>
</div>
)
}
}
.panel-box {
margin-bottom: 20px;
> .ant-collapse-item {
> .ant-collapse-header {
padding-left: 10px;
}
}
}
import React, { PropTypes } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { Link } from 'react-router';
import { Menu, Icon, Badge, notification } from 'antd';
// import { getCaseMenu, updateNavPath, updateCollapse, updateStatus } from '../../store/modules/menu/menu_action';
// import { getCaseList } from '../../actions/case';
// import { getAllCaseManage } from '../../actions/case_manage';
// import { logout } from '../../actions/user';
// import { getCaseList } from '../../store/modules/myCase/my_case_action';
// import { getMyTaskList } from '../../store/modules/myTask/my_task_action';
// import { getMyFocusList } from '../../store/modules/myFocus/my_focus_action';
// import { getCaseManageList } from '../../store/modules/caseManage/case_manage_action';
// import { getCaseGroupList } from '../../store/modules/caseGroup/case_group_action';
// import { logout } from '../../store/modules/user/user_action';
// import OPERATOR_INFO from '../../constants/OperatorInfo';
// import * as Util from '../../util';
import logo from './logo.png'
import touxiang from './touxiang.png'
const SubMenu = Menu.SubMenu
// import styles from './index.less'
import styles from '../../views/App/index.less'
const defaultProps = {
leftMenu: [],
currentIndex: 0
}
const propTypes = {
leftMenu: PropTypes.array,
currentIndex: PropTypes.number
}
const contextTypes = {
router: PropTypes.object.isRequired,
store: PropTypes.object.isRequired
};
class Sidebar extends React.Component {
constructor (props) {
super(props)
this.menuClickHandle = this.menuClickHandle.bind(this);
this.logout = this.logout.bind(this);
}
componentDidMount () {
}
menuClickHandle (item) {
this.props.updateNavPath(item.keyPath, item.key)
console.log('menuClickHandle click ', item);
this.setState({
current: item.key,
});
}
logout() {
this.props.logout();
}
onClick(e) {
/**
* 点击侧栏菜单,根据不同的 `Tab` 状态查询不同的信息
*/
// let getList = function(){},reqParams = {};
// if (this.props.leftMenuType == 'my_case') {
// getList = this.props.getCaseList;
// reqParams = this.props.myCaseReqParams;
// reqParams.pageId = 1;
// }
// if (this.props.leftMenuType == 'my_focus') {
// getList = this.props.getMyFocusList;
// reqParams = this.props.myFocusReqParams;
// reqParams.pageId = 1;
// }
// if (this.props.leftMenuType == 'my_task') {
// getList = this.props.getMyTaskList;
// reqParams = this.props.myTaskReqParams;
// reqParams.pageId = 1;
// }
// if (this.props.leftMenuType == 'case_manage') {
// getList = this.props.getCaseManageList;
// reqParams = this.props.caseManageReqParams;
// reqParams.pageId = 1;
// }
// if (this.props.leftMenuType == 'case_group') {
// getList = this.props.getCaseGroupList;
// reqParams = this.props.caseGroupReqParams;
// reqParams.pageId = 1;
// }
// switch (e.key) {
// case 'logout':
// this.props.logout();
// notification.success({
// message: 'Logout Success',
// description: 'goodbye',
// duration: 2,
// });
// this.context.router.replace('/login');
// break;
// case 'ongoing':
// reqParams.status = 1;
// break;
// case 'completed':
// reqParams.status = 2;
// break;
// case 'confirm_completed':
// reqParams.status = 3;
// break;
// case 'closed':
// reqParams.status = 4;
// break;
// default :
// this.props.other(e.key)
// break;
// }
// getList(reqParams)
// this.props.updateStatus(reqParams.status);
}
render () {
// const { leftMenu } = this.props
// let defaultSelectedKeys;
// switch (this.props.status) {
// case 1 :
// defaultSelectedKeys = ['ongoing']
// break;
// case 2 :
// defaultSelectedKeys = ['completed']
// break;
// case 3 :
// defaultSelectedKeys = ['confirm_completed']
// break;
// case 4 :
// defaultSelectedKeys = ['closed']
// break;
// }
const leftMenu = [
{
key: 'ongoing',
name: '待处理数',
icon: 'info-circle-o',
dot: false
},
{
key: 'completed',
name: '已完成数',
icon: 'check-circle-o',
dot: false
},
{
key: 'confirm_completed',
name: '确认完成',
icon: 'check-circle',
dot: false
},
{
key: 'closed',
name: '已关闭数',
icon: 'poweroff',
dot: false
},
{
key: 'gratuity',
name: '获得打赏',
icon: 'pay-circle-o',
dot: false
},
{
key: 'thumb_up',
name: '总点赞数',
icon: 'like',
dot: false
},
{
key: 'dislike',
name: '总差评数',
icon: 'dislike',
dot: false
},
// {
// key: 'logout',
// name: '退出登录',
// icon: 'logout',
// dot: false
// }
];
let openKey = []
const menu = leftMenu.map((item) => {
openKey.push('sub'+item.key)
return (
<Menu.Item style={{ zIndex: 10}} key={item.key}>
<Badge dot={item.dot}>
<Icon type={item.icon} />
</Badge>
<span className={styles["nav-text"]}>{item.name}</span>
<span className={styles["nav-badge"]} style={{float:'right'}}>{ item.num }</span>
</Menu.Item>
)
});
// <div className="nav-portrait-title">编辑显示昵称</div>
// return (
// <aside className="ant-layout-sider">
// <div className="ant-layout-logo"><img src={logo} /><span className="nav-text">催费跟踪后台</span></div>
// <div className="ant-layout-portrait">
// <div className="nav-portrait"><img src={OPERATOR_INFO.avatarUrl + OPERATOR_INFO.operatorId} /></div>
// <div className="nav-portrait-name">{OPERATOR_INFO.operator}</div>
// <div className="nav-portrait-title" onClick={this.logout}>注销</div>
// </div>
// <Menu mode="inline" theme="dark" onClick={this.onClick.bind(this)} selectedKeys={defaultSelectedKeys}>
// { menu }
// </Menu>
// </aside>
// )
return (
<aside className={styles["ant-layout-sider"]}>
<div className={styles["ant-layout-logo"]}><img src={logo} /><span className={styles["nav-text"]}>催费跟踪后台</span></div>
<div className={styles["ant-layout-portrait"]}>
<div className={styles["nav-portrait"]}><img src={touxiang} /></div>
<div className={styles["nav-portrait-name"]}>aaa</div>
<div className={styles["nav-portrait-title"]} onClick={this.logout}>注销</div>
</div>
<Menu mode="inline" theme="dark" onClick={this.onClick.bind(this)}>
{ menu }
</Menu>
</aside>
)
}
}
Sidebar.propTypes = propTypes;
Sidebar.defaultProps = defaultProps;
Sidebar.contextTypes = contextTypes;
function mapStateToProps(state) {
// console.log('state.menu.leftMenu', state.menu.leftMenu);
return {
// leftMenuType : state.menu.leftMenuType,
// leftMenu : state.menu.leftMenu,
// currentIndex : state.menu.currentIndex,
// status : state.menu.status,
// myCaseReqParams : Util.myCaseParamsFromat(state),
// myCasePager : state.myCase.pager,
// myTaskReqParams : Util.myTaskParamsFromat(state),
// myTaskPager : state.myTask.pager,
// myFocusReqParams : Util.myFocusParamsFromat(state),
// myFocusPager : state.myFocus.pager,
// caseManageReqParams : Util.caseManageParamsFromat(state),
// caseManagePager : state.caseManage.pager,
// caseGroupReqParams : Util.caseGroupParamsFromat(state),
// caseGroupPager : state.caseGroup.pager
}
}
function mapDispatchToProps(dispatch) {
return {
// getCaseMenu : bindActionCreators(getCaseMenu, dispatch),
// updateNavPath : bindActionCreators(updateNavPath, dispatch),
// logout : bindActionCreators(logout, dispatch),
// updateStatus : bindActionCreators(updateStatus, dispatch),
// getCaseList : bindActionCreators(getCaseList, dispatch),
// getCaseManageList : bindActionCreators(getCaseManageList, dispatch),
// getMyTaskList : bindActionCreators(getMyTaskList, dispatch),
// getMyFocusList : bindActionCreators(getMyFocusList, dispatch),
// getCaseGroupList : bindActionCreators(getCaseGroupList, dispatch)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Sidebar)
// .ant-layout-aside .ant-layout-logo {
// width: 150px;
// height: 32px;
// background: #333;
// border-radius: 6px;
// margin: 16px 24px 16px 28px;
// }
// .ant-layout-aside .ant-layout-sider {
// width: 224px;
// background: #404040;
// position: absolute;
// overflow: auto;
// padding-bottom: 24px;
// height: 100%;
// }
// .ant-layout-aside .ant-layout-sider > .ant-menu {
// margin-bottom: 20px;
// }
/*********************/
.nav-text {
vertical-align: baseline;
display: inline-block;
white-space: nowrap;
}
.ant-layout-logo {
position: relative;
width: 150px;
height: 32px;
// background: #333;
color: #999;
border-radius: 6px;
margin: 16px 24px 16px 28px;
padding: 7px 0px 0 60px;
transition: all 0.3s ease;
}
.ant-layout-logo > img {
position: absolute;
top: 0;
left: -11px;
height: 100%;
}
.ant-layout-sider {
width: 224px;
background: #404040;
position: absolute;
overflow: visible;
padding-bottom: 24px;
height: 100%;
transition: all 0.3s ease;
}
.nav-portrait img {
width: 120px;
height: 120px;
border-radius: 50%;
transition: all 1s ease;
}
// 头像
.nav-portrait {
text-align: center;
margin-bottom: 10px;
margin-top: 20px;
transition: all 3s ease;
}
.nav-portrait img {
width: 120px;
height: 120px;
border-radius: 50%;
transition: all 1s ease;
}
.nav-portrait-title {
color: #ccc;
text-align: center;
cursor: pointer;
transition: all 3s ease;
}
.nav-portrait-title:hover {
text-decoration: underline;
}
.nav-portrait-name {
color: #2db7f5;
text-align: center;
transition: all 3s ease;
}
.ant-layout-aside-collapse .ant-layout-sider > .ant-layout-portrait > .nav-portrait {
height: 32px;
transition: all 3s ease;
}
.ant-layout-aside-collapse .ant-layout-sider > .ant-layout-portrait > .nav-portrait img {
width: 32px;
height: 32px;
transition: all 0s ease;
}
.ant-layout-aside-collapse .ant-layout-sider > .ant-layout-portrait > .nav-portrait-title,
.ant-layout-aside-collapse .ant-layout-sider > .ant-layout-portrait > .nav-portrait-name {
display: none;
transition: all 3s ease;
}
import React, {PropTypes} from 'react';
import { Icon } from 'antd';
import './index.less'
const defaultProps = {
}
const propTypes = {
}
class Star extends React.Component {
constructor() {
super()
}
handleClick(event, onClick) {
event.preventDefault();
event.stopPropagation();
onClick();
}
render() {
const { onClick, style, star } = this.props;
return (
<span
style={style}
className="pull-right star-color"
onClick = {(event) => {this.handleClick(event, onClick)}}>
<Icon type={star ? "star" : "star-o"} />
</span>
)
}
}
Star.propTypes = propTypes;
Star.defaultProps = defaultProps;
export default Star;
\ No newline at end of file
.tree-select .star-color {
display: none;
}
.star-color {
color: #2db7f5;
}
\ No newline at end of file
import React, { Component, PropTypes } from 'react';
import classnames from 'classnames';
import styles from './Todo.less';
const Todo = ({ data, onToggleComplete }) => {
const { text, isComplete } = data;
const todoCls = classnames({
[styles.normal]: true,
[styles.isComplete]: isComplete,
});
return (
<div className={todoCls}>
<div className={styles.checkbox}>
<input
type="checkbox"
value=""
checked={isComplete}
onChange={onToggleComplete.bind(this)}
/>
</div>
<div className={styles.text}>
{text}
</div>
</div>
);
};
Todo.propTypes = {
data: PropTypes.object.isRequired,
onToggleComplete: PropTypes.func.isRequired,
};
export default Todo;
.normal {
display: flex;
}
.checkbox {
margin-right: 6px;
}
.isComplete {
color: #ccc;
text-decoration: line-through;
}
import React, { Component, PropTypes } from 'react';
import { Spin } from 'antd';
import Todo from './Todo';
import styles from './Todos.less';
import { getAll } from '../../services/todos';
class TodosContainer extends Component {
constructor(props) {
super(props);
this.state = {
list: [],
loading: false,
};
}
loadTodos() {
this.setState({ loading: true });
getAll().then(({ jsonResult }) => {
this.setState({
list: jsonResult.data,
loading: false,
});
})
}
handleToggleComplete = (id) => {
const newList = this.state.list.map(todo => {
if (id === todo.id) {
return { ...todo, isComplete: !todo.isComplete };
} else {
return todo;
}
});
this.setState({
list: newList,
});
}
componentDidMount() {
this.loadTodos();
}
render() {
const { location } = this.props;
const { list, loading } = this.state;
const todos = filter({ list, loading }, location.pathname);
return (
<Todos todos={todos} onToggleComplete={this.handleToggleComplete} />
);
}
}
const Todos = ({ todos, onToggleComplete }) => {
const renderList = () => {
const { list, loading } = todos;
if (loading) {
return <Spin />;
}
return (
<div className={styles.list}>
{list.map(item => <Todo
key={item.id}
data={item}
onToggleComplete={onToggleComplete.bind(this, item.id)}
/>
)}
</div>
);
};
return (
<div className={styles.normal}>
{renderList()}
</div>
);
};
Todos.propTypes = {};
function filter(todos, pathname) {
const newList = todos.list.filter(todo => {
if (pathname === '/actived') {
return !todo.isComplete;
}
if (pathname === '/completed') {
return todo.isComplete;
}
return true;
});
return { ...todos, list: newList };
}
export default TodosContainer;
import React, { Component, PropTypes } from 'react';
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import Header from '../components/Header';
import Content from '../components/Content';
import * as Actions from '../actions';
class App extends Component{
render(){
const {todos, actions} = this.props;
return (
<div>
<Header actions={actions} />
<Content todos={todos} actions={actions} />
</div>
);
}
}
function mapStateToProps(state){
return {
todos : state.todos
}
}
function mapDispatchToProps(dispatch){
return{
actions : bindActionCreators(Actions, dispatch)
}
}
module.exports = connect(
mapStateToProps,
mapDispatchToProps
)(App);
export const ADD_TODO = 'ADD_TODO'
export const DELETE_TODO = 'DELETE_TODO'
export const EDIT_TODO = 'EDIT_TODO'
export const COMPLETE_TODO = 'COMPLETE_TODO'
export const COMPLETE_ALL = 'COMPLETE_ALL'
export const CLEAR_COMPLETED = 'CLEAR_COMPLETED'
/**
* 1、处理 `Ag` 参数
* 2、appId、token、ts 加密传输
* 3、提供AgUrl
*/
import md5 from 'md5';
const appID = window.globalConfig.appid;
const token = window.globalConfig.token;
const ts = new Date().getTime().toString().substring(0,10);
const agUrl = window.globalConfig.url;
const agConf = {
appID : appID,
token : token,
ts : ts,
sign : md5(appID + ts + token + 'false'),
agUrl : agUrl
}
export default agConf
\ No newline at end of file
export const KEY_ENTER = 13;
export const KEY_ESCAPE = 27;
/**
*
*/
export default {
operator : window.globalConfig.operator,
operatorId : window.globalConfig.operatorId,
rootTree : window.globalConfig.rootTree,
avatarUrl : window.globalConfig.avatarUrl
}
\ No newline at end of file
export const PAGER = {
pageId : 1,
recPerPage : 10,
total : 0
}
\ No newline at end of file
import types from '../store/types'
export default {
'408': types.NEED_LOGIN // 需要登录
};
export const IMAGE_HOST_TEST = 'http://res.ikaibei.com/uploadtest/'
export const IMAGE_HOST_PROD = 'http://res.ikaibei.com/upload/'
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" type="text/css" href="./index.css"/>
<!--[if lt IE 10]>
<script src="https://as.alipayobjects.com/g/component/??console-polyfill/0.2.2/index.js,es5-shim/4.5.7/es5-shim.min.js,es5-shim/4.5.7/es5-sham.min.js,html5shiv/3.7.2/html5shiv.min.js,media-match/2.0.2/media.match.min.js"></script>
<![endif]-->
</head>
<body>
<div id="root"></div>
</body>
<script src="./common.js"></script>
<script src="./index.js"></script>
</html>
import './index.html';
import './index.less';
import ReactDOM from 'react-dom';
import React from 'react';
import { browserHistory } from 'react-router';
import App from '../components/App';
import Routes from '../routes/index';
const Provider = require('react-redux').Provider;
const configureStore = require('../store/configureStore');
const store = configureStore()
ReactDOM.render(
<Provider store={store}>
<Routes history={browserHistory} />
</Provider>,
document.getElementById('root')
);
:global {
html, body, #root {
height: 100%;
}
body {
background: #fafafa;
}
}
import React, { Component, PropTypes } from 'react';
import { Router, Route, IndexRoute, Link } from 'react-router';
import styles from './MainLayout.less';
const MainLayout = ({ children }) => {
return (
<div className={styles.normal}>
<div className={styles.head}>
<h1>Todo App</h1>
</div>
<div className={styles.content}>
<div className={styles.side}>
<h2>Filters:</h2>
<Link to="/">All</Link><br />
<Link to="/actived">Actived</Link><br />
<Link to="/completed">Completed</Link><br />
<Link to="/404">404</Link><br />
</div>
<div className={styles.main}>
{children}
</div>
</div>
<div className={styles.foot}>
Built with react, react-router, ant-tool, css-modules, antd...
</div>
</div>
);
};
MainLayout.propTypes = {
children: PropTypes.element.isRequired,
};
export default MainLayout;
.normal {
display: flex;
flex-direction: column;
height: 100%;
}
.head {
margin-bottom: 20px;
background: cadetblue;
height: 80px;
padding: 8px;
color: #fff;
}
.content {
flex: 1;
display: flex;
}
.side {
padding: 8px;
width: 20%;
min-width: 200px;
background: #fafafa;
margin-right: 20px;
}
.main {
padding: 8px;
flex: 1 0 auto;
}
.foot {
margin-top: 20px;
background: greenyellow;
padding: 8px;
}
import {combineReducers} from 'redux';
import todos from './todos';
const rootReducer = combineReducers({
todos
});
export default rootReducer;
import * as Types from '../constants/actionTypes';
import * as Actions from '../actions';
import objectAssign from 'object-assign';
const initialState = [{
text : 'Hello Ivan!',
completed : false,
id : 1
}]
export default function todos(state = initialState, action){
switch(action.type){
case Types.ADD_TODO:
return [
...state,
{
id : state.reduce((maxId, todo) => Math.max(todo.id, maxId), -1) + 1,
completed : false,
text : action.text
}
];
case Types.COMPLETE_TODO:
return state.map(todo =>
todo.id === action.id ? objectAssign({}, todo, {completed : !todo.completed}) : todo
);
default:
return state;
}
}
\ No newline at end of file
import React, { PropTypes } from 'react';
import { Router, Route, IndexRoute, Link } from 'react-router';
import App from '../components/App';
import Appp from '../views/App';
import NotFound from '../components/NotFound';
const Routes = ({ history }) =>
<Router history={history}>
<Route path="/" component={App} />
<Route path="/actived" component={App} />
<Route path="/completed" component={App} />
<Route path="/test" component={Appp}/>
<Route path="*" component={NotFound}/>
</Router>;
Routes.propTypes = {
history: PropTypes.any,
};
export default Routes;
import xFetch from './xFetch';
export async function getAll() {
return xFetch('/api/todos');
}
import fetch from 'isomorphic-fetch';
import cookie from 'js-cookie';
const errorMessages = (res) => `${res.status} ${res.statusText}`;
function check401(res) {
if (res.status === 401) {
location.href = '/401';
}
return res;
}
function check404(res) {
if (res.status === 404) {
return Promise.reject(errorMessages(res));
}
return res;
}
function jsonParse(res) {
return res.json().then(jsonResult => ({ ...res, jsonResult }));
}
function errorMessageParse(res) {
const { success, message } = res.jsonResult;
if (!success) {
return Promise.reject(message);
}
return res;
}
function xFetch(url, options) {
const opts = { ...options };
opts.headers = {
...opts.headers,
authorization: cookie.get('authorization') || '',
};
return fetch(url, opts)
.then(check401)
.then(check404)
.then(jsonParse)
.then(errorMessageParse);
}
export default xFetch;
import { createStore, applyMiddleware } from 'redux'
import thunkMiddleware from 'redux-thunk'
import createLogger from 'redux-logger'
import rootReducer from '../reducers'
export default function configureStore(initialState) {
const store = createStore(
rootReducer,
initialState,
applyMiddleware(thunkMiddleware, createLogger())
// applyMiddleware(thunkMiddleware)
)
if (module.hot) {
// Enable Webpack hot module replacement for reducers
module.hot.accept('../reducers', () => {
const nextReducer = require('../reducers').default
store.replaceReducer(nextReducer)
})
}
return store
}
/**
* 统一管理 `Action` 将 `Action` 中的方法打包提供给 `View` 使用
*
* @connect(
* state => ({...state}),
* dispatch => bindActionCreators(Action, dispatch)
* )
*
* 将逻辑代码统一放在 `Action` 层,这样有利于逻辑重用,且在修改逻辑代码时,不需要改动 `View` 层
*/
import * as addCaseAction from './modules/addCase/add_case_action' // 添加case
import * as caseManageAction from './modules/caseManage/case_manage_action' // case管理
import * as caseRankAction from './modules/caseRank/case_rank_action' // case排名
import * as leftMenuAction from './modules/leftMenu/left_menu_action' // 左侧菜单
import * as myCaseAction from './modules/myCase/my_case_action' // 我的发布
import * as myFocusAction from './modules/myFocus/my_focus_action' // 我的关注
import * as myTaskAction from './modules/myTask/my_task_action' // 我的任务
import * as topMenuAction from './modules/topMenu/top_menu_action' // 顶部菜单
import * as userAction from './modules/user/user_action' // 用户
export default {
...addCaseAction,
...caseManageAction,
...caseRankAction,
...leftMenuAction,
...myCaseAction,
...myFocusAction,
...myTaskAction,
...topMenuAction,
...userAction,
}
import {createStore, applyMiddleware, combineReducers} from 'redux';
import thunkMiddleware from 'redux-thunk';
import promiseMiddleware from './middlewares/promiseMiddleware'
import createLogger from 'redux-logger'
import { browserHistory } from 'react-router'
import { routerMiddleware, push } from 'react-router-redux'
const loggerMiddleware = createLogger({
level: 'info',
collapsed: true
})
//使用redux的combineReducers方法将所有reducer打包起来
import reducer from './reducers'
import initState from './initState'
/**
* 一、createStore(reducer, [initialState])
*
* 参数:
* 1、 reducer (Function): 接收两个参数,分别是当前的 state 树和要处理的 action,返回新的 state 树。
* 2、 [initialState] (any): 初始时的 state。
* 在同构应用中,你可以决定是否把服务端传来的 state 水合(hydrate)后传给它,或者从之前保存的用户会话中恢复一个传给它。
* 如果你使用 combineReducers 创建 reducer,它必须是一个普通对象,与传入的 keys 保持同样的结构。否则,你可以自由传入任何 reducer 可理解的内容。
*
* 返回值:
* (Store): 保存了应用所有 state 的对象。改变 state 的惟一方法是 dispatch action。你也可以 subscribe 监听 state 的变化,然后更新 UI。
*
*
*
* applyMiddleware(...middlewares)
*
* desc:
* 使用包含自定义功能的 middleware 来扩展 Redux
* Middleware 并不需要和 createStore 绑在一起使用,也不是 Redux 架构的基础组成部分,但它带来的益处让我们认为有必要在 Redux 核心中包含对它的支持。因此,虽然不同的 middleware 可能在易用性和用法上有所不同
*
* 参数:
* ...middlewares (arguments): 遵循 Redux middleware API 的函数。
* 每个 middleware 接受 Store 的 dispatch 和 getState 函数作为命名参数,并返回一个函数。
* 该函数会被传入 被称为 next 的下一个 middleware 的 dispatch 方法,并返回一个接收 action 的新函数,这个函数可以直接调用 next(action),或者在其他需要的时刻调用,甚至根本不去调用它。
* 调用链中最后一个 middleware 会接受真实的 store 的 dispatch 方法作为 next 参数,并借此结束调用链。
* 所以,middleware 的函数签名是 ({ getState, dispatch }) => next => action。
*
* 返回值:
* (Function) 一个应用了 middleware 后的 store enhancer。
* 这个 store enhancer 就是一个函数,并且需要应用到 createStore。它会返回一个应用了 middleware 的新的 createStore。
*/
const createStoreWithMiddleware = applyMiddleware(
// `thunk` 中间件由 `Redux` 提供。作用是使action创建函数可以返回一个function代替一个action对象
thunkMiddleware,
// `applyMiddleware` 来自 `Redux` 可以包装 `Store` 的 `dispatch`, 将 `promise`
promiseMiddleware({ promiseTypeSuffixes: ['PENDING', 'SUCCESS', 'ERROR'] }),
// 在控制台里能看到 redux-logger 中间件输出的 action 日志,它们清晰地反映了业务逻辑是怎样的 。如果有其他人在编辑 todolist,基于 websocket 服务端推送技术的支持,你也可以直接看到别人的操作过程。
// loggerMiddleware,
routerMiddleware(browserHistory)
)(createStore);
const store = createStoreWithMiddleware(reducer, initState)
export default store
// // 默认初始化store
// export default function configureStore(initialState) {
// return createStoreWithMiddleware(reducer, initialState);
// }
/**
* States
*
*/
import * as addCaseState from './modules/addCase/add_case_state' // 添加case
import * as caseManageState from './modules/caseManage/case_manage_state' // case管理
import * as caseRankState from './modules/caseRank/case_rank_state' // case排名
import * as myCaseState from './modules/myCase/my_case_state' // 我的发布
import * as myFocusState from './modules/myFocus/my_focus_state' // 我的关注
import * as myTaskState from './modules/myTask/my_task_state' // 我的任务
import * as MenuState from './modules/menu/menu_state' // 顶部菜单
import * as userState from './modules/user/user_state' // 用户
/**
* 初始化states
*
* @return {[type]} [description]
*/
const initialState = {
// addCase : new addCaseState,
// caseManage : new caseManageState,
// myCase : new myCaseState,
// myFocus : new myFocusState,
// myTask : new myTaskState,
// menu : new MenuState,
// user : new userState,
}
export default initialState
import { isPromise } from '../../util'
const defaultTypes = ['PENDING', 'FULFILLED', 'REJECTED']
export default function promiseMiddleware (config = {}) {
const promiseTypeSuffixes = config.promiseTypeSuffixes || defaultTypes
return (_ref) => {
const dispatch = _ref.dispatch
return next => action => {
if (!isPromise(action.payload)) {
return next(action)
}
const { type, payload, meta, params = {} } = action
const { promise, data } = payload
const [ PENDING, FULFILLED, REJECTED ] = (meta || {}).promiseTypeSuffixes || promiseTypeSuffixes
/**
* Dispatch the first async handler. This tells the
* reducer that an async action has been dispatched.
*/
next({
type: `${type}_${PENDING}`,
...!!data ? { payload: data, params } : {},
...!!meta ? { meta } : {}
})
const isAction = resolved => resolved && (resolved.meta || resolved.payload)
const isThunk = resolved => typeof resolved === 'function'
const getResolveAction = isError => ({
type: `${type}_${isError ? REJECTED : FULFILLED}`,
...!!meta ? { meta } : {},
...!!isError ? { error: true } : {}
})
/**
* Re-dispatch one of:
* 1. a thunk, bound to a resolved/rejected object containing ?meta and type
* 2. the resolved/rejected object, if it looks like an action, merged into action
* 3. a resolve/rejected action with the resolve/rejected object as a payload
*/
action.payload.promise = promise.then(
(resolved = {}) => {
const resolveAction = getResolveAction()
return dispatch(isThunk(resolved) ? resolved.bind(null, resolveAction) : {
...resolveAction,
...isAction(resolved) ? resolved : {
...!!resolved && { payload: resolved, params }
}
})
},
(rejected = {}) => {
const resolveAction = getResolveAction(true)
return dispatch(isThunk(rejected) ? rejected.bind(null, resolveAction) : {
...resolveAction,
...isAction(rejected) ? rejected : {
...!!rejected && { payload: rejected, params }
}
})
}
)
return action
}
}
}
import { isPromise } from '../util';
const defaultTypes = ['PENDING', 'FULFILLED', 'REJECTED'];
export default function promiseMiddleware(config = {}) {
const promiseTypeSuffixes = config.promiseTypeSuffixes || defaultTypes;
return (_ref) => {
const dispatch = _ref.dispatch;
return next => action => {
if (!isPromise(action.payload)) {
return next(action);
}
const { type, payload, meta } = action;
const { promise, data } = payload;
const [ PENDING, FULFILLED, REJECTED ] = (meta || {}).promiseTypeSuffixes || promiseTypeSuffixes;
/**
* Dispatch the first async handler. This tells the
* reducer that an async action has been dispatched.
*/
next({
type: `${type}_${PENDING}`,
...!!data ? { payload: data } : {},
...!!meta ? { meta } : {}
});
const isAction = resolved => resolved && (resolved.meta || resolved.payload);
const isThunk = resolved => typeof resolved === 'function';
const getResolveAction = isError => ({
type: `${type}_${isError ? REJECTED : FULFILLED}`,
...!!meta ? { meta } : {},
...!!isError ? { error: true } : {}
});
/**
* Re-dispatch one of:
* 1. a thunk, bound to a resolved/rejected object containing ?meta and type
* 2. the resolved/rejected object, if it looks like an action, merged into action
* 3. a resolve/rejected action with the resolve/rejected object as a payload
*/
action.payload.promise = promise.then(
(resolved = {}) => {
const resolveAction = getResolveAction();
return dispatch(isThunk(resolved) ? resolved.bind(null, resolveAction) : {
...resolveAction,
...isAction(resolved) ? resolved : {
...!!resolved && { payload: resolved }
}
});
},
(rejected = {}) => {
const resolveAction = getResolveAction(true);
return dispatch(isThunk(rejected) ? rejected.bind(null, resolveAction) : {
...resolveAction,
...isAction(rejected) ? rejected : {
...!!rejected && { payload: rejected }
}
});
},
);
return action;
};
};
}
import { Record } from 'immutable';
/**
* immutable 确定操作的对象是不可变的,更好的维护性能
* 具体说明在 `immutable.md` 文件中
*/
const InitState = Record({
typeList : [],
fileList : [],
execList : [],
execCollectList : [],
focusList : [],
focusCollectList : [],
loading : false,
isRootOrgShow : true,
executorUser : undefined,
focusUser : undefined,
caseNo : '',
orgValidateStatus : 'success',
orgList : [],
orgCollectionList : [],
orgId : '',
orgName : '',
})
export default InitState
\ No newline at end of file
import _ from 'lodash';
import { message } from 'antd';
import { createReducer } from '../../../util';
import types from '../../types';
import InitState from './case_detail_state';
export default createReducer(new InitState, {
[`${types.GET_CASE_INFO}_SUCCESS`]: (state, data) => {
return state.set('caseInfo', data.content)
.set('loading', false);
},
[`${types.GET_CASE_INFO}_PENDING`]: (state, data) => {
return state.set('loading', true);
},
[`${types.UPDATE_LOAD}`]: (state, data, params) => {
return state.set('loading', data.loading)
},
[`${types.ADD_COMMENT}_SUCCESS`]: (state, data) => {
message.success('评论成功');
return state.set('loading', false);
},
[`${types.ADD_COMMENT}_PENDING`]: (state, data) => {
return state.set('loading', true)
},
[`${types.UPDATE_MODEL_VISIBLE}`]: (state, data, params) => {
return state.set('updModalVisible', params.visible)
},
[`${types.UPDATE_CASE_DETAIL_VISIBLE}`]: (state, data, params) => {
return state
.set('updModalVisible', params.state_value.updModalVisible !== undefined ? params.state_value.updModalVisible : state.updModalVisible)
.set('updExecVisible', params.state_value.updExecVisible !== undefined ? params.state_value.updExecVisible : state.updExecVisible)
.set('loading', params.state_value.loading !== undefined ? params.state_value.loading : state.loading)
.set('updGroupVisible', params.state_value.updGroupVisible !== undefined ? params.state_value.updGroupVisible : state.updGroupVisible)
.set('updFocusUserVisible', params.state_value.updFocusUserVisible !== undefined ? params.state_value.updFocusUserVisible : state.updFocusUserVisible)
.set('updCreateUserVisible', params.state_value.updCreateUserVisible !== undefined ? params.state_value.updCreateUserVisible : state.updCreateUserVisible)
.set('selectedExec', params.state_value.selectedExec !== undefined ? params.state_value.selectedExec : state.selectedExec)
.set('selectedCreateUser', params.state_value.selectedCreateUser !== undefined ? params.state_value.selectedCreateUser : state.selectedCreateUser)
.set('orgName', params.state_value.orgName !== undefined ? params.state_value.orgName : state.orgName)
.set('orgId', params.state_value.orgId !== undefined ? params.state_value.orgId : state.orgId)
},
[`${types.UPDATE_EXEC}_SUCCESS`]: (state, data) => {
message.success('修改成功');
return state.set('loading', false);
},
[`${types.GET_DETAIL_ROOT_ORGS}_SUCCESS`]: (state, data, params) => {
const result = data.content && data.content.map(org => {
return {
key: org.uuid,
value: org.uuid,
name: org.name,
isLeaf: org.is_all && org.is_all === '0' ? true : false,
}
})
return state.set('orgList', result)
// .set('orgName', result && result.length>0 ? result[0].name : '请联系管理员配置组权限')
},
[`${types.GET_DETAIL_ORGS_BY_ID}`]: (state, data, params) => {
const result = params.data.content && params.data.content.map(org => {
return {
key: org.uuid,
name: org.name,
isLeaf: false, // TODO 子节点的权限不做约束
}
})
/**
* 通过Id获取到子节点信息
*
* 遍历整个 `tree` 数据,将获取到的子节点信息加到匹配的Id的节点下
* 返回新的节点数据
*
*/
const orgList = Object.assign([], state.orgList, [])
getNewTreeData(orgList, params.key, result, 10);
return state.set('orgList', orgList)
},
[`${types.UPD_DETAIL_ORG_VALUE}`]: (state, data, params) => {
return state.set('orgName', params.orgName)
.set('orgId', params.orgId)
},
[`${types.UPDATE_EXEC}_PENDING`]: (state, data) => {
return state.set('loading', true);
},
[`${types.UPDATE_CREATE_USER}_SUCCESS`]: (state, data) => {
message.success('修改成功');
return state.set('loading', false);
},
[`${types.UPDATE_CREATE_USER}_PENDING`]: (state, data) => {
return state.set('loading', true);
},
[`${types.UPDATE_FOCUS}_SUCCESS`]: (state, data) => {
message.success('修改成功');
return state.set('loading', false);
},
[`${types.UPDATE_FOCUS}_PENDING`]: (state, data) => {
return state.set('loading', true);
},
[`${types.SUBMIT_UPDATE_CASE}_SUCCESS`]: (state, data) => {
console.log('data', data);
message.success('修改成功');
return state.set('loading', false)
.set('updModalVisible', false);
},
[`${types.SUBMIT_UPDATE_CASE}_PENDING`]: (state) => {
return state.set('loading', true)
},
[`${types.SUBMIT_UPDATE_CASE}_ERROR`]: (state) => {
message.success('修改失败');
return state.set('loading', false)
},
})
// 构建新的树结构
function getNewTreeData(treeData, curKey, child, level) {
/**
* getNewTreeData(treeData, curKey, child, level)
*
* 参数:
* 1、 `treeData` 🌲树控件数据
* 2、 `curKey` 选中的 `key`
* 3、 `child` 子节点
* 4、 `level` 层级
*
* desc:
* 将子节点加入对应的节点中
*
* 判断🌲树控件层级不符合标准则退出
*
* 遍历节点,如果有子节点,则递归判断子节点
* 没有则将节点加入子节点中
*
*/
const loop = (data) => {
data.forEach((item) => {
if (curKey.indexOf(item.key) === 0) {
if (child.length == 0) {
// message.info('提示:没有数据了!');
item.isLeaf = true;
} else {
item.children = child;
}
} else {
if (item.children) {
loop(item.children);
}
}
});
};
loop(treeData);
return treeData;
}
\ No newline at end of file
import { Record, Map, List } from 'immutable';
/**
* immutable 确定操作的对象是不可变的,更好的维护性能
* 具体说明在 `immutable.md` 文件中
*/
const InitState = Record({
caseInfo : {},
updModalVisible : false,
updExecVisible : false,
updGroupVisible : false,
updCreateUserVisible: false,
updFocusUserVisible: false,
loading : false,
selectedExec : null,
selectedCreateUser : null,
orgList : [],
orgId : '',
orgName : '',
})
export default InitState
\ No newline at end of file
import api from '../../../api';
import types from '../../types';
import reqwest from 'reqwest';
import AG_CONF from '../../../constants/AgCode';
import OPERATOR_INFO from '../../../constants/OperatorInfo';
import { caseMenu } from '../../../../fake/leftMenu';
/**
* 获取case_group列表
*
* @export
* @param {any} reqParams
* @param {any} queryType
* @returns
*/
export function getCaseGroupList(reqParams, queryType) {
console.log('case group reqParams', reqParams);
return {
type: types.GET_CASE_GROUP_LIST,
payload: {
promise: api.get('case/group', { params: reqParams })
// promise: reqwest({
// url : AG_CONF.agUrl + 'case2/tasklist_group',
// method : 'get',
// type : 'json',
// data : [
// { name: 'sign', value: AG_CONF.sign },
// { name: 'ts', value: AG_CONF.ts },
// { name: 'appID', value: AG_CONF.appID } ,
// { name: 'caseNo', value: reqParams.caseNo },
// { name: 'searchMessage', value: reqParams.searchMessage },
// { name: 'taskType', value: reqParams.taskType },
// { name: 'sortType', value: reqParams.sortType },
// { name: 'status', value: reqParams.status },
// { name: 'groupId', value: reqParams.groupId },
// { name: 'isShowAll', value: reqParams.isShowAll },
// ]
// })
},
params: {
reqParams: reqParams,
queryType: queryType
}
}
}
/**
* 修改state
*
* @export
* @param {any} state_value
* @returns
*/
export function updGroupStateValue(state_value) {
return {
type: types.UPDATE_CASE_GROUP_STATE,
params: {
state_value: state_value
}
}
}
/**
* 获取根节点
*
* @export
* @param {any} reqParams
* @returns
*/
export function getRootOrgs(reqParams) {
return dispatch => {
dispatch({
type: types.GET_ROOT_ORGS,
payload: {
content: OPERATOR_INFO.rootTree
},
})
// 在初始化后,加载case列表数据
if (OPERATOR_INFO.rootTree && OPERATOR_INFO.rootTree.length > 0) {
const groupId = OPERATOR_INFO.rootTree[0].org_id;
dispatch(getCaseGroupList({
...reqParams,
groupId: groupId
}))
dispatch(getGroupStatistics(groupId))
} else {
// 在初始化后,初始化侧栏菜单数据
dispatch({
type: types.INIT_MENU,
params: {
leftMenu: caseMenu
}
})
}
}
}
/**
* 根据Id获取子节点
*
* @export
* @param {any} reqParams
* @param {any} data
* @returns
*/
export function getOrgsById(reqParams, data) {
return {
type: types.GET_ORGS_BY_ID,
params: {
key: reqParams,
data: data
}
}
}
/**
* 选中子节点,查询case列表
* 修改 `case group` 中的树控件的值
*
* @export
* @param {any} org_value
* @param {any} reqParams
* @returns
*/
export function updOrgValue(org_value, reqParams) {
return dispatch => {
dispatch({
type: types.UPD_ORG_VALUE,
params: {
orgValue: org_value,
orgId: reqParams.groupId
}
})
// 在修改树控件值的同时加载对应的case信息
dispatch(getCaseGroupList(reqParams))
// 设置id
dispatch(getGroupStatistics(reqParams.groupId))
}
}
/**
* 获取case_group列表
* 获取初始化的 `Group` 统计数据
* @export
* @param {any} groupId
* @param {any} isShowAll
* @returns
*/
export function getGroupStatistics(groupId, isShowAll) {
return {
type: types.GET_GROUP_STATISTICS,
payload: {
promise: reqwest({
url: AG_CONF.agUrl + 'case2/statistics_group',
method: 'get',
type: 'json',
data: [
{ name: 'sign', value: AG_CONF.sign },
{ name: 'ts', value: AG_CONF.ts },
{ name: 'appID', value: AG_CONF.appID },
{ name: 'groupId', value: groupId },
{ name: 'isShowAll', value: isShowAll },
]
})
},
params: {
leftMenu: caseMenu
}
}
}
/**
* 修改 rootKey 值
*
* @export
* @param {any} rootKey
* @returns
*/
export function updCaseGroupRootKey(rootKey) {
return {
type: types.UPDATE_CASE_GROUP_ROOT_KEY,
params: {
rootKey: rootKey
}
}
}
/**
* 获取case类型列表
*
* @export
* @returns
*/
export function getCaseTypeList() {
return {
type: types.GET_CASE_GROUP_SCREENING_TYPE,
payload: {
promise: reqwest({
url: AG_CONF.agUrl + 'case2/type',
method: 'get',
type: 'json',
data: [
{ name: 'sign', value: AG_CONF.sign },
{ name: 'ts', value: AG_CONF.ts },
{ name: 'appID', value: AG_CONF.appID }
]
})
}
}
}
/**
* 修改 showSearch 值
*
* @export
* @param {any} showSearch
* @returns
*/
export function updGroupShowSearch(showSearch) {
return {
type: types.UPDATE_CASE_GROUP_SHOW_SEARCH,
params: {
showSearch: !showSearch
}
}
}
/**
* 清除 state 中搜索项的 Value
*
* @export
* @param {any} state
* @returns
*/
export function clearCaseGroupSearch(state) {
const reqParams = {
pageId: 1,
recPerPage: 10,
groupId: state.groupId,
status: state.status
}
return {
type: types.CLEAR_CASE_GROUP_SEARCH,
payload: {
promise: api.get('case/group', { params: reqParams })
}
}
}
\ No newline at end of file
import _ from 'lodash';
import { message } from 'antd';
import { createReducer, getNewPager } from '../../../util';
import types from '../../types';
import InitState from './case_group_state';
import { fromJS, List } from 'immutable';
export default createReducer(new InitState, {
[`${types.GET_CASE_GROUP_LIST}_SUCCESS`]: (state, data, params) => {
let result = data.content;
result && result.map((item, index) => {
item.key = item.caseNo;
})
return state.set('loading', false)
.set('pager', getNewPager(data.pager, state.pager))
.set('caseGroupList', result)
.set('caseNo', params.reqParams.caseNo || '')
.set('taskType', params.reqParams.taskType || '')
.set('sortType', params.reqParams.sortType || '')
.set('create_time', params.reqParams.create_time || '')
.set('status', params.reqParams.status || 1)
.set('isDesc', params.reqParams.isDesc || 0)
},
[`${types.GET_CASE_GROUP_LIST}_ERROR`]: (state, data, params) => {
return state.set('loading', false)
},
[`${types.GET_CASE_GROUP_LIST}_PENDING`]: (state, data) => {
return state.set('loading', true)
},
[`${types.GET_CASE_GROUP}_PENDING`]: (state, data) => {
return state.set('loading', true)
},
[`${types.GET_ROOT_ORGS}`]: (state, data, params) => {
const result = data.content && data.content.map(org => {
return {
key: org.org_id,
name: org.org_name,
isLeaf: org.is_all && org.is_all === '0' ? true : false,
}
})
// state.reqParams.groupId = result && result.length>0 ? result[0].key : null;
return state.set('orgList', result)
.set('orgValue', result && result.length > 0 ? result[0].name : '请联系管理员配置组权限')
.set('orgId', result && result.length > 0 ? result[0].key : null)
},
[`${types.GET_ORGS_BY_ID}`]: (state, data, params) => {
const result = params.data && params.data.content.map(org => {
return {
key: org.uuid,
name: org.name,
isLeaf: false,
}
})
/**
* 通过Id获取到子节点信息
*
* 遍历整个 `tree` 数据,将获取到的子节点信息加到匹配的Id的节点下
* 返回新的节点数据
*
*/
const orgList = Object.assign([], state.orgList, [])
getNewTreeData(orgList, params.key, result, 10);
return state.set('orgList', orgList)
},
[`${types.UPD_ORG_VALUE}`]: (state, data, params) => {
// state.reqParams.groupId = params.orgId;
return state.set('orgValue', params.orgValue)
.set('orgId', params.orgId)
},
[`${types.UPDATE_CASE_GROUP_ROOT_KEY}`]: (state, data, params) => {
return state.set('rootKey', params.rootKey)
},
[`${types.GET_CASE_GROUP_SCREENING_TYPE}_SUCCESS`]: (state, data, params) => {
const typeList = _.map(data.content, type => {
return {
text: type.case_type,
value: type.id,
}
});
return state.set('typeList', typeList)
},
[`${types.UPDATE_CASE_GROUP_SHOW_SEARCH}`]: (state, data, params) => {
return state.set('showSearch', params.showSearch)
},
[`${types.CLEAR_CASE_GROUP_SEARCH}_SUCCESS`]: (state, data, params) => {
let result = data.content;
result && result.map((item, index) => {
item.key = item.caseNo;
})
return state
.set('loading', false)
.set('pager', getNewPager(data.pager, state.pager))
.set('caseGroupList', result)
.set('keyword_value', '')
.set('caseNo', '')
.set('taskType', '')
.set('sortType', '')
.set('create_time', '')
.set('isDesc', 0)
.set('sourceType', '')
.set('sourceUser', '')
.set('searchType', '')
.set('startTime', '')
.set('endTime', '')
},
[`${types.CLEAR_CASE_GROUP_SEARCH}_ERROR`]: (state, data, params) => {
console.log('group erroe');
return state
.set('loading', false)
.set('pager', 10)
.set('caseGroupList', [])
.set('keyword_value', '')
.set('caseNo', '')
.set('taskType', '')
.set('sortType', '')
.set('create_time', '')
.set('isDesc', 0)
.set('sourceType', '')
.set('sourceUser', '')
.set('searchType', '')
.set('startTime', '')
.set('endTime', '')
},
[`${types.UPDATE_CASE_GROUP_STATE}`]: (state, data, params) => {
return state
.set('keyword_value', params.state_value.keyword_value !== undefined ? params.state_value.keyword_value : state.keyword_value)
.set('caseNo', params.state_value.caseNo !== undefined ? params.state_value.caseNo : state.caseNo)
.set('taskType', params.state_value.taskType !== undefined ? params.state_value.taskType : state.taskType)
.set('sortType', params.state_value.sortType !== undefined ? params.state_value.sortType : state.sortType)
.set('create_time', params.state_value.create_time !== undefined ? params.state_value.create_time : state.create_time)
.set('isDesc', params.state_value.isDesc !== undefined ? params.state_value.isDesc : state.isDesc)
.set('sourceType', params.state_value.sourceType !== undefined ? params.state_value.sourceType : state.sourceType)
.set('sourceUser', params.state_value.sourceUser !== undefined ? params.state_value.sourceUser : state.sourceUser)
.set('searchType', params.state_value.searchType !== undefined ? params.state_value.searchType : state.searchType)
.set('startTime', params.state_value.startTime !== undefined ? params.state_value.startTime : state.startTime)
.set('endTime', params.state_value.endTime !== undefined ? params.state_value.endTime : state.endTime)
}
})
// 构建新的树结构
function getNewTreeData(treeData, curKey, child, level) {
/**
* getNewTreeData(treeData, curKey, child, level)
*
* 参数:
* 1、 `treeData` 🌲树控件数据
* 2、 `curKey` 选中的 `key`
* 3、 `child` 子节点
* 4、 `level` 层级
*
* desc:
* 将子节点加入对应的节点中
*
* 判断🌲树控件层级不符合标准则退出
*
* 遍历节点,如果有子节点,则递归判断子节点
* 没有则将节点加入子节点中
*
*/
const loop = (data) => {
data.forEach((item) => {
if (curKey.indexOf(item.key) === 0) {
if (child.length == 0) {
// message.info('提示:没有数据了!');
item.isLeaf = true;
} else {
item.children = child;
}
} else {
if (item.children) {
loop(item.children);
}
}
});
};
loop(treeData);
return treeData;
}
\ No newline at end of file
import { Record, Map, List } from 'immutable';
import { PAGER } from '../../../constants/ProjectConf';
/**
* immutable 确定操作的对象是不可变的,更好的维护性能
* 具体说明在 `immutable.md` 文件中
*/
const InitState = Record({
caseGroupList : [],
typeList : [],
loading : false,
showSearch : false,
rootKey : '',
keyword_value : '',
caseNo : '',
taskType : '',
sortType : '',
create_time : '',
status : 1,
isDesc : 0,
sourceType : '',
sourceUser : '',
searchType : '',
startTime : '',
endTime : '',
orgList : List(),
orgValue : '',
orgId : null,
// groupId : '',
isShowAll : 0,
pager: PAGER
})
export default InitState
\ No newline at end of file
import api from '../../../api';
import types from '../../types';
import reqwest from 'reqwest';
import AG_CONF from '../../../constants/AgCode';
import OPERATOR_INFO from '../../../constants/OperatorInfo';
/**
* 获取case_manage列表
*
* @export
* @param {any} reqParams
* @param {any} queryType
* @returns
*/
export function getCaseManageList(reqParams, queryType) {
console.log('case manage reqParams', reqParams);
return {
type: types.GET_CASE_MANAGE_LIST,
payload: {
promise: api.get('case/all_page', { params: reqParams })
},
params: {
reqParams: reqParams,
queryType: queryType
}
}
}
/**
* 修改state值
*
* @export
* @param {any} state_value
* @returns
*/
export function updManageStateValue(state_value) {
return {
type: types.UPDATE_CASE_MANAGE_STATE_VALUE,
params: {
state_value: state_value
}
}
}
/**
* 修改 rootKey 值
*
* @export
* @param {any} rootKey
* @returns
*/
export function updManageRootKey(rootKey) {
return {
type: types.UPDATE_CASE_MANAGE_ROOT_KEY,
params: {
rootKey: rootKey
}
}
}
/**
* 获取case类型列表
*
* @export
* @returns
*/
export function getCaseTypeList() {
return {
type: types.GET_CASE_MANAGE_SCREENING_TYPE,
payload: {
promise: reqwest({
url: AG_CONF.agUrl + 'case2/type',
method: 'get',
type: 'json',
data: [
{ name: 'sign', value: AG_CONF.sign },
{ name: 'ts', value: AG_CONF.ts },
{ name: 'appID', value: AG_CONF.appID }
]
})
}
}
}
/**
* 修改 showSearch 值
*
* @export
* @param {any} showSearch
* @returns
*/
export function updManageShowSearch(showSearch) {
return {
type: types.UPDATE_CASE_MANAGE_SHOW_SEARCH,
params: {
showSearch: !showSearch
}
}
}
/**
* 清除 state 中搜索项的 Value
*
* @export
* @param {any} state
* @returns
*/
export function clearCaseManageSearch(state) {
const reqParams = {
pageId: 1,
recPerPage: 10,
status: state.status
}
return {
type: types.CLEAR_CASE_MANAGE_SEARCH,
payload: {
promise: api.get('case/all_page', { params: reqParams })
}
}
}
import _ from 'lodash';
import { message } from 'antd';
import { createReducer, getNewPager } from '../../../util';
import types from '../../types';
import InitState from './case_manage_state';
export default createReducer(new InitState, {
[`${types.GET_CASE_MANAGE_LIST}_SUCCESS`]: (state, data, params) => {
let result = data.content;
result.map((item, index) => {
item.key = item.caseNo;
})
return state.set('loading', false)
.set('pager', getNewPager(data.pager, state.pager))
.set('caseManageList', result)
.set('caseNo', params.reqParams.caseNo)
.set('taskType', params.reqParams.taskType)
.set('sortType', params.reqParams.sortType)
.set('create_time', params.reqParams.create_time)
.set('status', params.reqParams.status)
.set('isDesc', params.reqParams.isDesc)
},
[`${types.GET_CASE_MANAGE_LIST}_PENDING`]: (state, data) => {
return state.set('loading', true)
},
[`${types.GET_CASE_MANAGE}_PENDING`]: (state, data) => {
return state.set('loading', true)
},
[`${types.UPDATE_CASE_MANAGE_ROOT_KEY}`]: (state, data, params) => {
console.log('params', params);
return state.set('rootKey', params.rootKey)
},
[`${types.GET_CASE_MANAGE_SCREENING_TYPE}_SUCCESS`]: (state, data, params) => {
const typeList = _.map(data.content, type => {
return {
text: type.case_type,
value: type.id,
}
});
return state.set('typeList', typeList)
},
[`${types.UPDATE_CASE_MANAGE_SHOW_SEARCH}`]: (state, data, params) => {
return state.set('showSearch', params.showSearch)
},
[`${types.CLEAR_CASE_MANAGE_SEARCH}_SUCCESS`]: (state, data, params) => {
let result = data.content;
result.map((item, index) => {
item.key = item.caseNo;
})
return state
.set('loading', false)
.set('pager', getNewPager(data.pager, state.pager))
.set('caseManageList', result)
.set('keyword_value', '')
.set('caseNo', '')
.set('taskType', '')
.set('sortType', '')
.set('create_time', '')
.set('isDesc', 0)
.set('sourceType', '')
.set('sourceUser', '')
.set('searchType', '')
.set('startTime', '')
.set('endTime', '')
.set('isTimeout', '')
},
[`${types.UPDATE_CASE_MANAGE_STATE_VALUE}`]: (state, data, params) => {
return state
.set('keyword_value', params.state_value.keyword_value !== undefined ? params.state_value.keyword_value : state.keyword_value)
.set('caseNo', params.state_value.caseNo !== undefined ? params.state_value.caseNo : state.caseNo)
.set('taskType', params.state_value.taskType !== undefined ? params.state_value.taskType : state.taskType)
.set('sortType', params.state_value.sortType !== undefined ? params.state_value.sortType : state.sortType)
.set('create_time', params.state_value.create_time !== undefined ? params.state_value.create_time : state.create_time)
.set('isDesc', params.state_value.isDesc !== undefined ? params.state_value.isDesc : state.isDesc)
.set('sourceType', params.state_value.sourceType !== undefined ? params.state_value.sourceType : state.sourceType)
.set('sourceUser', params.state_value.sourceUser !== undefined ? params.state_value.sourceUser : state.sourceUser)
.set('searchType', params.state_value.searchType !== undefined ? params.state_value.searchType : state.searchType)
.set('startTime', params.state_value.startTime !== undefined ? params.state_value.startTime : state.startTime)
.set('endTime', params.state_value.endTime !== undefined ? params.state_value.endTime : state.endTime)
.set('isTimeout', params.state_value.isTimeout !== undefined ? params.state_value.isTimeout : state.isTimeout)
}
})
import { Record } from 'immutable';
import { PAGER } from '../../../constants/ProjectConf';
/**
* immutable 确定操作的对象是不可变的,更好的维护性能
* 具体说明在 `immutable.md` 文件中
*/
const InitState = Record({
caseManageList : [],
typeList : [],
loading : false,
showSearch : false,
rootKey : '',
keyword_value : '',
caseNo : '',
taskType : '',
sortType : '',
create_time : '',
status : 1,
isDesc : 0,
sourceType : '',
sourceUser : '',
searchType : '',
startTime : '',
endTime : '',
isTimeout : '',
pager: PAGER
})
export default InitState
import api from '../../../api';
import types from '../../types';
import reqwest from 'reqwest';
import AG_CONF from '../../../constants/AgCode';
import OPERATOR_INFO from '../../../constants/OperatorInfo';
// 获取case_rank列表
export function getCaseRankList(reqParams, queryType) {
console.log('case rank reqParams', reqParams);
return {
type: types.GET_CASE_RANK_LIST,
payload: {
//promise: reqwest({
// url: AG_CONF.agUrl + 'case2/statistics_rank?sign=' + AG_CONF.sign + '&ts=' + AG_CONF.ts + '&appID=' + AG_CONF.appID,
// type: 'json',
// method: 'get',
// data : [
// { name: 'sourceType', value:reqParams.sourceType },
// { name: 'sourceUser', value:reqParams.sourceUser },
// { name: 'startTime', value:reqParams.startTime },
// { name: 'endTime', value:reqParams.endTime },
// { name: 'isDesc', value:reqParams.isDesc },
// { name: 'pageNum', value:reqParams.pageId },
// { name: 'pageSize', value:reqParams.recPerPage }
// ]
//})
promise: api.get('case2/statistics_rank', {params: reqParams})
},
params: {
reqParams: reqParams,
queryType: queryType
}
}
}
export function updRankStateValue(state_value) {
/**
* 修改值可以做统一处理
* 这里是统一修改 `State` 的值
* 分开过多状态会显得更乱
*
*/
return {
type: types.UPDATE_CASE_RANK_STATE_VALUE,
params: {
state_value: state_value
}
}
}
// 修改 rootKey 值
export function updRankRootKey(rootKey) {
return {
type: types.UPDATE_CASE_RANK_ROOT_KEY,
params: {
rootKey: rootKey
}
}
}
// 获取case类型列表
export function getCaseTypeList() {
return {
type: types.GET_CASE_RANK_SCREENING_TYPE,
payload: {
promise: reqwest({
url : AG_CONF.agUrl + 'case2/type',
method : 'get',
type : 'json',
data : [
{ name: 'sign', value: AG_CONF.sign },
{ name: 'ts', value: AG_CONF.ts },
{ name: 'appID', value: AG_CONF.appID }
]
})
}
}
}
// 修改 showSearch 值
export function updRankShowSearch(showSearch) {
return {
type: types.UPDATE_CASE_RANK_SHOW_SEARCH,
params: {
showSearch: !showSearch
}
}
}
// 清除 state 中搜索项的 Value
export function clearCaseRankSearch(state) {
console.log(state)
const reqParams = {
sourceType : 'remain',
pageId : 1,
recPerPage : 10,
status : state.status
}
return {
type: types.CLEAR_CASE_RANK_SEARCH,
payload: {
//promise: api.get('case/all_page', {params: reqParams})
}
}
}
// 按关键字获取员工列表
export function getExecutorKeywordList(keyword) {
/*
todo:需要添加关键字过滤机制时在此处理
*/
console.log("进入员工搜索");
return {
type: types.GET_RANKUSER_LIST_BY_KEYWORD,
payload: {
promise: reqwest({
url: AG_CONF.agUrl + 'account/search?sign=' + AG_CONF.sign + '&ts=' + AG_CONF.ts + '&appID=' + AG_CONF.appID,
type: 'json',
method: 'post',
data: {
page: '1',
pageSize: '15',
keyword: keyword
}
})
}
}
}
\ No newline at end of file
import _ from 'lodash';
import { message } from 'antd';
import { createReducer, getNewPager } from '../../../util';
import types from '../../types';
import InitState from './case_rank_state';
export default createReducer(new InitState, {
[`${types.GET_CASE_RANK_LIST}_SUCCESS`]: (state, data, params) => {
let result = data.content;
result.map((item, index) => {
item.key = item.caseNo;
})
return state.set('loading', false)
.set('pager', getNewPager(data.pager, state.pager))
.set('caseRankList', result)
.set('caseNo', params.reqParams.caseNo)
.set('taskType', params.reqParams.taskType)
.set('sortType', params.reqParams.sortType)
.set('create_time', params.reqParams.create_time)
.set('status', params.reqParams.status)
.set('isDesc', params.reqParams.isDesc)
},
[`${types.GET_CASE_RANK_LIST}_PENDING`]: (state, data) => {
return state.set('loading', true)
},
[`${types.GET_CASE_RANK}_PENDING`]: (state, data) => {
return state.set('loading', true)
},
[`${types.UPDATE_CASE_RANK_ROOT_KEY}`]: (state, data, params) => {
console.log('params', params);
return state.set('rootKey', params.rootKey)
},
[`${types.GET_CASE_RANK_SCREENING_TYPE}_SUCCESS`]: (state, data, params) => {
const typeList = _.map(data.content, type => {
return {
text: type.case_type,
value: type.id,
}
});
return state.set('typeList', typeList)
},
[`${types.UPDATE_CASE_RANK_SHOW_SEARCH}`]: (state, data, params) => {
return state.set('showSearch', params.showSearch)
},
[`${types.CLEAR_CASE_RANK_SEARCH}`]: (state, data, params) => {
//let result = data.content;
//result.map((item, index) => {
// item.key = item.caseNo;
//})
return state
.set('loading', false)
//.set('pager', getNewPager(data.pager, state.pager))
//.set('caseRankList', result)
.set('keyword_value', '')
.set('caseNo', '')
.set('taskType', '')
.set('sortType', '')
.set('create_time', '')
.set('isDesc', 0)
.set('sourceType', '')
.set('sourceUser', {})
.set('searchType', '')
.set('startTime', '')
.set('endTime', '')
.set('isTimeout', '')
},
[`${types.UPDATE_CASE_RANK_STATE_VALUE}`]: (state, data, params) => {
return state
.set('keyword_value', params.state_value.keyword_value !== undefined ? params.state_value.keyword_value : state.keyword_value)
.set('caseNo', params.state_value.caseNo !== undefined ? params.state_value.caseNo : state.caseNo)
.set('taskType', params.state_value.taskType !== undefined ? params.state_value.taskType : state.taskType)
.set('sortType', params.state_value.sortType !== undefined ? params.state_value.sortType : state.sortType)
.set('create_time', params.state_value.create_time !== undefined ? params.state_value.create_time : state.create_time)
.set('isDesc', params.state_value.isDesc !== undefined ? params.state_value.isDesc : state.isDesc)
.set('sourceType', params.state_value.sourceType !== undefined ? params.state_value.sourceType : state.sourceType)
.set('sourceUser', params.state_value.sourceUser !== undefined ? params.state_value.sourceUser : state.sourceUser)
.set('searchType', params.state_value.searchType !== undefined ? params.state_value.searchType : state.searchType)
.set('startTime', params.state_value.startTime !== undefined ? params.state_value.startTime : state.startTime)
.set('endTime', params.state_value.endTime !== undefined ? params.state_value.endTime : state.endTime)
.set('isTimeout', params.state_value.isTimeout !== undefined ? params.state_value.isTimeout : state.isTimeout)
},
[`${types.GET_RANKUSER_LIST_BY_KEYWORD}_SUCCESS`]: (state, data) => {
const execList = _.compact(_.map(data.content, (account, index) => {
if (account.disable == 0) {
return account
}
}))
return state.set('execList', execList)
},
})
import { Record } from 'immutable';
import { PAGER } from '../../../constants/ProjectConf';
/**
* immutable 确定操作的对象是不可变的,更好的维护性能
* 具体说明在 `immutable.md` 文件中
*/
const InitState = Record({
caseRankList : [],
typeList : [],
execList : [],
loading : false,
showSearch : false,
rootKey : '',
keyword_value : '',
caseNo : '',
taskType : '',
sortType : '',
create_time : '',
status : 1,
isDesc : 0,
sourceType : 'remain',
sourceUser : {},
searchType : '',
startTime : '',
endTime : '',
isTimeout : '',
pager: PAGER
})
export default InitState
import api from '../../../api';
import types from '../../types';
import reqwest from 'reqwest';
import AG_CONF from '../../../constants/AgCode';
import OPERATOR_INFO from '../../../constants/OperatorInfo';
import {emptyMenu, caseMenu} from '../../../../fake/leftMenu';
/**
* 顶部菜单切换,更新面包屑
*
* @export
* @param {any} path
* @param {any} key
* @returns
*/
export function updateNavPath(path, key) {
return {
type: types.UPDATE_NAVPATH,
payload: {
data: path,
key: key
}
}
}
/**
* 获取case顶部菜单
* 向服务端获取 `顶部菜单` 信息,服务端可以自由控制 `顶部菜单` 的权限问题
*
* @export
* @returns
*/
export function getTopMenu() {
return {
type: types.GET_TOP_MENU,
payload: {
promise: api.get('topmenu', {})
}
}
}
/**
* 获取cese侧边菜单数据(我的发布、我的case、我的关注)
*
* 获取 `侧边菜单` 的统计数据
* 根据 `taskMatch` 字段获取筛选
* 我的发布 = 1
* 我的case = 2
* 我的关注 = 3
*
* @export
* @param {any} taskMatchObj
* @returns
*/
export function getCaseMenu(taskMatchObj) {
return {
type: types.GET_LEFT_MENU,
payload: {
promise: api.get('report/my', { params: taskMatchObj })
},
params: {
...taskMatchObj,
leftMenu: caseMenu
}
}
}
/**
* 获取cese侧边菜单数据(我的发布、我的case、我的关注)
* 目前添加case侧边菜单不需要数据,所以先传一个空菜单
*
* @export
* @returns
*/
export function getAddCaseLeftMenu() {
return {
type: types.GET_ADD_CASE_LEFT_MENU,
payload: {
leftMenu: emptyMenu
}
}
}
/**
*
* 获取 `我的管理侧边菜单` 的统计数据
* 我的管理统计数据是独立的接口,所以在 `Action` 中开一个独立的动作
*
* 优化:
* 可以通过传参来判断需要访问那个接口
* type = myCase、myTask、myFocu、manage
* 判断type类型获取相应的结果刷新 `State`
*
* @export
* @param {any} param
* @returns
*/
export function getCaseManageMenu(param) {
return {
type: types.GET_MANAGE_LEFT_MENU,
payload: {
promise: api.get('report/all_page', { params: param })
},
params: {
leftMenu: caseMenu
}
}
}
/**
* 侧栏菜单的隐藏显示控制
*
* 通过点击切换按钮触发该功能
* 目前在 `View/App` 下控制,打开与隐藏的Class
*
* @export
* @param {any} collapse
* @returns
*/
export function updateCollapse(collapse) {
return {
type: types.UPDATE_COLLAPSE,
payload: {
collapse: collapse,
}
}
}
/**
* 修改 state
*
* @export
* @param {any} status
* @returns
*/
export function updateStatus(status) {
return {
type: types.UPDATE_STATUS,
payload: {
status: status,
}
}
}
import _ from 'lodash';
import { message } from 'antd';
import { createReducer } from '../../../util';
import types from '../../types';
import InitState from './menu_state';
export default createReducer(new InitState, {
[`${types.GET_TOP_MENU}_SUCCESS`]: (state, data) => {
console.log('data', data)
return state.set('topMenu', data.content)
},
[`${types.UPDATE_NAVPATH}`]: (state, data) => {
let navpath = [], tmpOb, tmpKey, child, selectClass = 'ant-menu-item-selected';
/**
* 判断 `Action` 传来的数据是否有 `面包屑` 信息
*
* `Menu` 控件传来的值 ['子级控件值', '父级控件值'],将数组倒序,先遍历父级标签
* 如果不做方向操作,`child` 没有子级菜单列表,导致程序出错
*
* 判断如果是父级标签,查询菜单Json,取到对应Key的值。
* 储存该菜单的子集菜单集合到 `child` 中
* 将 `key`、`name` 添加到 `面包屑` 集合中
*
* 判断如果是子级标签,取出对应的Key值
* 判断 `child` 是否有值,
* 取到对应的子级数据中的Json
* 将 `key`、`name` 添加到 `面包屑` 集合中
*
* 在面包屑组件中遍历 `navpath` 构建 `Breadcrumb` 标签的值,按顺序显示相关内容
*
* `selectClass` 用于解决同步菜单二级菜单点击时 `class` 选中状态的问题,目前没有二级菜单,所以暂时没有用处
*
*/
if (data.data) {
data.data.reverse().map((item) => {
if (item.indexOf('sub') != -1) {
tmpKey = item.replace('sub', '');
tmpOb = _.find(state.topMenu, function(o) {
return o.key == tmpKey;
});
child = tmpOb.child;
navpath.push({
key: tmpOb.key,
name: tmpOb.name
})
// selectClass = ''
}
if (item.indexOf('menu') != -1) {
tmpKey = item.replace('menu', '');
if (child) {
tmpOb = _.find(child, function(o) {
return o.key == tmpKey;
});
}
navpath.push({
key: tmpOb.key,
name: tmpOb.name
})
}
})
}
return state.set('currentIndex', data.key * 1)
.set('navpath', navpath)
.set('selectClass', selectClass)
},
[`${types.UPDATE_STATUS}`]: (state, data) => {
return state.set('status', data.status)
},
[`${types.GET_LEFT_MENU}_SUCCESS`]: (state, data, params) => {
let report = data.content, leftMenuType;
params.leftMenu.map((item) => {
switch (item.key) {
case 'ongoing':
item.num = report.pending || 0;
break;
case 'completed':
item.num = report.finish || 0;
break;
case 'confirm_completed':
item.num = report.confirmFinish || 0;
break;
case 'closed':
item.num = report.closed || 0;
break;
case 'gratuity':
item.num = report.reward || 0;
break;
case 'thumb_up':
item.num = report.likeTotal || 0;
break;
case 'dislike':
item.num = report.booingTotal || 0;
break;
}
})
switch (params.taskMatch) {
case 1:
leftMenuType = 'my_case'
break;
case 2:
leftMenuType = 'my_task'
break;
case 3:
leftMenuType = 'my_focus'
break;
default:
break;
}
return state.set('leftMenuType', leftMenuType)
.set('leftMenu', params.leftMenu)
},
[`${types.GET_MANAGE_LEFT_MENU}_SUCCESS`]: (state, data, params) => {
let case_manage = data.content;
params.leftMenu.map((item) => {
switch (item.key) {
case 'ongoing':
item.num = case_manage.pending || 0;
break;
case 'completed':
item.num = case_manage.finish || 0;
break;
case 'confirm_completed':
item.num = case_manage.confirmFinish || 0;
break;
case 'closed':
item.num = case_manage.closed || 0;
break;
case 'gratuity':
item.num = case_manage.reward || 0;
break;
case 'thumb_up':
item.num = case_manage.likeTotal || 0;
break;
case 'dislike':
item.num = case_manage.booingTotal || 0;
break;
}
})
return state.set('leftMenuType', 'case_manage')
.set('leftMenu', params.leftMenu)
},
[`${types.GET_GROUP_STATISTICS}_SUCCESS`]: (state, data, params) => {
let case_group = data.content;
const leftMenu = _.map(params.leftMenu, ((item) => {
switch (item.key) {
case 'ongoing':
item.num = case_group.pending || 0;
break;
case 'completed':
item.num = case_group.finish || 0;
break;
case 'confirm_completed':
item.num = case_group.confirmFinish || 0;
break;
case 'closed':
item.num = case_group.closed || 0;
break;
case 'gratuity':
item.num = case_group.reward || 0;
break;
case 'thumb_up':
item.num = case_group.likeTotal || 0;
break;
case 'dislike':
item.num = case_group.booingTotal || 0;
break;
}
return item;
}))
return state.set('leftMenuType', 'case_group')
.set('leftMenu', leftMenu)
},
[`${types.INIT_MENU}`]: (state, data, params) => {
params.leftMenu.map((item) => {
item.num = 0;
})
return state.set('leftMenuType', '')
},
[`${types.UPDATE_COLLAPSE}`]: (state, data) => {
return state.set('collapse', !data.collapse)
},
[`${types.GET_ADD_CASE_LEFT_MENU}`]: (state, data) => {
return state.set('leftMenu', data.leftMenu)
},
})
\ No newline at end of file
import { Record, Map } from 'immutable';
/**
* immutable 确定操作的对象是不可变的,更好的维护性能
* 具体说明在 `immutable.md` 文件中
*/
const InitState = Record({
currentIndex : 0,
leftMenu : [],
leftMenuType : '',
topMenu : [],
navpath : [],
collapse : false,
selectClass : '',
selectKey : 'my_case',
status : 1
})
export default InitState
\ No newline at end of file
import api from '../../../api';
import types from '../../types';
import reqwest from 'reqwest';
import AG_CONF from '../../../constants/AgCode';
import OPERATOR_INFO from '../../../constants/OperatorInfo';
/**
* 获取case列表
*
* @export
* @param {any} reqParams
* @param {any} queryType
* @returns
*/
export function getCaseList(reqParams, queryType) {
reqParams.taskMatch = 1; // TODO 侧栏菜单查询时没有带 `taskMatch` 先在 `Action` 中固定该值,之后想法办处理
console.log('my case reqParams', reqParams);
return {
type: types.GET_MY_CASE_LIST,
payload: {
promise: api.get('case/my', { params: reqParams })
},
params: {
reqParams: reqParams,
queryType: queryType
}
}
}
/**
* 修改case状态为关闭
*
* @export
* @param {any} case_id
* @param {any} reqParams
* @returns
*/
export function updStatusClose(case_id, reqParams) {
return dispatch => {
dispatch({
type: types.UPDATE_STATUS_CLOSE,
payload: {
promise: api.post('case/close', { params: { id: case_id } }).then(function(result) {
if (result.code == '0') {
dispatch(getCaseList(reqParams))
}
}),
}
})
}
}
/**
* 修改case状态为确认完成
*
* @export
* @param {any} case_id
* @param {any} reqParams
* @returns
*/
export function updStatusConfirmFinish(case_id, reqParams) {
return dispatch => {
dispatch({
type: types.UPDATE_STATUS_CONFIRM_FINISH,
payload: {
promise: api.post('case/create_finish', { params: { id: case_id } }).then(function(result) {
if (result.code == '0') {
dispatch(getCaseList(reqParams))
}
}),
}
})
}
}
/**
* 修改state
*
* @export
* @param {any} state_value
* @returns
*/
export function updMyCaseStateValue(state_value) {
return {
type: types.UPDATE_MY_CASE_STATE_VALUE,
params: {
state_value: state_value
}
}
}
/**
* 修改 rootKey 值
*
* @export
* @param {any} rootKey
* @returns
*/
export function updMyCaseRootKey(rootKey) {
return {
type: types.UPDATE_MY_CASE_ROOT_KEY,
params: {
rootKey: rootKey
}
}
}
/**
* 获取case类型列表
*
* @export
* @returns
*/
export function getCaseTypeList() {
return {
type: types.GET_MY_CASE_SCREENING_TYPE,
payload: {
promise: reqwest({
url: AG_CONF.agUrl + 'case2/type',
method: 'get',
type: 'json',
data: [
{ name: 'sign', value: AG_CONF.sign },
{ name: 'ts', value: AG_CONF.ts },
{ name: 'appID', value: AG_CONF.appID }
]
})
}
}
}
/**
* 清除 state 中搜索项的 Value
*
* @export
* @param {any} state
* @returns
*/
export function clearMyCaseSearch(state) {
const reqParams = {
pageId: 1,
recPerPage: 10,
taskMatch: 1,
status: state.status
}
return {
type: types.CLEAR_MY_CASE_SEARCH,
payload: {
promise: api.get('case/my', { params: reqParams })
}
}
}
\ No newline at end of file
import _ from 'lodash';
import { message } from 'antd';
import { createReducer, getNewPager } from '../../../util';
import types from '../../types';
import InitState from './my_case_state';
export default createReducer(new InitState, {
[`${types.GET_MY_CASE_LIST}_SUCCESS`]: (state, data, params) => {
let result = data.content;
result.map((item, index) => {
item.key = item.caseNo;
})
return state.set('loading', false)
.set('pager', getNewPager(data.pager, state.pager))
.set('caseList', result)
.set('caseNo', params.reqParams.caseNo)
.set('taskType', params.reqParams.taskType)
.set('sortType', params.reqParams.sortType)
.set('create_time', params.reqParams.create_time)
.set('status', params.reqParams.status)
.set('isDesc', params.reqParams.isDesc)
},
[`${types.GET_MY_CASE_LIST}_PENDING`]: (state, data) => {
return state.set('loading', true)
},
[`${types.GET_MY_CASE}_PENDING`]: (state, data) => {
return state.set('loading', true)
},
[`${types.UPDATE_STATUS_CLOSE}_SUCCESS`]: (state, data) => {
message.success('操作成功');
return state
},
[`${types.UPDATE_STATUS_CONFIRM_FINISH}_SUCCESS`]: (state, data) => {
message.success('操作成功');
return state
},
// [`${types.UPDATE_STATUS_CLOSE}_ERROR`]: (state, data) => {
// /**
// * 如果 `util` 里无法全局处理 `ERROR` 时启动该 `reducer`
// */
// message.error('操作失败');
// return state
// },
// [`${types.UPDATE_STATUS_CONFIRM_FINISH}_ERROR`]: (state, data) => {
// /**
// * 如果 `util` 里无法全局处理 `ERROR` 时启动该 `reducer`
// */
// message.error('操作失败');
// return state
// },
[`${types.UPDATE_MY_CASE_KEYWORD}`]: (state, data, params) => {
return state.set('keyword_value', params.keyword_value)
},
[`${types.UPDATE_MY_CASE_NO_VALUE}`]: (state, data, params) => {
return state.set('caseNo', params.case_no)
},
[`${types.UPDATE_MY_CASE_KEYWORD_FOCUS}`]: (state, data, params) => {
return state.set('focus', params.focus)
},
[`${types.UPDATE_MY_CASE_NO_FOCUS}`]: (state, data, params) => {
return state.set('no_focus', params.focus)
},
[`${types.UPDATE_MY_CASE_ROOT_KEY}`]: (state, data, params) => {
return state.set('rootKey', params.rootKey)
},
[`${types.GET_MY_CASE_SCREENING_TYPE}_SUCCESS`]: (state, data, params) => {
const typeList = _.map(data.content, type => {
return {
text: type.case_type,
value: type.id,
}
});
return state.set('typeList', typeList)
},
[`${types.CLEAR_MY_CASE_SEARCH}_SUCCESS`]: (state, data, params) => {
let result = data.content;
result.map((item, index) => {
item.key = item.caseNo;
})
return state
.set('loading', false)
.set('pager', getNewPager(data.pager, state.pager))
.set('caseList', result)
.set('keyword_value', '')
.set('caseNo', '')
.set('taskType', '')
.set('sortType', '')
.set('create_time', '')
.set('isDesc', 0)
},
[`${types.UPDATE_MY_CASE_STATE_VALUE}`]: (state, data, params) => {
return state
.set('keyword_value', params.state_value.keyword_value !== undefined ? params.state_value.keyword_value : state.keyword_value)
.set('caseNo', params.state_value.caseNo !== undefined ? params.state_value.caseNo : state.caseNo)
.set('taskType', params.state_value.taskType !== undefined ? params.state_value.taskType : state.taskType)
.set('sortType', params.state_value.sortType !== undefined ? params.state_value.sortType : state.sortType)
.set('create_time', params.state_value.create_time !== undefined ? params.state_value.create_time : state.create_time)
.set('isDesc', params.state_value.isDesc !== undefined ? params.state_value.isDesc : state.isDesc)
}
})
import { Record, Map } from 'immutable';
import { PAGER } from '../../../constants/ProjectConf';
/**
* immutable 确定操作的对象是不可变的,更好的维护性能
* 具体说明在 `immutable.md` 文件中
*/
const InitState = Record({
caseList : [],
typeList : [],
loading : false,
rootKey : '',
keyword_value : '',
caseNo : '',
taskType : '',
sortType : '',
create_time : '',
status : 1,
isDesc : 0,
taskMatch: 1,
pager: PAGER
})
export default InitState
\ No newline at end of file
import api from '../../../api';
import types from '../../types';
import reqwest from 'reqwest';
import AG_CONF from '../../../constants/AgCode';
import OPERATOR_INFO from '../../../constants/OperatorInfo';
/**
* 获取case列表
*
* @export
* @param {any} reqParams
* @param {any} queryType
* @returns
*/
export function getMyFocusList(reqParams, queryType) {
reqParams.taskMatch = 3; // TODO 侧栏菜单查询时没有带 `taskMatch` 先在 `Action` 中固定该值,之后想法办处理
console.log('my focus case_param', reqParams);
return {
type: types.GET_MY_FOCUS_LIST,
payload: {
promise: api.get('case/my', { params: reqParams })
},
params: {
reqParams: reqParams,
queryType: queryType
}
}
}
/**
* 修改 rootKey 值
*
* @export
* @param {any} rootKey
* @returns
*/
export function updMyFocusRootKey(rootKey) {
return {
type: types.UPDATE_MY_FOCUS_ROOT_KEY,
params: {
rootKey: rootKey
}
}
}
/**
* 获取case类型列表
*
* @export
* @returns
*/
export function getCaseTypeList() {
return {
type: types.GET_MY_FOCUS_SCREENING_TYPE,
payload: {
promise: reqwest({
url: AG_CONF.agUrl + 'case2/type',
method: 'get',
type: 'json',
data: [
{ name: 'sign', value: AG_CONF.sign },
{ name: 'ts', value: AG_CONF.ts },
{ name: 'appID', value: AG_CONF.appID }
]
})
}
}
}
/**
* 修改state
*
* @export
* @param {any} state_value
* @returns
*/
export function updMyFocusStateValue(state_value) {
return {
type: types.UPDATE_MY_FOCUS_STATE_VALUE,
params: {
state_value: state_value
}
}
}
/**
* 清除 state 中搜索项的 Value
*
* @export
* @param {any} state
* @returns
*/
export function clearMyFocusSearch(state) {
const reqParams = {
pageId: 1,
recPerPage: 10,
taskMatch: 3,
status: state.status
}
return {
type: types.CLEAR_MY_FOCUS_SEARCH,
payload: {
promise: api.get('case/my', { params: reqParams })
}
}
}
import _ from 'lodash';
import { message } from 'antd';
import { createReducer, getNewPager } from '../../../util';
import types from '../../types';
import InitState from './my_focus_state';
export default createReducer(new InitState, {
[`${types.GET_MY_FOCUS_LIST}_SUCCESS`]: (state, data, params) => {
let result = data.content;
result.map((item, index) => {
item.key = item.caseNo;
})
return state.set('loading', false)
.set('pager', getNewPager(data.pager, state.pager))
.set('caseList', result)
.set('caseNo', params.reqParams.caseNo)
.set('taskType', params.reqParams.taskType)
.set('sortType', params.reqParams.sortType)
.set('create_time', params.reqParams.create_time)
.set('status', params.reqParams.status)
.set('isDesc', params.reqParams.isDesc)
},
[`${types.GET_MY_FOCUS_LIST}_PENDING`]: (state, data) => {
return state.set('loading', true)
},
[`${types.GET_MY_FOCUS}_PENDING`]: (state, data) => {
return state.set('loading', true)
},
[`${types.UPDATE_STATUS_FINISH}_SUCCESS`]: (state, data) => {
message.success('操作成功');
return state
},
// [`${types.UPDATE_STATUS_FINISH}_ERROR`]: (state, data) => {
// /**
// * 如果 `util` 里无法全局处理 `ERROR` 时启动该 `reducer`
// */
// message.error('操作失败');
// return state
// },
[`${types.UPDATE_MY_FOCUS_ROOT_KEY}`]: (state, data, params) => {
return state.set('rootKey', params.rootKey)
},
[`${types.GET_MY_FOCUS_SCREENING_TYPE}_SUCCESS`]: (state, data, params) => {
const typeList = _.map(data.content, type => {
return {
text: type.case_type,
value: type.id,
}
});
return state.set('typeList', typeList)
},
[`${types.CLEAR_MY_FOCUS_SEARCH}_SUCCESS`]: (state, data, params) => {
let result = data.content;
result.map((item, index) => {
item.key = item.caseNo;
})
return state
.set('loading', false)
.set('pager', getNewPager(data.pager, state.pager))
.set('caseList', result)
.set('keyword_value', '')
.set('caseNo', '')
.set('taskType', '')
.set('sortType', '')
.set('create_time', '')
.set('isDesc', 0)
},
[`${types.UPDATE_MY_FOCUS_STATE_VALUE}`]: (state, data, params) => {
return state
.set('keyword_value', params.state_value.keyword_value !== undefined ? params.state_value.keyword_value : state.keyword_value)
.set('caseNo', params.state_value.caseNo !== undefined ? params.state_value.caseNo : state.caseNo)
.set('taskType', params.state_value.taskType !== undefined ? params.state_value.taskType : state.taskType)
.set('sortType', params.state_value.sortType !== undefined ? params.state_value.sortType : state.sortType)
.set('create_time', params.state_value.create_time !== undefined ? params.state_value.create_time : state.create_time)
.set('isDesc', params.state_value.isDesc !== undefined ? params.state_value.isDesc : state.isDesc)
}
})
\ No newline at end of file
import { Record, Map } from 'immutable';
import { PAGER } from '../../../constants/ProjectConf';
/**
* immutable 确定操作的对象是不可变的,更好的维护性能
* 具体说明在 `immutable.md` 文件中
*/
const InitState = Record({
caseList : [],
typeList : [],
loading : false,
focus : false,
no_focus : false,
rootKey : '',
keyword_value : '',
caseNo : '',
taskType : '',
sortType : '',
create_time : '',
status : 1,
isDesc : 0,
taskMatch: 3,
pager: PAGER
})
export default InitState
\ No newline at end of file
import api from '../../../api';
import types from '../../types';
import reqwest from 'reqwest';
import AG_CONF from '../../../constants/AgCode';
import OPERATOR_INFO from '../../../constants/OperatorInfo';
/**
* 获取case列表
*
* @export
* @param {any} reqParams
* @param {any} queryType
* @returns
*/
export function getMyTaskList(reqParams, queryType) {
reqParams.taskMatch = 2; // TODO 侧栏菜单查询时没有带 `taskMatch` 先在 `Action` 中固定该值,之后想法办处理
console.log('my task case_param', reqParams);
return {
type: types.GET_MY_TASK_LIST,
payload: {
promise: api.get('case/my', { params: reqParams })
},
params: {
reqParams: reqParams,
queryType: queryType
}
}
}
/**
* 设置case状态 -> 完成
*
* desc:
* 先将case发送将case状态设置为完成 `Action`,如果设置成功则在发送查询case列表的 `Action`
*
* 这里用到了 `dispatch` 的触发机制,猜想是用递归的方式调用 `Action` 方法,
* 有时间需要深入研究
*
*/
export function updStatusFinish(case_id, reqParams) {
return dispatch => {
dispatch({
type: types.UPDATE_STATUS_FINISH,
payload: {
promise: api.post('case/execte_finish', { params: { id: case_id } }).then(function(result) {
if (result.code == '0') {
dispatch(getMyTaskList(reqParams))
}
}),
}
})
}
}
/**
* 修改 rootKey 值
*
* @export
* @param {any} rootKey
* @returns
*/
export function updMyTaskRootKey(rootKey) {
return {
type: types.UPDATE_MY_TASK_ROOT_KEY,
params: {
rootKey: rootKey
}
}
}
/**
* 获取case类型列表
*
* @export
* @returns
*/
export function getCaseTypeList() {
return {
type: types.GET_MY_TASK_SCREENING_TYPE,
payload: {
promise: reqwest({
url: AG_CONF.agUrl + 'case2/type',
method: 'get',
type: 'json',
data: [
{ name: 'sign', value: AG_CONF.sign },
{ name: 'ts', value: AG_CONF.ts },
{ name: 'appID', value: AG_CONF.appID }
]
})
}
}
}
/**
* 修改state
*
* @export
* @param {any} state_value
* @returns
*/
export function updMyTaskStateValue(state_value) {
return {
type: types.UPDATE_MY_TASK_STATE_VALUE,
params: {
state_value: state_value
}
}
}
/**
* 清除 state 中搜索项的 Value
*
* @export
* @param {any} state
* @returns
*/
export function clearMyTaskSearch(state) {
const reqParams = {
pageId: 1,
recPerPage: 10,
taskMatch: 2,
status: state.status
}
return {
type: types.CLEAR_MY_TASK_SEARCH,
payload: {
promise: api.get('case/my', { params: reqParams })
}
}
}
\ No newline at end of file
import _ from 'lodash';
import { message } from 'antd';
import { createReducer, getNewPager } from '../../../util';
import types from '../../types';
import InitState from './my_task_state';
export default createReducer(new InitState, {
[`${types.GET_MY_TASK_LIST}_SUCCESS`]: (state, data, params) => {
let result = data.content;
result.map((item, index) => {
item.key = item.caseNo;
})
return state.set('loading', false)
.set('pager', getNewPager(data.pager, state.pager))
.set('caseList', result)
.set('caseNo', params.reqParams.caseNo)
.set('taskType', params.reqParams.taskType)
.set('sortType', params.reqParams.sortType)
.set('create_time', params.reqParams.create_time)
.set('status', params.reqParams.status)
.set('isDesc', params.reqParams.isDesc)
},
[`${types.GET_MY_TASK_LIST}_PENDING`]: (state, data) => {
return state.set('loading', true)
},
[`${types.GET_MY_TASK}_PENDING`]: (state, data) => {
return state.set('loading', true)
},
[`${types.UPDATE_STATUS_FINISH}_SUCCESS`]: (state, data) => {
message.success('操作成功');
return state
},
// [`${types.UPDATE_STATUS_FINISH}_ERROR`]: (state, data) => {
// /**
// * 如果 `util` 里无法全局处理 `ERROR` 时启动该 `reducer`
// */
// message.error('操作失败');
// return state
// },
[`${types.UPDATE_MY_TASK_ROOT_KEY}`]: (state, data, params) => {
return state.set('rootKey', params.rootKey)
},
[`${types.GET_MY_TASK_SCREENING_TYPE}_SUCCESS`]: (state, data, params) => {
const typeList = _.map(data.content, type => {
return {
text: type.case_type,
value: type.id,
}
});
return state.set('typeList', typeList)
},
[`${types.CLEAR_MY_TASK_SEARCH}_SUCCESS`]: (state, data, params) => {
let result = data.content;
result.map((item, index) => {
item.key = item.caseNo;
})
return state
.set('loading', false)
.set('pager', getNewPager(data.pager, state.pager))
.set('caseList', result)
.set('keyword_value', '')
.set('caseNo', '')
.set('taskType', '')
.set('sortType', '')
.set('create_time', '')
.set('isDesc', 0)
},
[`${types.UPDATE_MY_TASK_STATE_VALUE}`]: (state, data, params) => {
return state
.set('keyword_value', params.state_value.keyword_value !== undefined ? params.state_value.keyword_value : state.keyword_value)
.set('caseNo', params.state_value.caseNo !== undefined ? params.state_value.caseNo : state.caseNo)
.set('taskType', params.state_value.taskType !== undefined ? params.state_value.taskType : state.taskType)
.set('sortType', params.state_value.sortType !== undefined ? params.state_value.sortType : state.sortType)
.set('create_time', params.state_value.create_time !== undefined ? params.state_value.create_time : state.create_time)
.set('isDesc', params.state_value.isDesc !== undefined ? params.state_value.isDesc : state.isDesc)
}
})
\ No newline at end of file
import { Record, Map } from 'immutable';
import { PAGER } from '../../../constants/ProjectConf';
/**
* immutable 确定操作的对象是不可变的,更好的维护性能
* 具体说明在 `immutable.md` 文件中
*/
const InitState = Record({
caseList : [],
typeList : [],
loading : false,
focus : false,
no_focus : false,
rootKey : '',
keyword_value : '',
caseNo : '',
taskType : '',
sortType : '',
create_time : '',
status : 1,
isDesc : 0,
taskMatch: 2,
pager: PAGER
})
export default InitState
\ No newline at end of file
import api from '../../../api';
import {getCookie} from '../../../util';
import types from '../../types';
import reqwest from 'reqwest';
import AG_CONF from '../../../constants/AgCode';
import OPERATOR_INFO from '../../../constants/OperatorInfo';
/**
* 判断 `cookis` 中是否有 `uid` 没有触发没有发现 `uid` 的 `Action`
*
* 如果有 `uid` 通过 `uid` 向服务端获取用户信息
*
*/
export function fetchProfile() {
let uid = getCookie('uid');
if (uid === undefined) {
return { type: types.UID_NOT_FOUND };
}
return {
type: types.FETCH_PROFILE,
payload: {
// promise: api.post('my')
user: 'admin'
}
}
}
/**
* 登录
*
* 通过 `用户账号/密码` 获取用户信息
*/
export function login(user, password) {
return {
type: types.LOGIN,
// payload: {
// promise: api.put('/login', {
// data: {
// user: user,
// password: password
// }
// })
// }
payload: {
user: 'admin'
}
}
}
/**
* 退出功能:
*
* 如果是服务端维护退出状态则发送退出请求
* 如果是在本地维护登录状态,则清空本地 `cookis` 与 `state` 中缓存的用户信息
*
*/
export function logout() {
return {
type: types.LOGOUT,
payload: {
promise: api.post('logout')
}
}
}
import _ from 'lodash';
import { message } from 'antd';
import { createReducer } from '../../../util';
import types from '../../types';
import InitState from './user_state';
export default createReducer(new InitState, {
[`${types.LOGIN}_PENDING`]: (state, data) => {
return state.set('loggingIn', true)
},
[`${types.LOGIN}_ERROR`]: (state, data) => {
return state.set('loggingIn', false)
.set('user', null)
.set('loginErrors', data.message)
},
[`${types.LOGIN}_SUCCESS`]: (state, data) => {
return state.set('loggingIn', true)
.set('user', data.conten.user)
.set('loginErrors', null)
},
[`${types.LOGOUT}_SUCCESS`]: (state, data) => {
return state.set('loggingOut', true)
.set('user', null)
.set('loginErrors', null)
},
[`${types.FETCH_PROFILE}_SUCCESS`]: (state, data) => {
return state.set('loggingIn', false)
.set('user', data.conten.user)
.set('loginErrors', null)
},
})
\ No newline at end of file
import { Record, Map } from 'immutable';
/**
* immutable 确定操作的对象是不可变的,更好的维护性能
* 具体说明在 `immutable.md` 文件中
*/
const InitState = Record({
user: null,
loggingIn: false,
loggingOut: false,
loginErrors: null
})
export default InitState
import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';
import user from './modules/user/user_reducer';
import menu from './modules/menu/menu_reducer';
import myCase from './modules/myCase/my_case_reducer';
import myTask from './modules/myTask/my_task_reducer';
import myFocus from './modules/myFocus/my_focus_reducer';
import addCase from './modules/addCase/add_case_reducer';
import caseManage from './modules/caseManage/case_manage_reducer';
import caseGroup from './modules/caseGroup/case_group_reducer';
import caseDetail from './modules/caseDetail/case_detail_reducer';
import caseRank from './modules/caseRank/case_rank_reducer';
/**
* combineReducers(reducers)
*
* desc:
* combineReducers 辅助函数的作用是,把一个由多个不同 reducer 函数作为 value 的 object,合并成一个最终的 reducer 函数,然后就可以对这个 reducer 调用 createStore。
* 合并后的 reducer 可以调用各个子 reducer,并把它们的结果合并成一个 state 对象。state 对象的结构由传入的多个 reducer 的 key 决定。
*
* 最终,state 对象的结构会是这样的:
*
* {
* reducer1: ...
* reducer2: ...
* }
*
* 自定义 `State` 树名称:
* 通过为传入对象的 reducer 命名不同来控制 state key 的命名。例如,你可以调用 combineReducers({ todos: myTodosReducer, counter: myCounterReducer }) 将 state 结构变为 { todos, counter }。
* 通常的做法是命名 reducer,然后 state 再去分割那些信息,因此你可以使用 ES6 的简写方法:combineReducers({ counter, todos })。这与 combineReducers({ counter: counter, todos: todos }) 一样。
*
* 参数:
* reducers (Object): 一个对象,它的值(value) 对应不同的 reducer 函数,这些 reducer 函数后面会被合并成一个。下面会介绍传入 reducer 函数需要满足的规则。
*
* 返回值:
* (Function):一个调用 reducers 对象里所有 reducer 的 reducer,并且构造一个与 reducers 对象结构相同的 state 对象。
*
* 注意,每个传入 combineReducers 的 reducer 都需满足以下规则:
* 1、所有未匹配到的 action,必须把它接收到的第一个参数也就是那个 state 原封不动返回。(在 `switch` 最后 `return state`)
* 2、永远不能返回 undefined。当过早 return 时非常容易犯这个错误,为了避免错误扩散,遇到这种情况时 combineReducers 会抛异常。
* 3、如果传入的 state 就是 undefined,一定要返回对应 reducer 的初始 state。根据上一条规则,初始 state 禁止使用 undefined。
* 使用 ES6 的默认参数值语法来设置初始 state 很容易,但你也可以手动检查第一个参数是否为 undefined。(`state = initState`,当 `state` 为 `undefined` 时会赋默认值 `initState`)
*
*/
export default combineReducers({
user,
menu,
caseManage,
caseGroup,
caseDetail,
caseRank,
myCase,
myTask,
addCase,
myFocus,
routing: routerReducer
});
import keyMirror from 'key-mirror'
/**
* key-mirror:
* keyMirror() 创建的对象,值会与名字一致,编码起来更方便
*/
export default keyMirror({
// Add Case
SUBMIT_CASE : null,
GET_CASE_TYPE : null,
GET_EXEC_LIST_BY_KEYWORD : null,
GET_EXEC_COLLECTION_LIST : null,
GET_FOCUS_LIST_BY_KEYWORD : null,
GET_FOCUS_COLLECTION_LIST : null,
UPD_DEFAULT_FILE_LIST : null,
GET_ADD_ROOT_ORGS : null,
GET_ADD_ORGS_BY_ID : null,
UPD_ADD_ORG_VALUE : null,
SET_STATE : null,
SUBMIT_UPDATE_CASE : null,
UPDATE_ADD_CASE_STATE_VALUE : null,
EXEC_STAR : null,
FOCUS_STAR : null,
ORG_STAR : null,
GET_ADD_COLLECTION_ORGS : null,
GET__ORGS_LIST_BY_KEYWORD : null,
// Case Manage
GET_CASE_MANAGE : null,
GET_CASE_MANAGE_LIST : null,
UPDATE_CASE_MANAGE_ROOT_KEY : null,
GET_CASE_MANAGE_SCREENING_TYPE : null,
UPDATE_CASE_MANAGE_SHOW_SEARCH : null,
CLEAR_CASE_MANAGE_SEARCH : null,
UPDATE_CASE_MANAGE_SOURCE_USER : null,
UPDATE_CASE_MANAGE_STATE_VALUE : null,
// Case RANK
GET_CASE_RANK : null,
GET_CASE_RANK_LIST : null,
UPDATE_CASE_RANK_ROOT_KEY : null,
GET_CASE_RANK_SCREENING_TYPE : null,
UPDATE_CASE_RANK_SHOW_SEARCH : null,
CLEAR_CASE_RANK_SEARCH : null,
UPDATE_CASE_RANK_SOURCE_USER : null,
UPDATE_CASE_RANK_STATE_VALUE : null,
GET_RANKUSER_LIST_BY_KEYWORD : null,
// Case Group
GET_CASE_GROUP : null,
GET_CASE_GROUP_LIST : null,
UPDATE_CASE_GROUP_STATE : null, // TODO 该功能还未想好
GET_ROOT_ORGS : null,
GET_ORGS_BY_ID : null,
UPD_ORG_VALUE : null,
GET_GROUP_STATISTICS : null,
UPDATE_CASE_GROUP_ROOT_KEY : null,
GET_CASE_GROUP_SCREENING_TYPE : null,
UPDATE_CASE_GROUP_SHOW_SEARCH : null,
CLEAR_CASE_GROUP_SEARCH : null,
// My Case
GET_MY_CASE : null,
GET_MY_CASE_LIST : null,
UPDATE_STATUS_CLOSE : null,
UPDATE_STATUS_CONFIRM_FINISH : null,
UPDATE_MY_CASE_ROOT_KEY : null,
GET_MY_CASE_SCREENING_TYPE : null,
UPDATE_MY_CASE_STATE_VALUE : null,
CLEAR_MY_CASE_SEARCH : null,
// My Task
GET_MY_TASK : null,
GET_MY_TASK_LIST : null,
UPDATE_STATUS_FINISH : null,
UPDATE_MY_TASK_ROOT_KEY : null,
GET_MY_TASK_SCREENING_TYPE : null,
UPDATE_MY_TASK_STATE_VALUE : null,
CLEAR_MY_TASK_SEARCH : null,
// My Focus
GET_MY_FOCUS : null,
GET_MY_FOCUS_LIST : null,
UPDATE_MY_FOCUS_ROOT_KEY : null,
GET_MY_FOCUS_SCREENING_TYPE : null,
UPDATE_MY_FOCUS_STATE_VALUE : null,
CLEAR_MY_FOCUS_SEARCH : null,
// Menu
UPDATE_NAVPATH : null,
GET_TOP_MENU : null,
GET_LEFT_MENU : null,
GET_MANAGE_LEFT_MENU : null,
UPDATE_COLLAPSE : null,
UPDATE_STATUS : null,
INIT_MENU : null,
GET_ADD_CASE_LEFT_MENU : null,
// User
UID_NOT_FOUND : null,
FETCH_PROFILE : null,
LOGIN : null,
LOGOUT : null,
// Case Detail
GET_CASE_INFO : null,
UPDATE_LOAD : null,
ADD_COMMENT : null,
UPDATE_MODEL_VISIBLE : null,
UPDATE_CASE_DETAIL_VISIBLE : null,
UPDATE_EXEC : null,
GET_DETAIL_ORGS_BY_ID : null,
GET_DETAIL_ROOT_ORGS : null,
UPD_DETAIL_ORG_VALUE : null,
UPDATE_CREATE_USER : null,
UPDATE_FOCUS : null
})
let Promise = window.Promise;
if (!Promise) {
Promise = function (executor) {
executor(this.resolve.bind(this), this.reject.bind(this));
this._thens = [];
};
Promise.prototype = {
then: function (onResolve, onReject, onProgress) {
this._thens.push({resolve: onResolve, reject: onReject, progress: onProgress});
},
'catch': function (onReject) {
this._thens.push({reject: onReject});
},
resolve: function (value) {
this._complete('resolve', value);
},
reject: function (reason) {
this._complete('reject', reason);
},
progress: function (status) {
let i = 0;
let aThen;
while (aThen = this._thens[i++]) {
aThen.progress && aThen.progress(status);
}
},
_complete: function (which, arg) {
this.then = which === 'resolve' ?
function (resolve) { resolve && resolve(arg); } :
function (resolve, reject) { reject && reject(arg); };
this.resolve = this.reject = this.progress =
function () { throw new Error('Promise already completed.'); };
let aThen;
let i = 0;
while (aThen = this._thens[i++]) {
aThen[which] && aThen[which](arg);
}
delete this._thens;
}
};
}
export default Promise;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment