Commit 57866842 authored by 前端-钟卫鹏's avatar 前端-钟卫鹏

fix

parent 1c8b68d7
......@@ -20,3 +20,5 @@
# project
# mockStatic
/.idea
......@@ -23,7 +23,7 @@
"@ant-design/icons": "^4.2.1",
"@umijs/preset-react": "1.x",
"@umijs/test": "^3.2.0",
"god": "0.0.12",
"god": "0.0.24",
"lint-staged": "^10.0.7",
"mobx": "^5.15.4",
"mobx-react": "^6.2.2",
......
......@@ -3,6 +3,7 @@ import { history, RequestConfig } from 'umi';
import React from 'react'
import MobxProvider from './store'
import 'mobx-react-lite/batchingForReactDom'
import './global.less'
let extraRoutes: never[] = []
......@@ -12,13 +13,13 @@ let extraRoutes: never[] = []
* @date 2020-05-20
* @export
* @param {IRoutes} { routes } 预先配置好的路由
* @example
* @example
* routes.unshift({
* path: '/foo',
* exact: true,
* component: require('/extraRoutes/foo').default,
* });
*
*
*/
// export function patchRoutes({ routes }: IRoutes) {
// routes.concat(extraRoutes as [])
......@@ -40,7 +41,7 @@ let extraRoutes: never[] = []
// // 做权限校验
// fetch('/auth').then((res: any) => {
// if (res.isLogin) {
// oldRender()
// oldRender()
// } else {
// history.push('/login')
// }
......@@ -95,4 +96,4 @@ export function rootContainer(container) {
// ],
// requestInterceptors: [],
// responseInterceptors: []
// }
\ No newline at end of file
// }
@import '~@/styles/theme.less';
// antd default
// antd default
h1, h2, h3, h4, h5, h6 {
color: #6B778C;
}
......@@ -14,4 +14,87 @@ h1, h2, h3, h4, h5, h6 {
width: 1024px;
margin-left: auto;
margin-right: auto;
}
\ No newline at end of file
}
// 公共的title伪类竖线
.commonPanelTitle {
padding-left: 8px;
position: relative;
&::before {
content: "";
display: inline-block;
position: absolute;
left: 0;
top: 50%;
margin-top: -.42667rem;
width: 2px;
height: .85333rem;
background-color: #00B37A;
box-shadow: 0 0.14933rem 0.256rem 0 rgba(97,144,232,.2);
border-radius: 1px;
}
}
// 公共间隔
.mr-10{
margin-right: 10px;
}
.mr-20{
margin-right: 20px;
}
.mr-30{
margin-right: 30px;
}
.mr-50{
margin-right: 50px;
}
.mr-100{
margin-right: 100px;
}
.ml-10{
margin-left: 10px;
}
.ml-20{
margin-left: 20px;
}
.ml-30{
margin-left: 30px;
}
.ml-50{
margin-left: 50px;
}
.ml-100{
margin-left: 100px;
}
.mt-10{
margin-top: 10px;
}
.mt-20{
margin-top: 20px;
}
.mt-30{
margin-top: 30px;
}
.mt-50{
margin-top: 50px;
}
.mt-100{
margin-top: 100px;
}
.mb-10{
margin-bottom: 10px;
}
.mb-20{
margin-bottom: 20px;
}
.mb-30{
margin-bottom: 30px;
}
.mb-50{
margin-bottom: 50px;
}
.mb-100{
margin-bottom: 100px;
}
// This file is automatically generated.
// Please do not change this file!
interface CssExports {
'commonPanelTitle': string;
'lingxi-business-content1024': string;
'lingxi-business-margin_content': string;
'lingxiBusinessContent1024': string;
'lingxiBusinessMarginContent': string;
'mb-10': string;
'mb-100': string;
'mb-20': string;
'mb-30': string;
'mb-50': string;
'mb10': string;
'mb100': string;
'mb20': string;
'mb30': string;
'mb50': string;
'ml-10': string;
'ml-100': string;
'ml-20': string;
'ml-30': string;
'ml-50': string;
'ml10': string;
'ml100': string;
'ml20': string;
'ml30': string;
'ml50': string;
'mr-10': string;
'mr-100': string;
'mr-20': string;
'mr-30': string;
'mr-50': string;
'mr10': string;
'mr100': string;
'mr20': string;
'mr30': string;
'mr50': string;
'mt-10': string;
'mt-100': string;
'mt-20': string;
'mt-30': string;
'mt-50': string;
'mt10': string;
'mt100': string;
'mt20': string;
'mt30': string;
'mt50': string;
}
export const cssExports: CssExports;
export default cssExports;
import React from 'react'
import React, { useState } from 'react'
import { Form, Row, Col, Input, Button } from 'antd'
import {
UserOutlined,
LockOutlined,
ExclamationCircleFilled
} from '@ant-design/icons';
import styles from '../index.less'
import { ExclamationCircleFilled } from '@ant-design/icons'
const LoginWrap: React.FC = () => {
const isValied = true
const [validFrame, setValidFrame] = useState(false)
const [validButton, setValidButton] = useState(false)
const finish = (value) => {
console.log(value)
}
return (
<>
<p>{isValied ? '当前手机号码:xxxxxxxxx' : '请使用平台账号登录'}</p>
<p>{validFrame ? '当前手机号码:xxxxxxxxx' : '请使用平台账号登录'}</p>
{
isValied ?
validFrame ?
<>
<Row style={{marginTop: 62, marginBottom: 74}}>
<Col>
<Input/>
<Row gutter={[0,80]}>
<Col span={16}>
<Input size='large'/>
</Col>
<Col offset={1} span={7}>
<Button type='default' size='large'>获取验证码</Button>
</Col>
<Col>
<Button type='default'>获取验证码</Button>
</Row>
<Row>
<Col span={24}>
<Button type='primary' size='large' htmlType='submit' block>点击登录</Button>
</Col>
</Row>
<Button type='primary' size='large' htmlType='submit' block>点击登录</Button>
</>
:
<Form
......@@ -39,7 +49,7 @@ const LoginWrap: React.FC = () => {
]
}
>
<Input type='text' placeholder='用户名/手机号' size='large'/>
<Input prefix={<UserOutlined />} placeholder='用户名/手机号' size='large'/>
</Form.Item>
<Form.Item
name='password'
......@@ -52,23 +62,24 @@ const LoginWrap: React.FC = () => {
]
}
>
<Input type='password' placeholder='请输入密码' size='large'/>
</Form.Item>
<Form.Item
className={styles.loginVerBtn}
>
<Button ghost type='primary' block size='large'>点击进行验证</Button>
<Input.Password prefix={<LockOutlined />} placeholder='请输入密码' size='large'/>
</Form.Item>
{ validButton && (<Form.Item
className={styles.loginVerBtn}
>
<Button ghost type='primary' block size='large'>点击进行验证</Button>
</Form.Item>)
}
<Form.Item>
<Button type='primary' size='large' htmlType='submit' block>点击登录</Button>
</Form.Item>
</Form>
}
</>
)
}
export default LoginWrap
\ No newline at end of file
export default LoginWrap
import React, { useState } from 'react'
import { Form, Row, Col, Input, Button } from 'antd'
import {
UserOutlined,
LockOutlined,
ExclamationCircleFilled
} from '@ant-design/icons';
import styles from '../index.less'
const ScanLoginWrap: React.FC = () => {
return (
<div className={styles.scanLoginWrap}>
<h2>扫码登录</h2>
</div>
)
}
export default ScanLoginWrap
......@@ -12,6 +12,7 @@
padding: 141px 0 102px;
}
.loginMain {
position: relative;
background: @white;
padding: 64px 56px 0;
color: #6B778C;
......@@ -19,9 +20,39 @@
font-size: 32px;
margin-bottom: 32px;
}
& .qrcodeLogin{
position: absolute;
right: 8px;
top: 8px;
width: 32px;
height: 32px;
background: url("../../../mockStatic/qr_code1.png") center center no-repeat;
background-size: cover;
&:hover{
background: url("../../../mockStatic/qr_code2.png") center center no-repeat;
}
}
& .scanTips{
display: flex;
}
}
.loginDesc {
background: #9f9;
//background: #9f9;
background: url("../../../mockStatic/image_ad.png") center center no-repeat;
background-size: cover;
& .adBox{
color: @white;
text-align: center;
& h2{
color: @white;
margin-top: 20px;
height: 80px;
line-height: 80px;
}
& p{
padding: 10px 60px;
}
}
}
.thirdLogin {
height: 64px;
......@@ -32,6 +63,16 @@
background: #EBF7F2;
}
.scanLoginWrap{
text-align: center;
&>h2{
color: #6B778C;
}
}
// register
.register {
width: 100%;
......@@ -45,8 +86,9 @@
.registerBox {
width: 100%;
height: 700px;
//height: 700px;
background: #fff;
padding-bottom: 40px;
}
.stepWrap {
......@@ -56,10 +98,11 @@
display: flex;
align-items: center;
}
.form-box {
.formBoxStep1 {
width: 320px;
margin: 40px auto 0;
}
.formBefore {
width: 54px;
line-height: 40px;
......@@ -69,4 +112,76 @@
color: #42526E;
border: 1px solid #DFE1E6;
border-right: 0;
}
\ No newline at end of file
}
.formBoxStep2{
width: 704px;
margin: 0px auto 0;
& h3{
margin-top: 48px;
}
}
.continueButton{
display: block;
width: 320px;
height: 40px;
margin: 8px auto;
}
.identityRadio{
display: flex;
flex-direction: column;
text-align: center;
& label{
width: 320px;
height: 48px;
margin: 12px auto;
vertical-align: middle;
line-height: 48px;
}
}
.businessRadio{
display: flex;
flex-wrap: wrap;
width: 320px;
margin: 0 auto;
text-align: center;
& label{
width: 148px;
height: 32px;
line-height: 32px;
margin: 8px 0;
}
& label:nth-child(odd) {
margin-right: 24px;
}
}
.formBoxStep3{
width: 704px;
margin: 0px auto 0;
text-align: center;
& .description{
margin-bottom: 40px;
& p{
height:20px;
font-size:14px;
color:rgba(66,82,110,1);
line-height:20px;
}
}
&.guid{
height:22px;
font-size:14px;
color:rgba(107,119,140,1);
line-height:22px;
}
& h2{
font-size:24px;
color:rgba(23,43,77,1);
margin: 24px 0;
}
& img{
display: block;
margin: 0 auto;
}
}
// This file is automatically generated.
// Please do not change this file!
interface CssExports {
'form-box': string;
'adBox': string;
'businessRadio': string;
'commonPanelTitle': string;
'continueButton': string;
'description': string;
'formBefore': string;
'formBox': string;
'formBoxStep1': string;
'formBoxStep2': string;
'formBoxStep3': string;
'guid': string;
'identityRadio': string;
'lingxi-business-content1024': string;
'lingxi-business-margin_content': string;
'lingxiBusinessContent1024': string;
......@@ -16,8 +24,51 @@ interface CssExports {
'loginMain': string;
'loginVerBtn': string;
'loginWrap': string;
'mb-10': string;
'mb-100': string;
'mb-20': string;
'mb-30': string;
'mb-50': string;
'mb10': string;
'mb100': string;
'mb20': string;
'mb30': string;
'mb50': string;
'ml-10': string;
'ml-100': string;
'ml-20': string;
'ml-30': string;
'ml-50': string;
'ml10': string;
'ml100': string;
'ml20': string;
'ml30': string;
'ml50': string;
'mr-10': string;
'mr-100': string;
'mr-20': string;
'mr-30': string;
'mr-50': string;
'mr10': string;
'mr100': string;
'mr20': string;
'mr30': string;
'mr50': string;
'mt-10': string;
'mt-100': string;
'mt-20': string;
'mt-30': string;
'mt-50': string;
'mt10': string;
'mt100': string;
'mt20': string;
'mt30': string;
'mt50': string;
'qrcodeLogin': string;
'register': string;
'registerBox': string;
'scanLoginWrap': string;
'scanTips': string;
'stepWrap': string;
'thirdLogin': string;
}
......
import React from 'react';
import React, { useState } from 'react';
import globalStyles from '@/global.less';
import styles from './index.less'
import cx from 'classnames';
import { Row, Col, Form, Input, Button, Space } from 'antd';
import TextLink from '@/components/TextLink';
import { ExclamationCircleFilled } from '@ant-design/icons';
import {
ExclamationCircleFilled,
ScanOutlined
} from '@ant-design/icons';
import LoginWrap from './components/loginWrap';
import ScanLoginWrap from './components/ScanLoginWrap';
// import leftPicture from '../../../mockStatic/image_ad.png'
const User: React.FC = () => {
const [isScanQrCode,setIsScanQrCode] = useState(true)
return (
<Row className={cx(styles.loginWrap, globalStyles.lingxiBusinessContent1024)}>
<Col className={cx(styles.loginItem, styles.loginDesc)}>
left
<div className={styles.adBox}>
{/*<img src={leftPicture} alt="数商云"/>*/}
<h2>数商云,驱动全链数字化运营</h2>
<p>「数商云」,是一家领先的企业全链数字化运营服务 提供商。致力于通过大数据、云计算等新技术协助企业打造渠道端—营销端—数据端等全链 数字化运营体系,全面提升企业运营效益与智慧数字化商业转型。</p>
</div>
</Col>
<Col className={cx(styles.loginItem, styles.loginCtl)}>
<div className={styles.loginMain}>
<a className={styles.qrcodeLogin} />
<h2>欢迎您</h2>
<LoginWrap/>
<Row justify='end' style={{marginTop: 16}}>
<Space size={32}>
<TextLink>免费注册</TextLink>
<TextLink>忘记密码</TextLink>
</Space>
</Row>
{ isScanQrCode ? (
<>
<ScanLoginWrap/>
<div className={styles.scanTips}>
<ScanOutlined style={{width:28,height:28}} />
<span>打开 App<br />扫一扫登录</span>
</div>
</>
) : (
<>
<ScanLoginWrap/>
<Row justify='end' style={{marginTop: 16}}>
<Space size={32}>
<TextLink>免费注册</TextLink>
<TextLink>忘记密码</TextLink>
</Space>
</Row>
</>
)
}
</div>
<Row className={styles.thirdLogin} align='middle' justify='center'>
<Col>其他方式登录</Col>
......@@ -33,4 +57,4 @@ const User: React.FC = () => {
)
}
export default User
\ No newline at end of file
export default User
import React, { useState } from 'react'
import { Input, Form, Steps, Button, Row, Space } from 'antd'
import React, { useState, useEffect } from 'react'
import { Input, Form, Steps, Button, Row, Col, Radio, Divider, Tooltip, Upload, message } from 'antd'
import {
UploadOutlined,
QuestionCircleOutlined
} from '@ant-design/icons';
import styles from './index.less'
import globalStyles from '@/global.less'
import cx from 'classnames'
import { FormPage } from 'god'
import { IFormControllers, IFormButtonTypes } from 'god/dist/src/form-page'
import { Link } from 'umi'
import { Link, history } from 'umi'
import im_success from '../../../mockStatic/im_success.png'
const { TextArea } = Input;
const Step = Steps.Step
const formItemLayout = {
labelCol: {
span: 2,
order: 2
},
wrapperCol: {
span: 22,
order: 1
},
};
const stepList = [
{ title: '填写信息', key: 'message' },
{ title: '完善资料', key: 'over' },
......@@ -19,6 +36,7 @@ const registerForm: IFormControllers[] = [
{
type: 'Input',
name: 'phone',
span: 24,
inputProps: {
addonBefore: <div className={styles.formBefore}>+86</div>,
placeholder: '请输入你的手机号码',
......@@ -27,28 +45,49 @@ const registerForm: IFormControllers[] = [
{
type: 'Verification',
name: 'code',
span: 24,
inputProps: {
}
},
{
type: 'Input',
name: 'password',
span: 24,
inputProps: {
type: 'password',
placeholder: '设置你的密码',
}
},
// rules: [
// { required: true, message: '密码为必填项!' },
// { pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[^]{8,20}$/, message: '密码长度8-20个字符,必须包含大小写字母和数字!' }
// ],
},
{
type: 'Input',
name: 'confirmPassword',
span: 24,
dependencies: ['password'],
inputProps: {
type: 'password',
placeholder: '请再次输入你的登录密码',
}
},
// rules: [
// { required: true, message: '请再次确认密码!' },
// ({ getFieldValue }) => ({
// validator(rule, value) {
// if (!value || getFieldValue('password') === value) {
// return Promise.resolve();
// }
// return Promise.reject('两次的密码输入不一致!');
// },
// }),
// ]
},
{
type: 'Input',
name: 'email',
span: 24,
inputProps: {
type: 'email',
placeholder: '请输入你的邮箱(选填)',
......@@ -57,26 +96,112 @@ const registerForm: IFormControllers[] = [
{
type: 'CheckBox',
name: 'readme',
label: <>
<span>阅读并同意</span>
<Link to='/'>《会员服务协议》</Link>
<Link to='/'>《法律条款》</Link>
<Link to='/'>《隐私政策》</Link>
</>
span: 24,
labelCol: {
span: 22,
order: 2,
},
wrapperCol: {
span: 2,
order: 1,
},
style: {overflow: 'visible'},
label: <span style={{fontSize:12,overflow:'visible'}}>阅读并同意<Link to='/'>《会员服务协议》</Link><Link to='/'>《法律条款》</Link><Link to='/'>《隐私政策》</Link></span>,
colon: false,
}
]
const registerButtons: IFormButtonTypes[] = [
{
text: '同意协议并注册',
type: 'primary',
htmlType: 'submit',
block: true,
disabled: true,
disabled: false,
}
]
let timeChange; // 定时器
const UserRegistry = () => {
const [current, setCurrent] = useState(0)
const [identityForm1] = Form.useForm();
const [licenseForm] = Form.useForm();
const [current, setCurrent] = useState(1.1)
const handleOneSubmit = (values) => {
console.log(values, 'values')
if(values.phone) setCurrent(1)
}
const handleJumpLogin = () => {
history.push('/user/login')
}
const onChange = (value) => {
console.log(value.target.value,'value')
}
const handleSecondSubmit = (values) => {
console.log(values,'values')
setCurrent(1.1)
}
const handleLicenseSubmit = (values) => {
console.log(values, 'values')
setCurrent(2)
}
const [time, setTime] = useState(5);
useEffect(() => {
clearInterval(timeChange)
}, [])
useEffect(() => {
console.log(current)
if(current === 2) runTimerJump()
}, [current])
useEffect(() => {
if(time < 0){
clearInterval(timeChange)
setTime(5)
// history.push('/user/login')
console.log('执行登录跳转!')
}
}, [time])
const runTimerJump = () => {
timeChange = setInterval(() => setTime(t => --t), 1000)
}
const normFile = e => {
console.log('上传Upload 事件:', e);
if (Array.isArray(e)) {
return e;
}
return e && e.fileList;
}
const checkoutFile = (rule, value) => {
if(value && value.length){
let length = value.length
let obj = value[length-1]
const isLt5M = obj.size / 1024 / 1024 < 5;
if (isLt5M) {
return Promise.resolve();
}else{
return Promise.reject('附件大小不能超过5M!');
}
}else{
return Promise.reject();
}
}
const beforeUpload = (file) => {
const isLt5M = file.size / 1024 / 1024 < 5;
if (!isLt5M) {
message.error('附件大小不能超过5M!');
}
console.log(isLt5M)
return isLt5M;
}
return (
<div className={cx(styles.register, globalStyles.lingxiBusinessContent1024)}>
<h3>欢迎您注册数商云账号</h3>
......@@ -86,16 +211,173 @@ const UserRegistry = () => {
stepList.map(v => <Step title={v.title} key={v.key}/>)
}
</Steps>
<div className={styles.formBox}>
<FormPage renderFormLists={registerForm} renderButtonLists={registerButtons}>
<Row justify='center' align='middle'>
已有平台账号?<Button type='link'>去登陆</Button>
</Row>
</FormPage>
</div>
{
current === 0 && <div className={styles.formBoxStep1}>
<FormPage
renderFormLists={registerForm}
renderButtonLists={registerButtons}
onSubmit={handleOneSubmit}
>
<Row justify='center' align='middle'>
已有平台账号?<Button type='link' onClick={handleJumpLogin}>去登陆</Button>
</Row>
</FormPage>
</div>
}
{
current === 1 && <div className={styles.formBoxStep2}>
<Form
form={identityForm1}
name="identity_information"
onFinish={handleSecondSubmit}
>
<h3 className="commonPanelTitle">请选择您的身份</h3>
<Divider />
<Form.Item name='identity'>
<Radio.Group onChange={onChange} defaultValue="a" className={styles.identityRadio} name="identity">
<Radio.Button value="a">企业</Radio.Button>
<Radio.Button value="b">个人</Radio.Button>
</Radio.Group>
</Form.Item>
<h3 className="commonPanelTitle">请选择您要开展的业务</h3>
<Divider />
<Form.Item name='business'>
<Radio.Group onChange={onChange} defaultValue="f" className={styles.businessRadio} name="business">
<Radio.Button value="c">采购</Radio.Button>
<Radio.Button value="d">商品销售</Radio.Button>
<Radio.Button value="e">加工服务</Radio.Button>
<Radio.Button value="f">物流服务</Radio.Button>
<Radio.Button value="g">金融服务</Radio.Button>
<Radio.Button value="h">保险服务</Radio.Button>
</Radio.Group>
</Form.Item>
<Row>
<Button type='primary' className={styles.continueButton} htmlType="submit">下一步:继续</Button>
</Row>
</Form>
</div>
}
{
current === 1.1 && <div className={styles.formBoxStep2}>
<Form
{...formItemLayout}
form={licenseForm}
name="license_information"
onFinish={handleLicenseSubmit}
size="large"
colon={false}
>
<h3 className="commonPanelTitle">请填写营业执照信息</h3>
<Divider />
<Row gutter={[20,0]}>
<Col span={12}>
<Form.Item
name="companyName"
label={
<>
<Tooltip title="请填写法定代表人信息请填请填写法定代表人信息请填写法定代表人信息请填写法定代表人信息请填写法定代表人信息请填写法定代表人信息">
<QuestionCircleOutlined />
</Tooltip>
</>
}
>
<Input placeholder="请输入公司名称(必填)" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="companyType"
label={
<>
<Tooltip title="请填写法定代表人信息请填写法定代表人信息请填写法定代表人信表人信息请填写法定代表人信息请填写法定代表人信息请填写法定代表人信息">
<QuestionCircleOutlined />
</Tooltip>
</>
}
>
<Input placeholder="请输入企业类型(必填)" />
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
name="business"
labelCol={{span:1,order:2}}
wrapperCol={{span:23,order:1}}
label={
<>
<Tooltip title="请填写法定代表人信息请填写法定代表人信息请填写法定代表人信表人信息请填写法定代表人信息请填写法定代表人信息请填写法定代表人信息">
<QuestionCircleOutlined />
</Tooltip>
</>
}
>
<TextArea placeholder="请输入经营范围(必填)" rows={4} />
</Form.Item>
<Form.Item
name="runLicense"
valuePropName="fileList"
getValueFromEvent={normFile}
extra="附件大小不能超过5M"
rules={[
{
required: true,
message: '营业执照附件为必须项!'
},
{
validator: checkoutFile
}
]}
>
<Upload name="logo" action="/upload.do" beforeUpload={beforeUpload}>
<Button>
<UploadOutlined /> 上传营业执照附件
</Button>
</Upload>
</Form.Item>
</Col>
</Row>
<h3 className="commonPanelTitle">请填写法定代表人信息</h3>
<Divider />
<Row gutter={[20,0]}>
<Col span={12}>
<Form.Item
name="legalInfo"
label={
<>
<Tooltip title="请填写法定代表人信息请填写法定代表人信息请填写法定代表人信息请填写法定代定代表人信息请填写法定代表人信息请填写法定代表人信息">
<QuestionCircleOutlined />
</Tooltip>
</>
}
>
<Input placeholder="请输入法人身份证号码(必填)" />
</Form.Item>
</Col>
</Row>
<Row>
<Button type='primary' className={styles.continueButton} htmlType="submit">提交注册资料</Button>
</Row>
</Form>
</div>
}
{
current === 2 && <div className={styles.formBoxStep3}>
<img src={im_success} alt="待审核"/>
<h2>您的注册资料已经提交成功,请等待平台审核</h2>
<div className={styles.description}>
<p>审核结果会以短信通知您</p>
<p>您也可以登录平台查看审核结果</p>
</div>
<p className={styles.guid}>
<span>{time}s 后自动跳转至登录页</span>
<br />
<span><Link to="/user/login">立即跳转</Link></span>
</p>
</div>
}
</div>
</div>
)
}
export default UserRegistry
\ No newline at end of file
export default UserRegistry
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