Commit 0a0039c0 authored by tjy's avatar tjy

新增会员详情页面

parent 884fa0f0
......@@ -23,6 +23,13 @@ const memberAbility =
component: '@/pages/member/memberMaintain/addMember',
},
{
path: '/memberAbility/manage/memberDetail',
name: 'memberDetail',
hideInMenu: true,
hidePageHeader: true,
component: '@/pages/member/memberMaintain/memberDetail',
},
{
path: '/memberAbility/manage/memberPrSubmit',
name: 'memberPrSubmit',
component: '@/pages/member/memberPrSubmit/index',
......
.flex-bet {
display : flex;
justify-content: space-between;
align-items : center;
}
.checkbox-tree-list {
display : flex;
flex-direction: column;
padding : 0;
li {
align-items: center;
height : 48px;
}
}
\ No newline at end of file
import React, { RefObject, useRef } from 'react'
import { Button, Checkbox } from 'antd'
import { useSelections } from '@umijs/hooks';
import { findTreeKeys } from '@/utils';
import './index.less';
export interface CheckboxTreeProps {
title?: React.ReactNode,
checkedNodes?: any[],
handleChange?(e?),
disabled?: boolean,
actions?: RefObject<any>
}
const CheckboxTree:React.FC<CheckboxTreeProps> = (props) => {
const { title, checkedNodes = [], actions, handleChange, disabled } = props
const checkedKeys = findTreeKeys(checkedNodes, 'id')
const { selected, setSelected, toggleAll, toggle, isSelected, allSelected, unSelectAll, selectAll } = useSelections(
checkedKeys,
[]
);
if (actions) {
actions.current.selected = selected
actions.current.setSelected = setSelected
actions.current.getSelected = () => selected
}
const toggleSelectAll = () => {
checkChange()
if (allSelected) {
unSelectAll()
} else {
selectAll()
}
}
const checkChange = (e?) => {
handleChange && handleChange(e)
}
return (
<div>
{ title &&
<div className='flex-bet'>
<div>{props.title}</div>
<Button onClick={toggleSelectAll} type='link' disabled={disabled}>{ allSelected ? '取消全选' : '全选'}</Button>
</div>
}
<ul className='checkbox-tree-list'>
{ checkedNodes && checkedNodes.map((v, i) => {
return <li key={v.id}>
<Checkbox onChange={checkChange} disabled={disabled} onClick={() => toggle(v.id)} checked={isSelected(v.id)}>{v.buttonName}</Checkbox>
</li>
}) }
</ul>
</div>
)
}
CheckboxTree.defaultProps = {
checkedNodes: []
}
export default CheckboxTree
\ No newline at end of file
import React, { useState, ReactText, useImperativeHandle } from 'react'
import React, { useState, ReactText, useImperativeHandle, useEffect, useRef } from 'react'
import { Tree, Space, Tooltip, Button } from 'antd'
import { findItemAndDelete, findTreeKeys } from '@/utils'
import './index.less'
......@@ -10,6 +10,7 @@ import { EventDataNode } from 'rc-tree/lib/interface'
import { useSelections } from '@umijs/hooks'
export interface TabTreeActions {
selected: ReactText[],
getExpandedKeys: () => ReactText[],
getSelectKey: () => ReactText,
getSelectKeys: () => ReactText[],
......@@ -26,14 +27,15 @@ export interface toolsRenderProps {
export interface TabTreeProps extends TreeProps {
treeData: any[],
fetchData(params?): Promise<any>,
fetchData?(params?): Promise<any>,
actions?: TabTreeActions,
title?: React.ReactNode,
// 若传入该字段, 则会作为tree识别的节点, 默认是`key`, 传入后原有的key值将无效
customKey?: string | number,
customTitle?: string | number,
handleSelect?: (key: ReactText, node: EventDataNode) => void | Promise<any>,
toolsRender?: toolsRenderProps
toolsRender?: toolsRenderProps,
getMenuSelectData?(): Promise<any>
}
export interface InnermostTreeNodeProps {
......@@ -45,8 +47,16 @@ export interface RenderIconsProps {
toolsRender?: toolsRenderProps
}
export const useTreeActions = (): TabTreeActions => {
export const useTreeActions = (action?): TabTreeActions => {
const actionRef = useRef<any>(null)
actionRef.current = actionRef.current || action || createTreeActions()
return actionRef.current
}
export const createTreeActions = () => {
const actions: TabTreeActions = {
selected: [],
getExpandedKeys(){ return [] },
getSelectKey(){ return '' },
getSelectKeys(){ return [] },
......@@ -107,13 +117,13 @@ function transformSingleTitle(data, nowKey, checkable, disabled, toolsRender, cu
}
data[item]._title = data[item]._title || data[item].title
data[item].title = <span className='god-tabtree-title' style={{display: 'flex', alignItems: 'center', justifyContent: 'space-between'}}>
{ (checkable || (data[item].children && data[item].children.length !== 0)) ? data[item].title : <InnermostTreeNode>{data[item].title}</InnermostTreeNode> }
{ (checkable || data[item].children) ? data[item].title : <InnermostTreeNode>{data[item].title}</InnermostTreeNode> }
<div>
{ toolsRender && <RenderIcons node={data[item]} nowKey={nowKey} toolsRender={toolsRender}/> }
</div>
</span>
// 使选中样式受控
data[item].className= cx('god-tabtree-select', nowKey === data[item].key ? 'show' : 'hide')
data[item].className= cx('god-tabtree-select', Number(nowKey) === Number(data[item].key) ? 'show' : 'hide')
if (disabled) {
data[item].disableCheckbox = disabled
}
......@@ -135,9 +145,12 @@ const TabTree:React.FC<TabTreeProps> = (props) => {
customKey,
customTitle,
toolsRender,
disabled
disabled,
getMenuSelectData
} = props
const selfActions = useTreeActions(actions)
// 需展开的key
const [expandkeys, setExpandkeys] = useState<ReactText[]>([])
// 当前选中的node
......@@ -150,6 +163,14 @@ const TabTree:React.FC<TabTreeProps> = (props) => {
checkedKeys,
[]
);
useEffect(() => {
if (getMenuSelectData) {
getMenuSelectData().then(res => {
const { ids } = res.data
setSelected(ids)
})
}
}, [])
const toggleSelectAll = () => {
if (allSelected) {
......@@ -158,18 +179,18 @@ const TabTree:React.FC<TabTreeProps> = (props) => {
selectAll()
}
}
if (actions) {
actions.getExpandedKeys = () => expandkeys
actions.getSelectKey = () => selectKey
actions.getSelectKeys = () => selected
actions.setSelectKeys = (keys: ReactText[]) => {
if (selfActions) {
selfActions.getExpandedKeys = () => expandkeys
selfActions.getSelectKey = () => selectKey
selfActions.getSelectKeys = () => selected
selfActions.selected = selected
selfActions.setSelectKeys = (keys: ReactText[]) => {
setSelected(keys)
}
actions.setExpandedKeys = (keys: ReactText[]) => {
selfActions.setExpandedKeys = (keys: ReactText[]) => {
setExpandkeys(keys)
}
actions.setSelectKey = (key: ReactText) => {
selfActions.setSelectKey = (key: ReactText) => {
setSelectKey(key)
}
}
......@@ -196,14 +217,14 @@ const TabTree:React.FC<TabTreeProps> = (props) => {
expandedKeys={expandkeys}
onCheck={(keys, nodes) => {
const { node, checked, checkedNodes } = nodes
checked ? batchSelect(keys as any) : setSelected(checkedNodes)
checked ? batchSelect(keys as any) : setSelected(checkedNodes.map(v => v.key))
}}
onSelect={(keys, e) => {
// 控制点击node时可以展开
const { node, selected } = e
// 用户自定义的选择后触发事件
if (props.handleSelect) {
const result:any = props.handleSelect(node.key, node)
const result = props.handleSelect(node.key, node)
// 存在返回值则不执行选中事件, 一般用于切换node时,不希望离开当前页面
if (result !== undefined) {
result.then(() => {
......
......@@ -37,14 +37,14 @@ export interface UserRegister {
export interface RuleConfiguration {
value: number;
lable: string;
label: string;
platformType: number;
}
export interface PayWayResponse {
payType: number;
value: number;
lable: string;
label: string;
}
export interface PayInitializeConfig {
......
......@@ -51,9 +51,9 @@ export default {
'menu.pageCustomized.templateDetail': '模版详情',
// 会员能力
'menu.memberAbility': '会员管理',
'menu.memberAbility.memberImport': '会员导入',
'menu.memberAbility.addMember': '新增会员',
'menu.memberAbility.memberMaintain': '会员维护',
'menu.memberAbility.addMember': '新增会员',
'menu.memberAbility.memberDetail': '会员详情',
'menu.memberAbility.memberPrSubmit': '待提交审核',
'menu.memberAbility.auditPrSubmit': '待提交审核详情',
'menu.memberAbility.memberPr1': '待审核(一级)',
......
This diff is collapsed.
......@@ -63,9 +63,17 @@ const auditList: React.FC<PageProps> = props => {
align: 'center',
key: 'name',
render: (text: any, record: any) => {
let path =
props.pageType === '1'
? 'auditPrSubmit'
: props.pageType === '2'
? 'auditPr1'
: props.pageType === '3'
? 'auditPr2'
: 'auditPrComfirm';
return (
<EyePreview
url={`/memberCenter/tranactionAbility/stockSellStorage/addWarehouse?id=${record.id}&preview=1`}
url={`/memberAbility/manage/${path}?id=${record.memberId}&preview=1`}
>
{text}
</EyePreview>
......
......@@ -100,6 +100,11 @@
}
}
.authCol {
padding : 24px;
background-color: #fff;
}
.nameCell {
text-align: left;
......
import React, { useState, useRef, useEffect } from 'react';
import { usePageStatus, PageStatus } from '@/hooks/usePageStatus';
import { Row, Col, Tabs, Steps, Badge } from 'antd';
import TabTree, {
useTreeActions,
createTreeActions,
} from '@/components/TabTree';
import CheckboxTree from '@/components/CheckBoxTree';
import { useTreeTabs } from '@/hooks/useTreeTabs';
import styles from '../index.less';
interface PageProps {
detailData: any;
}
const { TabPane } = Tabs;
const { Step } = Steps;
const treeActions = createTreeActions();
const AuthDetail: React.FC<PageProps> = (props: any) => {
const { detailData } = props;
const { pageStatus, id } = usePageStatus();
const {
treeData,
handleSelect,
nodeRecord,
getTreeMaps,
setIsEditForm,
isEditForm,
setTreeData,
} = useTreeTabs({
// fetchItemDetailData: Promise.resolve({data: detailData})
});
useEffect(() => {
setTreeData(detailData?.auths);
}, []);
const actionRef = useRef({});
const formInitValue = nodeRecord ? getTreeMaps(nodeRecord.key) : null;
const [formValue, setFormValue] = useState<any>(null);
// 编辑和预览模式下需回显数据
const fetchRoleDetail = id => {
// 10秒缓存
// const res = await PublicApi.getRoleDetails(
// { id },
// { useCache: true, ttl: 10 * 1000 },
// );
// return res;
};
// 储存的按钮数据
const [buttonInfos, setButtonInfos] = useState<any>([]);
useEffect(() => {
if (!id) return;
// fetchRoleDetail(id).then(res => {
// const { data } = res;
// setFormValue(data);
// });
}, []);
useEffect(() => {
if (formInitValue) {
// 显示右侧checkbox
setButtonInfos(formInitValue.buttons || []);
// 回显右侧checkbox的值
// if (actionRef.current.setSelected) {
// PublicApi.getMenuRoleButtonList({
// memberId: id,
// menuId: formInitValue.id,
// }).then(res => {
// const { data } = res;
// actionRef.current.setSelected(data.ids);
// });
// }
}
}, [getTreeMaps]);
return (
<Row>
<Col className={styles['authCol']} span={15}>
<TabTree
title="菜单列表"
customKey="id"
checkable
actions={treeActions}
treeData={treeData}
handleSelect={handleSelect}
disabled={pageStatus === PageStatus.PREVIEW}
/>
</Col>
<Col className={styles['authCol']} span={8} offset={1}>
<CheckboxTree
actions={actionRef}
disabled={pageStatus === PageStatus.PREVIEW}
handleChange={e => setIsEditForm(true)}
checkedNodes={buttonInfos}
title="菜单按钮访问权限"
/>
</Col>
</Row>
);
};
export default AuthDetail;
import React, { useState } from 'react';
import { Row, Col, Tabs, Steps, Badge } from 'antd';
import { StandardTable } from 'god';
import { ColumnType } from 'antd/lib/table/interface';
import styles from '../index.less';
interface PageProps {
detailData: any;
}
const { TabPane } = Tabs;
const { Step } = Steps;
const BaseDetail: React.FC<PageProps> = props => {
const { detailData } = props;
const [fActived, setfActived] = useState('1');
const [lActived, setlActived] = useState('1');
const columns: ColumnType<any>[] = [
{
title: '序号',
dataIndex: 'id',
align: 'center',
key: 'id',
},
{
title: '操作角色',
dataIndex: 'roleName',
align: 'center',
key: 'roleName',
},
{
title: '状态',
dataIndex: 'statusName',
align: 'center',
key: 'statusName',
render: (text: any, record: any) => <Badge color="#FFC400" text={text} />,
},
{
title: '操作',
dataIndex: 'operation',
align: 'center',
key: 'operation',
},
{
title: '操作时间',
dataIndex: 'operateTime',
align: 'center',
key: 'operateTime',
},
{
title: '审核意见',
dataIndex: 'reason',
align: 'center',
key: 'reason',
},
];
const innerColumns: ColumnType<any>[] = [
{
title: '序号',
dataIndex: 'id',
align: 'center',
key: 'id',
},
{
title: '操作人',
dataIndex: 'operator',
align: 'center',
key: 'operator',
},
{
title: '部门',
dataIndex: 'org',
align: 'center',
key: 'org',
},
{
title: '职位',
dataIndex: 'jobTitle',
align: 'center',
key: 'jobTitle',
},
{
title: '状态',
dataIndex: 'innerStatusName',
align: 'center',
key: 'innerStatusName',
render: (text: any, record: any) => <Badge color="#FFC400" text={text} />,
},
{
title: '操作',
dataIndex: 'operation',
align: 'center',
key: 'operation',
},
{
title: '操作时间',
dataIndex: 'operateTime',
align: 'center',
key: 'operateTime',
},
{
title: '审核意见',
dataIndex: 'reason',
align: 'center',
key: 'reason',
},
];
const renderInfoTemplate = (params: any) => {
const { type, item } = params;
return (
<>
<div className={styles['mainCol-title']}>{item.groupName}</div>
<div className={styles['mainCol-row']}>
{item.elements.map((items: any, indexs: string) => {
return (
<div className={styles['mainCol-row-col']} key={indexs}>
<div className={styles['mainCol-row-col-option']}>
{items.fieldCNName}
</div>
<div className={styles['mainCol-row-col-option']}>
{items.fieldValue}
</div>
</div>
);
})}
</div>
</>
);
};
return (
<Row>
<Col className={styles['mainCol']} span={24}>
<Tabs activeKey={fActived} onChange={val => setfActived(val)}>
<TabPane tab="外部审核流程" key="1">
<Steps
style={{ padding: '34px 0' }}
progressDot
current={detailData?.currentOuterStep - 1}
>
{detailData?.outerVerifySteps?.map((item, index) => {
return (
<Step
key={index}
title={item.roleName}
description={item.stepName}
/>
);
})}
</Steps>
</TabPane>
<TabPane tab="内部审核流程" key="2">
<Steps
style={{ padding: '34px 0' }}
progressDot
current={detailData?.currentInnerStep - 1}
>
{detailData?.innerVerifySteps?.map((item, index) => {
return (
<Step
key={index}
title={item.roleName}
description={item.stepName}
/>
);
})}
</Steps>
</TabPane>
</Tabs>
</Col>
{detailData?.groups?.map((item, index) => {
return (
<Col className={styles['mainCol']} span={24} key={index}>
{renderInfoTemplate({ type: '1', item })}
</Col>
);
})}
<Col className={styles['mainCol']} span={24}>
<Tabs activeKey={lActived} onChange={val => setlActived(val)}>
<TabPane tab="流转记录" key="1">
<div style={{ marginBottom: '40px' }}>
<StandardTable
tableProps={{
pagination: false,
rowKey: 'id',
}}
columns={columns}
fetchTableData={(params: any) =>
Promise.resolve({ data: detailData?.history })
}
/>
</div>
</TabPane>
<TabPane tab="内部单据流转记录" key="2">
<div style={{ marginBottom: '40px' }}>
<StandardTable
tableProps={{
pagination: false,
rowKey: 'id',
}}
columns={innerColumns}
fetchTableData={(params: any) =>
Promise.resolve({ data: detailData?.innerHistory })
}
/>
</div>
</TabPane>
</Tabs>
</Col>
</Row>
);
};
export default BaseDetail;
......@@ -39,6 +39,115 @@
}
}
.headerTop {
display : flex;
align-items: center;
font-size : 20px;
font-family: PingFangSC-Medium, PingFang SC;
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 : #172B4D;
margin: 0 8px 0 12px;
}
}
.mainCol {
background-color: #fff;
margin-bottom : 24px;
padding : 0 24px;
box-sizing : border-box;
&-title {
font-size : 16px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color : #172B4D;
padding : 20px 0;
}
&:nth-last-of-type(1) {
margin: 0;
}
&-row {
display : flex;
flex-wrap : wrap;
padding-bottom: 16px;
&-col {
display: flex;
width : calc(100% / 2);
padding: 16px 0;
&-option {
flex : 1;
font-size : 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color : #6B778C;
&:nth-last-of-type(1) {
flex : 3;
padding-right: 20px;
box-sizing : border-box;
color : #172B4D;
}
}
}
}
&-rows {
display : flex;
padding-bottom: 16px;
&-cols {
flex: 1;
.cols-main {
display: flex;
padding: 16px 0;
&:nth-last-of-type(1) {
padding-bottom: 0;
}
&-options {
flex : 1;
font-size : 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color : #6B778C;
&:nth-last-of-type(1) {
flex : 3;
padding-right: 20px;
box-sizing : border-box;
color : #172B4D;
}
}
}
}
}
}
.authCol {
padding : 24px;
background-color: #fff;
}
.subRow {
width: 100%;
......
......@@ -83,9 +83,7 @@ const memberMaintain: React.FC<[]> = () => {
<div className={style.nameCell}>
<div
className={style.nameCellTitle}
onClick={() =>
history.push('/memberAbility/manage/addMember?type=check')
}
onClick={() => history.push('/memberAbility/manage/memberDetail')}
>
{text}&nbsp;
<EyeOutlined />
......
import React, { useState, useEffect, useRef, ReactNode } from 'react';
import { history } from 'umi';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { PageHeader, Tag, Badge, Tabs, Steps, Descriptions } from 'antd';
import { StandardTable } from 'god';
import { ColumnType } from 'antd/lib/table/interface';
import { usePageStatus, PageStatus } from '@/hooks/usePageStatus';
import { PublicApi } from '@/services/api';
import styles from './index.less';
import BaseDetail from './component/baseDetail';
import AuthDetail from './component/AuthDetail';
const { TabPane } = Tabs;
const { Step } = Steps;
const MemberDetail: React.FC<{}> = () => {
const { pageStatus, id } = usePageStatus();
const [hActived, setHActived] = useState('1');
const [detailData, setDetailData] = useState<any>({});
useEffect(() => {
const fetchDetailData = async () => {
const { data } = await PublicApi.getMemberValidateCommitDetail({
memberId: '2',
validateId: '63',
});
setDetailData(data);
};
fetchDetailData();
}, []);
return (
<PageHeaderWrapper
title={
<>
<PageHeader
style={{ padding: '0' }}
onBack={() => window.history.back()}
title={
<>
<div className={styles['headerTop']}>
<div className={styles['headerTop-prefix']}>广</div>
<div className={styles['headerTop-name']}>
广州市极致皮具有限公司
</div>
<div className={styles[`levelIcon${'1'}`]}></div>
</div>
</>
}
footer={
<Tabs activeKey={hActived} onChange={val => setHActived(val)}>
<TabPane tab="基本信息" key="1" />
<TabPane tab="权限信息" key="2" />
<TabPane tab="等级信息" key="3" />
<TabPane tab="权益信息" key="4" />
<TabPane tab="诚信信息" key="5" />
</Tabs>
}
>
<Descriptions size="small" column={3} style={{ padding: '0 32px' }}>
<Descriptions.Item label="会员类型">{123}</Descriptions.Item>
<Descriptions.Item label="会员角色">{123}</Descriptions.Item>
<Descriptions.Item label="会员状态">
<Tag color="green"></Tag>
</Descriptions.Item>
<Descriptions.Item label="外部状态">
<Tag color="gold"></Tag>
</Descriptions.Item>
<Descriptions.Item label="内部状态">
<Badge color="#669EDE" text={123} />
</Descriptions.Item>
</Descriptions>
</PageHeader>
</>
}
>
{hActived === '1' ? (
<BaseDetail detailData={detailData} />
) : hActived === '2' ? (
<AuthDetail detailData={detailData} />
) : hActived === '3' ? (
''
) : hActived === '4' ? (
''
) : (
''
)}
</PageHeaderWrapper>
);
};
export default MemberDetail;
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment