264 lines
9.4 KiB
TypeScript
264 lines
9.4 KiB
TypeScript
import { Button } from '@tarojs/components';
|
||
import Taro, { useLoad, useShareAppMessage } from '@tarojs/taro';
|
||
|
||
import { useCallback, useEffect, useState } from 'react';
|
||
|
||
import CommonDialog from '@/components/common-dialog';
|
||
import PageLoading from '@/components/page-loading';
|
||
import SafeBottomPadding from '@/components/safe-bottom-padding';
|
||
import { EventName, OpenSource, PageUrl } from '@/constants/app';
|
||
import { CollectEventName } from '@/constants/event';
|
||
import { MaterialViewSource } from '@/constants/material';
|
||
import ProfileViewFragment from '@/fragments/profile/view';
|
||
import useInviteCode from '@/hooks/use-invite-code';
|
||
import { RESPONSE_ERROR_CODE } from '@/http/constant';
|
||
import { HttpError } from '@/http/error';
|
||
import { JobManageInfo } from '@/types/job';
|
||
import { MaterialProfile } from '@/types/material';
|
||
import { IJobMessage } from '@/types/message';
|
||
import { copy } from '@/utils/common';
|
||
import { collectEvent } from '@/utils/event';
|
||
import { requestHasPublishedJob, requestJobDetail } from '@/utils/job';
|
||
import { getMaterialShareMessage, requestReadProfile, requestShareProfile } from '@/utils/material';
|
||
import { isChatWithSelf, postCreateChat } from '@/utils/message';
|
||
import { getInviteCodeFromQueryAndUpdate } from '@/utils/partner';
|
||
import { getPageQuery, navigateBack, navigateTo, redirectTo } from '@/utils/route';
|
||
import Toast from '@/utils/toast';
|
||
import './index.less';
|
||
|
||
const PREFIX = 'page-material-view';
|
||
|
||
interface IViewContext {
|
||
resumeId: string;
|
||
source: MaterialViewSource.AnchorList | MaterialViewSource.Chat;
|
||
jobId?: string;
|
||
}
|
||
|
||
interface IShareContext {
|
||
resumeId: string;
|
||
source: MaterialViewSource.Share;
|
||
shareCode: string;
|
||
c?: string;
|
||
}
|
||
|
||
const isShareContext = (context: IViewContext | IShareContext): context is IShareContext => {
|
||
return !!(context as IShareContext).shareCode;
|
||
};
|
||
|
||
const requestProfile = async (context: IViewContext | IShareContext) => {
|
||
if (!context.resumeId) {
|
||
throw new Error('参数错误');
|
||
}
|
||
if (isShareContext(context)) {
|
||
const { resumeId, shareCode } = context;
|
||
const profileDetail = await requestShareProfile({ resumeId, shareCode });
|
||
return profileDetail;
|
||
} else {
|
||
const { resumeId, jobId } = context;
|
||
const profileDetail = await requestReadProfile({ resumeId, jobId });
|
||
return profileDetail;
|
||
}
|
||
};
|
||
|
||
export default function MaterialViewPage() {
|
||
const [contactEnable, setContactEnable] = useState(true);
|
||
const [profile, setProfile] = useState<MaterialProfile | null>(null);
|
||
const [jobId, setJobId] = useState<string>();
|
||
const [errorTips, setErrorTips] = useState<string>('');
|
||
const [publishDialogVisible, setPublishDialogVisible] = useState(false);
|
||
const [certificationDialogVisible, setCertificationDialogVisible] = useState(false);
|
||
const [noTimeDialogVisible, setNoTimeDialogVisible] = useState(false);
|
||
const [noVipLimitVisible, setNoVipLimitVisible] = useState(false);
|
||
const [vipExpiredVisible, setVipExpiredVisible] = useState(false);
|
||
const inviteCode = useInviteCode();
|
||
|
||
const onDev = useCallback(async () => profile && copy(profile.userId), [profile]);
|
||
|
||
const handleClickContact = useCallback(async () => {
|
||
if (!profile) {
|
||
return;
|
||
}
|
||
try {
|
||
if (jobId) {
|
||
const toUserId = profile.userId;
|
||
if (isChatWithSelf(toUserId)) {
|
||
Toast.error('不能与自己聊天');
|
||
return;
|
||
}
|
||
const jobDetail = await requestJobDetail(jobId);
|
||
const chat = await postCreateChat(toUserId);
|
||
const jobMessage: IJobMessage = {
|
||
id: jobDetail.id,
|
||
title: jobDetail.title,
|
||
employType: jobDetail.employType,
|
||
salary: jobDetail.salary,
|
||
lowPriceForFullTime: jobDetail.lowPriceForFullTime,
|
||
highPriceForFullTime: jobDetail.highPriceForFullTime,
|
||
lowPriceForPartyTime: jobDetail.lowPriceForPartyTime,
|
||
highPriceForPartyTime: jobDetail.highPriceForPartyTime,
|
||
};
|
||
navigateTo(PageUrl.MessageChat, { chatId: chat.chatId, job: jobMessage, jobId });
|
||
return;
|
||
}
|
||
if (!(await requestHasPublishedJob())) {
|
||
setPublishDialogVisible(true);
|
||
return;
|
||
}
|
||
navigateTo(PageUrl.JobSelectMyPublish, { source: OpenSource.MaterialViewPage });
|
||
} catch (error) {
|
||
const e = error as HttpError;
|
||
const errorCode = e.errorCode;
|
||
if (errorCode === RESPONSE_ERROR_CODE.INSUFFICIENT_BALANCE) {
|
||
setErrorTips('今日10次开聊次数已用完,请明日再来');
|
||
} else {
|
||
Toast.error('请求失败请重试');
|
||
}
|
||
}
|
||
}, [profile, jobId]);
|
||
|
||
const handleClickNoViewTimes = useCallback(() => {
|
||
setNoTimeDialogVisible(false);
|
||
navigateBack();
|
||
}, []);
|
||
|
||
const handleClickGoPublish = useCallback(() => {
|
||
setPublishDialogVisible(false);
|
||
redirectTo(PageUrl.CertificationManage);
|
||
}, []);
|
||
|
||
const handleClickGoCertification = useCallback(() => {
|
||
setCertificationDialogVisible(false);
|
||
redirectTo(PageUrl.CertificationStart);
|
||
}, []);
|
||
|
||
useEffect(() => {
|
||
const callback = (select: JobManageInfo, source: OpenSource) =>
|
||
source === OpenSource.MaterialViewPage && setJobId(select.id);
|
||
Taro.eventCenter.on(EventName.SELECT_MY_PUBLISH_JOB, callback);
|
||
return () => {
|
||
Taro.eventCenter.off(EventName.SELECT_MY_PUBLISH_JOB, callback);
|
||
};
|
||
}, []);
|
||
|
||
useLoad(async () => {
|
||
const context = getPageQuery<IViewContext | IShareContext>();
|
||
getInviteCodeFromQueryAndUpdate(context as BL.Anything);
|
||
try {
|
||
const profileDetail = await requestProfile(context);
|
||
setProfile(profileDetail);
|
||
if (!isShareContext(context)) {
|
||
setJobId(context.jobId);
|
||
Taro.eventCenter.trigger(EventName.VIEW_MATERIAL_SUCCESS, profileDetail.id);
|
||
}
|
||
if (context.source === MaterialViewSource.Chat) {
|
||
setContactEnable(false);
|
||
}
|
||
Taro.setNavigationBarTitle({ title: profileDetail.name || '主播模卡' });
|
||
} catch (error) {
|
||
const e = error as HttpError;
|
||
const errorCode = e.errorCode;
|
||
collectEvent(CollectEventName.VIEW_MATERIAL_FAILED, { context, error: e.info?.() || e.message });
|
||
console.error(e);
|
||
if (errorCode === RESPONSE_ERROR_CODE.BOSS_NOT_AUTH) {
|
||
setCertificationDialogVisible(true);
|
||
} else if (errorCode === RESPONSE_ERROR_CODE.NO_PUBLISHED_JOB) {
|
||
setPublishDialogVisible(true);
|
||
} else if (errorCode === RESPONSE_ERROR_CODE.INSUFFICIENT_BALANCE) {
|
||
setNoTimeDialogVisible(true);
|
||
} else if (errorCode === RESPONSE_ERROR_CODE.INSUFFICIENT_FREE_BALANCE) {
|
||
setNoVipLimitVisible(true);
|
||
} else if (errorCode === RESPONSE_ERROR_CODE.BOSS_VIP_EXPIRED) {
|
||
setVipExpiredVisible(true);
|
||
} else {
|
||
Toast.error(e.message || '加载失败');
|
||
}
|
||
}
|
||
});
|
||
|
||
useShareAppMessage(async () => {
|
||
const shareMessage = await getMaterialShareMessage(profile, true, inviteCode);
|
||
return shareMessage as BL.Anything;
|
||
});
|
||
|
||
if (!profile) {
|
||
return (
|
||
<>
|
||
<PageLoading />
|
||
<CommonDialog
|
||
content="要查看主播详情,请先完成实人认证"
|
||
confirm="去认证"
|
||
visible={certificationDialogVisible}
|
||
onClose={() => setCertificationDialogVisible(false)}
|
||
onClick={handleClickGoCertification}
|
||
/>
|
||
<CommonDialog
|
||
content="请先发布一个认证通告"
|
||
confirm="去发布"
|
||
visible={publishDialogVisible}
|
||
onClose={() => setPublishDialogVisible(false)}
|
||
onClick={handleClickGoPublish}
|
||
/>
|
||
<CommonDialog
|
||
content="请先发布一个认证通告"
|
||
confirm="去发布"
|
||
visible={noVipLimitVisible}
|
||
onClose={() => setNoVipLimitVisible(false)}
|
||
onClick={handleClickGoPublish}
|
||
>
|
||
<div className={`${PREFIX}__no-time-tips`}>免费查看模卡详情次数已用完</div>
|
||
</CommonDialog>
|
||
<CommonDialog
|
||
content="请先发布一个认证通告"
|
||
confirm="去发布"
|
||
visible={vipExpiredVisible}
|
||
onClose={() => setVipExpiredVisible(false)}
|
||
onClick={handleClickGoPublish}
|
||
/>
|
||
<CommonDialog
|
||
content="今日查看模卡详情次数已用完"
|
||
confirm="确定"
|
||
visible={noTimeDialogVisible}
|
||
onClick={handleClickNoViewTimes}
|
||
>
|
||
<div className={`${PREFIX}__no-time-tips`}> 当前每个通告单日查看次数为 20 次</div>
|
||
</CommonDialog>
|
||
</>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<div className={PREFIX}>
|
||
<ProfileViewFragment profile={profile} editable={false} onDev={onDev} />
|
||
<div className={`${PREFIX}__footer`}>
|
||
<div className={`${PREFIX}__footer__buttons`}>
|
||
<Button className={`${PREFIX}__footer__buttons__share`} openType="share">
|
||
分享
|
||
</Button>
|
||
{contactEnable && (
|
||
<Button className={`${PREFIX}__footer__buttons__contact`} onClick={handleClickContact}>
|
||
立即联系
|
||
</Button>
|
||
)}
|
||
</div>
|
||
<SafeBottomPadding />
|
||
</div>
|
||
<div>
|
||
<CommonDialog
|
||
content="请先发布一个认证通告"
|
||
confirm="去发布"
|
||
visible={publishDialogVisible}
|
||
onClose={() => setPublishDialogVisible(false)}
|
||
onClick={handleClickGoPublish}
|
||
/>
|
||
<CommonDialog
|
||
content={errorTips}
|
||
confirm="确定"
|
||
visible={!!errorTips}
|
||
onClose={() => setErrorTips('')}
|
||
onClick={() => setErrorTips('')}
|
||
/>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|