Commit 5accb7f3 authored by Bill's avatar Bill

添加账号安全设置

parent cfaadec9
......@@ -45,6 +45,19 @@ const AuthConfigRoute = {
path: '/memberCenter/systemSetting/collection',
name: 'collection',
component: '@/pages/systemSetting/collection',
},
// 账户安全设置
{
path: '/memberCenter/systemSetting/accountSetting',
name: 'accountSetting',
component: '@/pages/accountSetting'
},
{
path: '/memberCenter/systemSetting/editAccount',
name: 'editAccount',
component: '@/pages/accountSetting/editAccount',
hideInMenu: true,
hidePageHeader: true
}
],
......
......@@ -246,4 +246,6 @@ export default {
'menu.systemSetting.authConfig.userDetail': '用户详情',
'menu.systemSetting.collection': '收藏管理',
'menu.systemSetting.accountSetting': '账号安全设置',
'menu.systemSetting.editAccount': '编辑账号信息'
};
\ No newline at end of file
.passwordContainer {
position: relative;
.erros {
position: absolute;
top: 0;
right: 0;
}
}
\ No newline at end of file
import React from 'react';
// import { SchemaForm } from '@formily/antd';
import { Form, Input, Row, Col, Button, Select } from 'antd';
import styles from './index.less';
import { StepForwardOutlined } from '@ant-design/icons'
const Option = Select.Option;
const EditDataComponent = ({type}) => {
const renderPwd = () => {
return (
<>
<Form.Item
label="登录密码"
className={styles.passwordContainer}
>
<Row gutter={10}>
<Col span={18}>
<Form.Item
name="password"
rules={[{ required: true, message: 'Please input the captcha you got!' }]}
>
<Input.Password />
</Form.Item>
</Col>
<div className={styles.erros}>
<p>密码长度8-20个字符</p>
<p>密码长度8-20个字符</p>
<p>密码长度8-20个字符</p>
</div>
</Row>
</Form.Item>
<Form.Item
label="确认密码"
name="password"
rules={[{ required: true, message: 'Please input your password!' }]}
>
<Row gutter={10}>
<Col span={18}>
<Form.Item
name="captcha"
noStyle
rules={[{ required: true, message: 'Please input the captcha you got!' }]}
>
<Input.Password />
</Form.Item>
</Col>
</Row>
</Form.Item>
</>
)
}
const renderPhone = () => {
return (
<>
<Form.Item label="新的手机号码">
<Row gutter={10}>
<Col span={4}>
<Select>
<Option value="jack"> <StepForwardOutlined />jack</Option>
</Select>
</Col>
<Col span={14}>
<Form.Item
name="captcha"
noStyle
rules={[{ required: true, message: 'Please input the captcha you got!' }]}
>
<Input />
</Form.Item>
</Col>
</Row>
</Form.Item>
<Form.Item label="验证码">
<Row gutter={10}>
<Col span={14}>
<Form.Item
name="phoneCaptcha"
noStyle
rules={[{ required: true, message: 'Please input the captcha you got!' }]}
>
<Input />
</Form.Item>
</Col>
<Col span={6}>
<Button>获取验证码</Button>
</Col>
</Row>
</Form.Item>
</>
)
}
const renderEmail = () => {
return (
<>
<Form.Item label="邮箱地址">
<Row gutter={10}>
<Col span={14}>
<Form.Item
name="email"
noStyle
rules={[{ required: true, message: 'Please input the captcha you got!' }]}
>
<Input />
</Form.Item>
</Col>
<Col span={6}>
<Button>获取验证码</Button>
</Col>
</Row>
</Form.Item>
<Form.Item label="邮箱验证码">
<Row gutter={10}>
<Col span={18}>
<Form.Item
name="emailCaptcha"
noStyle
rules={[{ required: true, message: 'Please input the captcha you got!' }]}
>
<Input />
</Form.Item>
</Col>
</Row>
</Form.Item>
</>
)
}
return (
<div>
{
renderEmail()
}
</div>
)
}
export default EditDataComponent
\ No newline at end of file
.box {
}
.container {
height: 32px;
line-height: 32px;
font-size: 14px;
background: #EBF7F2;
border: 1px solid #00B37A;
margin: 8px 0 32px 0;
width: 495px;
cursor: pointer;
position: relative;
.btn {
color: #00B37A;
text-align: center;
}
}
.sliderVerify {
position: absolute;
top: 50%;
left: 50%;
// background-color: #fff;
z-index: 99;
// transform: translateX(-130px);
margin-left: -130px;
margin-top: -136px;
}
\ No newline at end of file
import React, { useState } from 'react';
import styles from './index.less';
import { Row, Col } from 'antd';
import SliderVerify from '../SliderVerify';
const imageUrl = 'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=1689053532,4230915864&fm=26&gp=0.jpg'
const SafeVerification = () => {
const [visible, setVisible] = useState(false)
const handleVisible = () => {
setVisible(true)
}
const cancel = () => {
setVisible(false)
}
// console.log(visible)
const handleSuccess = () => {
setVisible(false);
}
return (
<div className={styles.box}>
<Row>
<Col span={16} offset={3}>
<div className={styles.container}>
<div className={styles.btn} onClick={handleVisible}>
点击进行验证
</div>
<div className={styles.sliderVerify}>
<SliderVerify
visible={visible}
onCancel={cancel}
onSuccess={handleSuccess}
imageUrl={imageUrl}
/>
</div>
</div>
</Col>
</Row>
</div>
)
}
export default SafeVerification
\ No newline at end of file
.sliderContainer {
display: flex;
flex-direction: row;
justify-content: center;
border: 1px solid #e6dede;
position: relative;
width: 260px;
box-shadow: 2px 2px 2px #e6dede;
border-radius: 4px;
background-color: #fff;
}
.loading {
display: flex;
flex-direction: row;
justify-content: center;
font-weight: 600;
font-size: 16px;
}
.container {
display: flex;
flex-direction: column;
// align-items: center;
padding: 5px 5px;
justify-content: center;
user-select: none;
.imageContainer {
margin-bottom: 15px;
background-size:100% 100%;
position: relative;
.canvas {
position: absolute;
left: 25px;
top: 45px;
}
.target {
position: absolute;
left: 175px;
top: 45px;
}
}
.slider {
width: 250px;
height: 45px;
position: relative;
border-radius: 45px;
.sliderHandle {
width: 45px;
height: 45px;
border-radius: 50%;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
background-color: #fff;
z-index: 99;
position: absolute;
left: 0;
top: 0;
right: auto;
// transform: translateX(-50%);
box-shadow: 1px 5px 2px #eee;
cursor: pointer;
}
.sliderRail {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
border-radius: 45px;
background-color: #f5f5f5;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.sliderTrack {
position: absolute;
top: 0;
left: 0;
z-index: 89;
right: 0;
bottom: 0;
border-top-left-radius: 45px;
border-bottom-left-radius: 45px ;
background-color: #91d5ff;
}
}
.footer {
display: flex;
flex-direction: row;
margin-top: 15px;
font-size: 20px;
color: #999;
padding: 5px 0 0 15px;
border-top: 1px solid #e6dede;
.cancel {
margin-right: 15px;
cursor: pointer;
}
.reset {
cursor: pointer;
}
}
}
\ No newline at end of file
import React, { useState, useCallback, useEffect, useMemo, useRef } from 'react'
import styles from './index.less';
import { DoubleRightOutlined, CloseCircleOutlined, RedoOutlined } from '@ant-design/icons'
import { createClipPath } from './utils';
import { Spin } from 'antd';
const fragmentSize = 37;
const imageWidth = 250;
const imageHeight = 150;
// const imageUrl = 'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=1689053532,4230915864&fm=26&gp=0.jpg'
const differ = 5;
const READY = 0;
const SUCCESS = 1;
const ERROR = 2
interface SliderVerifyProps {
visible: boolean,
onCancel: any,
onSuccess?: any,
imageUrl: string
}
const SliderVerify: React.FC<SliderVerifyProps> = (props) => {
const [dragging, setDragging] = useState(false);
const [origin, setOrigin] = useState({ x: 0, y: 0 });
const [offset, setOffset] = useState({ x: 0, y: 0});
const [loading, setLoading] = useState(false);
const [clipImagePosition, setClipImagePosition] = useState({x: 0, y: 0});
const [status, setStatus] = useState(READY);
// const [visible, setVisible] = useState(props.visible || false)
const { visible, imageUrl } = props;
const shadowCanvas = useRef(null)
const fragmentCanvas = useRef(null);
const mouseDown = ({clientX, clientY}) => {
console.log("mouseDown", clientX);
setOrigin((state) => ({ x: clientX, y: clientY}))
setDragging(true);
};
const mouseMove = ({clientX, clientY}) => {
if(!dragging || status !== READY) {
return ;
}
let x = clientX - origin.x; // 计算拖动的距离
const min = 0;
const max = imageWidth - fragmentSize;
let currX = x;
currX = currX < min ? 0 : currX > max ? max : currX
const transition = {x: currX, y: origin.y };
setOffset((state) => {return {...state, ...transition}});
};
const mouseUp = () => {
if(!dragging || status !== READY) {
return ;
}
console.log("up")
setDragging(false)
const targetX = clipImagePosition.x;
const currentX = offset.x;
const match = Math.abs(targetX - currentX) <= 5;
if(match) {
onSuccess();
} else {
onError()
}
};
useEffect(() => {
if(visible) {
reRender();
}
}, [visible])
const sliderHandleStyle = useMemo(() => ({
left: (offset.x),
transition: (!dragging ? 'left 500ms' : 'none' )
}), [offset, dragging])
const trackStyle = useMemo(() => ({
width: !dragging && status == READY ? 0 : (offset.x + 22.5) + 'px',
transition: (!dragging ? 'left 500ms' : 'none' )
}), [offset, dragging])
const onSuccess = () => {
console.log("success");
setStatus(SUCCESS);
props.onSuccess && props.onSuccess();
setOffset({x: 0, y: 0})
}
const onError = () => {
console.log("error")
// setOffset({x: 0, y: 0})
reRender()
}
const onReset = () => {
reRender();
}
const reRender = () => {
setLoading(true);
setStatus(READY);
setOffset({x: 0, y: 0})
const objImage = new Image()
console.log(imageUrl)
objImage.addEventListener("load", () => {
console.log(objImage.width);
// 先获取两个ctx
const ctxShadow = shadowCanvas.current.getContext("2d")
const ctxFragment = fragmentCanvas.current.getContext("2d")
// 让两个ctx拥有同样的裁剪路径(可滑动小块的轮廓)
const styleIndex = Math.floor(Math.random() * 16)
createClipPath(ctxShadow, fragmentSize, styleIndex)
createClipPath(ctxFragment, fragmentSize, styleIndex)
// 随机生成裁剪图片的开始坐标
const clipX = Math.floor(fragmentSize + (imageWidth - 2 * fragmentSize) * Math.random())
const clipY = Math.floor((imageHeight - fragmentSize) * Math.random())
console.log(clipX, clipY);
const scaleWidth = objImage.width / imageWidth;
const scaleHeight = objImage.height / imageHeight;
// 让小块绘制出被裁剪的部分
// 175 是小图的, 还原成原图 应该是 x / 175 = objImage.width / imageWidth;
ctxFragment.drawImage(objImage, clipX * scaleWidth, clipY * scaleHeight,
fragmentSize * scaleWidth, fragmentSize * scaleHeight, 0, 0, fragmentSize, fragmentSize)
// 让阴影canvas带上阴影效果
ctxShadow.fillStyle = "rgba(0, 0, 0, 0.5)"
ctxShadow.fill()
// 恢复画布状态
ctxShadow.restore()
ctxFragment.restore()
// 设置裁剪小块的位置
setClipImagePosition({x: clipX, y: clipY});
// 修改状态
setLoading(false);
})
objImage.src = imageUrl
}
const handleClose = () => {
props.onCancel && props.onCancel()
}
return (
<>
{
!visible
? null
: (
<div>
{
loading
? <div className={styles.loading}><Spin /></div>
: null
}
<div className={styles.sliderContainer} style={{visibility: !loading ? 'visible' : 'hidden'}}>
<div className={styles.container}>
<div className={styles.imageContainer} style={{width: imageWidth, height: '150px', backgroundImage: `url("${imageUrl}")` }}>
<canvas
className={styles.canvas}
width={37}
height={37}
ref={shadowCanvas}
style={{ left: clipImagePosition.x + "px", top: clipImagePosition.y + "px" }}
/>
<canvas
className={styles.target}
width={37}
height={37}
ref={fragmentCanvas}
style={{ left: offset.x + "px", top: clipImagePosition.y + "px" }}
></canvas>
</div>
<div className={styles.slider} onMouseMove={mouseMove} onMouseLeave={mouseUp}>
<div className={styles.sliderHandle} onMouseDown={mouseDown} onMouseUp={mouseUp} style={sliderHandleStyle} ><DoubleRightOutlined /></div>
<div className={styles.sliderRail}>
<div className={styles.text}>向右滑动验证</div>
</div>
<div className={styles.sliderTrack} style={trackStyle}></div>
</div>
<div className={styles.footer}>
<div className={styles.cancel} onClick={handleClose}>
<CloseCircleOutlined />
</div>
<div className={styles.reset} onClick={onReset}>
<RedoOutlined />
</div>
</div>
</div>
</div>
</div>
)
}
</>
);
}
export default SliderVerify;
\ No newline at end of file
// 生成裁剪路径
export function createClipPath(ctx, size = 100, styleIndex = 0) {
// 这里对应的是左, 下。 右, 上 四种位置,顺时针或者逆时针向内 凹凸
const styles = [
[0, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0],
[0, 0, 1, 1],
[0, 1, 0, 0],
[0, 1, 0, 1],
[0, 1, 1, 0],
[0, 1, 1, 1],
[1, 0, 0, 0],
[1, 0, 0, 1],
[1, 0, 1, 0],
[1, 0, 1, 1],
[1, 1, 0, 0],
[1, 1, 0, 1],
[1, 1, 1, 0],
[1, 1, 1, 1]
]
const style = styles[styleIndex]
const r = 0.1 * size
ctx.save()
ctx.beginPath()
// left
ctx.moveTo(r, r)
ctx.lineTo(r, 0.5 * size - r)
// r 园中心x, 0.5 * size 圆中心Y, r 半径, 1.5*Math.PI 起始角, 0.5*Math.PI结束角, 顺时针/逆时针
ctx.arc(r, 0.5 * size, r, 1.5 * Math.PI, 0.5 * Math.PI, style[0])
ctx.lineTo(r, size - r)
// bottom
ctx.lineTo(0.5 * size - r, size - r)
ctx.arc(0.5 * size, size - r, r, Math.PI, 0, style[1])
ctx.lineTo(size - r, size - r)
// right
ctx.lineTo(size - r, 0.5 * size + r)
ctx.arc(size - r, 0.5 * size, r, 0.5 * Math.PI, 1.5 * Math.PI, style[2])
ctx.lineTo(size - r, r)
// top
ctx.lineTo(0.5 * size + r, r)
ctx.arc(0.5 * size, r, r, 0, Math.PI, style[3])
ctx.lineTo(r, r)
ctx.clip()
ctx.closePath()
}
\ No newline at end of file
.header {
margin: 12px 0 32px 0;
.title {
width: 112px;
height: 22px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #6B778C;
line-height: 22px;
margin-bottom: 16px;
}
.value {
height: 32px;
font-size: 24px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #172B4D;
line-height: 32px;
}
}
\ No newline at end of file
import React from 'react';
import styles from './index.less'
const TypeForHeader = (props) => {
const {type = 'phone'} = props;
const phoneRender = () => {
return (
<>
<div className={styles.title}>当前绑定手机号码</div>
<div className={styles.value}>+86 185 2929 6758</div>
</>
)
}
const emailRender = () => {
return (
<>
<div className={styles.title}>当前已认证邮箱</div>
<div className={styles.value}>735051883@qq.com</div>
</>
)
}
const payCodeRender = () => {
return (
null
)
}
const selectTypeRender = () => {
const { type = 'phone' } = props;
if(type == 'phone') {
return phoneRender();
} else if(type == 'email') {
return emailRender();
} else {
return payCodeRender()
}
}
return (
<div className={styles.header}>
{
selectTypeRender()
}
</div>
)
}
export default TypeForHeader
\ No newline at end of file
.container {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
background-color: #fff;
padding: 36px 24px;
width: 610px;
.infos {
display: flex;
flex-direction: row;
.image {
margin-right: 22px;
width: 72px;
height: 72px;
}
.details {
.title {
font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 600;
color: #172B4D;
line-height: 24px;
margin-bottom: 16px;
}
.tips {
font-size: 13px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #42526E;
line-height: 22px;
margin-bottom: 0;
}
}
}
.controls {
width: 90px;
text-align: right;
// cursor: pointer;
}
}
\ No newline at end of file
import React from 'react';
import styles from './index.less';
import account_tips from '@/assets/imgs/account_tips.png';
import { Link } from 'umi';
const TITLE_NAP = {
'loginPwd': {
title: '登录密码',
desc: "互联网账号存在被盗风险,建议您定期更改密码以保护账号安全"
},
'email': {
title: '邮箱验证',
desc: "您验证的邮箱:{{email}}"
},
'phone': {
title: '手机验证',
desc: "您验证的手机:{{phone}}, 若丢失或已停用,请立刻更换,避免账号被盗"
} ,
'paycode': {
title: '支付密码',
desc: "您的支付密码已开启,建议您定期更换新的支付密码,提高安全性"
}
}
const TypeVerify = (props) => {
const { type, email, phone } = props;
const titleRender = () => {
return TITLE_NAP[type].title
}
const descRender = () => {
if(type == 'email' && email == '') {
return "你还没有绑定邮箱"
} else if(type == 'paycode') {
return "请前往设置支付密码"
}
return TITLE_NAP[type].desc.replace(/\{\{(.*?)\}\}/, (match, key) => { return props[key] });
}
const renderLink = () => {
if(type == 'email' && email == '') {
return <a>设置邮箱</a>
} else if(type == 'paycode') {
return <a>设置支付密码</a>
}
return <Link to={`/memberCenter/systemSetting/editAccount?type=${type}`}>修改</Link>
}
return (
<div className={styles.container}>
<div className={styles.infos}>
<div className={styles.image}>
<img src={account_tips} />
</div>
<div className={styles.details}>
<p className={styles.title}>{titleRender()}</p>
<p className={styles.tips}>{descRender()}</p>
</div>
</div>
<div className={styles.controls}>
{
renderLink()
}
</div>
</div>
)
}
export default TypeVerify;
\ No newline at end of file
import React from 'react';
// import { SchemaForm } from '@formily/antd';
import { Form, Input, Button, Row, Col } from 'antd';
import SafeVerification from '../../SafeVerification';
import TypeForHeader from '../../TypeForHeader';
import EditDataComponent from '../../EditDataComponent';
const layout = {
labelCol: { span: 3 },
wrapperCol: { span: 13 },
labelAlign: "left"
};
const tailLayout = {
wrapperCol: { offset: 3, span: 13 },
};
const EmailVerifyPanel = () => {
return (
<div>
<TypeForHeader type="email" />
<Form
{...layout}
name="basic"
>
<Form.Item label="验证码">
<Row gutter={10}>
<Col span={14}>
<Form.Item
name="captcha"
noStyle
rules={[{ required: true, message: 'Please input the captcha you got!' }]}
>
<Input />
</Form.Item>
</Col>
<Col span={6}>
<Button>获取验证码</Button>
</Col>
</Row>
</Form.Item>
<SafeVerification />
<EditDataComponent type="password" />
<Form.Item {...tailLayout}>
<Button type="primary" htmlType="submit">
提交
</Button>
</Form.Item>
</Form>
</div>
)
}
export default EmailVerifyPanel;
\ No newline at end of file
import React from 'react';
// import { SchemaForm } from '@formily/antd';
import { Form, Input, Button, Row, Col } from 'antd';
import SafeVerification from '../../SafeVerification';
import TypeForHeader from '../../TypeForHeader';
import EditDataComponent from '../../EditDataComponent';
const layout = {
labelCol: { span: 3 },
wrapperCol: { span: 13 },
labelAlign: "left"
};
const tailLayout = {
wrapperCol: { offset: 3, span: 13 },
};
const PaycodeVerifyPanel = () => {
return (
<div>
<TypeForHeader type="payCode" />
<Form
{...layout}
name="basic"
>
<Form.Item label="验证码">
<Row gutter={10}>
<Col span={14}>
<Form.Item
name="captcha"
noStyle
rules={[{ required: true, message: 'Please input the captcha you got!' }]}
>
<Input />
</Form.Item>
</Col>
<Col span={6}>
<Button>获取验证码</Button>
</Col>
</Row>
</Form.Item>
<SafeVerification />
<EditDataComponent type="password" />
<Form.Item {...tailLayout}>
<Button type="primary" htmlType="submit">
提交
</Button>
</Form.Item>
</Form>
</div>
)
}
export default PaycodeVerifyPanel;
\ No newline at end of file
import React from 'react';
// import { SchemaForm } from '@formily/antd';
import { Form, Input, Button, Row, Col } from 'antd';
import SafeVerification from '../../SafeVerification';
import TypeForHeader from '../../TypeForHeader';
import EditDataComponent from '../../EditDataComponent';
const layout = {
labelCol: { span: 3 },
wrapperCol: { span: 13 },
labelAlign: "left"
};
const tailLayout = {
wrapperCol: { offset: 3, span: 13 },
};
const PhoneVerifyPanel = () => {
return (
<div>
<TypeForHeader type="phone"/>
<Form
{...layout}
name="basic"
>
<Form.Item label="验证码">
<Row gutter={10}>
<Col span={14}>
<Form.Item
name="captcha"
noStyle
rules={[{ required: true, message: 'Please input the captcha you got!' }]}
>
<Input />
</Form.Item>
</Col>
<Col span={6}>
<Button>获取验证码</Button>
</Col>
</Row>
</Form.Item>
<SafeVerification />
<EditDataComponent type="password" />
<Form.Item {...tailLayout}>
<Button type="primary" htmlType="submit">
提交
</Button>
</Form.Item>
</Form>
</div>
)
}
export default PhoneVerifyPanel;
\ No newline at end of file
import React from 'react';
import { Tabs } from 'antd';
import PhoneVerifyPanel from './PhoneVerifyPanel';
import PaycodeVerifyPanel from './PaycodeVerifyPanel';
import EmailVerifyPanel from './EmailVerifyPanel';
const { TabPane } = Tabs;
const VerifyPanel = () => {
return (
<Tabs defaultActiveKey="1" >
<TabPane tab="手机校验码验证" key="1">
<PhoneVerifyPanel />
</TabPane>
<TabPane tab="邮箱验证" key="2">
<EmailVerifyPanel />
</TabPane>
<TabPane tab="支付密码验证" key="3">
<PaycodeVerifyPanel />
</TabPane>
</Tabs>
)
}
export default VerifyPanel;
\ No newline at end of file
import Panel from './Panel';
export default Panel
\ No newline at end of file
import React from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { Card } from 'antd';
import ReutrnEle from '@/components/ReturnEle';
import { history } from 'umi';
import VerifyPanel from './components/VerifyPanel';
const MAP = {
'loginPwd': '修改登录密码',
'email': '修改邮箱',
'phone': '修改手机',
'paycode': '重置支付密码'
}
const EditAccount = (props) => {
const { type = 'loginPwd' } = props.location.query
// const { type } = props;
console.log(props);
return (
<PageHeaderWrapper
onBack={() => history.goBack()}
backIcon={<ReutrnEle description="返回" />}
title={MAP[type]}
>
<Card>
<VerifyPanel />
</Card>
</PageHeaderWrapper>
)
}
export default EditAccount;
\ No newline at end of file
.page {
display: flex;
flex-direction: row;
flex-wrap: wrap;
.item {
margin: 0 24px 24px 0;
}
}
\ No newline at end of file
import React, { useEffect, useState } from 'react';
import { Card } from 'antd';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import TypeVerify from './components/TypeVerify';
import styles from './index.less';
import { PublicApi } from '@/services/api';
const getData = async () => {
///member/security/get
const res = await PublicApi.getMemberSecurityGet();
return res.data
}
const AccountSetting = () => {
const [account, setAccount] = useState({})
useEffect(() => {
async function init() {
const res = await getData();
console.log(res);
setAccount(res);
}
init()
}, [])
const TYPES = ['loginPwd', 'email', 'phone', 'paycode']
return (
<PageHeaderWrapper>
<div className={styles.page}>
{
TYPES.map((item) => {
return (
<div className={styles.item} key={item}>
<TypeVerify type={item} phone={account.phone} email={account.email} />
</div>
)
})
}
</div>
</PageHeaderWrapper>
)
}
export default AccountSetting;
\ No newline at end of file
......@@ -495,8 +495,10 @@ const PositionSetting:React.FC<PositionSettingProps> = (props) => {
return parentState.value
});
// 商城类型修改的时候,就清空商品
addSchemaAction.setFieldValue('productId', "");
addSchemaAction.setFieldValue('productName', "");
if(!id) {
addSchemaAction.setFieldValue('productId', "");
addSchemaAction.setFieldValue('productName', "");
}
}
})
// FormEffectHooks.
......@@ -507,7 +509,7 @@ const PositionSetting:React.FC<PositionSettingProps> = (props) => {
schema={schema}
/>
<ModalTable
modalTitle='选择渠道会员'
modalTitle='选择会员'
confirm={handleOkAddMember}
cancel={handleCancelAddMember}
visible={visibleChannelMember}
......
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