Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
S
shuniu-admin-react
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
superman
shuniu-admin-react
Commits
9b2c994c
Commit
9b2c994c
authored
Jul 19, 2016
by
superman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update
parent
deccc40d
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
2386 additions
and
461 deletions
+2386
-461
workspace.xml
.idea/workspace.xml
+628
-313
proxy.config.js
proxy.config.js
+51
-1
HuikuanInfoForm.jsx
src/components/HuikuanInfoForm/HuikuanInfoForm.jsx
+53
-0
ProductBaseElement.jsx
src/components/ProductBaseElement/ProductBaseElement.jsx
+63
-0
ProductBaseInfo.jsx
src/components/ProductBaseInfo/ProductBaseInfo.jsx
+223
-0
ProductBaseInfo.less
src/components/ProductBaseInfo/ProductBaseInfo.less
+5
-0
ShouyiYongjingForm.jsx
src/components/ShouyiYongjingForm/ShouyiYongjingForm.jsx
+111
-0
YongjingSuanFaItem.jsx
src/components/YongjingSuanFaItem/YongjingSuanFaItem.jsx
+70
-0
App.jsx
src/containers/App/App.jsx
+1
-2
Login.less
src/containers/Login/Login.less
+1
-0
AddItem.jsx
src/containers/Product/AddItem.jsx
+265
-85
AddItem.less
src/containers/Product/AddItem.less
+9
-0
EditItem.jsx
src/containers/Product/EditItem.jsx
+321
-0
Item.jsx
src/containers/Product/Item.jsx
+90
-0
List.jsx
src/containers/Product/List.jsx
+28
-5
AddItem.jsx
src/containers/Trade/AddItem.jsx
+120
-0
Commission.jsx
src/containers/Trade/Commission.jsx
+60
-0
Contract.jsx
src/containers/Trade/Contract.jsx
+64
-0
Item.jsx
src/containers/Trade/Item.jsx
+6
-2
Item.less
src/containers/Trade/Item.less
+5
-2
List.jsx
src/containers/Trade/List.jsx
+2
-2
index.less
src/entries/index.less
+7
-3
product.js
src/reducers/product.js
+41
-13
trade.js
src/reducers/trade.js
+1
-1
index.js
src/routes/index.js
+11
-1
product.js
src/sagas/product.js
+76
-3
product.js
src/services/product.js
+26
-2
xFetch.js
src/services/xFetch.js
+7
-2
utils.js
src/utils.js
+41
-24
No files found.
.idea/workspace.xml
View file @
9b2c994c
This diff is collapsed.
Click to expand it.
proxy.config.js
View file @
9b2c994c
...
...
@@ -24,5 +24,55 @@ module.exports = {
});
},
500
);
},
'/api/*'
:
'http://react.yanky.cn/'
,
//'http://192.168.1.126:8080/',
'/api/catessddsd'
:
function
(
req
,
res
)
{
setTimeout
(()
=>
{
res
.
json
({
status
:
1
,
result
:[
{
value
:
1
,
label
:
'信托'
,
children
:[
{
value
:
101
,
label
:
'房产'
},{
value
:
102
,
label
:
'政府'
},{
value
:
103
,
label
:
'企业流贷'
}
]
},{
value
:
2
,
label
:
'资管'
,
children
:[
{
value
:
201
,
label
:
'房产'
},{
value
:
202
,
label
:
'政府'
},{
value
:
203
,
label
:
'企业流贷'
}
]
},{
value
:
3
,
label
:
'私募'
,
children
:[
{
value
:
301
,
label
:
'契约型'
}
]
}
]
})
},
100
);
},
'/api/*'
:
'http://react.yanky.cn/'
,
//'http://192.168.1.126:8080/'
};
src/components/HuikuanInfoForm/HuikuanInfoForm.jsx
0 → 100644
View file @
9b2c994c
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'
;
@
Form
.
create
()
export
default
class
HuikuanInfoForm
extends
Component
{
constructor
(
props
,
context
)
{
super
(
props
,
context
);
}
static
propsType
=
{};
render
()
{
const
formItemLayout
=
{
labelCol
:
{
span
:
4
},
wrapperCol
:
{
span
:
14
},
};
const
{
form
:{
getFieldProps
}}
=
this
.
props
;
return
(
<
Form
horizontal
>
<
Form
.
Item
label=
"名称"
{
...
formItemLayout
}
wrapperCol=
{
{
span
:
6
}
}
>
<
Input
placeholder=
""
{
...
getFieldProps
('
hkzhnc
')}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"银行帐号"
{
...
formItemLayout
}
wrapperCol=
{
{
span
:
6
}
}
>
<
Input
placeholder=
""
{
...
getFieldProps
('
yhzh
')}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"开户行"
{
...
formItemLayout
}
>
<
Input
placeholder=
""
{
...
getFieldProps
('
khh
')}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"打款须知"
{
...
formItemLayout
}
>
<
Input
type=
"textarea"
rows=
{
10
}
placeholder=
""
{
...
getFieldProps
('
dkxz
')}
/>
</
Form
.
Item
>
</
Form
>
);
}
}
src/components/ProductBaseElement/ProductBaseElement.jsx
0 → 100644
View file @
9b2c994c
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
>
);
}
}
src/components/ProductBaseInfo/ProductBaseInfo.jsx
0 → 100644
View file @
9b2c994c
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
,
arrayRemoveIndex
,
UUID
}
from
'../../utils'
;
const
ProductStatus
=
Object
.
keys
(
PRODUCT_STATUS
);
@
Form
.
create
()
export
default
class
ProductBaseInfo
extends
Component
{
static
propsType
=
{
cates
:
PropTypes
.
array
,
product
:
PropTypes
.
object
,
user
:
PropTypes
.
object
,
dispatch
:
PropTypes
.
func
};
constructor
(
props
,
context
)
{
super
(
props
,
context
);
this
.
state
=
{
priviewVisible
:
false
,
priviewImage
:
''
,
fileList
:
[]
};
const
{
itemPic
}
=
props
;
if
(
itemPic
)
{
this
.
state
.
fileList
.
push
({
uid
:
UUID
(),
status
:
'done'
,
url
:
itemPic
,
thumbUrl
:
itemPic
});
}
}
handleCancel
()
{
this
.
setState
({
priviewVisible
:
false
,
});
};
onChange
(
value
)
{
console
.
log
(
value
);
};
handleSubmit
(
e
)
{
e
.
preventDefault
();
const
data
=
this
.
props
.
form
.
getFieldsValue
();
if
(
Array
.
isArray
(
data
.
categoryL1
)
&&
data
.
categoryL1
.
length
===
2
){
data
.
categoryL2
=
data
.
categoryL1
[
1
];
data
.
categoryL1
=
data
.
categoryL1
[
0
];
}
else
{
delete
data
.
categoryL1
;
}
if
(
this
.
state
.
fileList
&&
this
.
state
.
fileList
[
0
]
&&
this
.
state
.
fileList
[
0
].
url
){
data
[
'item-pic'
]
=
this
.
state
.
fileList
[
0
].
url
;
}
data
.
id
=
this
.
props
.
product
.
id
;
console
.
log
(
'收到表单值:'
,
data
);
this
.
props
.
dispatch
({
type
:
'UPDATE_PRODUCT_ITEM'
,
item
:
data
});
};
normFile
(
e
)
{
if
(
Array
.
isArray
(
e
))
{
return
e
;
}
return
e
&&
e
.
fileList
;
};
handleUpload
(
info
)
{
let
fileList
=
info
.
fileList
;
// 3. 按照服务器返回信息筛选成功上传的文件
fileList
=
fileList
.
filter
((
file
)
=>
{
if
(
file
.
response
)
{
return
file
.
response
.
status
===
1
;
}
return
true
;
});
// 1. 上传列表数量的限制
// 只显示最近上传的一个,旧的会被新的顶掉
fileList
=
fileList
.
slice
(
-
2
);
// 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
;
file
.
thumbUrl
=
result
[
0
].
url
+
'!t'
;
}
}
return
file
;
});
this
.
setState
({
fileList
});
};
render
()
{
const
formItemLayout
=
{
labelCol
:
{
span
:
4
},
wrapperCol
:
{
span
:
14
},
};
const
{
user
,
cates
,
product
,
form
:{
getFieldProps
}}
=
this
.
props
;
let
productCate
=
[];
if
(
product
&&
product
.
categoryId
&&
product
.
categoryParentId
)
{
productCate
=
[
product
.
categoryParentId
,
product
.
categoryId
];
}
const
styles
=
require
(
'./ProductBaseInfo.less'
);
return
(
<
Form
horizontal
onSubmit=
{
this
.
handleSubmit
.
bind
(
this
)
}
>
<
Form
.
Item
label=
"商品类目"
{
...
formItemLayout
}
wrapperCol=
{
{
span
:
6
}
}
>
<
Cascader
options=
{
cates
}
defaultValue=
{
productCate
}
{
...
getFieldProps
('
categoryL1
',
{
initialValue
:
productCate
})}
placeholder=
"请选产品类目"
/>
</
Form
.
Item
>
{
product
&&
<
Form
.
Item
label=
"商品状态"
{
...
formItemLayout
}
>
<
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
}
>
<
Input
placeholder=
"商品标题"
{
...
getFieldProps
('
itemTitle
',
{
initialValue
:
product
.
itemTitle
})}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"商品短标题"
{
...
formItemLayout
}
wrapperCol=
{
{
span
:
6
}
}
>
<
Input
placeholder=
"商品短标题"
{
...
getFieldProps
('
itemShortTitle
',
{
initialValue
:
product
.
itemShortTitle
})}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"商品主图"
{
...
formItemLayout
}
>
<
Upload
action=
"/api/fileUpload/upload"
listType=
"picture-card"
multiple=
{
true
}
headers=
{
{
authorization
:
user
&&
user
.
token
,
}
}
onChange=
{
this
.
handleUpload
.
bind
(
this
)
}
onPreview=
{
(
file
)
=>
{
this
.
setState
({
priviewImage
:
file
.
url
,
priviewVisible
:
true
,
});
}
}
fileList=
{
this
.
state
.
fileList
}
>
<
Icon
type=
"upload"
/>
<
div
className=
"ant-upload-text"
>
上传照片
</
div
>
</
Upload
>
<
Modal
visible=
{
this
.
state
.
priviewVisible
}
footer=
{
null
}
width=
"100vw"
className=
{
styles
.
imgPriviewDialog
}
style=
{
{
height
:
'100vh'
,
background
:
'transparent'
}
}
onCancel=
{
this
.
handleCancel
.
bind
(
this
)
}
>
<
img
src=
{
this
.
state
.
priviewImage
}
style=
{
{
maxWidth
:
'100%'
}
}
/>
</
Modal
>
</
Form
.
Item
>
<
Form
.
Item
label=
"商品简介"
{
...
formItemLayout
}
>
<
Input
type=
"textarea"
rows=
{
5
}
placeholder=
"商品简介"
{
...
getFieldProps
('
summary
',
{
initialValue
:
product
.
summary
})}
/>
</
Form
.
Item
>
<
Form
.
Item
wrapperCol=
{
{
offset
:
4
,
span
:
10
}
}
style=
{
{
marginTop
:
30
}
}
>
<
Button
type=
"primary"
htmlType=
"submit"
><
Icon
type=
"save"
/>
保存
</
Button
>
</
Form
.
Item
>
</
Form
>
);
}
}
src/components/ProductBaseInfo/ProductBaseInfo.less
0 → 100644
View file @
9b2c994c
.imgPriviewDialog{
:global(.ant-modal-content){
background-color: transparent;
}
}
src/components/ShouyiYongjingForm/ShouyiYongjingForm.jsx
0 → 100644
View file @
9b2c994c
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
YongjingSuanFaItem
,
{
YongjingTransform
,
CreateYongjing
}
from
'../YongjingSuanFaItem/YongjingSuanFaItem'
;
import
{
arrayRemoveIndex
}
from
'../../utils'
;
@
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
)
}
}
/**
* 添加佣金算法
* @param e
*/
handleAddYongjing
(
e
)
{
e
.
preventDefault
();
let
yongjing
=
[].
concat
(
this
.
state
.
yongjing
);
yongjing
.
push
(
CreateYongjing
());
this
.
setState
({
yongjing
:
yongjing
});
}
/**
* 删除佣金算法
* @param index
* @param e
*/
handleRemoveYongjin
(
index
,
e
)
{
e
.
preventDefault
();
const
yongjing
=
arrayRemoveIndex
(
this
.
state
.
yongjing
,
index
);
console
.
log
(
yongjing
);
this
.
setState
({
yongjing
:
yongjing
});
}
render
()
{
const
formItemLayout
=
{
labelCol
:
{
span
:
4
},
wrapperCol
:
{
span
:
14
},
};
const
{
form
:{
getFieldProps
}}
=
this
.
props
;
return
(
<
Form
horizontal
>
<
Form
.
Item
label=
"产品的预期收益"
{
...
formItemLayout
}
wrapperCol=
{
{
span
:
6
}
}
>
<
Input
placeholder=
"产品的预期收益"
{
...
getFieldProps
('
yqsy
')}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"佣金算法"
{
...
formItemLayout
}
>
<
Input
.
Group
>
<
Col
span=
"5"
className=
"tac"
>
最小投资额
</
Col
>
<
Col
span=
"5"
className=
"tac"
>
最大投资额
</
Col
>
<
Col
span=
"5"
className=
"tac"
>
收益
</
Col
>
<
Col
span=
"5"
className=
"tac"
>
佣金
</
Col
>
</
Input
.
Group
>
{
this
.
state
.
yongjing
.
map
((
item
,
index
)
=>
<
YongjingSuanFaItem
{
...
item
}
remove=
{
this
.
handleRemoveYongjin
.
bind
(
this
,
index
)
}
/>
)
}
<
Row
style=
{
{
marginTop
:
15
}
}
>
<
Col
span=
"20"
className=
"tac"
>
<
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
>
</
Form
>
);
}
}
src/components/YongjingSuanFaItem/YongjingSuanFaItem.jsx
0 → 100644
View file @
9b2c994c
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
>
);
}
}
src/containers/App/App.jsx
View file @
9b2c994c
...
...
@@ -31,11 +31,10 @@ export default class App extends Component {
<
Collapse
accordion
>
<
Panel
header=
"产品管理"
>
<
Link
to=
"/products"
>
产品列表
</
Link
><
br
/>
<
Link
to=
"/products/
add
"
>
增加产品
</
Link
>
<
Link
to=
"/products/
create
"
>
增加产品
</
Link
>
</
Panel
>
<
Panel
header=
"订单管理"
>
<
Link
to=
"/trades"
>
订单列表
</
Link
><
br
/>
<
Link
to=
"/trade/add"
>
增加订单
</
Link
>
</
Panel
>
</
Collapse
>
</
div
>
...
...
src/containers/Login/Login.less
View file @
9b2c994c
...
...
@@ -11,6 +11,7 @@
.login-bg {
width: 50%;
height:100vh;
overflow: hidden;
}
...
...
src/containers/Product/AddItem.jsx
View file @
9b2c994c
This diff is collapsed.
Click to expand it.
src/containers/Product/AddItem.less
0 → 100644
View file @
9b2c994c
.normal {
display: flex;
flex-direction: column;
height: 100%;
& > :global(.ant-tabs) {
flex: 1;
overflow: auto;
}
}
src/containers/Product/EditItem.jsx
0 → 100644
View file @
9b2c994c
This diff is collapsed.
Click to expand it.
src/containers/Product/Item.jsx
0 → 100644
View file @
9b2c994c
import
React
,
{
Component
,
PropTypes
}
from
'react'
;
import
{
connect
}
from
'react-redux'
;
import
{
Link
}
from
'react-router'
;
import
{
Row
,
Col
,
Form
,
Input
,
Button
,
Checkbox
,
Select
,
message
,
Tabs
,
Cascader
,
Radio
,
Upload
,
Icon
,
Modal
,
DatePicker
,
Table
,
Spin
}
from
'antd'
;
@
connect
(
state
=>
({
item
:
state
.
product
.
item
,
loading
:
state
.
product
.
loading
}))
export
default
class
Item
extends
Component
{
componentWillMount
()
{
this
.
fetchItem
(
this
.
props
.
params
.
id
);
};
fetchItem
(
id
)
{
this
.
props
.
dispatch
({
type
:
'FETCH_PRODUCT_ITEM'
,
id
});
};
handleGoBack
(
e
)
{
e
.
preventDefault
();
this
.
props
.
history
.
goBack
();
};
render
()
{
const
tw
=
6
;
const
vw
=
18
;
const
styles
=
require
(
'../Trade/Item.less'
);
const
{
item
,
loading
}
=
this
.
props
;
return
(
<
Spin
spinning=
{
loading
}
>
{
item
&&
<
div
className=
{
styles
.
trade
}
>
<
div
className=
{
styles
.
tradeTable
}
>
<
Row
type=
"flex"
justify=
"space-around"
align=
"middle"
>
<
Col
span=
{
tw
}
>
产品标题
</
Col
>
<
Col
span=
{
vw
}
>
{
item
.
itemTitle
}
</
Col
>
</
Row
>
<
Row
type=
"flex"
justify=
"space-around"
align=
"middle"
>
<
Col
span=
{
tw
}
>
产品短标题
</
Col
>
<
Col
span=
{
vw
}
>
{
item
.
itemShortTitle
}
</
Col
>
</
Row
>
<
Row
type=
"flex"
justify=
"space-around"
align=
"middle"
>
<
Col
span=
{
tw
}
>
产品标题
</
Col
>
<
Col
span=
{
vw
}
>
{
item
.
itemTitle
}
</
Col
>
</
Row
>
<
Row
type=
"flex"
justify=
"space-around"
align=
"middle"
>
<
Col
span=
{
tw
}
>
产品标题
</
Col
>
<
Col
span=
{
vw
}
>
{
item
.
itemTitle
}
</
Col
>
</
Row
>
<
Row
type=
"flex"
justify=
"space-around"
align=
"middle"
>
<
Col
span=
{
tw
}
>
产品标题
</
Col
>
<
Col
span=
{
vw
}
>
{
item
.
itemTitle
}
</
Col
>
</
Row
>
</
div
>
<
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=
{
'/trades/create/'
+
item
.
id
+
'?title='
+
item
.
itemShortTitle
}
><
Button
>
报单
</
Button
></
Link
>
</
p
>
</
div
>
}
</
Spin
>
);
}
}
src/containers/Product/List.jsx
View file @
9b2c994c
...
...
@@ -2,13 +2,21 @@ import React, {Component, PropTypes} from 'react';
import
{
connect
}
from
'react-redux'
;
import
{
Table
,
Icon
}
from
'antd'
;
import
{
params
,
formatDateTime
,
productStatusToString
}
from
'../../utils'
;
import
{
Link
}
from
'react-router'
;
const
columns
=
[
{
title
:
'ID'
,
dataIndex
:
'id'
,
key
:
'id'
,
width
:
60
},
{
title
:
'类目'
,
dataIndex
:
'cateId'
,
key
:
'cateId'
,
width
:
80
,
className
:
'tac'
,
render
:
(
cateId
,
record
)
=>
(<
span
data
-
cate
-
id=
{
cateId
}
>
{
record
.
cateName
}
</
span
>)
},
{
title
:
'标题'
,
...
...
@@ -18,16 +26,22 @@ const columns = [
},
{
title
:
'募集比率'
,
dataIndex
:
'rate'
,
key
:
'rate'
key
:
'rate'
,
width
:
120
,
className
:
'tac'
,
},
{
title
:
'状态'
,
dataIndex
:
'status'
,
key
:
'status'
,
width
:
120
,
className
:
'tac'
,
render
:
(
status
,
record
)
=>
(<
span
data
-
status=
{
status
}
>
{
productStatusToString
(
status
)
}
</
span
>)
},
{
title
:
'创建时间'
,
dataIndex
:
'dateCreated'
,
key
:
'dateCreated'
,
width
:
150
,
className
:
'tac'
,
render
:
(
dateCreated
,
record
)
=>
(
<
span
>
{
dateCreated
&&
formatDateTime
(
dateCreated
)
}
...
...
@@ -36,11 +50,15 @@ const columns = [
},
{
title
:
'操作'
,
key
:
'operation'
,
width
:
120
,
className
:
'tac'
,
render
:
(
text
,
record
)
=>
(
<
span
>
<
a
href=
{
'/product/item?id='
+
record
.
id
}
>
详情
</
a
>
<
span
className=
"ant-divider"
></
span
>
<
a
href=
"#"
>
公告
</
a
>
<
span
className=
"ant-divider"
></
span
>
<
Link
to=
{
'/trades/add/'
+
record
.
id
+
'?title='
+
record
.
shortTitle
}
>
报单
</
Link
>
</
span
>
)
}
...
...
@@ -69,6 +87,10 @@ export default class List extends Component {
});
};
handleRowClick
({
id
}){
this
.
props
.
history
.
push
(
'/products/'
+
id
);
}
render
()
{
...
...
@@ -101,7 +123,8 @@ export default class List extends Component {
dataSource=
{
Array
.
isArray
(
items
)?
items
:[]
}
loading=
{
loading
}
pagination=
{
pagination
}
scroll=
{
{
y
:
window
.
innerHeight
-
280
}
}
scroll=
{
{
y
:
window
.
innerHeight
-
290
}
}
onRowClick=
{
this
.
handleRowClick
.
bind
(
this
)
}
/>
</
div
>;
}
...
...
src/containers/Trade/AddItem.jsx
0 → 100644
View file @
9b2c994c
import
React
,
{
Component
,
PropTypes
}
from
'react'
;
import
{
connect
}
from
'react-redux'
;
import
{
Form
,
Input
,
Button
,
Checkbox
,
message
,
Tabs
,
DatePicker
,
Upload
,
Icon
,
Modal
}
from
'antd'
;
@
Form
.
create
()
export
default
class
AddItem
extends
Component
{
constructor
()
{
super
(...
arguments
);
this
.
state
=
{
priviewVisible
:
false
,
priviewImage
:
''
,
};
}
handleCancel
()
{
this
.
setState
({
priviewVisible
:
false
,
});
}
render
()
{
const
formItemLayout
=
{
labelCol
:
{
span
:
6
},
wrapperCol
:
{
span
:
14
},
};
const
props
=
{
action
:
'/upload.do'
,
listType
:
'picture-card'
,
defaultFileList
:
[{
uid
:
-
1
,
name
:
'xxx.png'
,
status
:
'done'
,
url
:
'https://os.alipayobjects.com/rmsportal/NDbkJhpzmLxtPhB.png'
,
thumbUrl
:
'https://os.alipayobjects.com/rmsportal/NDbkJhpzmLxtPhB.png'
,
}],
onPreview
:
(
file
)
=>
{
this
.
setState
({
priviewImage
:
file
.
url
,
priviewVisible
:
true
,
});
},
};
return
(
<
div
>
<
Form
horizontal
>
<
Form
.
Item
{
...
formItemLayout
}
label=
"产品"
>
<
Input
value=
{
this
.
props
.
location
.
query
.
title
}
readOnly
/>
<
Input
type=
"hidden"
/>
</
Form
.
Item
>
<
Form
.
Item
{
...
formItemLayout
}
label=
"理财师手机号"
>
<
Input
/>
</
Form
.
Item
>
<
Form
.
Item
{
...
formItemLayout
}
label=
"投资人姓名"
>
<
Input
/>
</
Form
.
Item
>
<
Form
.
Item
{
...
formItemLayout
}
label=
"投资人身份证号码"
>
<
Input
/>
</
Form
.
Item
>
<
Form
.
Item
{
...
formItemLayout
}
label=
"投资人身份证正反面照片"
>
<
Upload
{
...
props
}
>
<
Icon
type=
"plus"
/>
<
div
className=
"ant-upload-text"
>
上传照片
</
div
>
</
Upload
>
<
Modal
visible=
{
this
.
state
.
priviewVisible
}
footer=
{
null
}
onCancel=
{
this
.
handleCancel
.
bind
(
this
)
}
>
<
img
alt=
"example"
src=
{
this
.
state
.
priviewImage
}
/>
</
Modal
>
</
Form
.
Item
>
<
Form
.
Item
{
...
formItemLayout
}
label=
"投资人实际打款金额"
>
<
Input
/>
</
Form
.
Item
>
<
Form
.
Item
{
...
formItemLayout
}
label=
"投资人实际打款时间"
>
<
DatePicker
showTime
format=
"yyyy-MM-dd HH:mm:ss"
placeholder=
"请选择时间"
/>
</
Form
.
Item
>
<
Form
.
Item
{
...
formItemLayout
}
label=
"投资人银行卡开户行"
>
<
Input
/>
</
Form
.
Item
>
<
Form
.
Item
{
...
formItemLayout
}
label=
"投资人银行卡照片"
>
<
Upload
{
...
props
}
>
<
Icon
type=
"plus"
/>
<
div
className=
"ant-upload-text"
>
上传照片
</
div
>
</
Upload
>
<
Modal
visible=
{
this
.
state
.
priviewVisible
}
footer=
{
null
}
onCancel=
{
this
.
handleCancel
.
bind
(
this
)
}
>
<
img
alt=
"example"
src=
{
this
.
state
.
priviewImage
}
/>
</
Modal
>
</
Form
.
Item
>
<
Form
.
Item
{
...
formItemLayout
}
label=
"投资人打款凭条照片"
>
<
Upload
{
...
props
}
>
<
Icon
type=
"plus"
/>
<
div
className=
"ant-upload-text"
>
上传照片
</
div
>
</
Upload
>
<
Modal
visible=
{
this
.
state
.
priviewVisible
}
footer=
{
null
}
onCancel=
{
this
.
handleCancel
.
bind
(
this
)
}
>
<
img
alt=
"example"
src=
{
this
.
state
.
priviewImage
}
/>
</
Modal
>
</
Form
.
Item
>
<
Form
.
Item
{
...
formItemLayout
}
className=
"clearfix"
label=
"投资人合同签字页照片"
>
<
Upload
{
...
props
}
>
<
Icon
type=
"plus"
/>
<
div
className=
"ant-upload-text"
>
上传照片
</
div
>
</
Upload
>
<
Modal
visible=
{
this
.
state
.
priviewVisible
}
footer=
{
null
}
onCancel=
{
this
.
handleCancel
.
bind
(
this
)
}
>
<
img
alt=
"example"
src=
{
this
.
state
.
priviewImage
}
/>
</
Modal
>
</
Form
.
Item
>
<
Form
.
Item
wrapperCol=
{
{
span
:
14
,
offset
:
6
}
}
>
<
Button
type=
"primary"
style=
{
{
marginRight
:
'1em'
}
}
>
提交
</
Button
>
<
Button
onClick=
{
(
e
)
=>
{
e
.
preventDefault
();
this
.
props
.
history
.
goBack
();}
}
>
返回
</
Button
>
</
Form
.
Item
>
</
Form
>
</
div
>
);
}
}
src/containers/Trade/Commission.jsx
0 → 100644
View file @
9b2c994c
import
React
,
{
Component
,
PropTypes
}
from
'react'
;
import
{
connect
}
from
'react-redux'
;
import
{
Form
,
Input
,
Button
,
Checkbox
,
message
,
Row
,
Col
}
from
'antd'
;
@
connect
(
state
=>
({
item
:
state
.
trade
.
item
}))
export
default
class
Commission
extends
Component
{
componentWillMount
()
{
const
{
dispatch
,
params
:{
id
}}
=
this
.
props
;
dispatch
({
type
:
'FETCH_TRADE_ITEM'
,
id
});
};
handleGoBack
(
e
)
{
e
.
preventDefault
();
this
.
props
.
history
.
goBack
();
};
handleCommission
(
e
){
e
.
preventDefault
();
alert
(
'二次确认后发放'
);
}
render
()
{
const
{
item
}
=
this
.
props
;
const
styles
=
require
(
'./Item.less'
);
const
tw
=
8
;
const
vw
=
16
;
return
(
<
div
className=
{
styles
.
trade
}
>
<
h1
className=
"tac"
>
佣金发放
</
h1
>
<
div
className=
{
styles
.
tradeTable
}
>
<
Row
type=
"flex"
justify=
"space-around"
align=
"middle"
>
<
Col
span=
{
tw
}
>
产品
</
Col
>
<
Col
span=
{
vw
}
>
{
item
.
title
}
</
Col
>
</
Row
>
<
Row
type=
"flex"
justify=
"space-around"
align=
"middle"
>
<
Col
span=
{
tw
}
>
确认打款金额
</
Col
>
<
Col
span=
{
vw
}
>
{
item
.
remittanceAmount
}
</
Col
>
</
Row
>
<
Row
type=
"flex"
justify=
"space-around"
align=
"middle"
>
<
Col
span=
{
tw
}
>
实际佣金
</
Col
>
<
Col
span=
{
vw
}
>
{
item
.
realReturn
&&
item
.
realReturn
.
yj
}
</
Col
>
</
Row
>
</
div
>
<
p
>
<
Button
onClick=
{
this
.
handleGoBack
.
bind
(
this
)
}
>
返回
</
Button
>
<
Button
onClick=
{
this
.
handleCommission
.
bind
(
this
)
}
>
发放
</
Button
>
</
p
>
</
div
>
);
}
}
src/containers/Trade/Contract.jsx
0 → 100644
View file @
9b2c994c
import
React
,
{
Component
,
PropTypes
}
from
'react'
;
import
{
connect
}
from
'react-redux'
;
import
{
Form
,
Input
,
Button
,
Checkbox
,
message
,
Row
,
Col
}
from
'antd'
;
@
connect
(
state
=>
({
item
:
state
.
trade
.
item
}))
export
default
class
Contract
extends
Component
{
componentWillMount
()
{
const
{
dispatch
,
params
:{
id
}}
=
this
.
props
;
dispatch
({
type
:
'FETCH_TRADE_ITEM'
,
id
});
};
handleGoBack
(
e
)
{
e
.
preventDefault
();
this
.
props
.
history
.
goBack
();
};
handleSubmit
(
e
){
e
.
preventDefault
();
alert
(
'实现保存物流订单号的流程'
);
}
render
()
{
const
{
item
}
=
this
.
props
;
const
styles
=
require
(
'./Item.less'
);
const
tw
=
8
;
const
vw
=
16
;
return
(
<
div
className=
{
styles
.
trade
}
>
<
h1
className=
"tac"
>
合同物流
</
h1
>
<
div
className=
{
styles
.
tradeTable
}
>
<
Row
type=
"flex"
justify=
"space-around"
align=
"middle"
>
<
Col
span=
{
tw
}
>
产品
</
Col
>
<
Col
span=
{
vw
}
>
{
item
.
title
}
</
Col
>
</
Row
>
<
Row
type=
"flex"
justify=
"space-around"
align=
"middle"
>
<
Col
span=
{
tw
}
>
确认打款金额
</
Col
>
<
Col
span=
{
vw
}
>
{
item
.
remittanceAmount
}
</
Col
>
</
Row
>
<
Row
type=
"flex"
justify=
"space-around"
align=
"middle"
>
<
Col
span=
{
tw
}
>
实际佣金
</
Col
>
<
Col
span=
{
vw
}
>
{
item
.
realReturn
&&
item
.
realReturn
.
yj
}
</
Col
>
</
Row
>
<
Row
type=
"flex"
justify=
"space-around"
align=
"middle"
>
<
Col
span=
{
tw
}
className=
"isRequire"
>
顺丰运单
</
Col
>
<
Col
span=
{
vw
}
><
Input
placeholder=
"请填写顺丰运单编号"
/></
Col
>
</
Row
>
</
div
>
<
p
>
<
Button
onClick=
{
this
.
handleGoBack
.
bind
(
this
)
}
>
返回
</
Button
>
<
Button
onClick=
{
this
.
handleSubmit
.
bind
(
this
)
}
>
保存
</
Button
>
</
p
>
</
div
>
);
}
}
src/containers/Trade/Item.jsx
View file @
9b2c994c
import
React
,
{
Component
,
PropTypes
}
from
'react'
;
import
{
connect
}
from
'react-redux'
;
import
{
Link
}
from
'react-router'
;
import
{
Form
,
Input
,
Button
,
Checkbox
,
message
,
Row
,
Col
}
from
'antd'
;
import
{
formatDateTime
,
...
...
@@ -19,10 +20,11 @@ export default class Item extends Component {
id
});
};
handleGoBack
(
e
){
e
.
preventDefault
();
this
.
props
.
history
.
goBack
();
}
}
;
render
()
{
const
{
item
}
=
this
.
props
;
...
...
@@ -115,6 +117,8 @@ export default class Item extends Component {
</
div
>
<
p
>
<
Button
onClick=
{
this
.
handleGoBack
.
bind
(
this
)
}
>
返回
</
Button
>
<
Link
to=
{
'/trades/commission/'
+
item
.
id
}
><
Button
>
发放佣金
</
Button
></
Link
>
<
Link
to=
{
'/trades/contract/'
+
item
.
id
}
><
Button
>
邮寄合同
</
Button
></
Link
>
</
p
>
</
div
>
);
...
...
src/containers/Trade/Item.less
View file @
9b2c994c
...
...
@@ -2,7 +2,10 @@
p {
text-align: center;
padding: 20px 0;
max-width: 800px;
//max-width: 800px;
button {
margin: auto 10px;
}
}
}
...
...
@@ -10,7 +13,7 @@
.tradeTable {
border-top: 1px solid #e9e9e9;
border-bottom: 1px solid #e9e9e9;
max-width: 800px;
//
max-width: 800px;
//margin: auto;
font-size: 14px;
:global(.ant-row),
...
...
src/containers/Trade/List.jsx
View file @
9b2c994c
...
...
@@ -62,9 +62,9 @@ const columns = [
className
:
'tac'
,
render
:
(
text
,
record
)
=>
(
<
span
>
<
Link
to=
{
'/trades/
'
+
record
.
id
}
>
邮寄
合同
</
Link
>
<
Link
to=
{
'/trades/
contract/'
+
record
.
id
}
onClick=
{
e
=>
e
.
stopPropagation
()
}
>
合同
</
Link
>
<
span
className=
"ant-divider"
></
span
>
<
Link
to=
{
'/trades/
'
+
record
.
id
}
>
发放
佣金
</
Link
>
<
Link
to=
{
'/trades/
commission/'
+
record
.
id
}
onClick=
{
e
=>
e
.
stopPropagation
()
}
>
佣金
</
Link
>
</
span
>
)
}
...
...
src/entries/index.less
View file @
9b2c994c
...
...
@@ -2,5 +2,9 @@
:global {
html, body, #root {
height: 100%;
font-size: 14px;
}
.ant-table{
font-size: 14px !important;
}
}
src/reducers/product.js
View file @
9b2c994c
import
{
handleActions
}
from
'redux-actions'
;
import
{
combineReducer
}
from
'redux'
;
import
{
handleActions
}
from
'redux-actions'
;
import
{
combineReducer
}
from
'redux'
;
const
product
=
handleActions
({
[
'FETCH_PRODUCT_LIST'
](
state
)
{
return
{
...
state
,
loading
:
true
,
};
return
{...
state
,
loading
:
true
,
};
},
[
'FETCH_PRODUCT_LIST_SUCCESS'
](
state
,
action
)
{
return
{
...
state
,
loading
:
false
,
items
:
action
.
items
,
total
:
action
.
total
};
return
{...
state
,
loading
:
false
,
items
:
action
.
items
,
total
:
action
.
total
};
},
[
'FETCH_PRODUCT_LIST_FAILED'
](
state
,
action
)
{
return
{
...
state
,
err
:
action
.
err
,
loading
:
false
,
};
return
{...
state
,
err
:
action
.
err
,
loading
:
false
,};
},
[
'FETCH_PRODUCT_CATES'
](
state
){
return
{...
state
,
loading
:
true
};
},
[
'FETCH_PRODUCT_CATES_SUCCESS'
](
state
,
action
){
return
{...
state
,
loading
:
false
,
cates
:
action
.
cates
};
},
[
'FETCH_PRODUCT_CATES_FAILED'
](
state
,
action
){
return
{...
state
,
err
:
action
.
err
,
loading
:
false
};
},
[
'FETCH_PRODUCT_ITEM'
](
state
){
return
{...
state
,
loading
:
true
}
},
[
'FETCH_PRODUCT_ITEM_SUCCESS'
](
state
,
action
){
return
{...
state
,
loading
:
false
,
item
:
action
.
item
}
},
[
'FETCH_PRODUCT_ITEM_FAILED'
](
state
,
action
){
return
{...
state
,
err
:
action
.
err
,
loading
:
false
}
},
[
'UPDATE_PRODUCT_ITEM'
](
state
){
return
{...
state
,
loading
:
true
};
},
[
'UPDATE_PRODUCT_ITEM_SUCCESS'
](
state
){
return
{...
state
,
loading
:
false
};
},
[
'UPDATE_PRODUCT_ITEM_FAILED'
](
state
,
action
){
return
{...
state
,
loading
:
false
,
err
:
action
.
err
};
}
},
{
cates
:[],
items
:
[],
loading
:
false
,
});
...
...
src/reducers/trade.js
View file @
9b2c994c
...
...
@@ -17,7 +17,7 @@ const trade = handleActions({
[
'FETCH_TRADE_ITEM_SUCCESS'
](
state
,
action
){
return
{...
state
,
loading
:
false
,
item
:
action
.
item
}
},
[
'FETCH_TRADE_ITEM_FAILED'
](
state
){
[
'FETCH_TRADE_ITEM_FAILED'
](
state
,
action
){
return
{...
state
,
err
:
action
.
err
,
loading
:
false
}
}
},
{
...
...
src/routes/index.js
View file @
9b2c994c
...
...
@@ -6,8 +6,13 @@ import Login from '../containers/Login/Login';
import
App
from
'../containers/App/App'
;
import
ProductList
from
'../containers/Product/List'
;
import
ProductAddItem
from
'../containers/Product/AddItem'
;
import
ProductEditItem
from
'../containers/Product/EditItem'
;
import
ProductItem
from
'../containers/Product/Item'
;
import
TradeList
from
'../containers/Trade/List'
;
import
TradeItem
from
'../containers/Trade/Item'
;
import
Commission
from
'../containers/Trade/Commission'
;
import
Contract
from
'../containers/Trade/Contract'
;
import
TradeAddItem
from
'../containers/Trade/AddItem'
;
export
default
(
store
)
=>
{
...
...
@@ -24,11 +29,16 @@ export default (store)=> {
<
IndexRoute
component
=
{
Home
}
/
>
<
Route
path
=
"products"
>
<
IndexRoute
component
=
{
ProductList
}
/
>
<
Route
path
=
"add"
component
=
{
ProductAddItem
}
/
>
<
Route
path
=
":id"
component
=
{
ProductItem
}
/
>
<
Route
path
=
"create"
component
=
{
ProductAddItem
}
/
>
<
Route
path
=
":id/edit"
component
=
{
ProductEditItem
}
/
>
<
/Route
>
<
Route
path
=
"trades"
>
<
IndexRoute
component
=
{
TradeList
}
/
>
<
Route
path
=
":id"
component
=
{
TradeItem
}
/
>
<
Route
path
=
"commission/:id"
component
=
{
Commission
}
/
>
<
Route
path
=
"contract/:id"
component
=
{
Contract
}
/
>
<
Route
path
=
"create/:pid"
component
=
{
TradeAddItem
}
/
>
<
/Route
>
<
Route
path
=
"/actived"
component
=
{
Home
}
/
>
<
Route
path
=
"/completed"
component
=
{
Home
}
/
>
...
...
src/sagas/product.js
View file @
9b2c994c
import
{
takeLatest
}
from
'redux-saga'
;
import
{
take
,
call
,
put
,
fork
,
cancel
,
select
}
from
'redux-saga/effects'
;
import
{
fetchList
}
from
'../services/product'
;
import
{
fetchList
,
fetchCates
,
fetchItem
,
updateItem
}
from
'../services/product'
;
import
{
message
}
from
'antd'
;
function
*
getList
(
query
)
{
...
...
@@ -28,6 +28,79 @@ function* watchProductList() {
}
}
function
*
getCates
()
{
try
{
const
cates
=
yield
call
(
fetchCates
);
yield
put
({
type
:
'FETCH_PRODUCT_CATES_SUCCESS'
,
cates
});
}
catch
(
err
)
{
console
.
log
(
err
);
message
.
error
(
err
);
yield
put
({
type
:
'FETCH_PRODUCT_CATES_FAILED'
,
err
,
});
}
}
function
*
watchProductCates
()
{
yield
takeLatest
(
'FETCH_PRODUCT_CATES'
,
getCates
);
}
function
*
getItem
(
id
)
{
try
{
const
item
=
yield
call
(
fetchItem
,
id
);
yield
put
({
type
:
'FETCH_PRODUCT_ITEM_SUCCESS'
,
item
});
}
catch
(
err
)
{
console
.
log
(
err
);
message
.
error
(
err
);
yield
put
({
type
:
'FETCH_PRODUCT_ITEM_FAILED'
,
err
});
}
}
function
*
watchProductItem
()
{
while
(
true
)
{
const
{
id
}
=
yield
take
(
'FETCH_PRODUCT_ITEM'
);
yield
fork
(
getItem
,
id
);
}
}
function
*
editItem
(
item
)
{
try
{
yield
call
(
updateItem
,
item
);
yield
put
({
type
:
'UPDATE_PRODUCT_ITEM_SUCCESS'
,
});
}
catch
(
err
){
console
.
log
(
err
);
message
.
error
(
err
);
yield
put
({
type
:
'UPDATE_PRODUCT_ITEM_FAILED'
,
err
});
}
}
function
*
watchEditProductItem
(){
while
(
true
){
const
{
item
}
=
yield
take
(
'UPDATE_PRODUCT_ITEM'
);
yield
fork
(
editItem
,
item
);
}
}
export
default
function
*
()
{
yield
fork
(
watchProductList
);
yield
fork
(
watchProductCates
);
yield
fork
(
watchProductItem
);
yield
fork
(
watchEditProductItem
);
}
src/services/product.js
View file @
9b2c994c
import
xFetch
from
'./xFetch'
;
import
{
params
}
from
'../utils'
;
import
{
serialize
}
from
'../utils'
;
export
async
function
fetchList
(
query
)
{
return
xFetch
(
'/api/products'
+
'?'
+
params
(
query
));
return
xFetch
(
'/api/products'
+
'?'
+
serialize
(
query
));
}
export
async
function
fetchCates
()
{
return
xFetch
(
'/api/cates'
);
}
export
async
function
fetchItem
(
id
)
{
return
xFetch
(
'/api/products/'
+
id
,
{
method
:
'GET'
});
}
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
)
});
}
src/services/xFetch.js
View file @
9b2c994c
...
...
@@ -5,7 +5,7 @@ const errorMessages = (res) => `${res.status} ${res.statusText}`;
function
check401
(
res
)
{
if
(
res
.
status
===
401
)
{
//location.href = '/401
';
location
.
href
=
'/login
'
;
}
return
res
;
}
...
...
@@ -33,7 +33,7 @@ function xFetch(url, options) {
const
opts
=
{...
options
};
let
user
;
try
{
user
=
JSON
.
parse
(
sessionStorage
.
getItem
(
'user'
));
user
=
JSON
.
parse
(
sessionStorage
.
getItem
(
'user'
))
||
{}
;
}
catch
(
ex
){
user
=
{};
}
...
...
@@ -41,6 +41,11 @@ function xFetch(url, options) {
...
opts
.
headers
,
authorization
:
user
.
token
||
''
,
};
if
(
opts
.
method
!=
'GET'
){
opts
.
headers
[
'content-type'
]
=
'application/x-www-form-urlencoded'
;
}
return
fetch
(
url
,
opts
)
.
then
(
check401
)
...
...
src/utils.js
View file @
9b2c994c
export
const
params
=
query
=>
Object
.
keys
(
query
).
map
((
key
)
=>
{
return
key
+
'='
+
query
[
key
];
}).
join
(
'&'
);
// export const params = query => Object.keys(query).map((key)=> {
// return key + '=' + query[key];
// }).join('&');
export
function
serialize
(
obj
,
prefix
)
{
var
str
=
[];
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
));
}
}
return
str
.
join
(
"&"
);
}
export
const
leftPad
=
num
=>
{
return
num
>=
10
?
num
:
(
'0'
+
num
);
...
...
@@ -21,28 +36,19 @@ export const formatDateTime = (time = 0, format = 'YYYY-MM-DD hh:mm:ss') => {
});
};
export
const
PRODUCT_STATUS
=
{
'-9'
:
'草稿'
,
0
:
'已删除'
,
1
:
'未发布'
,
5
:
'预热中'
,
11
:
'募集中'
,
17
:
'已暂停'
,
21
:
'已封账'
,
31
:
'已成立'
,
}
export
const
productStatusToString
=
status
=>
{
switch
(
status
)
{
case
0
:
return
'无效, 已删除'
;
case
1
:
return
'未发布'
;
case
5
:
return
'预热中'
;
case
11
:
return
'募集中'
;
case
17
:
return
'暂停'
;
case
21
:
return
'已封账'
;
case
31
:
return
'产品成立'
;
case
-
9
:
return
'草稿'
;
default
:
return
'未定义'
;
}
return
PRODUCT_STATUS
[
status
]
||
'未定义'
;
};
...
...
@@ -82,4 +88,15 @@ export const tradeCreateTypeToString = type => {
default
:
return
'未知创建者'
;
}
}
};
export
const
arrayRemoveIndex
=
(
arr
,
index
)
=>
{
return
arr
.
concat
(
arr
.
splice
(
index
).
splice
(
1
));
};
export
const
UUID
=
(()
=>
{
let
_UUID
=
0
;
return
()
=>
{
return
_UUID
++
;
}
})();
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment