feat: first commit
This commit is contained in:
3
src/pages/certification/index.config.ts
Normal file
3
src/pages/certification/index.config.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '个人认证',
|
||||
});
|
||||
79
src/pages/certification/index.less
Normal file
79
src/pages/certification/index.less
Normal file
@ -0,0 +1,79 @@
|
||||
@import '@/styles/common.less';
|
||||
@import '@/styles/variables.less';
|
||||
|
||||
.page-certification {
|
||||
padding: 40px 24px;
|
||||
|
||||
&__id-card-container {
|
||||
width: 100%;
|
||||
.flex-row();
|
||||
}
|
||||
|
||||
&__id-card {
|
||||
flex: 1;
|
||||
height: 178px;
|
||||
.flex-column();
|
||||
justify-content: center;
|
||||
background: #F2F2F2;
|
||||
border-radius: 12px;
|
||||
margin: 24px 0;
|
||||
|
||||
&:first-child {
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
&__image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
}
|
||||
|
||||
&__describe {
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
font-weight: 400;
|
||||
color: @blColorG1;
|
||||
margin-top: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
&__verify {
|
||||
.flex-column();
|
||||
|
||||
&__input {
|
||||
flex: 1;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
&__code-container {
|
||||
width: 100%;
|
||||
.flex-row();
|
||||
}
|
||||
|
||||
&__send {
|
||||
font-size: 32px;
|
||||
line-height: 32px;
|
||||
font-weight: 400;
|
||||
color: @blHighlightColor;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
&__footer {
|
||||
position: fixed;
|
||||
left: 24px;
|
||||
right: 24px;
|
||||
bottom: 0;
|
||||
background: #F5F6FA;
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
&__submit {
|
||||
.button(@width: 100%; @height: 80px);
|
||||
margin-bottom: 56px;
|
||||
}
|
||||
}
|
||||
252
src/pages/certification/index.tsx
Normal file
252
src/pages/certification/index.tsx
Normal file
@ -0,0 +1,252 @@
|
||||
import { BaseEventOrig, Button, Image, InputProps } from '@tarojs/components';
|
||||
import Taro, { UploadTask } from '@tarojs/taro';
|
||||
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import BlFormInput from '@/components/bl-form-input';
|
||||
import BlFormItem from '@/components/bl-form-item';
|
||||
import LoadingDialog from '@/components/loading-dialog';
|
||||
import SafeBottomPadding from '@/components/safe-bottom-padding';
|
||||
import { PageUrl } from '@/constants/app';
|
||||
import { CertificationStatusType } from '@/constants/company';
|
||||
import { CollectEventName, ReportEventId } from '@/constants/event';
|
||||
import useUserInfo from '@/hooks/use-user-info';
|
||||
import { ICertificationRequest } from '@/types/company';
|
||||
import { isValidIdCard, isValidPhone, logWithPrefix } from '@/utils/common';
|
||||
import { postCertification } from '@/utils/company';
|
||||
import { collectEvent, reportEvent } from '@/utils/event';
|
||||
import { chooseMedia } from '@/utils/material';
|
||||
import { redirectTo } from '@/utils/route';
|
||||
import Toast from '@/utils/toast';
|
||||
import { dispatchUpdateUser, requestUserInfo } from '@/utils/user';
|
||||
import { uploadVideo } from '@/utils/video';
|
||||
|
||||
import './index.less';
|
||||
|
||||
const PREFIX = 'page-certification';
|
||||
const log = logWithPrefix(PREFIX);
|
||||
const needIdCard = false;
|
||||
|
||||
const isValidCertificationInfo = (data: ICertificationRequest) => {
|
||||
const {
|
||||
name,
|
||||
// code,
|
||||
phone,
|
||||
idCardNo: idNumber,
|
||||
companyName: company,
|
||||
// idCardSideAUrl: leftIdCardUrl,
|
||||
// idCardSideBUrl: rightIdCardUrl,
|
||||
} = data;
|
||||
// if (!leftIdCardUrl || !rightIdCardUrl) {
|
||||
// return '请上传身份证照片';
|
||||
// }
|
||||
if (!name) {
|
||||
return '请输入姓名';
|
||||
}
|
||||
if (!idNumber || !isValidIdCard(idNumber)) {
|
||||
return '请输入正确的身份证';
|
||||
}
|
||||
if (!phone || !isValidPhone(phone)) {
|
||||
return '请输入正确的手机号';
|
||||
}
|
||||
// if (!code) {
|
||||
// return '验证码不能为空';
|
||||
// }
|
||||
if (!company) {
|
||||
return '请输入公司名称';
|
||||
}
|
||||
};
|
||||
|
||||
const uploadIdCard = async () => {
|
||||
let showLoading = false;
|
||||
try {
|
||||
const media = await chooseMedia({
|
||||
count: 1,
|
||||
mediaType: ['image'],
|
||||
sourceType: ['album', 'camera'],
|
||||
});
|
||||
if (!media) {
|
||||
return;
|
||||
}
|
||||
const { tempFiles } = media;
|
||||
const tempFile = tempFiles[0];
|
||||
if (!tempFile) {
|
||||
throw new Error('tempFile is not exist');
|
||||
}
|
||||
showLoading = true;
|
||||
Taro.showLoading({ title: '上传0%' });
|
||||
const onProgress: UploadTask.OnProgressUpdateCallback = res => {
|
||||
log('上传视频进度', res.progress, '总长度', res.totalBytesExpectedToSend, '已上传的长度', res.totalBytesSent);
|
||||
Taro.showLoading({ title: `上传${res.progress}%` });
|
||||
};
|
||||
const { url } = await uploadVideo(tempFile.tempFilePath, tempFile.fileType, onProgress, 'id-card');
|
||||
return url;
|
||||
} catch (e) {
|
||||
console.error('upload fail', e);
|
||||
Toast.error('上传失败');
|
||||
collectEvent(CollectEventName.UPDATE_ID_CARD_FAILED, e);
|
||||
} finally {
|
||||
showLoading && Taro.hideLoading();
|
||||
}
|
||||
};
|
||||
|
||||
export default function Certification() {
|
||||
const { phone } = useUserInfo();
|
||||
const [leftIdCardUrl, setLeftIdCardUrl] = useState('');
|
||||
const [rightIdCardUrl, setRightIdCardUrl] = useState('');
|
||||
const [name, setName] = useState('');
|
||||
const [idNumber, setIdNumber] = useState('');
|
||||
// const [code, setCode] = useState('');
|
||||
const [company, setCompany] = useState('');
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const handleClickIdCardLeft = useCallback(async () => {
|
||||
reportEvent(ReportEventId.CLICK_UPLOAD_ID_CARD, { type: 'left' });
|
||||
const url = await uploadIdCard();
|
||||
url && setLeftIdCardUrl(url);
|
||||
}, []);
|
||||
|
||||
const handleClickIdCardRight = useCallback(async () => {
|
||||
reportEvent(ReportEventId.CLICK_START_CERTIFICATION, { type: 'right' });
|
||||
const url = await uploadIdCard();
|
||||
url && setRightIdCardUrl(url);
|
||||
}, []);
|
||||
|
||||
const handleInputName = useCallback((e: BaseEventOrig<InputProps.inputEventDetail>) => {
|
||||
const value = e.detail.value || '';
|
||||
setName(value);
|
||||
}, []);
|
||||
|
||||
const handleInputIdNumber = useCallback((e: BaseEventOrig<InputProps.inputEventDetail>) => {
|
||||
const value = e.detail.value || '';
|
||||
setIdNumber(value);
|
||||
}, []);
|
||||
|
||||
// const handleInputCode = useCallback((e: BaseEventOrig<InputProps.inputEventDetail>) => {
|
||||
// const value = e.detail.value || '';
|
||||
// setCode(value);
|
||||
// }, []);
|
||||
|
||||
const handleInputCompany = useCallback((e: BaseEventOrig<InputProps.inputEventDetail>) => {
|
||||
const value = e.detail.value || '';
|
||||
setCompany(value);
|
||||
}, []);
|
||||
|
||||
const handleSubmit = useCallback(async () => {
|
||||
reportEvent(ReportEventId.CLICK_CERTIFICATION_SUBMIT);
|
||||
const data: ICertificationRequest = {
|
||||
name,
|
||||
// code,
|
||||
phone,
|
||||
idCardNo: idNumber,
|
||||
companyName: company,
|
||||
// idCardSideAUrl: leftIdCardUrl,
|
||||
// idCardSideBUrl: rightIdCardUrl,
|
||||
};
|
||||
const errMsg = isValidCertificationInfo(data);
|
||||
if (errMsg) {
|
||||
Toast.info(errMsg);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
setOpen(true);
|
||||
const { authSuc, msg } = await postCertification(data);
|
||||
if (!authSuc) {
|
||||
Toast.info(msg || '认证失败');
|
||||
return;
|
||||
}
|
||||
dispatchUpdateUser({ bossAuthStatus: CertificationStatusType.Success });
|
||||
redirectTo(PageUrl.CertificationManage);
|
||||
} catch (e) {
|
||||
console.error('submit error', e);
|
||||
Toast.error('认证失败请重试');
|
||||
collectEvent(CollectEventName.SUBMIT_CERTIFICATION_FAILED, e);
|
||||
} finally {
|
||||
setOpen(false);
|
||||
}
|
||||
}, [name, idNumber, phone, company]);
|
||||
// }, [leftIdCardUrl, rightIdCardUrl, name, idNumber, phone, company]);
|
||||
|
||||
useEffect(() => {
|
||||
if (phone) {
|
||||
return;
|
||||
}
|
||||
const requestPhone = async () => {
|
||||
collectEvent(CollectEventName.CERTIFICATION_PAGE, { info: 'start requestPhone' });
|
||||
const userInfo = await requestUserInfo();
|
||||
collectEvent(CollectEventName.CERTIFICATION_PAGE, { info: 'requestPhone success', phone: userInfo.phone });
|
||||
};
|
||||
requestPhone();
|
||||
}, [phone]);
|
||||
|
||||
return (
|
||||
<div className={PREFIX}>
|
||||
{needIdCard && (
|
||||
<BlFormItem title="上传身份证照片" subTitle={false} dynamicHeight>
|
||||
<div className={`${PREFIX}__id-card-container`}>
|
||||
<div className={`${PREFIX}__id-card`} onClick={handleClickIdCardLeft}>
|
||||
{leftIdCardUrl && <Image mode="aspectFit" className={`${PREFIX}__id-card__image`} src={leftIdCardUrl} />}
|
||||
{!leftIdCardUrl && (
|
||||
<>
|
||||
<Image
|
||||
mode="aspectFit"
|
||||
className={`${PREFIX}__id-card__icon`}
|
||||
src={require('@/statics/svg/upload-id-card-icon.svg')}
|
||||
/>
|
||||
<div className={`${PREFIX}__id-card__describe`}>身份证人像面</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className={`${PREFIX}__id-card`} onClick={handleClickIdCardRight}>
|
||||
{rightIdCardUrl && (
|
||||
<Image mode="aspectFit" className={`${PREFIX}__id-card__image`} src={rightIdCardUrl} />
|
||||
)}
|
||||
{!rightIdCardUrl && (
|
||||
<>
|
||||
<Image
|
||||
mode="aspectFit"
|
||||
className={`${PREFIX}__id-card__icon`}
|
||||
src={require('@/statics/svg/upload-id-card-icon.svg')}
|
||||
/>
|
||||
<div className={`${PREFIX}__id-card__describe`}>身份证国徽面</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</BlFormItem>
|
||||
)}
|
||||
<BlFormItem title="姓名" subTitle={false}>
|
||||
<BlFormInput value={name} onInput={handleInputName} />
|
||||
</BlFormItem>
|
||||
<BlFormItem title="身份证号" subTitle={false}>
|
||||
<BlFormInput value={idNumber} onInput={handleInputIdNumber} type="idcard" maxlength={18} />
|
||||
</BlFormItem>
|
||||
<BlFormItem title="手机号" subTitle="请使用本人名下的手机号" contentClassName={`${PREFIX}__verify`} dynamicHeight>
|
||||
<BlFormInput className={`${PREFIX}__verify__input`} value={phone} type="number" maxlength={11} disabled />
|
||||
{/* <div className={`${PREFIX}__verify__code-container`}>
|
||||
<BlFormInput
|
||||
className={`${PREFIX}__verify__input`}
|
||||
value={code}
|
||||
onInput={handleInputCode}
|
||||
type="number"
|
||||
maxlength={8}
|
||||
/>
|
||||
<div className={`${PREFIX}__verify__send`}>获取验证码</div>
|
||||
</div> */}
|
||||
</BlFormItem>
|
||||
<BlFormItem title="公司全称" subTitle={false}>
|
||||
<BlFormInput maxlength={200} value={company} onInput={handleInputCompany} />
|
||||
</BlFormItem>
|
||||
<SafeBottomPadding />
|
||||
<div className={`${PREFIX}__footer`}>
|
||||
<Button className={`${PREFIX}__submit`} onClick={handleSubmit}>
|
||||
提交
|
||||
</Button>
|
||||
<SafeBottomPadding />
|
||||
</div>
|
||||
<div>
|
||||
<LoadingDialog open={open} text="认证中" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user