Commit 55cc492a authored by superman's avatar superman

update

parent 9b2c994c
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
\ No newline at end of file
This diff is collapsed.
......@@ -74,5 +74,6 @@ module.exports = {
})
},100);
},
'/api/*':'http://react.yanky.cn/', //'http://192.168.1.126:8080/'
// '/api/*': 'http://react.yanky.cn/',
'/api/*': 'http://192.168.1.126:8080/'
};
......@@ -25,27 +25,46 @@ export default class HuikuanInfoForm extends Component {
super(props, context);
}
static propsType = {};
static propsType = {
product: PropTypes.object
};
handleSubmit(e){
e.preventDefault();
const data = this.props.form.getFieldsValue();
const {product} = this.props;
data.id = product.id;
console.log('收到表单值:', data);
this.props.dispatch({
type:'UPDATE_PRODUCT_ITEM',
item: data
});
}
render() {
const formItemLayout = {
labelCol: {span: 4},
wrapperCol: {span: 14},
};
const {form:{getFieldProps}} = this.props;
const {form:{getFieldProps}, product:{fundRaisedAccount}} = this.props;
return (
<Form horizontal>
<Form horizontal onSubmit={this.handleSubmit.bind(this)}>
<Form.Item label="名称" {...formItemLayout} wrapperCol={{span:6}}>
<Input placeholder="" {...getFieldProps('hkzhnc')} />
<Input placeholder="" {...getFieldProps('fundRaisedAccount.name', {initialValue: fundRaisedAccount.name})} />
</Form.Item>
<Form.Item label="银行帐号" {...formItemLayout} wrapperCol={{span:6}}>
<Input placeholder="" {...getFieldProps('yhzh')} />
<Input placeholder="" {...getFieldProps('fundRaisedAccount.number',{initialValue:fundRaisedAccount.number})} />
</Form.Item>
<Form.Item label="开户行" {...formItemLayout}>
<Input placeholder="" {...getFieldProps('khh')} />
<Input placeholder="" {...getFieldProps('fundRaisedAccount.bank',{initialValue:fundRaisedAccount.bank})} />
</Form.Item>
<Form.Item label="打款须知" {...formItemLayout}>
<Input type="textarea" rows={10} placeholder="" {...getFieldProps('dkxz')} />
<Input type="textarea" rows={10} placeholder="" {...getFieldProps('fundRaisedAccount.memo',{initialValue:fundRaisedAccount.memo})} />
</Form.Item>
<Form.Item wrapperCol={{offset: 4, span:10}} style={{marginTop:30}}>
<Button type="primary" htmlType="submit"><Icon type="save"/>保存</Button>
</Form.Item>
</Form>
);
......
import React, {Component, PropTypes} from 'react';
import {
Row,
Col,
Form,
Input,
Button,
Checkbox,
Select,
message,
Tabs,
Cascader,
Radio,
Upload,
Icon,
Modal,
DatePicker,
Table
} from 'antd';
export default class NextPrve extends Component {
constructor(props, context) {
super(props, context);
}
render(){
function handleStep (s){
this.props.handleStep(s);
}
return (
<div style={{textAlign:'center', borderTop:'1px solid #eee', height:60, paddingTop:20 }}>
{
this.state.step > 1 &&
<Button loading={this.props.loading}
style={{margin:'0 1em'}}
onClick={handleStep.bind(this, -1)}><Icon type="save"/>上一步</Button>
}
{
this.state.step < tabs.length &&
<Button type="primary" loading={this.props.loading}
style={{margin:'0 1em'}}
onClick={handleStep.bind(this, 1)}><Icon type="save"/>下一步</Button>
}
{
this.state.step == tabs.length &&
<Button type="primary" loading={this.props.loading}
><Icon type="solution"/>发布</Button>
}
</div>
);
}
}
import React, {Component, PropTypes} from 'react';
import {
Row,
Col,
Form,
Input,
Button,
Checkbox,
Select,
message,
Tabs,
Cascader,
Radio,
Upload,
Icon,
Modal,
DatePicker,
Table
} from 'antd';
import {UUID} from '../../utils';
export function BaseElementTransform(objs) {
return Object.keys(objs).map(key=>({
key: UUID(),
title: key,
content: objs[key]
}));
}
export function CreateBaseElement() {
return {key: UUID()};
}
export default class ProductBaseElement extends Component {
constructor(props, context) {
super(props, context);
}
static propsType = {
title: PropTypes.string,
content: PropTypes.string,
remove: PropTypes.func
};
render() {
return (
<Input.Group>
<Col span="6">
<Input placeholder="标题" defaultValue={this.props.title}/>
</Col>
<Col span="10">
<Input type="textarea" style={{height:28}} placeholder="内容" defaultValue={this.props.content}/>
</Col>
<Col span="4">
<Icon type="cross" onClick={this.props.remove}/>
</Col>
</Input.Group>
);
}
}
import React, {Component, PropTypes} from 'react';
import {
Row,
Col,
Form,
Input,
Button,
Checkbox,
Select,
message,
Tabs,
Cascader,
Radio,
Upload,
Icon,
Modal,
DatePicker,
Table
} from 'antd';
import {arrayRemoveIndex, UUID} from '../../utils';
export function CreateBaseElement() {
return {key: UUID()};
}
export function BaseElementTransform(arr) {
return Object.keys(objs).map(key=>({
key: UUID(),
name: key,
mobile: objs[key]
}));
}
@Form.create()
export default class ProductContactForm extends Component {
constructor(props, context) {
super(props, context);
this.state = {
staffs: props.product.staffs.map(staffs=> {
staffs.key = UUID();
return staffs;
})
};
}
static propsType = {
product: PropTypes.object,
};
/**
* 删除基本要素
* @param index
* @param e
*/
handleRemove(index, e) {
e.preventDefault();
const staffs = arrayRemoveIndex(this.state.staffs, index);
this.setState({staffs: staffs});
}
/**
* 添加基本要素
* @param e
*/
handleAdd(e) {
e.preventDefault();
let staffs = [].concat(this.state.staffs);
staffs.push({key: UUID()});
this.setState({staffs});
}
handleSubmit(e) {
e.preventDefault();
const formData = this.props.form.getFieldsValue();
const tmp = Object.keys(formData).map(index=> {
return {
...formData[index]
}
}).filter(item=>item.name && item.mobile);
const data = {
id: this.props.product.id,
staffs: JSON.stringify(tmp)
}
console.log('收到表单值:', data);
this.props.dispatch({
type: 'UPDATE_PRODUCT_ITEM',
item: data
});
}
render() {
const {form:{getFieldProps}} = this.props;
return (
<Form horizontal onSubmit={this.handleSubmit.bind(this)}>
<Form.Item>
{
this.state.staffs.map((item, index)=>
<div key={item.key} style={{marginBottom:8}}>
<Input.Group>
<Col span="6">
<Input placeholder="姓名"
{...getFieldProps(index + '.name', {
initialValue: item.name
})} />
</Col>
<Col span="10">
<Input placeholder="电话"
{...getFieldProps(index + '.mobile', {
initialValue: item.mobile
})}/>
</Col>
<Col span="4">
<Icon type="cross" onClick={this.handleRemove.bind(this, index)}/>
</Col>
</Input.Group>
</div>
)
}
</Form.Item>
<Form.Item wrapperCol={{offset: 4, span:10}} style={{marginTop:30}}>
<Button onClick={this.handleAdd.bind(this)} style={{marginRight:'1em'}}><Icon
type="plus"/>添加</Button>
<Button type="primary" htmlType="submit"><Icon type="save"/>保存</Button>
</Form.Item>
</Form>
);
}
}
import React, {Component, PropTypes} from 'react';
import {
Row,
Col,
Form,
Input,
Button,
Checkbox,
Select,
message,
Tabs,
Cascader,
Radio,
Upload,
Icon,
Modal,
DatePicker,
Table
} from 'antd';
import {PRODUCT_STATUS, formatDateTime} from '../../utils';
const ProductStatus = Object.keys(PRODUCT_STATUS);
@Form.create()
export default class ProductDateTimeForm extends Component {
constructor(props, context) {
super(props, context);
}
handleSubmit(e) {
e.preventDefault();
const formData = this.props.form.getFieldsValue();
const data = {
id: this.props.product.id
};
if (formData.fundReservationStartTime) {
data.fundReservationStartTime = formatDateTime(formData.fundReservationStartTime);
}
if (formData.fundRaisedStartTime[0]) {
data.fundRaisedStartTime = formatDateTime(formData.fundRaisedStartTime[0]);
}
if (formData.fundRaisedStartTime[1]) {
data.fundRaisedEndTime = formatDateTime(formData.fundRaisedStartTime[0])
}
if (formData.remittanceEndTime) {
data.remittanceEndTime = formatDateTime(formData.remittanceEndTime);
}
if (formData.fundEstablishedTime[0]) {
data.fundEstablishedTime = formatDateTime(formData.fundEstablishedTime[0]);
}
if (formData.fundEstablishedTime[1]) {
data.fundExpireTime = formatDateTime(formData.fundEstablishedTime[1]);
}
data.status = formData.status;
console.log(data);
this.props.dispatch({
type: 'UPDATE_PRODUCT_ITEM',
item: data
});
}
render() {
const formItemLayout = {
labelCol: {span: 4},
wrapperCol: {span: 14},
};
const {cates, product, form:{getFieldProps}, isCreate} = this.props;
const {
fundReservationStartTime,
fundRaisedEndTime,
remittanceEndTime,
fundEstablishedTime,
fundExpireTime
} = product;
return (
<Form horizontal onSubmit={this.handleSubmit.bind(this)}>
{
!isCreate &&
<Form.Item label="商品状态" {...formItemLayout} wrapperCol={{span:20}}>
<Radio.Group {...getFieldProps('status', {initialValue: product.status + ''})}>
{
ProductStatus.map((status, index)=>
<Radio.Button key={status} data-value={status}
value={status}>{PRODUCT_STATUS[status]}</Radio.Button>
)
}
</Radio.Group>
</Form.Item>
}
<Form.Item label="预约开始时间" {...formItemLayout}>
<DatePicker showTime format="yyyy-MM-dd HH:mm:ss" placeholder="请选择预约开始时间"
{...getFieldProps('fundReservationStartTime', {
initialValue: fundReservationStartTime ? formatDateTime(fundReservationStartTime) : ''
})}
/>
</Form.Item>
<Form.Item label="募集开始与结束时间" {...formItemLayout}>
<DatePicker.RangePicker showTime format="yyyy-MM-dd HH:mm:ss"
{...getFieldProps('fundRaisedStartTime', {
initialValue: [
fundReservationStartTime ? formatDateTime(fundReservationStartTime) : '',
fundRaisedEndTime ? formatDateTime(fundRaisedEndTime) : ''
]
})}
/>
</Form.Item>
<Form.Item label="汇款结束时间" {...formItemLayout}>
<DatePicker showTime format="yyyy-MM-dd HH:mm:ss" placeholder="请选择汇款结束时间"
{...getFieldProps('remittanceEndTime', {
initialValue: remittanceEndTime ? formatDateTime(remittanceEndTime) : ''
})}
/>
</Form.Item>
<Form.Item label="基金成立与到期时间" {...formItemLayout}>
<DatePicker.RangePicker showTime format="yyyy-MM-dd HH:mm:ss"
{...getFieldProps('fundEstablishedTime', {
initialValue: [
fundEstablishedTime ? formatDateTime(fundEstablishedTime) : '',
fundExpireTime ? formatDateTime(fundExpireTime) : ''
]
})}
/>
</Form.Item>
<Form.Item wrapperCol={{offset: 4, span:10}} style={{marginTop:30}}>
<Button type="primary" htmlType="submit"><Icon type="save"/>保存</Button>
</Form.Item>
</Form>
);
}
}
import React, {Component, PropTypes} from 'react';
import {
Row,
Col,
Form,
Input,
Button,
Checkbox,
Select,
message,
Tabs,
Cascader,
Radio,
Upload,
Icon,
Modal,
DatePicker,
Table
} from 'antd';
import {UUID} from '../../utils';
@Form.create()
export default class ProductDocumentsForm extends Component {
constructor(props, context) {
super(props, context);
this.state = {
fileList: props.product.documents.map(file=> {
file.uid = UUID();
file.url = file.file;
file.status = 'done';
return file;
})
};
}
static propsType = {
product: PropTypes.object,
};
handleUpload(info) {
let fileList = info.fileList;
// 3. 按照服务器返回信息筛选成功上传的文件
fileList = fileList.filter((file) => {
if (file.response) {
return file.response.status === 1;
}
return true;
});
// 2. 读取远程路径并显示链接
fileList = fileList.map((file) => {
if (file.response) {
// 组件会将 file.url 作为链接进行展示
//file.url = file.response.url;
const {result, status, message} = file.response;
if (status === 1 && result && result.length >= 1 && result[0].url) {
file.url = result[0].url;
}
}
return file;
});
this.setState({fileList});
}
handleSubmit(e){
e.preventDefault();
const files = [];
this.state.fileList.forEach(file=>{
files.push({
name: file.name,
file: file.url
});
});
const data = {
id: this.props.product.id,
documents: JSON.stringify(files)
};
console.log(data);
this.props.dispatch({
type: 'UPDATE_PRODUCT_ITEM',
item: data
});
}
render() {
const {user, product} = this.props;
return (
<Form horizontal onSubmit={this.handleSubmit.bind(this)} style={{maxWidth:'800px', margin:'auto'}}>
<Form.Item>
<Upload.Dragger action="/api/fileUpload/upload"
multiple={true}
headers={{
authorization: user && user.token,
}}
onChange={this.handleUpload.bind(this)}
fileList={this.state.fileList}>
<p className="ant-upload-drag-icon">
<Icon type="inbox"/>
</p>
<p className="ant-upload-text">点击或将文件拖拽到此区域上传</p>
<p className="ant-upload-hint">支持单个或批量上传,严禁上传公司内部资料及其他违禁文件</p>
</Upload.Dragger>
</Form.Item>
<Form.Item style={{marginTop:30, textAlign:'center'}}>
<Button type="primary" htmlType="submit"><Icon type="save"/>保存</Button>
</Form.Item>
</Form>
);
}
}
import React, {Component, PropTypes} from 'react';
import {
Row,
Col,
Form,
Input,
Button,
Checkbox,
Select,
message,
Tabs,
Cascader,
Radio,
Upload,
Icon,
Modal,
DatePicker,
Table
} from 'antd';
import {arrayRemoveIndex, UUID} from '../../utils';
export function CreateBaseElement() {
return {key: UUID()};
}
export function BaseElementTransform(objs) {
return Object.keys(objs).map(key=>({
key: UUID(),
title: key,
content: objs[key]
}));
}
@Form.create()
export default class HuikuanInfoForm extends Component {
constructor(props, context) {
super(props, context);
this.state = {
elements: BaseElementTransform(props.product.elements)
};
}
static propsType = {
product: PropTypes.object,
};
/**
* 删除基本要素
* @param index
* @param e
*/
handleRemoveElement(index, e) {
e.preventDefault();
const elements = arrayRemoveIndex(this.state.elements, index);
this.setState({elements: elements});
}
/**
* 添加基本要素
* @param e
*/
handleAddElement(e) {
e.preventDefault();
let elements = [].concat(this.state.elements);
elements.push(CreateBaseElement());
this.setState({elements: elements});
}
handleSubmit(e) {
e.preventDefault();
const formData = this.props.form.getFieldsValue();
const tmp = {};
Object.keys(formData).map(index=> {
if (formData[index].title != 'undefined') {
tmp[formData[index].title] = formData[index].content;
}
});
const data = {
id: this.props.product.id,
elements: JSON.stringify(tmp)
}
console.log('收到表单值:', data);
this.props.dispatch({
type: 'UPDATE_PRODUCT_ITEM',
item: data
});
}
render() {
const {form:{getFieldProps}} = this.props;
return (
<Form horizontal onSubmit={this.handleSubmit.bind(this)}>
<Form.Item>
<h3>可以设置以下要素,或者自定义其他要素</h3>
<p>总规模、投资亮点、托管方、结算方式、资金用途、融资方、担保主体、风控措施、还款来源、发行方、认购起点、大小额配比</p>
</Form.Item>
<Form.Item>
{
this.state.elements.map((item, index)=>
<div key={item.key} style={{marginBottom:8}}>
<Input.Group>
<Col span="6">
<Input
placeholder="标题" {...getFieldProps(index + '.title', {initialValue: item.title})} />
</Col>
<Col span="10">
<Input type="textarea" placeholder="内容" autosize
{...getFieldProps(index + '.content', {initialValue: item.content})}/>
</Col>
<Col span="4">
<Icon type="cross" onClick={this.handleRemoveElement.bind(this, index)}/>
</Col>
</Input.Group>
</div>
)
}
</Form.Item>
<Form.Item wrapperCol={{offset: 4, span:10}} style={{marginTop:30}}>
<Button onClick={this.handleAddElement.bind(this)} style={{marginRight:'1em'}}><Icon
type="plus"/>添加</Button>
<Button type="primary" htmlType="submit"><Icon type="save"/>保存</Button>
</Form.Item>
</Form>
);
}
}
......@@ -19,30 +19,40 @@ import {
Table
} from 'antd';
import YongjingSuanFaItem, {
YongjingTransform,
CreateYongjing
} from '../YongjingSuanFaItem/YongjingSuanFaItem';
import {arrayRemoveIndex} from '../../utils';
import {arrayRemoveIndex, formatMoney} from '../../utils';
import {UUID} from '../../utils';
export function YongjingTransform(arr) {
return arr.map(item=>({
...item,
key: UUID()
}));
}
export function CreateYongjing() {
return {key: UUID(), result: {}};
};
@Form.create()
export default class ShouyiYongjingForm extends Component {
static propsType = {
product: PropTypes.object,
user: PropTypes.object,
dispatch: PropTypes.func
};
constructor(props, context) {
super(props, context);
this.state = {
yongjing: YongjingTransform(props.yongjing)
}
yongjing: YongjingTransform(props.product.commissionAlg)
};
}
static propsType = {
product: PropTypes.object,
user: PropTypes.object,
dispatch: PropTypes.func
};
/**
* 添加佣金算法
* @param e
......@@ -66,6 +76,32 @@ export default class ShouyiYongjingForm extends Component {
this.setState({yongjing: yongjing});
}
handleSubmit(e){
e.preventDefault();
const formData = this.props.form.getFieldsValue();
const commissionAlg = [];
const data = {
id: this.props.product.id
};
Object.keys(formData).forEach(key=>{
if(/^[\d]+$/g.test(key)){
commissionAlg.push(formData[key]);
}else{
data[key] = formData[key];
}
});
data.commissionAlg = JSON.stringify(commissionAlg);
console.log(data);
this.props.dispatch({
type:'UPDATE_PRODUCT_ITEM',
item: data
});
}
render() {
const formItemLayout = {
labelCol: {span: 4},
......@@ -73,12 +109,19 @@ export default class ShouyiYongjingForm extends Component {
};
const {form:{getFieldProps}} = this.props;
const {form:{getFieldProps}, product} = this.props;
return (
<Form horizontal>
<Form horizontal onSubmit={this.handleSubmit.bind(this)}>
<Form.Item label="佣金结算方式" help="例如: 打款结佣、成立结佣" {...formItemLayout} wrapperCol={{span:6}}>
<Input placeholder="佣金结算方式" {...getFieldProps('settlement', {
initialValue:product.settlement
})} />
</Form.Item>
<Form.Item label="产品的预期收益" {...formItemLayout} wrapperCol={{span:6}}>
<Input placeholder="产品的预期收益" {...getFieldProps('yqsy')} />
<Input placeholder="产品的预期收益" {...getFieldProps('productProspectiveReturn', {
initialValue:product.productProspectiveReturn
})} />
</Form.Item>
<Form.Item label="佣金算法" {...formItemLayout}>
<Input.Group>
......@@ -89,8 +132,25 @@ export default class ShouyiYongjingForm extends Component {
</Input.Group>
{
this.state.yongjing.map((item, index)=>
<YongjingSuanFaItem {...item}
remove={this.handleRemoveYongjin.bind(this, index)}/>
<div key={item.key}>
<Input.Group>
<Col span="5">
<Input {...getFieldProps(index + '.min', {initialValue: item.min})} />
</Col>
<Col span="5">
<Input {...getFieldProps(index+ '.max', {initialValue: item.max})}/>
</Col>
<Col span="5">
<Input {...getFieldProps(index+'.sy', {initialValue: item.sy})}/>
</Col>
<Col span="5">
<Input {...getFieldProps(index+'.yj', {initialValue: item.yj})}/>
</Col>
<Col span="4">
<Icon type="cross" onClick={this.handleRemoveYongjin.bind(this, index)}/>
</Col>
</Input.Group>
</div>
)
}
<Row style={{marginTop:15}}>
......@@ -98,14 +158,16 @@ export default class ShouyiYongjingForm extends Component {
<Button style={{marginRight:'.5em'}}
onClick={this.handleAddYongjing.bind(this)}><Icon
type="plus"/>添加</Button>
<Button type="ghost" style={{marginLeft:'.5em'}}><Icon type="code"/>高级</Button>
</Col>
</Row>
</Form.Item>
<Form.Item label="最高佣金" {...formItemLayout} wrapperCol={{span:6}}>
<Input placeholder="最高佣金" readOnly disabled defaultValue={'jsdcjkdsh'} />
<Form.Item wrapperCol={{offset: 4, span:10}} style={{marginTop:30}}>
<Button type="primary" htmlType="submit"><Icon type="save"/>保存</Button>
</Form.Item>
</Form>
);
}
}
//<Button type="ghost" style={{marginLeft:'.5em'}}><Icon type="code"/>高级</Button>
//<YongjingSuanFaItem {...item} remove={this.handleRemoveYongjin.bind(this, index)}/>
import React, {Component, PropTypes} from 'react';
import {
Row,
Col,
Form,
Input,
Button,
Checkbox,
Select,
message,
Tabs,
Cascader,
Radio,
Upload,
Icon,
Modal,
DatePicker,
Table
} from 'antd';
import {UUID} from '../../utils';
export function YongjingTransform(arr) {
return arr.map(item=>({
...item,
key: UUID()
}));
}
export function CreateYongjing() {
return {key: UUID(), result: {}};
};
export default class YongjingSuanFaItem extends Component {
constructor(props, context) {
super(props, context);
}
static propsType = {
min: PropTypes.string,
max: PropTypes.string,
result: PropTypes.any,
remove: PropTypes.func
}
render() {
const {min, max, result:{sy, yj}} = this.props;
return (
<Input.Group>
<Col span="5">
<Input defaultValue={min}/>
</Col>
<Col span="5">
<Input defaultValue={max}/>
</Col>
<Col span="5">
<Input defaultValue={sy}/>
</Col>
<Col span="5">
<Input defaultValue={yj}/>
</Col>
<Col span="4">
<Icon type="cross" onClick={this.props.remove}/>
</Col>
</Input.Group>
);
}
}
import React, {Component, PropTypes} from 'react';
import {connect} from 'react-redux';
import {
Row,
Col,
Form,
Input,
Button,
Checkbox,
Select,
message,
Tabs,
Cascader,
Radio,
Upload,
Icon,
Modal,
DatePicker,
Table,
} from 'antd';
@connect(state=>({
loading: state.announcement.loading,
}))
@Form.create()
export default class AddItem extends Component{
constructor(props, content) {
super(props, content);
}
handleSubmit(e){
e.preventDefault();
const data = this.props.form.getFieldsValue();
data.itemId = this.props.location.query.itemId;
console.log(data);
this.props.dispatch({
type:'CREATE_ANNOUNCEMENT_ITEM',
data
});
}
render = ()=> {
const {loading, form:{getFieldProps}} = this.props;
const formItemLayout = {
labelCol: {span: 4},
wrapperCol: {span: 14},
};
return(
<Form horizontal onSubmit={this.handleSubmit.bind(this)}>
<Form.Item label="标题" {...formItemLayout}>
<Input placeholder="公告标题" {...getFieldProps('title')} />
</Form.Item>
<Form.Item label="内容" {...formItemLayout}>
<Input placeholder="公告内容" type="textarea" {...getFieldProps('announcement')} />
</Form.Item>
<Form.Item wrapperCol={{offset: 4, span:10}} style={{marginTop:30}}>
<Button type="primary" htmlType="submit" loading={loading}><Icon type="save"/>创建</Button>
</Form.Item>
</Form>
);
}
}
import React, {Component, PropTypes} from 'react';
import {connect} from 'react-redux';
import {
Row,
Col,
Form,
Input,
Button,
Checkbox,
Select,
message,
Tabs,
Cascader,
Radio,
Upload,
Icon,
Modal,
DatePicker,
Table,
} from 'antd';
@connect(state=>({
loading: state.announcement.loading,
announcement: state.announcement.item,
}))
@Form.create()
export default class EditItem extends Component {
constructor() {
super(...arguments);
}
componentWillMount() {
if (!(this.props.announcement && this.props.announcement.id)) {
this.fetchItem(this.props.params.id);
}
};
fetchItem(id) {
this.props.dispatch({
type: 'FETCH_ANNOUNCEMENT_ITEM',
id
});
};
handleSubmit(e) {
e.preventDefault();
const data = this.props.form.getFieldsValue();
console.log(data);
}
render() {
const {announcement, loading, form:{getFieldProps}} = this.props;
const formItemLayout = {
labelCol: {span: 4},
wrapperCol: {span: 14},
};
return (
<Form horizontal onSubmit={this.handleSubmit.bind(this)}>
<Form.Item label="标题" {...formItemLayout}>
<Input placeholder="公告标题" {...getFieldProps('title', {initialValue: announcement.title})} />
</Form.Item>
<Form.Item label="内容" {...formItemLayout}>
<Input placeholder="公告内容" type="textarea" {...getFieldProps('announcement', {initialValue: announcement.announcement})} />
</Form.Item>
<Form.Item wrapperCol={{offset: 4, span:10}} style={{marginTop:30}}>
<Button type="primary" htmlType="submit" loading={loading}><Icon type="save"/>保存</Button>
</Form.Item>
</Form>
);
}
}
import React, {Component, PropTypes} from 'react';
import {connect} from 'react-redux';
import {Table, Icon, Button} from 'antd';
import {serialize, formatDateTime, productStatusToString} from '../../utils';
import {Link} from 'react-router';
const columns = [
{
title: 'ID',
dataIndex: 'id',
key: 'id',
width: 60
}, {
title: '标题',
dataIndex: 'title',
key: 'title',
}, {
title: '创建时间',
dataIndex: 'dateCreated',
key: 'dateCreated',
width: 150,
className: 'tac',
render: (dateCreated, record)=>(
<span>
{dateCreated && formatDateTime(dateCreated)}
</span>
)
}, {
title: '状态',
dataIndex: 'status',
key: 'status',
width: 120,
className: 'tac',
render: (status, record)=>(<span data-status={status}>{status?'有效':'无效'}</span>)
}, {
title: '操作',
key: 'operation',
width: 120,
className: 'tac',
render: (text, record)=>(
<span>
<a href={'/product/item?id='+ record.id}></a>
</span>
)
}
];
@connect(state=>({
items: state.announcement.items,
loading: state.announcement.loading,
total: state.announcement.total,
}))
export default class List extends Component {
constructor(props, context) {
super(props, context);
}
componentWillMount() {
this.fetchList(this.props.location.query);
};
fetchList(query) {
this.props.dispatch({
type: 'FETCH_ANNOUNCEMENT_LIST',
query
});
};
handleRowClick({id}) {
this.props.history.push('/announcement/' + id + '/edit');
}
render() {
const {total, items, loading, history:{replace}, location:{pathname, query}} = this.props;
const pagination = {
total: total,
pageSize: parseInt(query.s, 10) || 10,
current: parseInt(query.p, 10) || 1,
showSizeChanger: true,
onShowSizeChange: (current, pageSize)=> {
console.log('Current: ', current, '; PageSize: ', pageSize);
query.p = current;
query.s = pageSize;
replace(pathname + '?' + serialize(query));
this.fetchList(query);
},
onChange: (current)=> {
console.log('Current: ', current);
query.p = current;
replace(pathname + '?' + serialize(query));
this.fetchList(query);
}
};
return <div>
<h1>公告列表</h1>
<Link to={'/announcement/create?itemId='+ query.itemId}><Button><Icon type="plus"/>添加</Button></Link>
<Table className="ant-table" columns={columns}
dataSource={Array.isArray(items)?items:[]}
loading={loading}
pagination={pagination}
scroll={{ y: window.innerHeight-290 }}
onRowClick={this.handleRowClick.bind(this)}
/>
</div>;
}
}
......@@ -22,7 +22,7 @@
padding: 8px;
width: 20%;
min-width: 200px;
//max-width: 200px;
max-width: 250px;
background: #fafafa;
border-right: 1px solid #ccc;
margin-right: 0px;
......
This diff is collapsed.
This diff is collapsed.
......@@ -78,7 +78,7 @@ export default class Item extends Component {
<p>
<Button onClick={this.handleGoBack.bind(this)}>返回</Button>
<Link to={'/products/'+ item.id+'/edit'}><Button>编辑</Button></Link>
<Link to={'/product/'+ item.id+'/edit'}><Button>公告</Button></Link>
<Link to={'/announcement?itemId='+item.id}><Button>公告</Button></Link>
<Link
to={'/trades/create/'+ item.id+'?title='+ item.itemShortTitle}><Button>报单</Button></Link>
</p>
......
import React, {Component, PropTypes} from 'react';
import {connect} from 'react-redux';
import {Table, Icon} from 'antd';
import {params, formatDateTime, productStatusToString} from '../../utils';
import {serialize, formatDateTime, productStatusToString} from '../../utils';
import {Link} from 'react-router';
......@@ -56,7 +56,7 @@ const columns = [
<span>
<a href={'/product/item?id='+ record.id}>详情</a>
<span className="ant-divider"></span>
<a href="#">公告</a>
<Link to={'/announcement?itemId='+record.id} onClick={e=>e.stopPropagation()}>公告</Link>
<span className="ant-divider"></span>
<Link to={'/trades/add/'+record.id+'?title='+record.shortTitle}>报单</Link>
</span>
......@@ -88,7 +88,7 @@ export default class List extends Component {
};
handleRowClick({id}){
this.props.history.push('/products/'+id);
this.props.history.push('/products/'+id+'/edit');
}
......@@ -106,13 +106,13 @@ export default class List extends Component {
console.log('Current: ', current, '; PageSize: ', pageSize);
query.p = current;
query.s = pageSize;
replace(pathname + '?' + params(query));
replace(pathname + '?' + serialize(query));
this.fetchList(query);
},
onChange: (current)=> {
console.log('Current: ', current);
query.p = current;
replace(pathname + '?' + params(query));
replace(pathname + '?' + serialize(query));
this.fetchList(query);
}
};
......
......@@ -2,8 +2,16 @@
display: flex;
flex-direction: column;
height: 100%;
& > :global(.ant-tabs) {
.tabs {
flex: 1;
overflow: auto;
display: flex;
:global {
.tablist {
}
.ant-tabs-content{
flex: 1;
}
}
}
}
......@@ -2,7 +2,7 @@ import React, {Component, PropTypes} from 'react';
import {connect} from 'react-redux';
import {Table, Icon} from 'antd';
import { Link } from 'react-router';
import {params, formatDateTime, tradeStatusToString} from '../../utils';
import {serialize, formatDateTime, tradeStatusToString} from '../../utils';
const columns = [
......@@ -110,13 +110,13 @@ export default class List extends Component {
console.log('Current: ', current, '; PageSize: ', pageSize);
query.p = current;
query.s = pageSize;
replace(pathname + '?' + params(query));
replace(pathname + '?' + serialize(query));
this.fetchList(query);
},
onChange: (current) => {
console.log('Current: ', current);
query.p = current;
replace(pathname + '?' + params(query));
replace(pathname + '?' + serialize(query));
this.fetchList(query);
}
};
......
import {handleActions} from 'redux-actions';
import {combineReducer} from 'redux';
const announcement = handleActions({
['FETCH_ANNOUNCEMENT_LIST'](state) {
return {...state, loading: true,};
},
['FETCH_ANNOUNCEMENT_LIST_SUCCESS'](state, action) {
return {...state, loading: false, items: action.items, total: action.total};
},
['FETCH_ANNOUNCEMENT_LIST_FAILED'](state, action) {
return {...state, err: action.err, loading: false};
},
['FETCH_ANNOUNCEMENT_ITEM'](state){
return {...state, loading: true}
},
['FETCH_ANNOUNCEMENT_ITEM_SUCCESS'](state, action){
return {...state, loading: false, item: action.item}
},
['FETCH_ANNOUNCEMENT_ITEM_FAILED'](state, action){
return {...state, err: action.err, loading: false}
},
['CREATE_ANNOUNCEMENT_ITEM'](state){
return {...state, loading: true}
},
['CREATE_ANNOUNCEMENT_ITEM_SUCCESS'](state, action){
return {...state, loading: false, item: action.item}
},
['CREATE_ANNOUNCEMENT_ITEM_FAILED'](state, action){
return {...state, err: action.err, loading: false}
},
}, {
items: [],
loading: false,
});
export default announcement;
......@@ -30,16 +30,25 @@ const product = handleActions({
return {...state, err: action.err, loading: false}
},
['UPDATE_PRODUCT_ITEM'](state){
return {...state, loading:true};
return {...state, loading: true};
},
['UPDATE_PRODUCT_ITEM_SUCCESS'](state){
return {...state, loading:false};
return {...state, loading: false};
},
['UPDATE_PRODUCT_ITEM_FAILED'](state, action){
return {...state, loading:false, err: action.err};
return {...state, loading: false, err: action.err};
},
['CREATE_PRODUCT_ITEM'](state){
return {...state, loading: true};
},
['CREATE_PRODUCT_ITEM_SUCCESS'](state, action){
return {...state, item: action.item, loading: false};
},
['CREATE_PRODUCT_FAILED'](state, action){
return {...state, loading: false, err: action.err};
}
}, {
cates:[],
cates: [],
items: [],
loading: false,
});
......
......@@ -13,6 +13,9 @@ import TradeItem from '../containers/Trade/Item';
import Commission from '../containers/Trade/Commission';
import Contract from '../containers/Trade/Contract';
import TradeAddItem from '../containers/Trade/AddItem';
import AnnouncementList from '../containers/Announcement/List';
import AnnouncementEditItem from '../containers/Announcement/EditItem';
import AnnouncementAddItem from '../containers/Announcement/AddItem';
export default (store)=> {
......@@ -29,8 +32,8 @@ export default (store)=> {
<IndexRoute component={Home}/>
<Route path="products" >
<IndexRoute component={ProductList} />
<Route path=":id" component={ProductItem} />
<Route path="create" component={ProductAddItem} />
<Route path=":id" component={ProductItem} />
<Route path=":id/edit" component={ProductEditItem} />
</Route>
<Route path="trades" >
......@@ -40,6 +43,11 @@ export default (store)=> {
<Route path="contract/:id" component={Contract} />
<Route path="create/:pid" component={TradeAddItem} />
</Route>
<Route path="announcement">
<IndexRoute component={AnnouncementList} />
<Route path="create" component={AnnouncementAddItem} />
<Route path=":id/edit" component={AnnouncementEditItem} />
</Route>
<Route path="/actived" component={Home}/>
<Route path="/completed" component={Home}/>
</Route>
......@@ -48,3 +56,5 @@ export default (store)=> {
</Route>
);
};
//
import {takeLatest} from 'redux-saga';
import {take, call, put, fork, cancel, select} from 'redux-saga/effects';
import {fetchList, fetchItem, createItem} from '../services/announcement';
import {message} from 'antd';
function* getList(query) {
try {
const {total, announcements} = yield call(fetchList, query);
yield put({
type: 'FETCH_ANNOUNCEMENT_LIST_SUCCESS',
total,
items: announcements
});
} catch (err) {
console.log(err);
message.error(err);
yield put({
type: 'FETCH_ANNOUNCEMENT_LIST_FAILED',
err,
});
}
}
function* watchList() {
while (true) {
const {query} = yield take('FETCH_ANNOUNCEMENT_LIST');
yield fork(getList, query);
}
}
function* getItem(id) {
try {
const item = yield call(fetchItem, id);
yield put({
type: 'FETCH_ANNOUNCEMENT_ITEM_SUCCESS',
item
});
} catch (err) {
console.log(err);
message.error(err);
yield put({
type: 'FETCH_ANNOUNCEMENT_ITEM_FAILED',
err
});
}
}
function* watchItem() {
while (true) {
const {id} = yield take('FETCH_ANNOUNCEMENT_ITEM');
yield fork(getItem, id);
}
}
function* addItem(data) {
try{
const item = yield call(createItem, data);
yield put({
type: 'CREATE_ANNOUNCEMENT_ITEM_SUCCESS',
item
});
}catch(err){
console.log(err);
message.error(err);
yield put({
type:'CREATE_ANNOUNCEMENT_ITEM_FAILED',
err
});
}
}
function* watchAdd() {
while (true) {
const {data} = yield take('CREATE_ANNOUNCEMENT_ITEM');
yield fork(addItem, data);
}
}
export default function*() {
yield fork(watchList);
yield fork(watchItem);
yield fork(watchAdd);
}
import {takeLatest} from 'redux-saga';
import {take, call, put, fork, cancel, select} from 'redux-saga/effects';
import {fetchList, fetchCates, fetchItem, updateItem} from '../services/product';
import {fetchList, fetchCates, fetchItem, updateItem, createItem} from '../services/product';
import {message} from 'antd';
function* getList(query) {
......@@ -77,6 +77,7 @@ function* watchProductItem() {
function* editItem(item) {
try{
yield call(updateItem, item);
message.success('保存成功!');
yield put({
type: 'UPDATE_PRODUCT_ITEM_SUCCESS',
});
......@@ -97,10 +98,32 @@ function* watchEditProductItem(){
}
}
function* addItem() {
try{
const item = yield call(createItem);
yield put({
type: 'CREATE_PRODUCT_ITEM_SUCCESS',
item
});
}catch(err){
console.log(err);
message.error(err);
yield put({
type:'CREATE_PRODUCT_ITEM_FAILED',
err
});
}
}
function* watchAddItem() {
yield takeLatest('CREATE_PRODUCT_ITEM', addItem);
}
export default function*() {
yield fork(watchProductList);
yield fork(watchProductCates);
yield fork(watchProductItem);
yield fork(watchEditProductItem);
yield fork(watchAddItem);
}
import xFetch from './xFetch';
import {serialize} from '../utils';
export async function fetchList(query) {
return xFetch('/api/announcement' + '?' + serialize(query));
}
export async function fetchItem(id) {
return xFetch('/api/announcements/' + id);
}
export async function createItem(item) {
return xFetch('/api/announcement/save', {
method: 'POST',
body: serialize(item)
});
}
......@@ -16,15 +16,13 @@ export async function fetchItem(id) {
}
export async function updateItem(item){
let form = new FormData();
Object.keys(item).map((key)=>{
form.append(key, item[key]);
});
//return xFetch('/api/products/create');
return xFetch('/api/products/'+ item.id, {
method:'PUT',
body: serialize(item)
});
}
export async function createItem() {
return xFetch('/api/products/create');
}
import xFetch from './xFetch';
import {serialize} from '../utils';
export async function fetch(username, password) {
let form = new FormData();
form.append('username', username);
form.append('password', password);
// let form = new FormData();
// form.append('username', username);
// form.append('password', password);
return xFetch('/api/authenticate', {
method: 'POST',
body: form
body: serialize({username, password})
});
}
......
......@@ -12,6 +12,7 @@ function check401(res) {
function check404(res) {
if (res.status === 404) {
// location.href='/404';
return Promise.reject(errorMessages(res));
}
return res;
......
......@@ -5,12 +5,14 @@
export function serialize(obj, prefix) {
var str = [];
for(var p in obj) {
for (var p in obj) {
if (obj.hasOwnProperty(p)) {
var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
str.push(typeof v == "object" ?
serialize(v, k) :
encodeURIComponent(k) + "=" + encodeURIComponent(v));
var k = prefix ? prefix + "." + p : p, v = obj[p];
if (typeof v !== 'undefined') {
str.push(typeof v == "object" ?
serialize(v, k) :
encodeURIComponent(k) + "=" + encodeURIComponent(v));
}
}
}
return str.join("&");
......@@ -37,23 +39,23 @@ export const formatDateTime = (time = 0, format = 'YYYY-MM-DD hh:mm:ss') => {
};
export const PRODUCT_STATUS = {
'-9':'草稿',
0:'已删除',
1:'未发布',
5:'预热中',
11:'募集中',
17:'已暂停',
21:'已封账',
31:'已成立',
'-9': '草稿',
0: '已删除',
1: '未发布',
5: '预热中',
11: '募集中',
17: '已暂停',
21: '已封账',
31: '已成立',
}
export const productStatusToString = status => {
export const productStatusToString = status => {
return PRODUCT_STATUS[status] || '未定义';
};
export const tradeStatusToString = status => {
switch (status){
switch (status) {
case 1 :
return '未报单,等待客户打款';
case 10:
......@@ -80,7 +82,7 @@ export const tradeStatusToString = status => {
};
export const tradeCreateTypeToString = type => {
switch (type){
switch (type) {
case 1:
return '后台创建';
case 5:
......@@ -100,3 +102,17 @@ export const UUID = (()=> {
return _UUID++;
}
})();
export function formatMoney(money = 0) {
let ret;
if (isNaN(money)) {
ret = '0';
} else if (money >= 1E10) {
ret = (money / 1E10) + '亿';
} else if (money >= 1E6) {
ret = (money / 1E6) + '万';
} else {
ret = (money / 1E2);
}
return ret;
}
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