feat: first commit

This commit is contained in:
eleanor.mao
2025-03-31 22:34:22 +08:00
commit d25187c9c8
390 changed files with 57031 additions and 0 deletions

View File

@ -0,0 +1,259 @@
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 { 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 { 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;
}
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 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>();
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);
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>
);
}