320 lines
11 KiB
TypeScript
320 lines
11 KiB
TypeScript
import { BaseEventOrig, Button, ButtonProps, Image, InputProps } from '@tarojs/components';
|
|
import Taro, { UploadTask } from '@tarojs/taro';
|
|
|
|
import { Dialog } from '@taroify/core';
|
|
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 CompanyPublishJobBuy from '@/components/product-dialog/steps-ui/company-publish-job-buy';
|
|
import SafeBottomPadding from '@/components/safe-bottom-padding';
|
|
import { EventName, PageUrl } from '@/constants/app';
|
|
import { CertificationStatusType } from '@/constants/company';
|
|
import { CollectEventName, ReportEventId } from '@/constants/event';
|
|
import { ProductType } from '@/constants/product';
|
|
import useCachedJobId from '@/hooks/use-cached-job';
|
|
import useUserInfo from '@/hooks/use-user-info';
|
|
import store from '@/store';
|
|
import { clearCachedJobId } from '@/store/actions';
|
|
import { ICertificationRequest } from '@/types/company';
|
|
import { isValidIdCard, isValidPhone, logWithPrefix } from '@/utils/common';
|
|
import { postCertification, getPhone } from '@/utils/company';
|
|
import { collectEvent, reportEvent } from '@/utils/event';
|
|
import { postPublishJob } from '@/utils/job';
|
|
import { chooseMedia } from '@/utils/material';
|
|
import { requestProductBalance } from '@/utils/product';
|
|
import { redirectTo } from '@/utils/route';
|
|
import Toast from '@/utils/toast';
|
|
import { dispatchUpdateUser, requestUserInfo } from '@/utils/user';
|
|
import { uploadVideo } from '@/utils/video';
|
|
|
|
import './index.less';
|
|
import { RESPONSE_ERROR_CODE } from '@/http/constant';
|
|
|
|
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 [revisedPhone, setRevisedPhone] = useState('');
|
|
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 [showBuy, setShowBuy] = useState(false);
|
|
const cachedJobId = useCachedJobId();
|
|
|
|
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 handleCloseBuy = useCallback(() => {
|
|
setShowBuy(false);
|
|
redirectTo(PageUrl.CertificationManage);
|
|
}, []);
|
|
|
|
const handlePublishJob = useCallback(async () => {
|
|
try {
|
|
Taro.showLoading();
|
|
await postPublishJob(cachedJobId!);
|
|
await Toast.success('通告发布成功', 1500, true);
|
|
store.dispatch(clearCachedJobId());
|
|
Taro.eventCenter.trigger(EventName.COMPANY_JOB_PUBLISH_CHANGED);
|
|
redirectTo(PageUrl.CertificationManage);
|
|
} catch (e) {
|
|
console.error('submit error', e.errorCode, e.errorMsg);
|
|
console.dir(e);
|
|
if (e.errorCode === RESPONSE_ERROR_CODE.JOB_EXIST_ONE_PUBLISHED) {
|
|
Toast.info(e.errorMsg || e.errorCode, 3000);
|
|
} else {
|
|
Toast.error('通告发布失败');
|
|
}
|
|
collectEvent(CollectEventName.PUBLISH_JOB_FAILED, e);
|
|
redirectTo(PageUrl.CertificationManage);
|
|
} finally {
|
|
Taro.hideLoading();
|
|
}
|
|
}, [cachedJobId]);
|
|
|
|
const handleSubmit = useCallback(async () => {
|
|
reportEvent(ReportEventId.CLICK_CERTIFICATION_SUBMIT);
|
|
const data: ICertificationRequest = {
|
|
name,
|
|
// code,
|
|
phone: revisedPhone || 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 });
|
|
|
|
const [time] = await requestProductBalance(ProductType.CompanyPublishJob);
|
|
if (time <= 0) {
|
|
setShowBuy(true);
|
|
Taro.hideLoading();
|
|
} else {
|
|
await handlePublishJob();
|
|
}
|
|
} catch (e) {
|
|
console.error('submit error', e);
|
|
Toast.error('认证失败请重试');
|
|
collectEvent(CollectEventName.SUBMIT_CERTIFICATION_FAILED, e);
|
|
} finally {
|
|
setOpen(false);
|
|
}
|
|
}, [name, idNumber, phone, revisedPhone, company]);
|
|
// }, [leftIdCardUrl, rightIdCardUrl, name, idNumber, phone, company]);
|
|
|
|
const handleGetPhoneNumber = async (e: BaseEventOrig<ButtonProps.onGetRealTimePhoneNumberEventDetail>) => {
|
|
if (e.detail.code) {
|
|
try {
|
|
const { phoneNumber } = await getPhone(e.detail.code);
|
|
setRevisedPhone(phoneNumber);
|
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
} catch (e) {
|
|
Toast.error('获取手机号失败');
|
|
}
|
|
} else {
|
|
Toast.error('获取手机号失败');
|
|
}
|
|
};
|
|
|
|
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={revisedPhone || phone}
|
|
type="number"
|
|
maxlength={11}
|
|
disabled
|
|
/>
|
|
<div className={`${PREFIX}__verify__update`}>
|
|
<Button openType="getRealtimePhoneNumber" onGetRealTimePhoneNumber={handleGetPhoneNumber}>
|
|
修改
|
|
</Button>
|
|
</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>
|
|
<Dialog open={showBuy} onClose={handleCloseBuy}>
|
|
<Dialog.Content>
|
|
<CompanyPublishJobBuy onNext={handlePublishJob} />
|
|
</Dialog.Content>
|
|
</Dialog>
|
|
</div>
|
|
);
|
|
}
|