Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
J
jinfa-admin
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
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linweijiong
jinfa-admin
Commits
593349ab
Commit
593349ab
authored
Mar 04, 2022
by
前端-许佳敏
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: 补充组件问题
parent
94c91d13
Show whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
3184 additions
and
0 deletions
+3184
-0
SelectItem.tsx
src/pages/memberManage/components/AreaSelect/SelectItem.tsx
+62
-0
index.less
src/pages/memberManage/components/AreaSelect/index.less
+0
-0
index.tsx
src/pages/memberManage/components/AreaSelect/index.tsx
+176
-0
index.less
src/pages/memberManage/components/AuditProcess/index.less
+0
-0
index.tsx
src/pages/memberManage/components/AuditProcess/index.tsx
+51
-0
index.less
src/pages/memberManage/components/BasicInfo/index.less
+11
-0
index.tsx
src/pages/memberManage/components/BasicInfo/index.tsx
+201
-0
index.less
src/pages/memberManage/components/EquityInfo/index.less
+141
-0
index.tsx
src/pages/memberManage/components/EquityInfo/index.tsx
+369
-0
index.less
src/pages/memberManage/components/FlowRecords/index.less
+0
-0
index.tsx
src/pages/memberManage/components/FlowRecords/index.tsx
+157
-0
index.less
src/pages/memberManage/components/HeadInfo/index.less
+22
-0
index.tsx
src/pages/memberManage/components/HeadInfo/index.tsx
+28
-0
index.less
src/pages/memberManage/components/LevelBrand/index.less
+12
-0
index.tsx
src/pages/memberManage/components/LevelBrand/index.tsx
+37
-0
index.less
src/pages/memberManage/components/LevelInfo/index.less
+176
-0
index.tsx
src/pages/memberManage/components/LevelInfo/index.tsx
+238
-0
index.less
src/pages/memberManage/components/PicWrap/index.less
+31
-0
index.tsx
src/pages/memberManage/components/PicWrap/index.tsx
+19
-0
index.less
src/pages/memberManage/components/SincerityInfo/index.less
+82
-0
index.tsx
src/pages/memberManage/components/SincerityInfo/index.tsx
+770
-0
index.less
src/pages/memberManage/components/StatusTag/index.less
+35
-0
index.tsx
src/pages/memberManage/components/StatusTag/index.tsx
+25
-0
constant.tsx
src/pages/memberManage/constant.tsx
+72
-0
auditSchema.ts
src/pages/memberManage/schema/auditSchema.ts
+165
-0
utils.tsx
src/pages/memberManage/utils.tsx
+304
-0
No files found.
src/pages/memberManage/components/AreaSelect/SelectItem.tsx
0 → 100644
View file @
593349ab
/*
* @Author: XieZhiXiong
* @Date: 2021-06-10 14:30:16
* @LastEditors: XieZhiXiong
* @LastEditTime: 2021-06-10 15:29:04
* @Description: 区域选择单个Select
*/
import
React
from
'react'
;
import
{
Select
}
from
'antd'
;
import
{
SelectProps
}
from
'antd/lib/select'
;
interface
IProps
extends
SelectProps
<
string
>
{
/**
* 选项
*/
options
:
{
/**
* 描述
*/
label
:
string
,
/**
* 值
*/
value
:
any
,
}[],
}
const
AreaSelectItem
=
(
props
:
IProps
)
=>
{
const
{
disabled
,
value
,
options
,
}
=
props
;
const
current
=
options
.
find
((
item
)
=>
item
.
value
===
value
);
if
(
!
disabled
)
{
return
(
<
Select
style=
{
{
width
:
'100%'
,
}
}
{
...
props
}
>
{
options
.
map
((
item
)
=>
(
<
Select
.
Option
key=
{
item
.
value
}
value=
{
item
.
value
}
>
{
item
.
label
}
</
Select
.
Option
>
))
}
</
Select
>
);
}
return
(
<
div
>
{
current
?.
label
}
</
div
>
);
};
export
default
AreaSelectItem
;
src/pages/memberManage/components/AreaSelect/index.less
0 → 100644
View file @
593349ab
src/pages/memberManage/components/AreaSelect/index.tsx
0 → 100644
View file @
593349ab
/*
* @Author: XieZhiXiong
* @Date: 2021-06-10 14:27:37
* @LastEditors: XieZhiXiong
* @LastEditTime: 2021-06-10 16:00:07
* @Description: 区域选择
*/
import
React
,
{
useState
,
useEffect
}
from
'react'
;
import
{
Row
,
Col
}
from
'antd'
;
import
SelectItem
from
'./SelectItem'
;
import
{
getMemberAreaCity
,
getMemberAreaDistrict
,
getMemberAreaProvince
}
from
'@/services/MemberV2Api'
;
function
isObj
(
value
)
{
return
typeof
value
===
'object'
;
};
type
AreaCodeType
=
{
/**
* 区域编码
*/
value
:
string
/**
* 区域名称
*/
label
:
string
}
const
AreaSelect
=
(
props
)
=>
{
const
{
mutators
,
editable
,
}
=
props
;
const
value
=
isObj
(
props
.
value
)
?
props
.
value
:
{};
const
XComponentProps
=
props
.
props
[
'x-component-props'
]
||
{};
const
SelectProps
=
{
...
XComponentProps
,
disabled
:
!
editable
||
XComponentProps
.
disabled
,
};
const
[
provinceList
,
setProvinceList
]
=
useState
<
AreaCodeType
[]
>
([]);
const
[
cityList
,
setCityList
]
=
useState
<
AreaCodeType
[]
>
([]);
const
[
districtList
,
setDistrictList
]
=
useState
<
AreaCodeType
[]
>
([]);
const
[
provinceLoading
,
setProvinceLoading
]
=
useState
(
false
);
const
[
cityLoading
,
setCityLoading
]
=
useState
(
false
);
const
[
districtLoading
,
setDistrictLoading
]
=
useState
(
false
);
const
[
provinceValue
,
setProvinceValue
]
=
useState
<
string
|
undefined
>
(
''
);
const
[
cityValue
,
setCityValue
]
=
useState
<
string
|
undefined
>
(
''
);
const
[
districtValue
,
setDistrictValue
]
=
useState
<
string
|
undefined
>
(
''
);
const
getProvinceList
=
async
()
=>
{
setProvinceLoading
(
true
);
const
res
=
await
getMemberAreaProvince
();
if
(
res
.
code
===
1000
)
{
setProvinceList
(
res
.
data
.
map
((
item
)
=>
({
label
:
item
.
name
,
value
:
item
.
code
})));
}
setProvinceLoading
(
false
);
};
const
getCityList
=
async
(
code
?:
string
)
=>
{
if
(
!
code
)
{
return
;
}
setCityLoading
(
true
);
const
res
=
await
getMemberAreaCity
({
code
});
if
(
res
.
code
===
1000
)
{
setCityList
(
res
.
data
.
map
((
item
)
=>
({
label
:
item
.
name
,
value
:
item
.
code
})));
}
setCityLoading
(
false
);
};
const
getDistrictList
=
async
(
code
?:
string
)
=>
{
if
(
!
code
)
{
return
;
}
setDistrictLoading
(
true
);
const
res
=
await
getMemberAreaDistrict
({
code
});
if
(
res
.
code
===
1000
)
{
setDistrictList
(
res
.
data
.
map
((
item
)
=>
({
label
:
item
.
name
,
value
:
item
.
code
})));
}
setDistrictLoading
(
false
);
};
useEffect
(()
=>
{
const
{
provinceCode
,
cityCode
,
districtCode
,
}
=
value
;
setProvinceValue
(
provinceCode
);
setCityValue
(
cityCode
);
setDistrictValue
(
districtCode
);
},
[
value
]);
useEffect
(()
=>
{
getProvinceList
();
},
[]);
useEffect
(()
=>
{
getCityList
(
provinceValue
);
},
[
provinceValue
]);
useEffect
(()
=>
{
getDistrictList
(
cityValue
);
},
[
cityValue
]);
const
handleProvinceChange
=
(
next
:
string
)
=>
{
setProvinceValue
(
next
);
setCityValue
(
undefined
);
setCityList
([]);
setDistrictList
([]);
setDistrictValue
(
undefined
);
mutators
.
change
({
...
value
,
provinceCode
:
next
,
cityCode
:
undefined
,
districtCode
:
undefined
});
};
const
handleCityChange
=
(
next
:
string
)
=>
{
setCityValue
(
next
);
setDistrictList
([]);
setDistrictValue
(
undefined
);
mutators
.
change
({
...
value
,
cityCode
:
next
,
districtCode
:
undefined
});
};
const
handleDistrictChange
=
(
next
:
string
)
=>
{
setDistrictValue
(
next
);
mutators
.
change
({
...
value
,
districtCode
:
next
});
};
return
(
<
div
style=
{
{
width
:
'100%'
,
}
}
>
<
Row
gutter=
{
16
}
>
<
Col
span=
{
8
}
>
<
SelectItem
placeholder=
"- 省 -"
allowClear
{
...
SelectProps
}
value=
{
provinceValue
}
options=
{
provinceList
}
loading=
{
provinceLoading
}
onChange=
{
handleProvinceChange
}
/>
</
Col
>
<
Col
span=
{
8
}
>
<
SelectItem
placeholder=
"- 市 -"
allowClear
{
...
SelectProps
}
value=
{
cityValue
}
options=
{
cityList
}
loading=
{
cityLoading
}
onChange=
{
handleCityChange
}
/>
</
Col
>
<
Col
span=
{
8
}
>
<
SelectItem
placeholder=
"- 县 / 区 -"
allowClear
{
...
SelectProps
}
value=
{
districtValue
}
options=
{
districtList
}
loading=
{
districtLoading
}
onChange=
{
handleDistrictChange
}
/>
</
Col
>
</
Row
>
</
div
>
);
};
AreaSelect
.
isFieldComponent
=
true
;
export
default
AreaSelect
src/pages/memberManage/components/AuditProcess/index.less
0 → 100644
View file @
593349ab
src/pages/memberManage/components/AuditProcess/index.tsx
0 → 100644
View file @
593349ab
import
React
from
'react'
;
import
{
Steps
,
Tabs
,
}
from
'antd'
;
import
MellowCard
from
'@/components/MellowCard'
;
import
styles
from
'./index.less'
;
interface
AuditProcessProp
{
outerVerifyCurrent
?:
number
;
innerVerifyCurrent
?:
number
;
outerVerifySteps
?:
{
step
:
number
,
stepName
:
string
,
roleName
:
string
}[];
innerVerifySteps
?:
{
step
:
number
,
stepName
:
string
,
roleName
:
string
}[];
};
const
AuditProcess
:
React
.
FC
<
AuditProcessProp
>
=
({
outerVerifyCurrent
=
0
,
innerVerifyCurrent
=
0
,
outerVerifySteps
=
[],
innerVerifySteps
=
[],
})
=>
(
<
MellowCard
>
<
Tabs
onChange=
{
()
=>
{}
}
>
<
Tabs
.
TabPane
tab=
"外部审核流程"
key=
"1"
>
<
Steps
style=
{
{
marginTop
:
30
}
}
progressDot
current=
{
outerVerifyCurrent
}
>
{
outerVerifySteps
.
map
(
item
=>
(
<
Steps
.
Step
key=
{
item
.
step
}
title=
{
item
.
stepName
}
description=
{
item
.
roleName
}
/>
))
}
</
Steps
>
</
Tabs
.
TabPane
>
<
Tabs
.
TabPane
tab=
"内部审核流程"
key=
"2"
>
<
Steps
style=
{
{
marginTop
:
30
}
}
progressDot
current=
{
innerVerifyCurrent
}
>
{
innerVerifySteps
.
map
(
item
=>
(
<
Steps
.
Step
key=
{
item
.
step
}
title=
{
item
.
roleName
}
description=
{
item
.
stepName
}
/>
))
}
</
Steps
>
</
Tabs
.
TabPane
>
</
Tabs
>
</
MellowCard
>
);
export
default
AuditProcess
;
\ No newline at end of file
src/pages/memberManage/components/BasicInfo/index.less
0 → 100644
View file @
593349ab
.basicInfo {
.descriptions {
:global {
.ant-descriptions-item-label {
flex: 0 0 128px;
color: rgba(107, 119, 140, 1);
}
}
}
}
\ No newline at end of file
src/pages/memberManage/components/BasicInfo/index.tsx
0 → 100644
View file @
593349ab
import
React
,
{
useState
}
from
'react'
;
import
{
Row
,
Col
,
Descriptions
,
}
from
'antd'
;
import
MellowCard
from
'@/components/MellowCard'
;
import
{
MEMBER_TYPE_CHANNEL_CORPORATE
,
MEMBER_TYPE_CHANNEL_INDIVIDUAL
,
}
from
'@/constants/const/member'
;
import
{
renderFieldTypeContent
}
from
'../../utils'
;
import
PicWrap
from
'../PicWrap'
;
import
FlowRecords
,
{
InnerHistoryItem
,
OuterHistoryItem
}
from
'../FlowRecords'
;
import
styles
from
'./index.less'
;
interface
BasicInfoProps
{
basic
?:
{
account
?:
string
,
phone
?:
string
,
email
?:
string
,
created
?:
string
,
};
channel
?:
{
memberType
?:
number
,
level
?:
string
,
type
?:
string
,
areas
?:
string
[],
desc
?:
string
,
};
extra
?:
{
groupName
:
string
,
elements
:
{
/**
* 注册资料id
*/
id
?:
number
,
/**
* 字段名称
*/
fieldName
?:
string
,
/**
* 中文名称
*/
fieldLocalName
?:
string
,
/**
* 字段类型
*/
fieldType
?:
string
,
/**
* 字段类型附加属性(该参数为map)
*/
attr
?:
{
[
key
:
string
]:
any
},
/**
* 字段长度
*/
fieldLength
?:
number
,
/**
* 是否可为空0-不能为空1-可以为空
*/
fieldEmpty
?:
number
,
/**
* 字段顺序
*/
fieldOrder
?:
number
,
/**
* 帮助信息
*/
fieldRemark
?:
string
,
/**
* 枚举标签列表
*/
fieldEnum
?:
{
value
?:
number
,
label
?:
string
,
}[],
/**
* 字段校验规则枚举:0-无校验规则,1-邮箱规则,2-手机号码规则,3-身份证规则,4-电话号码规则
*/
ruleEnum
?:
number
,
/**
* 校验规则的正则表达式
*/
pattern
?:
string
,
/**
* 校验错误的提示语
*/
msg
?:
string
,
/**
* 值
*/
fieldValue
?:
any
,
/**
* 是否禁用
*/
disabled
?:
boolean
,
}[],
}[];
outerHistory
?:
OuterHistoryItem
[];
innerHistory
?:
InnerHistoryItem
[];
channelRender
?:
React
.
ReactNode
;
// 自定义渲染渠道信息
}
const
BasicInfo
:
React
.
FC
<
BasicInfoProps
>
=
({
basic
=
{},
channel
=
{},
extra
=
[],
outerHistory
=
[],
innerHistory
=
[],
channelRender
,
})
=>
{
return
(
<
div
className=
{
styles
.
basicInfo
}
>
<
Row
gutter=
{
[
0
,
24
]
}
>
<
Col
span=
{
24
}
>
<
MellowCard
title=
"基本信息"
>
<
Descriptions
column=
{
2
}
className=
{
styles
.
descriptions
}
>
<
Descriptions
.
Item
label=
"登录账户"
>
{
basic
.
account
}
</
Descriptions
.
Item
>
<
Descriptions
.
Item
label=
"注册手机号"
>
{
basic
.
phone
}
</
Descriptions
.
Item
>
<
Descriptions
.
Item
label=
"注册邮箱"
>
{
basic
.
email
}
</
Descriptions
.
Item
>
<
Descriptions
.
Item
label=
"申请时间"
>
{
basic
.
created
}
</
Descriptions
.
Item
>
</
Descriptions
>
</
MellowCard
>
</
Col
>
{
(
channel
.
memberType
===
MEMBER_TYPE_CHANNEL_CORPORATE
||
channel
.
memberType
===
MEMBER_TYPE_CHANNEL_INDIVIDUAL
)
&&
(
<
Col
span=
{
24
}
>
<
MellowCard
title=
"渠道信息"
>
{
!
channelRender
?
(
<
Descriptions
column=
{
2
}
className=
{
styles
.
descriptions
}
>
<
Descriptions
.
Item
label=
"渠道级别"
>
{
channel
.
level
}
</
Descriptions
.
Item
>
<
Descriptions
.
Item
label=
"渠道类型"
>
{
channel
.
type
}
</
Descriptions
.
Item
>
<
Descriptions
.
Item
label=
"代理地市"
>
<
Row
gutter=
{
[
16
,
16
]
}
style=
{
{
flex
:
1
}
}
>
{
channel
.
areas
?
channel
.
areas
.
map
(
item
=>
(
<
Col
key=
{
item
}
span=
{
12
}
>
{
item
}
</
Col
>
))
:
null
}
</
Row
>
</
Descriptions
.
Item
>
<
Descriptions
.
Item
label=
"渠道描述"
>
{
channel
.
desc
}
</
Descriptions
.
Item
>
</
Descriptions
>
)
:
channelRender
}
</
MellowCard
>
</
Col
>
)
}
{
extra
.
map
((
item
,
index
)
=>
(
<
Col
key=
{
index
}
span=
{
24
}
>
<
MellowCard
title=
{
item
.
groupName
}
>
<
Row
gutter=
{
20
}
>
<
Col
span=
{
12
}
>
<
Descriptions
column=
{
1
}
className=
{
styles
.
descriptions
}
>
{
item
.
elements
.
map
((
ele
,
index
)
=>
(
index
+
1
)
%
2
!==
0
?
(
<
Descriptions
.
Item
key=
{
index
}
label=
{
ele
.
fieldLocalName
}
>
{
renderFieldTypeContent
(
ele
.
fieldType
as
any
,
ele
.
fieldValue
)
}
</
Descriptions
.
Item
>
)
:
null
)
}
</
Descriptions
>
</
Col
>
<
Col
span=
{
12
}
>
<
Descriptions
column=
{
1
}
className=
{
styles
.
descriptions
}
>
{
item
.
elements
.
map
((
ele
,
index
)
=>
(
index
+
1
)
%
2
===
0
?
(
<
Descriptions
.
Item
key=
{
index
}
label=
{
ele
.
fieldLocalName
}
>
{
renderFieldTypeContent
(
ele
.
fieldType
as
any
,
ele
.
fieldValue
)
}
</
Descriptions
.
Item
>
)
:
null
)
}
</
Descriptions
>
</
Col
>
</
Row
>
</
MellowCard
>
</
Col
>
))
}
<
Col
span=
{
24
}
>
<
FlowRecords
outerHistory=
{
outerHistory
}
innerHistory=
{
innerHistory
}
/>
</
Col
>
</
Row
>
</
div
>
);
};
export
default
BasicInfo
;
src/pages/memberManage/components/EquityInfo/index.less
0 → 100644
View file @
593349ab
@import '../../../../global/styles/utils.less';
.equityInfo {
.container {
display: flex;
flex-direction: column;
justify-content: center;
padding: 0 24px;
height: 192px;
background: #ffffff;
border-radius: 8px;
&-title {
margin-bottom: 20px;
line-height: 24px;
font-size: 14px;
font-weight: 500;
color: rgba(23, 43, 77, 1);
}
&-content {
}
}
.tofo {
display: flex;
padding: 0 0 4px;
margin: 0;
min-height: 101px;
overflow-x: auto;
.silkyScrollbar();
&-item {
flex: 0 0 33.333%;
list-style: none;
&-logo {
width: 40px;
height: 40px;
margin: 0 auto 4px;
text-align: center;
> img {
width: 100%;
height: 100%;
}
}
&-title {
margin-bottom: 9px;
line-height: 22px;
font-size: 12px;
font-weight: 400;
color: rgba(23, 43, 77, 1);
text-align: center;
:global {
.anticon {
margin-left: 4px;
}
}
}
&-extra {
text-align: center;
}
&-tag {
line-height: 22px;
padding: 0 6px;
font-size: 12px;
font-weight: 400;
text-align: center;
border-radius: 4px;
&-price {
color: rgba(101, 84, 192, 1);
background: rgba(234, 230, 255, 1);
}
&-recurrence {
color: rgba(230, 63, 59, 1);
background: rgba(255, 235, 230, 1);
}
&-integral {
color: rgba(255, 153, 31, 1);
background: rgba(255, 250, 230, 1);
}
}
}
}
.exhibition {
display: flex;
align-items: center;
&-left {
flex: 1;
}
&-right {
flex-shrink: 0;
}
&-title {
line-height: 20px;
margin-bottom: 24px;
font-size: 12px;
font-weight: 400;
color: rgba(107, 119, 140, 1);
}
&-amount {
font-size: 24px;
font-weight: 500;
color: rgba(23, 43, 77, 1);
line-height: 24px;
> span {
margin-left: 8px;
line-height: 12px;
font-size: 12px;
font-weight: 400;
color: rgba(107, 119, 140, 1);
}
}
&-logo {
width: 72px;
height: 72px;
> img {
width: 100%;
height: 100%;
}
}
}
}
\ No newline at end of file
src/pages/memberManage/components/EquityInfo/index.tsx
0 → 100644
View file @
593349ab
import
React
,
{
useState
,
useEffect
}
from
'react'
;
import
{
Row
,
Col
,
Tabs
,
Tooltip
,
}
from
'antd'
;
import
{
QuestionCircleOutlined
}
from
'@ant-design/icons'
;
import
classNames
from
'classnames'
;
import
PolymericTable
from
'@/components/PolymericTable'
;
import
{
EditableColumns
}
from
'@/components/PolymericTable/interface'
;
import
MellowCard
from
'@/components/MellowCard'
;
import
styles
from
'./index.less'
;
import
equity_1
from
'@/asserts/equity-1.png'
;
import
equity_2
from
'@/asserts/equity-2.png'
;
import
equity_3
from
'@/asserts/equity-3.png'
;
import
equity_4
from
'@/asserts/equity-4.png'
;
import
equity_5
from
'@/asserts/equity-5.png'
;
const
imgMap
=
{
1
:
equity_1
,
2
:
equity_2
,
3
:
equity_3
,
4
:
equity_4
,
5
:
equity_5
,
}
const
{
TabPane
}
=
Tabs
;
const
PAGE_SIZE
=
8
;
export
interface
ReceivedData
{
id
?:
number
;
createTime
?:
string
;
ruleName
?:
string
;
score
?:
number
;
remark
?:
string
;
};
export
interface
UsageData
{
id
?:
number
;
createTime
?:
string
;
rightTypeName
?:
string
;
spendTypeName
?:
string
;
point
?:
number
;
remark
?:
string
;
};
export
interface
FetchParams
{
current
:
number
;
pageSize
:
number
;
};
export
interface
EquityInfoProps
{
equityInfo
?:
{
sumReturnMoney
?:
number
,
// 累计返现金额
sumUsedPoint
?:
number
,
// 已用积分
sumPoint
?:
number
,
// 累计积分
rights
?:
{
acquireWay
:
string
,
id
:
number
,
name
:
string
,
paramWay
:
string
,
parameter
:
string
,
remark
:
string
,
rightTypeEnum
:
number
,
status
:
number
,
}[];
};
fetchReceivedList
?:
(
params
:
FetchParams
)
=>
Promise
<
{
data
:
ReceivedData
[]
,
totalCount
:
number
}
>
;
fetchUsageList
?:
(
params
:
FetchParams
)
=>
Promise
<
{
data
:
UsageData
[]
,
totalCount
:
number
}
>
;
}
const
equityTxtMap
=
{
1
:
'折扣'
,
2
:
'返现'
,
3
:
'积分'
,
};
const
clsMap
=
{
1
:
'tofo-item-tag-price'
,
2
:
'tofo-item-tag-recurrence'
,
3
:
'tofo-item-tag-integral'
,
};
const
EquityInfo
:
React
.
FC
<
EquityInfoProps
>
=
({
equityInfo
=
{},
fetchReceivedList
,
fetchUsageList
,
})
=>
{
const
[
receivedPage
,
setReceivedPage
]
=
useState
(
1
);
const
[
receivedSize
,
setReceivedSize
]
=
useState
(
PAGE_SIZE
);
const
[
receivedTotal
,
setReceivedTotal
]
=
useState
(
0
);
const
[
receivedList
,
setReceivedList
]
=
useState
<
ReceivedData
[]
>
([]);
const
[
receivedListLoading
,
setReceivedListLoading
]
=
useState
(
false
);
const
[
usagePage
,
setUsagePage
]
=
useState
(
1
);
const
[
usageSize
,
setUsageSize
]
=
useState
(
PAGE_SIZE
);
const
[
usageTotal
,
setUsageTotal
]
=
useState
(
0
);
const
[
usageList
,
setUsageList
]
=
useState
<
UsageData
[]
>
([]);
const
[
usageListLoading
,
setUsageListLoading
]
=
useState
(
false
);
const
receivedColumns
:
EditableColumns
[]
=
[
{
title
:
'ID'
,
dataIndex
:
'id'
,
align
:
'center'
,
},
{
title
:
'会员权益名称'
,
dataIndex
:
'rightTypeName '
,
align
:
'center'
,
},
{
title
:
'获取数量'
,
dataIndex
:
'point'
,
align
:
'center'
,
},
{
title
:
'获取时间'
,
dataIndex
:
'createTime'
,
align
:
'center'
,
},
{
title
:
'备注'
,
dataIndex
:
'remark'
,
align
:
'center'
,
ellipsis
:
true
,
},
];
const
usageColumns
:
EditableColumns
[]
=
[
{
title
:
'ID'
,
dataIndex
:
'id'
,
align
:
'center'
,
},
{
title
:
'会员权益名称'
,
dataIndex
:
'rightTypeName'
,
align
:
'center'
,
},
{
title
:
'会员权益使用名称'
,
dataIndex
:
'spendTypeName'
,
align
:
'center'
,
},
{
title
:
'使用数量'
,
dataIndex
:
'point'
,
align
:
'center'
,
},
{
title
:
'使用时间'
,
dataIndex
:
'createTime'
,
align
:
'center'
,
},
{
title
:
'备注'
,
dataIndex
:
'remark'
,
align
:
'center'
,
ellipsis
:
true
,
},
];
const
getReceivedList
=
(
params
?)
=>
{
if
(
fetchReceivedList
)
{
if
(
receivedListLoading
)
{
return
;
}
setReceivedListLoading
(
true
);
fetchReceivedList
({
current
:
receivedPage
,
pageSize
:
receivedSize
,
...
params
,
}).
then
(
res
=>
{
const
{
data
=
[],
totalCount
=
0
}
=
(
res
||
{});
setReceivedList
(
data
);
setReceivedTotal
(
totalCount
);
}).
finally
(()
=>
{
setReceivedListLoading
(
false
);
});
}
};
const
getUsageList
=
(
params
?)
=>
{
if
(
fetchUsageList
)
{
if
(
usageListLoading
)
{
return
;
}
setUsageListLoading
(
true
);
fetchUsageList
({
current
:
usagePage
,
pageSize
:
usageSize
,
...
params
,
}).
then
(
res
=>
{
const
{
data
=
[],
totalCount
=
0
}
=
(
res
||
{});
setUsageList
(
data
);
setUsageTotal
(
totalCount
);
}).
finally
(()
=>
{
setUsageListLoading
(
false
);
});
}
};
useEffect
(()
=>
{
getReceivedList
();
},
[]);
const
handleTabChange
=
key
=>
{
switch
(
key
)
{
case
'1'
:
getReceivedList
();
break
;
case
'2'
:
getUsageList
();
break
;
default
:
break
;
}
};
const
handleReceivedPaginationChange
=
(
page
:
number
,
size
:
number
)
=>
{
setReceivedPage
(
page
);
setReceivedSize
(
size
);
getReceivedList
({
current
:
page
,
pageSize
:
size
,
});
};
const
handleUsagePaginationChange
=
(
page
:
number
,
size
:
number
)
=>
{
setUsagePage
(
page
);
setUsageSize
(
size
);
getUsageList
({
current
:
page
,
pageSize
:
size
,
});
};
return
(
<
div
className=
{
styles
.
equityInfo
}
>
<
Row
gutter=
{
[
0
,
24
]
}
>
<
Col
span=
{
24
}
>
<
Row
gutter=
{
24
}
>
<
Col
span=
{
8
}
>
<
div
className=
{
styles
.
container
}
>
<
div
className=
{
styles
[
'container-title'
]
}
>
当前权益
</
div
>
<
div
className=
{
styles
[
'container-content'
]
}
>
<
ul
className=
{
styles
.
tofo
}
>
{
equityInfo
.
rights
?
equityInfo
.
rights
.
map
(
item
=>
(
<
li
key=
{
item
.
id
}
className=
{
styles
[
'tofo-item'
]
}
>
<
div
className=
{
styles
[
'tofo-item-logo'
]
}
>
<
img
src=
{
imgMap
[
item
.
rightTypeEnum
]
}
/>
</
div
>
<
div
className=
{
styles
[
'tofo-item-title'
]
}
>
{
item
.
name
}
<
Tooltip
title=
{
item
.
remark
}
>
<
QuestionCircleOutlined
/>
</
Tooltip
>
</
div
>
<
div
className=
{
styles
[
'tofo-item-extra'
]
}
>
<
span
className=
{
classNames
(
styles
[
'tofo-item-tag'
],
styles
[
clsMap
[
item
.
rightTypeEnum
]])
}
>
{
item
.
parameter
}
%
{
equityTxtMap
[
item
.
rightTypeEnum
]
||
''
}
</
span
>
</
div
>
</
li
>
))
:
null
}
</
ul
>
</
div
>
</
div
>
</
Col
>
<
Col
span=
{
8
}
>
<
div
className=
{
styles
.
container
}
>
<
div
className=
{
styles
[
'container-content'
]
}
>
<
div
className=
{
styles
.
exhibition
}
>
<
div
className=
{
styles
[
'exhibition-left'
]
}
>
<
div
className=
{
styles
[
'exhibition-title'
]
}
>
累计返现金额
</
div
>
<
div
className=
{
styles
[
'exhibition-amount'
]
}
>
{
equityInfo
?.
sumReturnMoney
}
<
span
>
CNY
</
span
>
</
div
>
</
div
>
<
div
className=
{
styles
[
'exhibition-right'
]
}
>
<
div
className=
{
styles
[
'exhibition-logo'
]
}
>
<
img
src=
{
imgMap
[
'4'
]
}
/>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
Col
>
<
Col
span=
{
8
}
>
<
div
className=
{
styles
.
container
}
>
<
div
className=
{
styles
[
'container-content'
]
}
>
<
div
className=
{
styles
.
exhibition
}
>
<
div
className=
{
styles
[
'exhibition-left'
]
}
>
<
div
className=
{
styles
[
'exhibition-title'
]
}
>
已用积分/总积分
</
div
>
<
div
className=
{
styles
[
'exhibition-amount'
]
}
>
{
equityInfo
?.
sumUsedPoint
}
/
{
equityInfo
?.
sumPoint
}
</
div
>
</
div
>
<
div
className=
{
styles
[
'exhibition-right'
]
}
>
<
div
className=
{
styles
[
'exhibition-logo'
]
}
>
<
img
src=
{
imgMap
[
'5'
]
}
/>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
Col
>
</
Row
>
</
Col
>
<
Col
span=
{
24
}
>
<
MellowCard
title=
"活跃分获取记录"
>
<
Tabs
onChange=
{
handleTabChange
}
>
<
TabPane
tab=
"权益获取记录"
key=
"1"
>
<
PolymericTable
dataSource=
{
receivedList
}
columns=
{
receivedColumns
}
loading=
{
receivedListLoading
}
pagination=
{
{
pageSize
:
receivedSize
,
total
:
receivedTotal
,
}
}
onPaginationChange=
{
handleReceivedPaginationChange
}
/>
</
TabPane
>
<
TabPane
tab=
"权益使用记录"
key=
"2"
>
<
PolymericTable
dataSource=
{
usageList
}
columns=
{
usageColumns
}
loading=
{
usageListLoading
}
pagination=
{
{
pageSize
:
usageSize
,
total
:
usageTotal
,
}
}
onPaginationChange=
{
handleUsagePaginationChange
}
/>
</
TabPane
>
</
Tabs
>
</
MellowCard
>
</
Col
>
</
Row
>
</
div
>
);
};
export
default
EquityInfo
;
src/pages/memberManage/components/FlowRecords/index.less
0 → 100644
View file @
593349ab
src/pages/memberManage/components/FlowRecords/index.tsx
0 → 100644
View file @
593349ab
import
React
from
'react'
;
import
{
Tabs
,
Badge
,
}
from
'antd'
;
import
PolymericTable
from
'@/components/PolymericTable'
;
import
{
EditableColumns
}
from
'@/components/PolymericTable/interface'
;
import
MellowCard
from
'@/components/MellowCard'
;
import
StatusTag
from
'@/components/StatusTag'
;
import
{
MEMBER_INNER_STATUS_BADGE_COLOR
,
MEMBER_OUTER_STATUS_TYPE
,
}
from
'../../constant'
;
export
interface
InnerHistoryItem
{
createTime
?:
string
,
id
?:
number
,
innerStatus
?:
number
,
innerStatusName
?:
string
,
operation
?:
string
,
operatorJobTitle
?:
string
,
operatorName
?:
string
,
operatorOrgName
?:
string
,
remark
?:
string
,
};
export
interface
OuterHistoryItem
{
createTime
?:
string
,
id
?:
number
,
operation
?:
string
,
operatorRoleName
?:
string
,
outerStatus
?:
number
,
outerStatusName
?:
string
,
remark
?:
string
,
};
interface
FlowRecordsProps
{
outerHistory
?:
OuterHistoryItem
[];
innerHistory
?:
InnerHistoryItem
[];
};
const
FlowRecords
:
React
.
FC
<
FlowRecordsProps
>
=
({
outerHistory
=
[],
innerHistory
=
[]
})
=>
{
const
outerColumns
:
EditableColumns
<
OuterHistoryItem
>
[]
=
[
{
title
:
'序号'
,
dataIndex
:
'index'
,
align
:
'center'
,
render
:
(
text
,
record
,
index
)
=>
index
+
1
,
},
{
title
:
'操作角色'
,
dataIndex
:
'operatorRoleName'
,
align
:
'center'
,
},
{
title
:
'状态'
,
dataIndex
:
'outerStatusName'
,
align
:
'center'
,
render
:
(
text
,
record
)
=>
(
<
StatusTag
type=
{
MEMBER_OUTER_STATUS_TYPE
[
record
.
outerStatus
as
number
]
}
title=
{
text
}
/>
),
},
{
title
:
'操作'
,
dataIndex
:
'operation'
,
align
:
'center'
,
},
{
title
:
'操作时间'
,
dataIndex
:
'createTime'
,
align
:
'center'
,
ellipsis
:
true
,
},
{
title
:
'审核意见'
,
dataIndex
:
'remark'
,
align
:
'center'
,
ellipsis
:
true
,
},
];
const
innerColumns
:
EditableColumns
<
InnerHistoryItem
>
[]
=
[
{
title
:
'序号'
,
dataIndex
:
'index'
,
align
:
'center'
,
render
:
(
text
,
record
,
index
)
=>
index
+
1
,
},
{
title
:
'操作人'
,
dataIndex
:
'operatorName'
,
align
:
'center'
,
},
{
title
:
'部门'
,
dataIndex
:
'operatorOrgName'
,
align
:
'center'
,
},
{
title
:
'职位'
,
dataIndex
:
'operatorJobTitle'
,
align
:
'center'
,
},
{
title
:
'状态'
,
dataIndex
:
'innerStatusName'
,
align
:
'center'
,
render
:
(
text
,
record
)
=>
(
<
Badge
color=
{
MEMBER_INNER_STATUS_BADGE_COLOR
[
record
.
innerStatus
as
number
]
||
'#606266'
}
text=
{
text
}
/>
),
},
{
title
:
'操作'
,
dataIndex
:
'operation'
,
align
:
'center'
,
},
{
title
:
'操作时间'
,
dataIndex
:
'createTime'
,
align
:
'center'
,
ellipsis
:
true
,
},
{
title
:
'审核意见'
,
dataIndex
:
'remark'
,
align
:
'center'
,
ellipsis
:
true
,
},
];
return
(
<
MellowCard
>
<
Tabs
onChange=
{
()
=>
{
}
}
>
<
Tabs
.
TabPane
tab=
"流转记录"
key=
"1"
>
<
PolymericTable
dataSource=
{
outerHistory
}
columns=
{
outerColumns
}
loading=
{
false
}
pagination=
{
null
}
/>
</
Tabs
.
TabPane
>
<
Tabs
.
TabPane
tab=
"内部单据流转记录"
key=
"2"
>
<
PolymericTable
dataSource=
{
innerHistory
}
columns=
{
innerColumns
}
loading=
{
false
}
pagination=
{
null
}
/>
</
Tabs
.
TabPane
>
</
Tabs
>
</
MellowCard
>
);
};
export
default
FlowRecords
;
\ No newline at end of file
src/pages/memberManage/components/HeadInfo/index.less
0 → 100644
View file @
593349ab
.head {
display: flex;
align-items: center;
font-size: 18px;
font-weight: 500;
&-prefix {
width: 48px;
height: 48px;
line-height: 48px;
border-radius: 4px;
border: 1px solid #DFE1E6;
color: #fff;
text-align: center;
background-color: #8777D9;
}
&-name {
color: #303133;
margin: 0 8px 0 12px;
}
}
src/pages/memberManage/components/HeadInfo/index.tsx
0 → 100644
View file @
593349ab
import
React
from
'react'
;
import
LevelBrand
from
'../LevelBrand'
;
import
styles
from
'./index.less'
;
export
interface
HeadInfoProps
{
info
:
{
name
?:
string
,
level
?:
number
,
};
extra
?:
React
.
ReactNode
;
};
const
HeadInfo
:
React
.
FC
<
HeadInfoProps
>
=
({
info
,
extra
})
=>
(
<
div
className=
{
styles
.
head
}
>
<
div
className=
{
styles
[
'head-prefix'
]
}
>
{
info
&&
info
.
name
&&
info
.
name
.
length
?
info
.
name
[
0
]
:
''
}
</
div
>
<
div
className=
{
styles
[
'head-name'
]
}
>
{
info
.
name
||
''
}
</
div
>
{
!
extra
?
(
<
LevelBrand
level=
{
info
.
level
}
/>
)
:
extra
}
</
div
>
);
export
default
HeadInfo
;
\ No newline at end of file
src/pages/memberManage/components/LevelBrand/index.less
0 → 100644
View file @
593349ab
.brand {
display: inline-block;
width: 54px;
height: 16px;
line-height: 16px;
> img {
width: 100%;
height: 100%;
}
}
\ No newline at end of file
src/pages/memberManage/components/LevelBrand/index.tsx
0 → 100644
View file @
593349ab
import
React
from
'react'
;
import
p_level1
from
'@/asserts/level1.png'
;
import
p_level2
from
'@/asserts/level2.png'
;
import
p_level3
from
'@/asserts/level3.png'
;
import
p_level4
from
'@/asserts/level4.png'
;
import
styles
from
'./index.less'
;
enum
levelEnum
{
'青铜会员'
=
1
,
'白银会员'
=
2
,
'黄金会员'
=
3
,
'钻石会员'
=
4
,
}
export
interface
LevelBrandProps
{
level
:
levelEnum
;
};
const
PIC_MAP
=
{
1
:
p_level1
,
2
:
p_level2
,
3
:
p_level3
,
4
:
p_level4
,
};
const
LevelBrand
:
React
.
FC
<
LevelBrandProps
>
=
({
level
})
=>
{
const
current
=
PIC_MAP
[
level
]
||
''
;
return
(
<
div
className=
{
styles
.
brand
}
>
{
current
&&
<
img
src=
{
current
}
/>
}
</
div
>
);
};
export
default
LevelBrand
;
\ No newline at end of file
src/pages/memberManage/components/LevelInfo/index.less
0 → 100644
View file @
593349ab
@card-prefix: card;
.levelInfo {
.infoWrap {
display: flex;
&-left {
margin-right: 40px;
flex-shrink: 0;
}
&-right {
flex: 1;
}
}
.card {
width: 338px;
height: 190px;
padding: 32px 24px 16px 24px;
background: linear-gradient(135deg, rgba(255, 235, 225, 1) 0%, rgba(251, 196, 167, 1) 100%);
box-shadow: 0 1px 2px 0 rgba(23, 43, 77, 0.12);
border-radius: 8px;
position: relative;
z-index: 0;
&-name {
min-height: 33px;
margin-bottom: 48px;
line-height: 33px;
font-size: 24px;
font-weight: 500;
color: rgba(164, 114, 104, 1);
}
&-progress {
padding: 0 72px 0 0;
:global {
.ant-progress-bg {
background: rgba(164, 114, 104, 1) !important;
}
.ant-progress-inner {
background-color: rgb(233, 191, 169, 1) !important;
}
}
}
&-txt {
display: flex;
justify-content: space-between;
}
&-experience {
font-size: 12px;
font-weight: 400;
color: rgba(164, 114, 104, 1);
line-height: 20px;
}
&-higher {
font-size: 12px;
font-weight: 400;
color: rgba(186, 140, 115, 1);
line-height: 20px;
}
&-level2 {
background: linear-gradient(135deg, rgba(233, 244, 255, 1) 0%, rgba(164, 185, 223, 1) 100%);
box-shadow: 0 1px 2px 0 rgba(23, 43, 77, 0.12);
.@{card-prefix} {
&-name {
color: rgba(91, 111, 146, 1);
}
&-progress {
:global {
.ant-progress-bg {
background: rgba(87, 108, 143, 1) !important;
}
.ant-progress-inner {
background-color: rgba(171, 192, 220, 1) !important;
}
}
}
&-experience {
color: rgba(91, 111, 146, 1);
}
&-higher {
color: rgba(133, 150, 179, 1);
}
}
}
&-level3 {
background: linear-gradient(135deg, rgba(255, 245, 222, 1) 0%, rgba(212, 191, 146, 1) 100%);
box-shadow: 0 1px 2px 0 rgba(23, 43, 77, 0.12);
.@{card-prefix} {
&-name {
color: rgba(141, 107, 56, 1);
}
&-progress {
:global {
.ant-progress-bg {
background: rgba(141, 107, 56, 1) !important;
}
.ant-progress-inner {
background-color: rgba(214, 195, 157, 1) !important;
}
}
}
&-experience {
color: rgba(141, 107, 56, 1);
}
&-higher {
color: rgba(174, 154, 113, 1);
}
}
}
&-level4 {
background: linear-gradient(135deg, rgba(232, 239, 255, 1) 0%, rgba(157, 162, 194, 1) 100%);
box-shadow: 0 1px 2px 0 rgba(23, 43, 77, 0.12);
.@{card-prefix} {
&-name {
color: rgba(89, 91, 113, 1);
}
&-progress {
:global {
.ant-progress-bg {
background: rgba(89, 91, 113, 1) !important;
}
.ant-progress-inner {
background-color: rgba(167, 170, 198, 1) !important;
}
}
}
&-experience {
color: rgba(89, 91, 113, 1);
}
&-higher {
color: rgba(134, 136, 166, 1);
}
}
}
&::after {
content: '';
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 100px;
z-index: -1;
width: 100px;
transform: skewX(24deg);
background: linear-gradient(rgba(255, 255, 255, .2), rgba(255, 255, 255, 0));
}
}
}
\ No newline at end of file
src/pages/memberManage/components/LevelInfo/index.tsx
0 → 100644
View file @
593349ab
import
React
,
{
useState
,
useEffect
}
from
'react'
;
import
{
Row
,
Col
,
Progress
,
}
from
'antd'
;
import
classNames
from
'classnames'
;
import
{
MiniArea
}
from
'@/components/Charts'
;
import
PolymericTable
from
'@/components/PolymericTable'
;
import
{
EditableColumns
}
from
'@/components/PolymericTable/interface'
;
import
MellowCard
from
'@/components/MellowCard'
;
import
styles
from
'./index.less'
;
const
PAGE_SIZE
=
8
;
export
interface
DataProps
{
id
?:
number
;
createTime
?:
string
;
ruleName
?:
string
;
score
?:
number
;
remark
?:
string
;
};
export
interface
FetchParams
{
current
:
number
;
pageSize
:
number
;
};
export
interface
LevelInfoProps
{
levelInfo
?:
{
level
?:
string
,
score
?:
number
,
nextLevel
?:
string
,
nextScore
?:
number
,
};
chartData
?:
{
x
:
React
.
ReactText
,
y
:
number
,
}[];
fetchList
?:
(
params
:
FetchParams
)
=>
Promise
<
{
data
:
DataProps
[],
totalCount
:
number
}
>
;
}
const
LevelInfo
:
React
.
FC
<
LevelInfoProps
>
=
({
levelInfo
=
{},
chartData
=
[],
fetchList
,
})
=>
{
const
score
=
levelInfo
.
score
||
0
;
const
nextScore
=
levelInfo
.
nextScore
||
0
;
const
[
page
,
setPage
]
=
useState
(
1
);
const
[
size
,
setSize
]
=
useState
(
PAGE_SIZE
);
const
[
total
,
setTotal
]
=
useState
(
0
);
const
[
list
,
setList
]
=
useState
<
DataProps
[]
>
([]);
const
[
listLoading
,
setListLoading
]
=
useState
(
false
);
const
columns
:
EditableColumns
[]
=
[
{
title
:
'ID'
,
dataIndex
:
'id'
,
align
:
'center'
,
},
{
title
:
'获取项目'
,
dataIndex
:
'ruleName'
,
align
:
'center'
,
},
{
title
:
'获取分值'
,
dataIndex
:
'score'
,
align
:
'center'
,
},
{
title
:
'获取时间'
,
dataIndex
:
'createTime'
,
align
:
'center'
,
},
{
title
:
'备注'
,
dataIndex
:
'remark'
,
align
:
'center'
,
ellipsis
:
true
,
},
];
const
getHistoryList
=
(
params
?)
=>
{
if
(
fetchList
)
{
setListLoading
(
true
);
fetchList
({
current
:
page
,
pageSize
:
size
,
...
params
,
}).
then
(
res
=>
{
const
{
data
=
[],
totalCount
=
0
}
=
(
res
||
{});
setList
(
data
);
setTotal
(
totalCount
);
}).
finally
(()
=>
{
setListLoading
(
false
);
});
}
};
useEffect
(()
=>
{
getHistoryList
();
},
[]);
const
handlePaginationChange
=
(
current
:
number
,
pageSize
:
number
)
=>
{
setPage
(
page
);
setSize
(
size
);
getHistoryList
({
current
,
pageSize
,
});
};
return
(
<
div
className=
{
styles
.
levelInfo
}
>
<
Row
gutter=
{
[
0
,
24
]
}
>
<
Col
span=
{
24
}
>
<
MellowCard
title=
"会员等级"
headStyle=
{
{
borderBottom
:
'none'
,
}
}
>
<
div
className=
{
styles
.
infoWrap
}
>
<
div
className=
{
styles
[
'infoWrap-left'
]
}
>
<
div
className=
{
classNames
(
styles
.
card
,
styles
[
'card-level1'
])
}
>
<
div
className=
{
styles
[
'card-name'
]
}
>
{
levelInfo
?.
level
}
</
div
>
<
div
className=
{
styles
[
'card-progress'
]
}
>
<
Progress
strokeWidth=
{
4
}
strokeLinecap=
"square"
showInfo=
{
false
}
percent=
{
nextScore
?
(
score
/
nextScore
)
*
100
:
100
}
/>
</
div
>
<
div
className=
{
styles
[
'card-txt'
]
}
>
<
div
className=
{
styles
[
'card-experience'
]
}
>
{
score
}
/
{
nextScore
}
</
div
>
<
div
className=
{
styles
[
'card-higher'
]
}
>
{
levelInfo
.
nextLevel
}
</
div
>
</
div
>
<
div
className=
{
styles
[
'card-higher'
]
}
>
当前活跃分
</
div
>
</
div
>
</
div
>
<
div
className=
{
styles
[
'infoWrap-right'
]
}
>
<
MiniArea
animate=
{
false
}
line
borderWidth=
{
2
}
height=
{
180
}
padding=
{
[
10
,
20
,
50
,
60
]
}
scale=
{
{
x
:
{
alias
:
`${new Date().getFullYear()}年`
,
// 别名
},
y
:
{
tickCount
:
5
,
alias
:
'活跃分'
,
// 别名
},
}
}
xAxis=
{
{
tickLine
:
undefined
,
label
:
undefined
,
title
:
{
style
:
{
fontSize
:
12
,
fill
:
'#C0C4CC'
,
fontWeight
:
400
,
rotate
:
90
,
},
},
}
}
yAxis=
{
{
tickLine
:
undefined
,
label
:
{
offset
:
10
,
},
title
:
{
style
:
{
fontSize
:
12
,
fill
:
'#C0C4CC'
,
fontWeight
:
400
,
rotate
:
90
,
},
},
grid
:
{
line
:
{
type
:
'line'
,
style
:
{
stroke
:
"#d9d9d9"
,
lineWidth
:
1
,
lineDash
:
[
2
,
2
]
}
}
},
}
}
color=
"l(90) 0:#AAC5FC 1:#FFFFFF"
data=
{
chartData
}
/>
</
div
>
</
div
>
</
MellowCard
>
</
Col
>
<
Col
span=
{
24
}
>
<
MellowCard
title=
"活跃分获取记录"
headStyle=
{
{
borderBottom
:
'none'
,
}
}
>
<
PolymericTable
dataSource=
{
list
}
columns=
{
columns
}
loading=
{
listLoading
}
pagination=
{
{
pageSize
:
size
,
total
,
}
}
onPaginationChange=
{
handlePaginationChange
}
/>
</
MellowCard
>
</
Col
>
</
Row
>
</
div
>
);
};
export
default
LevelInfo
;
src/pages/memberManage/components/PicWrap/index.less
0 → 100644
View file @
593349ab
.list {
display: flex;
align-items: center;
flex-wrap: wrap;
padding: 0;
margin: 0;
width: 100%;
overflow-x: auto;
&-item {
width: 175px;
height: 120px;
padding: 0 28px;
margin-bottom: 10px;
background: rgba(255, 255, 255, 1);
border: 1px solid rgba(235,236,240,1);
overflow: hidden;
list-style: none;
&:not(:last-child) {
margin-right: 16px;
}
> img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
}
\ No newline at end of file
src/pages/memberManage/components/PicWrap/index.tsx
0 → 100644
View file @
593349ab
import
React
from
'react'
;
import
styles
from
'./index.less'
;
interface
PicWrapProps
{
pics
:
string
[];
};
const
PicWrap
:
React
.
FC
<
PicWrapProps
>
=
({
pics
=
[]
})
=>
(
<
ul
className=
{
styles
.
list
}
>
{
pics
.
map
((
item
,
index
)
=>
(
<
li
key=
{
index
}
className=
{
styles
[
'list-item'
]
}
>
<
img
src=
{
item
}
/>
</
li
>
))
}
</
ul
>
);
export
default
PicWrap
;
\ No newline at end of file
src/pages/memberManage/components/SincerityInfo/index.less
0 → 100644
View file @
593349ab
.sincerityInfo {
.tofo {
height: 100%;
:global {
.antd-card {
height: 100%;
}
}
&-item {
width: 50%;
padding: 55px 24px;
&-logo {
width: 72px;
height: 72px;
}
}
}
}
.contentBox {
position: relative;
padding-right: 72px;
background: #ffffff;
&-main {
}
&-extra {
position: absolute;
top: 0;
right: 0;
bottom: 0;
}
.title {
margin-bottom: 20px;
line-height: 20px;
font-size: 12px;
font-weight: 400;
color: rgba(107, 119, 140, 1);
:global {
.anticon {
margin-left: 6px;
}
}
}
.txt {
line-height: 32px;
font-size: 24px;
font-weight: 500;
color: rgba(23, 43, 77, 1);
}
}
.record {
&-tabs {
:global {
.ant-tabs-nav::before {
border-bottom: none;
}
}
}
&-btns {
margin-bottom: 16px;
}
&-row {
:global {
.ant-table-cell:first-child {
background-color: rgba(250, 251, 252, 1);
}
}
}
}
\ No newline at end of file
src/pages/memberManage/components/SincerityInfo/index.tsx
0 → 100644
View file @
593349ab
import
React
,
{
useState
,
useEffect
}
from
'react'
;
import
{
Row
,
Col
,
Tabs
,
Card
,
Tooltip
,
Radio
,
Button
,
Spin
,
}
from
'antd'
;
import
{
QuestionCircleOutlined
,
SmileFilled
,
MehFilled
,
FrownFilled
,
}
from
'@ant-design/icons'
;
import
{
isJSONStr
}
from
'@/utils'
;
import
PolymericTable
from
'@/components/PolymericTable'
;
import
{
EditableColumns
}
from
'@/components/PolymericTable/interface'
;
import
{
Pie
}
from
'@/components/Charts'
;
import
MellowCard
from
'@/components/MellowCard'
;
import
styles
from
'./index.less'
;
import
equity_1
from
'@/asserts/equity-1.png'
;
import
equity_2
from
'@/asserts/equity-2.png'
;
import
equity_3
from
'@/asserts/equity-3.png'
;
import
equity_4
from
'@/asserts/equity-4.png'
;
import
equity_5
from
'@/asserts/equity-5.png'
;
const
imgMap
=
{
1
:
equity_1
,
2
:
equity_2
,
3
:
equity_3
,
4
:
equity_4
,
5
:
equity_5
,
}
const
{
TabPane
}
=
Tabs
;
interface
ContentBoxProps
{
title
?:
string
;
desc
?:
string
;
content
?:
React
.
ReactNode
;
extra
?:
React
.
ReactNode
;
};
const
ContentBox
:
React
.
FC
<
ContentBoxProps
>
=
({
title
=
'我是标题'
,
content
,
extra
,
desc
,
})
=>
(
<
div
className=
{
styles
.
contentBox
}
>
<
div
className=
{
styles
[
'contentBox-main'
]
}
>
<
div
className=
{
styles
.
title
}
>
{
title
}
<
Tooltip
title=
{
desc
}
>
<
QuestionCircleOutlined
/>
</
Tooltip
>
</
div
>
<
div
className=
{
styles
.
txt
}
>
{
content
}
</
div
>
</
div
>
<
div
className=
{
styles
[
'contentBox-extra'
]
}
>
{
extra
}
</
div
>
</
div
>
);
interface
MoodProps
{
type
:
'smile'
|
'notBad'
|
'sad'
;
};
const
Mood
:
React
.
FC
<
MoodProps
>
=
({
type
=
'smile'
})
=>
{
let
node
:
any
=
null
;
switch
(
type
)
{
case
'smile'
:
node
=
<><
SmileFilled
style=
{
{
color
:
'#41CC9E'
,
marginRight
:
4
}
}
/>
好评
</>;
break
;
case
'notBad'
:
node
=
<><
MehFilled
style=
{
{
color
:
'#FFC400'
,
marginRight
:
4
}
}
/>
中评
</>;
break
;
case
'sad'
:
node
=
<><
FrownFilled
style=
{
{
color
:
'#EF6260'
,
marginRight
:
4
}
}
/>
差评
</>;
break
;
default
:
break
;
}
return
node
;
};
const
PAGE_SIZE
=
5
;
export
interface
BasicInfo
{
pieData
:
{
x
:
string
,
y
:
number
,
}[],
items
:
{
id
:
number
,
creditTypeName
:
string
,
remark
:
string
,
creditPoint
:
number
,
currentPoint
:
number
,
}[],
loading
?:
boolean
,
};
export
interface
EstimateSumItems
{
id
?:
number
,
title
?:
JSX
.
Element
,
star
?:
number
,
last7days
?:
number
,
last30days
?:
number
,
last180days
?:
number
,
before180days
?:
number
,
sum
?:
number
,
};
export
interface
EstimateSum
{
dataSource
:
EstimateSumItems
[],
loading
?:
boolean
,
};
export
interface
ComplaintSum
{
dataSource
:
EstimateSumItems
,
loading
?:
boolean
,
};
export
interface
FetchParams
{
current
:
number
;
pageSize
:
number
;
};
export
interface
SalesProps
{
id
?:
number
;
createTime
?:
string
;
star
?:
number
;
comment
?:
string
;
product
?:
string
;
byMemberName
?:
string
;
remark
?:
string
;
};
export
interface
ComplaintProps
{
id
?:
number
;
createTime
?:
string
;
content
?:
string
;
reason
?:
string
;
byMemberName
?:
string
;
remark
?:
string
;
};
interface
SincerityInfoProps
{
basicInfo
?:
BasicInfo
;
salesEstimateSum
?:
EstimateSum
;
fetchSalesList
?:
(
params
:
FetchParams
)
=>
Promise
<
{
data
:
SalesProps
[]
,
totalCount
:
number
}
>
;
afterEstimateSum
?:
EstimateSum
;
fetchAfterList
?:
(
params
:
FetchParams
)
=>
Promise
<
{
data
:
SalesProps
[]
,
totalCount
:
number
}
>
;
complaintSum
?:
ComplaintSum
;
fetchComplaintList
?:
(
params
:
FetchParams
)
=>
Promise
<
{
data
:
ComplaintProps
[]
,
totalCount
:
number
}
>
;
};
const
SincerityInfo
:
React
.
FC
<
SincerityInfoProps
>
=
({
basicInfo
=
{},
salesEstimateSum
=
{},
fetchSalesList
,
afterEstimateSum
=
{},
fetchAfterList
,
complaintSum
=
{},
fetchComplaintList
,
})
=>
{
const
creditData
=
basicInfo
.
pieData
||
[];
const
integralItems
=
basicInfo
.
items
||
[];
const
{
dataSource
:
complaintSumData
}
=
complaintSum
;
const
[
salesEvaluate
,
setSalesEvaluate
]
=
useState
<
EstimateSumItems
[]
>
([]);
const
[
salesEvaluatePie
,
setSalesEvaluatePie
]
=
useState
<
{
x
:
string
,
y
:
number
}[]
>
([]);
const
[
afterEvaluate
,
setAfterEvaluate
]
=
useState
<
EstimateSumItems
[]
>
([]);
const
[
afterEvaluatePie
,
setAfterEvaluatePie
]
=
useState
<
{
x
:
string
,
y
:
number
}[]
>
([]);
const
[
salesTabKey
,
setSalesTabKey
]
=
useState
(
'evaluateSum'
);
const
[
afterTabKey
,
setAfterTabKey
]
=
useState
(
'evaluateSum'
);
const
[
salesPage
,
setSalesPage
]
=
useState
(
1
);
const
[
salesSize
,
setSalesSize
]
=
useState
(
PAGE_SIZE
);
const
[
salesTotal
,
setSalesTotal
]
=
useState
(
0
);
const
[
salesList
,
setSalesList
]
=
useState
<
any
[]
>
([]);
const
[
salesListLoading
,
setSalesListLoading
]
=
useState
(
false
);
const
[
afterPage
,
setAfterPage
]
=
useState
(
1
);
const
[
afterSize
,
setAfterSize
]
=
useState
(
PAGE_SIZE
);
const
[
afterTotal
,
setAfterTotal
]
=
useState
(
0
);
const
[
afterList
,
setAfterList
]
=
useState
<
any
>
([]);
const
[
afterListLoading
,
setAfterListLoading
]
=
useState
(
false
);
const
[
complainPage
,
setComplainPage
]
=
useState
(
1
);
const
[
complainSize
,
setComplainSize
]
=
useState
(
PAGE_SIZE
);
const
[
complainTotal
,
setComplainTotal
]
=
useState
(
0
);
const
[
complainList
,
setComplainList
]
=
useState
<
any
[]
>
([]);
const
[
complainListLoading
,
setComplainListLoading
]
=
useState
(
false
);
const
exchangeMood
=
(
star
:
number
):
React
.
ReactNode
=>
{
let
node
:
any
=
null
;
switch
(
star
)
{
case
1
:
case
2
:
{
node
=
(
<>
<
Mood
type=
"sad"
/>
<
span
>
差评
</
span
>
</>
);
break
;
}
case
3
:
{
node
=
(
<>
<
Mood
type=
"notBad"
/>
<
span
>
中评
</
span
>
</>
);
break
;
}
case
4
:
case
5
:
{
node
=
(
<>
<
Mood
type=
"smile"
/>
<
span
>
好评
</
span
>
</>
);
break
;
}
default
:
break
;
}
return
node
;
};
const
recordColumns
:
EditableColumns
[]
=
[
{
title
:
'投诉单号'
,
dataIndex
:
'remark'
,
},
{
title
:
'摘要'
,
dataIndex
:
'content'
,
ellipsis
:
true
,
},
{
title
:
'投诉方'
,
dataIndex
:
'byMemberName'
,
},
{
title
:
'投诉原因'
,
dataIndex
:
'reason'
,
ellipsis
:
true
,
},
{
title
:
'交易单据时间'
,
dataIndex
:
'createTime'
,
align
:
'center'
,
ellipsis
:
true
,
},
];
const
evaluateColumns
:
EditableColumns
[]
=
[
{
title
:
' '
,
dataIndex
:
'title'
,
align
:
'center'
,
},
{
title
:
'最近7天'
,
dataIndex
:
'last7days'
,
align
:
'center'
,
},
{
title
:
'最近30天'
,
dataIndex
:
'last30days'
,
align
:
'center'
,
},
{
title
:
'最近180天'
,
dataIndex
:
'last180days'
,
align
:
'center'
,
},
{
title
:
'180天前'
,
dataIndex
:
'before180days'
,
align
:
'center'
,
},
];
const
evaluateRecordColumns
:
EditableColumns
[]
=
[
{
title
:
'评论'
,
dataIndex
:
'star'
,
align
:
'center'
,
render
:
(
text
)
=>
exchangeMood
(
text
),
},
{
title
:
'评价内容'
,
dataIndex
:
'comment'
,
align
:
'center'
,
ellipsis
:
true
,
},
{
title
:
'交易商品'
,
dataIndex
:
'product'
,
align
:
'center'
,
ellipsis
:
true
,
render
:
text
=>
{
const
product
=
isJSONStr
(
text
)
||
{};
return
product
.
productName
||
''
;
},
},
{
title
:
'评价方'
,
dataIndex
:
'byMemberName'
,
align
:
'center'
,
},
{
title
:
'交易时间'
,
dataIndex
:
'createTime'
,
align
:
'center'
,
},
{
title
:
'订单号'
,
dataIndex
:
'remark'
,
align
:
'center'
,
},
];
const
summaryEvaluate
=
(
items
:
EstimateSumItems
[]):
EstimateSumItems
[]
=>
{
// 顺序写死的 1:表示好评,2:表示中评,3:表示差评
// 根据 1、2星级为差评,3星级为中评,4、5星级为好评往里边塞数据
const
source
=
items
||
[];
const
ret
=
[
{
id
:
1
,
title
:
(<
Mood
type=
"smile"
/>),
},
{
id
:
2
,
title
:
(<
Mood
type=
"notBad"
/>),
},
{
id
:
3
,
title
:
(<
Mood
type=
"sad"
/>),
},
];
for
(
let
i
=
0
;
i
<
source
.
length
;
i
++
)
{
const
item
=
source
[
i
];
const
{
star
,
...
rest
}
=
item
;
let
target
:
any
=
null
;
switch
(
item
.
star
)
{
case
1
:
case
2
:
{
target
=
ret
[
2
];
break
;
}
case
3
:
{
target
=
ret
[
1
];
break
;
}
case
4
:
case
5
:
{
target
=
ret
[
0
];
break
;
}
default
:
break
;
}
if
(
!
target
)
{
continue
;
}
// 大于 2 表示已经添加过一次数据,之后就累加上去,否则直接赋值
if
(
Object
.
keys
(
target
).
length
<=
2
)
{
target
=
Object
.
assign
(
target
,
rest
);
}
else
{
for
(
const
key
in
target
)
{
if
(
!
Object
.
prototype
.
hasOwnProperty
.
call
(
target
,
key
))
{
continue
;
}
// 排除 id、title 固定的 key
if
(
key
!==
'id'
&&
key
!==
'title'
)
{
target
[
key
]
+=
item
[
key
];
}
}
}
}
return
ret
;
};
// 取得评价统计 Pie 饼图数据
const
getSummaryEvaluatePie
=
(
data
:
EstimateSumItems
[])
=>
{
const
source
=
data
||
[];
const
count
=
source
.
reduce
((
pre
,
now
)
=>
(
now
.
sum
||
0
)
+
pre
,
0
);
const
good
=
source
[
0
]
&&
source
[
0
].
sum
?
source
[
0
].
sum
:
0
;
const
notBad
=
source
[
1
]
&&
source
[
1
].
sum
?
source
[
1
].
sum
:
0
;
const
bad
=
source
[
2
]
&&
source
[
2
].
sum
?
source
[
2
].
sum
:
0
;
const
ret
=
[
{
x
:
`好评
${
count
>
0
?
(
good
/
count
*
100
).
toFixed
(
2
)
:
'0'
}
%`
,
y
:
good
,
},
{
x
:
`中评
${
count
>
0
?
(
notBad
/
count
*
100
).
toFixed
(
2
)
:
0
}
%`
,
y
:
notBad
,
},
{
x
:
`差评
${
count
>
0
?
(
bad
/
count
*
100
).
toFixed
(
2
)
:
0
}
%`
,
y
:
bad
,
},
];
return
ret
;
};
// 获取交易评价记录列表
const
getSalesRecordList
=
(
extraParams
:
{[
key
:
string
]:
any
}
=
{})
=>
{
if
(
fetchSalesList
)
{
setSalesListLoading
(
true
);
fetchSalesList
({
current
:
salesPage
,
pageSize
:
salesSize
,
...
extraParams
,
}).
then
(
res
=>
{
const
{
data
=
[],
totalCount
=
0
}
=
(
res
||
{});
setSalesList
(
data
);
setSalesTotal
(
totalCount
);
}).
finally
(()
=>
{
setSalesListLoading
(
false
);
});
}
};
// 获取售后评价记录列表
const
getAfterRecordList
=
(
extraParams
:
{[
key
:
string
]:
any
}
=
{})
=>
{
if
(
fetchAfterList
)
{
setAfterListLoading
(
true
);
fetchAfterList
({
current
:
afterPage
,
pageSize
:
afterSize
,
...
extraParams
,
}).
then
(
res
=>
{
const
{
data
=
[],
totalCount
=
0
}
=
(
res
||
{});
setAfterList
(
data
);
setAfterTotal
(
totalCount
);
}).
finally
(()
=>
{
setAfterListLoading
(
false
);
});
}
};
// 获取投诉评价记录列表
const
getComplaintList
=
()
=>
{
if
(
fetchComplaintList
)
{
setComplainListLoading
(
true
);
fetchComplaintList
({
current
:
complainPage
,
pageSize
:
complainSize
,
}).
then
(
res
=>
{
const
{
data
=
[],
totalCount
=
0
}
=
(
res
||
{});
setComplainList
(
data
);
setComplainTotal
(
totalCount
);
}).
finally
(()
=>
{
setComplainListLoading
(
false
);
});
}
};
useEffect
(()
=>
{
getComplaintList
();
},
[]);
// 监听交易评价数据改变,组合所需数据
useEffect
(()
=>
{
const
evaluate
=
salesEstimateSum
&&
salesEstimateSum
.
dataSource
?
summaryEvaluate
(
salesEstimateSum
.
dataSource
)
:
[];
const
evaluatePie
=
getSummaryEvaluatePie
(
evaluate
);
setSalesEvaluate
(
evaluate
);
setSalesEvaluatePie
(
evaluatePie
);
},
[
salesEstimateSum
.
dataSource
]);
// 监听售后评价数据改变,组合所需数据
useEffect
(()
=>
{
const
evaluate
=
afterEstimateSum
&&
afterEstimateSum
.
dataSource
?
summaryEvaluate
(
afterEstimateSum
.
dataSource
)
:
[];
const
evaluatePie
=
getSummaryEvaluatePie
(
evaluate
);
setAfterEvaluate
(
evaluate
);
setAfterEvaluatePie
(
evaluatePie
);
},
[
afterEstimateSum
.
dataSource
]);
const
handleSalesTabChange
=
key
=>
{
if
(
key
===
'evaluateRecord'
)
{
getSalesRecordList
();
}
setSalesTabKey
(
key
);
};
const
handleAfterTabChange
=
key
=>
{
if
(
key
===
'evaluateRecord'
)
{
getAfterRecordList
();
}
setAfterTabKey
(
key
);
};
const
handleSalesPaginationChange
=
(
page
:
number
,
size
:
number
)
=>
{
setSalesPage
(
page
);
setSalesSize
(
size
);
getSalesRecordList
();
};
const
handleAfterPaginationChange
=
(
page
:
number
,
size
:
number
)
=>
{
setAfterPage
(
page
);
setAfterSize
(
size
);
getAfterRecordList
();
};
const
handleComplainPaginationChange
=
(
page
:
number
,
size
:
number
)
=>
{
setComplainPage
(
page
);
setComplainSize
(
size
);
getComplaintList
();
};
const
handleSalesRadioChange
=
value
=>
{
setSalesPage
(
1
);
getSalesRecordList
({
starLevel
:
value
,
});
};
const
handleAfterRadioChange
=
value
=>
{
setAfterPage
(
1
);
getAfterRecordList
({
starLevel
:
value
,
});
};
return
(
<
div
className=
{
styles
.
sincerityInfo
}
>
<
Row
gutter=
{
[
0
,
24
]
}
>
<
Col
span=
{
24
}
>
<
Spin
spinning=
{
Boolean
(
basicInfo
.
loading
)
}
>
<
Row
gutter=
{
24
}
>
<
Col
flex=
"386px"
>
<
MellowCard
title=
"信用积分"
fullHeight
>
<
Pie
hasLegend
subTitle=
"信用积分"
total=
{
()
=>
creditData
.
reduce
((
pre
,
now
)
=>
now
.
y
+
pre
,
0
)
}
data=
{
creditData
}
height=
{
178
}
colors=
{
[
'#6C9CEB'
,
'#8777D9'
,
'#FFC400'
,
'#41CC9E'
]
}
/>
</
MellowCard
>
</
Col
>
{
basicInfo
.
loading
===
false
&&
(
<
Col
flex=
"1"
>
<
div
className=
{
styles
.
tofo
}
>
<
MellowCard
fullHeight
>
{
integralItems
.
map
((
item
,
index
)
=>
(
<
Card
.
Grid
key=
{
item
.
id
}
className=
{
styles
[
'tofo-item'
]
}
>
<
ContentBox
title=
{
item
.
creditTypeName
}
desc=
{
`${item.remark}(${item.creditPoint})`
}
content=
{
item
.
currentPoint
}
extra=
{
<
img
className=
{
styles
[
'tofo-item-logo'
]
}
src=
{
imgMap
[
index
+
1
]
}
/>
}
/>
</
Card
.
Grid
>
))
}
</
MellowCard
>
</
div
>
</
Col
>
)
}
</
Row
>
</
Spin
>
</
Col
>
<
Col
span=
{
24
}
>
<
MellowCard
>
<
Tabs
className=
{
styles
[
'record-tabs'
]
}
activeKey=
{
salesTabKey
}
onChange=
{
handleSalesTabChange
}
tabBarExtraContent=
{
salesTabKey
===
'evaluateRecord'
?
(
<>
<
Button
type=
"text"
onClick=
{
()
=>
handleSalesRadioChange
(
3
)
}
>
好评
</
Button
>
<
Button
type=
"text"
onClick=
{
()
=>
handleSalesRadioChange
(
2
)
}
>
中评
</
Button
>
<
Button
type=
"text"
onClick=
{
()
=>
handleSalesRadioChange
(
1
)
}
>
差评
</
Button
>
<
Button
type=
"text"
onClick=
{
()
=>
handleSalesRadioChange
(
0
)
}
>
全部
</
Button
>
</>
)
:
null
}
>
<
TabPane
tab=
"交易评价统计"
key=
"evaluateSum"
>
<
Spin
spinning=
{
Boolean
(
salesEstimateSum
.
loading
)
}
>
<
Row
gutter=
{
24
}
>
<
Col
span=
{
8
}
>
<
Pie
hasLegend
subTitle=
"累计评价"
total=
{
()
=>
salesEvaluatePie
.
reduce
((
pre
,
now
)
=>
now
.
y
+
pre
,
0
)
}
data=
{
salesEvaluatePie
}
height=
{
178
}
colProps=
{
{
span
:
8
,
}
}
colors=
{
[
'#41CC9E'
,
'#FFC400'
,
'#EF6260'
]
}
/>
</
Col
>
<
Col
span=
{
16
}
>
<
PolymericTable
dataSource=
{
salesEvaluate
}
columns=
{
evaluateColumns
}
loading=
{
false
}
pagination=
{
null
}
rowClassName=
{
()
=>
styles
[
'record-row'
]
}
/>
</
Col
>
</
Row
>
</
Spin
>
</
TabPane
>
<
TabPane
tab=
"交易评价记录"
key=
"evaluateRecord"
>
<
PolymericTable
rowKey=
"remark"
dataSource=
{
salesList
}
columns=
{
evaluateRecordColumns
}
loading=
{
salesListLoading
}
pagination=
{
{
pageSize
:
salesSize
,
total
:
salesTotal
,
}
}
onPaginationChange=
{
handleSalesPaginationChange
}
/>
</
TabPane
>
</
Tabs
>
</
MellowCard
>
</
Col
>
<
Col
span=
{
24
}
>
<
MellowCard
>
<
Tabs
className=
{
styles
[
'record-tabs'
]
}
activeKey=
{
afterTabKey
}
onChange=
{
handleAfterTabChange
}
tabBarExtraContent=
{
afterTabKey
===
'evaluateRecord'
?
(
<>
<
Button
type=
"text"
onClick=
{
()
=>
handleAfterRadioChange
(
3
)
}
>
好评
</
Button
>
<
Button
type=
"text"
onClick=
{
()
=>
handleAfterRadioChange
(
2
)
}
>
中评
</
Button
>
<
Button
type=
"text"
onClick=
{
()
=>
handleAfterRadioChange
(
1
)
}
>
差评
</
Button
>
<
Button
type=
"text"
onClick=
{
()
=>
handleAfterRadioChange
(
0
)
}
>
全部
</
Button
>
</>
)
:
null
}
>
<
TabPane
tab=
"售后评价统计"
key=
"evaluateSum"
>
<
Spin
spinning=
{
Boolean
(
afterEstimateSum
.
loading
)
}
>
<
Row
gutter=
{
24
}
>
<
Col
span=
{
8
}
>
<
Pie
hasLegend
subTitle=
"累计评价"
total=
{
()
=>
afterEvaluatePie
.
reduce
((
pre
,
now
)
=>
now
.
y
+
pre
,
0
)
}
data=
{
afterEvaluatePie
}
height=
{
178
}
colProps=
{
{
span
:
8
,
}
}
colors=
{
[
'#41CC9E'
,
'#FFC400'
,
'#EF6260'
]
}
/>
</
Col
>
<
Col
span=
{
16
}
>
<
PolymericTable
dataSource=
{
afterEvaluate
}
columns=
{
evaluateColumns
}
loading=
{
false
}
pagination=
{
null
}
rowClassName=
{
()
=>
styles
[
'record-row'
]
}
/>
</
Col
>
</
Row
>
</
Spin
>
</
TabPane
>
<
TabPane
tab=
"售后评价记录"
key=
"evaluateRecord"
>
<
PolymericTable
rowKey=
"remark"
dataSource=
{
afterList
}
columns=
{
evaluateRecordColumns
}
loading=
{
afterListLoading
}
pagination=
{
{
pageSize
:
afterSize
,
total
:
afterTotal
,
}
}
onPaginationChange=
{
handleAfterPaginationChange
}
/>
</
TabPane
>
</
Tabs
>
</
MellowCard
>
</
Col
>
<
Col
span=
{
24
}
>
<
MellowCard
title=
"投诉记录"
>
<
div
className=
{
styles
[
'record-btns'
]
}
>
<
Radio
.
Group
buttonStyle=
"solid"
onChange=
{
()
=>
{
}
}
>
<
Button
type=
"text"
>
全部(
{
complaintSumData
?.
sum
}
)
</
Button
>
<
Button
type=
"text"
>
最近7天(
{
complaintSumData
?.
last7days
}
)
</
Button
>
<
Button
type=
"text"
>
最近30天(
{
complaintSumData
?.
last30days
}
)
</
Button
>
<
Button
type=
"text"
>
最近180天(
{
complaintSumData
?.
last180days
}
)
</
Button
>
<
Button
type=
"text"
>
180天前(
{
complaintSumData
?.
before180days
}
)
</
Button
>
</
Radio
.
Group
>
</
div
>
<
PolymericTable
rowKey=
"remark"
dataSource=
{
complainList
}
columns=
{
recordColumns
}
loading=
{
complainListLoading
}
pagination=
{
{
pageSize
:
complainSize
,
total
:
complainTotal
,
}
}
onPaginationChange=
{
handleComplainPaginationChange
}
/>
</
MellowCard
>
</
Col
>
</
Row
>
</
div
>
);
};
export
default
SincerityInfo
;
src/pages/memberManage/components/StatusTag/index.less
0 → 100644
View file @
593349ab
.tag {
line-height: 22px;
padding: 0 8px;
font-size: 12px;
font-weight: 400;
color: #00B37A;
background: #EBF7F2;
border-radius: 4px;
&__success {
color: #00B37A;
background: #EBF7F2;
}
&__warnning {
color: #FF991F;
background: #FFFAE6;
}
&__default {
color: #606266;
background: #F4F5F7;
}
&__danger {
color: #E63F3B;
background: #FFEBE6;
}
&__primary {
color: #3F7ED2;
background: #F0F8FF;
}
}
\ No newline at end of file
src/pages/memberManage/components/StatusTag/index.tsx
0 → 100644
View file @
593349ab
/*
* @Author: XieZhiXiong
* @Date: 2020-08-31 17:52:14
* @LastEditors: XieZhiXiong
* @LastEditTime: 2020-09-08 16:32:03
* @Description: 状态 tag
*/
import
React
from
'react'
;
import
classNames
from
'classnames'
;
import
styles
from
'./index.less'
;
interface
StatusTagProps
{
type
:
'success'
|
'warnning'
|
'default'
|
'danger'
|
'primary'
;
title
?:
string
;
};
const
StatusTag
:
React
.
FC
<
StatusTagProps
>
=
({
type
,
title
})
=>
{
const
cls
=
classNames
(
styles
.
tag
,
styles
[
`tag__
${
type
}
`
]);
return
(
<
span
className=
{
cls
}
>
{
title
}
</
span
>
);
};
export
default
StatusTag
;
\ No newline at end of file
src/pages/memberManage/constant.tsx
0 → 100644
View file @
593349ab
import
{
MEMBER_INNER_STATUS_TO_BE_COMMIT
,
MEMBER_INNER_STATUS_COMMIT_NOT_PASSED
,
MEMBER_INNER_STATUS_TO_BE_VERIFY_STEP1
,
MEMBER_INNER_STATUS_VERIFY_STEP1_NOT_PASSED
,
MEMBER_INNER_STATUS_TO_BE_VERIFY_STEP2
,
MEMBER_INNER_STATUS_VERIFY_STEP2_NOT_PASSED
,
MEMBER_INNER_STATUS_TO_CONFIRM
,
MEMBER_INNER_STATUS_VERIFY_NOT_PASSED
,
MEMBER_INNER_STATUS_VERIFY_PASSED
,
MEMBER_OUTER_STATUS_TO_PLATFORM_VERIFY
,
MEMBER_OUTER_STATUS_PLATFORM_VERIFYING
,
MEMBER_OUTER_STATUS_PLATFORM_VERIFY_PASSED
,
MEMBER_OUTER_STATUS_PLATFORM_VERIFY_NOT_PASSED
,
MEMBER_OUTER_STATUS_DEPOSITING
,
MEMBER_OUTER_STATUS_DEPOSITORY_PASSED
,
MEMBER_OUTER_STATUS_DEPOSITORY_NOT_PASSED
,
MEMBER_OUTER_STATUS_MODIFYING
,
MEMBER_OUTER_STATUS_MODIFY_PASSED
,
MEMBER_OUTER_STATUS_MODIFY_NOT_PASSED
,
MEMBER_STATUS_NORMAL
,
MEMBER_STATUS_FROZEN
,
}
from
'@/constants/const/member'
;
export
const
STATUS_COLOR_MAP
=
{
0
:
'#669EDE'
,
1
:
'#41CC9E'
,
2
:
'#EF6260'
,
};
export
const
STATUS_COLOR_TXT
=
{
0
:
'待审核'
,
1
:
'审核通过'
,
2
:
'冻结'
,
};
// 会员状态 StatusTag map
export
const
MEMBER_STATUS_TAG_MAP
=
{
[
MEMBER_STATUS_NORMAL
]:
'success'
,
[
MEMBER_STATUS_FROZEN
]:
'default'
};
// 会员外部状态 StatusTag map
export
const
MEMBER_OUTER_STATUS_TYPE
=
{
[
MEMBER_OUTER_STATUS_TO_PLATFORM_VERIFY
]:
'default'
,
[
MEMBER_OUTER_STATUS_PLATFORM_VERIFYING
]:
'warning'
,
[
MEMBER_OUTER_STATUS_PLATFORM_VERIFY_PASSED
]:
'success'
,
[
MEMBER_OUTER_STATUS_PLATFORM_VERIFY_NOT_PASSED
]:
'danger'
,
[
MEMBER_OUTER_STATUS_DEPOSITING
]:
'warning'
,
[
MEMBER_OUTER_STATUS_DEPOSITORY_PASSED
]:
'success'
,
[
MEMBER_OUTER_STATUS_DEPOSITORY_NOT_PASSED
]:
'danger'
,
[
MEMBER_OUTER_STATUS_MODIFYING
]:
'warning'
,
[
MEMBER_OUTER_STATUS_MODIFY_PASSED
]:
'success'
,
[
MEMBER_OUTER_STATUS_MODIFY_NOT_PASSED
]:
'danger'
,
};
// 会员内部状态 Tag badge map
export
const
MEMBER_INNER_STATUS_BADGE_COLOR
=
{
[
MEMBER_INNER_STATUS_TO_BE_COMMIT
]:
'grey'
,
[
MEMBER_INNER_STATUS_COMMIT_NOT_PASSED
]:
'red'
,
[
MEMBER_INNER_STATUS_TO_BE_VERIFY_STEP1
]:
'orange'
,
[
MEMBER_INNER_STATUS_VERIFY_STEP1_NOT_PASSED
]:
'red'
,
[
MEMBER_INNER_STATUS_TO_BE_VERIFY_STEP2
]:
'orange'
,
[
MEMBER_INNER_STATUS_VERIFY_STEP2_NOT_PASSED
]:
'red'
,
[
MEMBER_INNER_STATUS_TO_CONFIRM
]:
'blue'
,
[
MEMBER_INNER_STATUS_VERIFY_NOT_PASSED
]:
'red'
,
[
MEMBER_INNER_STATUS_VERIFY_PASSED
]:
'green'
,
};
\ No newline at end of file
src/pages/memberManage/schema/auditSchema.ts
0 → 100644
View file @
593349ab
import
{
ISchema
}
from
'@formily/antd'
;
import
{
FORM_FILTER_PATH
}
from
'@/formSchema/const'
;
export
const
auditSchema
:
ISchema
=
{
type
:
'object'
,
properties
:
{
MEGA_LAYOUT
:
{
type
:
'object'
,
'x-component'
:
'mega-layout'
,
properties
:
{
topLayout
:
{
type
:
'object'
,
'x-component'
:
'mega-layout'
,
'x-component-props'
:
{
grid
:
true
,
},
properties
:
{
ctl
:
{
type
:
'object'
,
'x-component'
:
'ControllerBtns'
,
},
name
:
{
type
:
'string'
,
'x-component'
:
'Search'
,
'x-component-props'
:
{
placeholder
:
'搜索'
,
tip
:
'输入 会员名称 进行搜索'
,
},
},
},
},
[
FORM_FILTER_PATH
]:
{
type
:
'object'
,
'x-component'
:
'flex-layout'
,
'x-component-props'
:
{
colStyle
:
{
marginLeft
:
20
,
},
},
properties
:
{
memberTypeId
:
{
type
:
'string'
,
default
:
undefined
,
enum
:
[],
'x-component-props'
:
{
placeholder
:
'会员类型(全部)'
,
allowClear
:
true
,
style
:
{
width
:
160
,
},
},
},
// status: {
// type: 'string',
// default: undefined,
// enum: [],
// 'x-component-props': {
// placeholder: '会员状态(全部)',
// allowClear: true,
// },
// },
roleId
:
{
type
:
'string'
,
default
:
undefined
,
enum
:
[],
'x-component-props'
:
{
placeholder
:
'会员角色(全部)'
,
allowClear
:
true
,
style
:
{
width
:
160
,
},
},
},
level
:
{
type
:
'string'
,
default
:
undefined
,
enum
:
[],
'x-component-props'
:
{
placeholder
:
'会员等级(全部)'
,
allowClear
:
true
,
style
:
{
width
:
160
,
},
},
},
source
:
{
type
:
'string'
,
default
:
undefined
,
enum
:
[],
'x-component-props'
:
{
placeholder
:
'申请来源(全部)'
,
allowClear
:
true
,
style
:
{
width
:
160
,
},
},
},
'[startDate, endDate]'
:
{
type
:
'string'
,
default
:
''
,
'x-component'
:
'dateSelect'
,
'x-component-props'
:
{
placeholder
:
'时间范围(全部)'
,
allowClear
:
true
,
style
:
{
width
:
160
,
},
},
},
submit
:
{
'x-component'
:
'Submit'
,
'x-mega-props'
:
{
span
:
1
,
},
'x-component-props'
:
{
children
:
'查询'
,
},
},
},
},
},
},
},
};
export
const
auditModalSchema
:
ISchema
=
{
type
:
'object'
,
properties
:
{
MEGA_LAYOUT
:
{
type
:
'object'
,
'x-component'
:
'mega-layout'
,
'x-component-props'
:
{
labelAlign
:
'top'
,
},
properties
:
{
agree
:
{
type
:
'string'
,
default
:
1
,
enum
:
[
{
label
:
'审核通过'
,
value
:
1
},
{
label
:
'审核不通过'
,
value
:
0
},
],
'x-component'
:
'radio'
,
'x-component-props'
:
{},
},
reason
:
{
type
:
'string'
,
title
:
'审核不通过原因'
,
'x-component'
:
'textarea'
,
required
:
true
,
'x-component-props'
:
{
placeholder
:
'在此输入你的内容,最长120个字符,60个汉字'
,
rows
:
5
,
},
'x-rules'
:
[
{
limitByte
:
true
,
// 自定义校验规则
maxByte
:
120
,
}
],
},
},
},
},
};
src/pages/memberManage/utils.tsx
0 → 100644
View file @
593349ab
import
React
from
'react'
;
import
{
PATTERN_MAPS
}
from
'@/constants/regExp'
;
import
PicWrap
from
'./components/PicWrap'
;
export
function
coverColFiltersItem
(
data
:
Array
<
{[
key
:
string
]:
any
}
>
,
dataIndex
:
string
,
item
:
{[
key
:
string
]:
any
}
)
{
const
index
=
data
.
findIndex
(
i
=>
i
.
dataIndex
===
dataIndex
);
if
(
index
!==
-
1
)
{
data
.
splice
(
index
,
1
,
{
...
data
[
index
],
filters
:
item
,
});
}
};
// 初始化内部流转记录
export
function
normalizeInnerHistory
(
source
:
{[
key
:
string
]:
any
}[])
{
const
ret
:
any
[]
=
[];
if
(
!
Array
.
isArray
(
source
))
{
return
ret
;
}
source
.
forEach
(
item
=>
{
const
atom
=
{
id
:
item
.
id
,
operator
:
item
.
operatorName
,
org
:
item
.
operatorOrgName
,
jobTitle
:
item
.
operatorJobTitle
,
innerStatusName
:
item
.
innerStatusName
,
innerStatus
:
item
.
innerStatus
,
operation
:
item
.
operation
,
operateTime
:
item
.
createTime
,
reason
:
item
.
remark
,
};
ret
.
push
(
atom
);
});
return
ret
;
};
// 初始化内部流转记录
export
function
normalizeOuterHistory
(
source
:
{[
key
:
string
]:
any
}[])
{
const
ret
:
any
[]
=
[];
if
(
!
Array
.
isArray
(
source
))
{
return
ret
;
}
source
.
forEach
(
item
=>
{
const
atom
=
{
id
:
item
.
id
,
roleName
:
item
.
operatorRoleName
,
status
:
item
.
outerStatus
,
statusName
:
item
.
outerStatusName
,
operation
:
item
.
operation
,
operateTime
:
item
.
createTime
,
reason
:
item
.
remark
,
};
ret
.
push
(
atom
);
});
return
ret
;
};
export
type
ElementType
=
{
/**
* 注册资料id
*/
id
?:
number
,
/**
* 字段名称
*/
fieldName
?:
string
,
/**
* 中文名称
*/
fieldLocalName
?:
string
,
/**
* 字段类型
*/
fieldType
?:
string
,
/**
* 字段类型附加属性(该参数为map)
*/
attr
?:
{
[
key
:
string
]:
any
},
/**
* 字段长度
*/
fieldLength
?:
number
,
/**
* 是否可为空0-不能为空1-可以为空
*/
fieldEmpty
?:
number
,
/**
* 字段顺序
*/
fieldOrder
?:
number
,
/**
* 帮助信息
*/
fieldRemark
?:
string
,
/**
* 枚举标签列表
*/
fieldEnum
?:
{
value
?:
number
,
label
?:
string
,
}[],
/**
* 字段校验规则枚举:0-无校验规则,1-邮箱规则,2-手机号码规则,3-身份证规则,4-电话号码规则
*/
ruleEnum
?:
number
,
/**
* 校验规则的正则表达式
*/
pattern
?:
string
,
/**
* 校验错误的提示语
*/
msg
?:
string
,
/**
* 值
*/
fieldValue
?:
any
,
/**
* 是否禁用
*/
disabled
?:
boolean
,
}
export
type
GroupItem
=
{
/**
* 组名
*/
groupName
:
string
,
/**
* 元素
*/
elements
:
ElementType
[],
}
export
type
FieldType
=
'string'
|
'long'
|
'upload'
|
'radio'
|
'select'
|
'checkbox'
|
'area'
|
string
&
{};
// 判断表单元素是否真的有值
const
fieldHasValue
=
(
fieldType
:
FieldType
,
value
:
any
):
boolean
=>
{
switch
(
fieldType
)
{
case
'string'
:
case
'long'
:
case
'radio'
:
case
'select'
:
return
!!
value
;
case
'upload'
:
case
'checkbox'
:
return
value
&&
value
.
length
>
0
;
case
'area'
:
return
value
&&
!!
value
.
provinceCode
;
default
:
return
true
;
}
};
// 字段校验规则枚举:0-无校验规则,1-邮箱规则,2-手机号码规则,3-身份证规则,4-电话号码规则
const
RULE_REG_MAP
=
{
1
:
PATTERN_MAPS
.
email
,
2
:
PATTERN_MAPS
.
phone
,
3
:
PATTERN_MAPS
.
identity
,
4
:
PATTERN_MAPS
.
tel
,
};
const
getFieldType
=
(
field
:
ElementType
,
editable
:
boolean
=
true
)
=>
{
const
isDisabled
=
(
!
editable
&&
fieldHasValue
(
field
.
fieldType
as
string
,
field
.
fieldValue
))
||
!!
field
.
disabled
;
// 默认是 输入框
let
description
:
{
[
key
:
string
]:
any
}
=
{
'x-component-props'
:
{
placeholder
:
field
.
fieldRemark
,
disabled
:
isDisabled
,
},
};
// 公共的属性
const
common
=
{
type
:
'string'
,
required
:
field
.
fieldEmpty
===
0
,
title
:
field
.
fieldLocalName
,
default
:
field
.
fieldValue
,
'x-rules'
:
[
(
field
.
ruleEnum
?
{
pattern
:
RULE_REG_MAP
[
field
.
ruleEnum
],
message
:
field
.
msg
,
}
:
null
),
(
field
.
pattern
?
{
pattern
:
field
.
pattern
,
message
:
field
.
msg
,
}
:
null
),
].
filter
(
Boolean
),
};
switch
(
field
.
fieldType
as
FieldType
)
{
case
'upload'
:
{
description
=
{
'x-component'
:
'CustomUpload'
,
'x-component-props'
:
{
showDesc
:
false
,
disabled
:
isDisabled
,
},
};
break
;
}
case
'radio'
:
{
description
=
{
'x-component'
:
'RadioGroup'
,
enum
:
field
.
fieldEnum
,
'x-component-props'
:
{
disabled
:
isDisabled
},
};
break
;
}
case
'select'
:
{
description
=
{
enum
:
field
.
fieldEnum
,
'x-component-props'
:
{
disabled
:
isDisabled
,
},
};
break
;
}
case
'checkbox'
:
{
description
=
{
'x-component'
:
'CheckboxGroup'
,
enum
:
field
.
fieldEnum
,
'x-component-props'
:
{
disabled
:
isDisabled
,
},
};
break
;
}
case
'area'
:
{
description
=
{
'x-component'
:
'AreaSelect'
,
'x-component-props'
:
{
disabled
:
isDisabled
,
},
// 这里判断 省级 是否有值,没值给 undefined
// 后台没值是返回 {provinceCode: '', cityCode: '', districtCode: ''}
default
:
field
.
fieldValue
?
field
.
fieldValue
.
provinceCode
?
field
.
fieldValue
:
undefined
:
undefined
,
};
break
;
}
default
:
break
;
}
return
Object
.
assign
({},
common
,
description
);
};
/**
* 根据后台生成注册资料 schema
* @param elements
* @param editable 有值的元素是否可编辑
* @returns
*/
export
function
createMemberSchema
(
elements
:
ElementType
[],
editable
:
boolean
=
true
)
{
const
components
=
{};
if
(
!
Array
.
isArray
(
elements
))
{
return
components
;
}
for
(
let
item
of
elements
)
{
components
[
item
.
fieldName
as
string
]
=
getFieldType
(
item
,
editable
);
}
return
components
;
};
// 根据 fieldType 渲染对应的内容
export
function
renderFieldTypeContent
(
fieldType
:
FieldType
,
fieldValue
:
any
):
React
.
ReactNode
{
// 默认渲染 string
let
node
:
React
.
ReactNode
=
fieldValue
;
switch
(
fieldType
)
{
case
'upload'
:
node
=
(
<
PicWrap
pics=
{
[
fieldValue
]
}
/>
);
break
;
default
:
break
;
}
return
node
;
};
\ No newline at end of file
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