import { Button, Image, Map, MapProps, Text } from '@tarojs/components'; import Taro, { useLoad, useShareAppMessage } from '@tarojs/taro'; import { Dialog } from '@taroify/core'; import React, { useCallback, useEffect, useState } from 'react'; import { CertificationStatusIcon } from '@/components/certification-status'; import CommonDialog from '@/components/common-dialog'; import DevDiv from '@/components/dev-div'; import JobRecommendList from '@/components/job-recommend-list'; import { JoinGroupHint } from '@/components/join-group-hint'; import LoginButton from '@/components/login-button'; import PageLoading from '@/components/page-loading'; import { PrejobPopup } from '@/components/prejob-popup'; import ProductJobContactDialog from '@/components/product-dialog/job-contact'; import CompanyPublishJobBuy from '@/components/product-dialog/steps-ui/company-publish-job-buy'; import { EventName, PageUrl, RoleType } from '@/constants/app'; import { CertificationStatusType } from '@/constants/company'; import { ReportEventId } from '@/constants/event'; import { EMPLOY_TYPE_TITLE_MAP, GET_CONTACT_TYPE, JobManageStatus } from '@/constants/job'; import { ProductType } from '@/constants/product'; import useInviteCode from '@/hooks/use-invite-code'; import { usePublishJob } from '@/hooks/use-publish-job'; import useUserInfo from '@/hooks/use-user-info'; import useRoleType from '@/hooks/user-role-type'; import { RESPONSE_ERROR_CODE } from '@/http/constant'; import { HttpError } from '@/http/error'; import { JobDetails } from '@/types/job'; import { IMaterialMessage } from '@/types/message'; import { GetProductIsUnlockResponse, ProductInfo } from '@/types/product'; import { switchRoleType } from '@/utils/app'; import { copy, logWithPrefix } from '@/utils/common'; import { reportEvent } from '@/utils/event'; import { getJobSalary, getJobTitle, requestJobDetail } from '@/utils/job'; import { calcDistance, isValidLocation } from '@/utils/location'; import { requestProfileDetail } from '@/utils/material'; import { isChatWithSelf, postCreateChat } from '@/utils/message'; import { getInviteCodeFromQueryAndUpdate } from '@/utils/partner'; import { requestProductBalance, requestProductUseRecord } from '@/utils/product'; import { getJumpUrl, getPageQuery, navigateTo } from '@/utils/route'; import { getCommonShareMessage } from '@/utils/share'; import { formatDate } from '@/utils/time'; import Toast from '@/utils/toast'; import { isNeedPhone } from '@/utils/user'; import './index.less'; const PREFIX = 'job-detail'; const log = logWithPrefix(PREFIX); const getMapCallout = (data: JobDetails): MapProps.callout | undefined => { if (!data.jobLocation?.address) { return; } return { display: 'ALWAYS', content: data.jobLocation.address, color: '#000000', bgColor: '#FFFFFF', fontSize: 12, textAlign: 'center', anchorX: 0, anchorY: 0, borderRadius: 4, borderWidth: 0, borderColor: '#FFFFFF', padding: 4, }; }; const AnchorFooter = (props: { data: JobDetails }) => { const { data } = props; const [errorTips, setErrorTips] = useState(''); const [showJobContactDialog, setShowJobContactDialog] = useState(false); const [showMaterialGuide, setShowMaterialGuide] = useState(false); const [productInfo, setProductInfo] = useState(); const [productRecord, setProductRecord] = useState(); const userInfo = useUserInfo(); const needPhone = isNeedPhone(userInfo); const getProductRecord = useCallback(async () => { const result = await requestProductUseRecord(ProductType.VIP, { jobId: data.id }); setProductRecord(result); }, [data.id]); const getProductBalance = useCallback(async (loading?: boolean) => { if (loading) { Taro.showLoading(); } const [, resp] = await requestProductBalance(ProductType.VIP); setProductInfo(resp); console.log(resp); if (loading) { Taro.hideLoading(); } return resp; }, []); const handleClickContact = useCallback(async () => { log('handleClickContact'); if (!data) { return; } reportEvent(ReportEventId.CLICK_JOB_CONTACT); try { if (data.isAuthed) { const toUserId = data.userId; if (isChatWithSelf(toUserId)) { Toast.error('不能与自己聊天'); return; } const chat = await postCreateChat(toUserId); let materialMessage: null | IMaterialMessage = null; if (!!productInfo?.isCreateResume) { const profile = await requestProfileDetail(); if (profile) { materialMessage = { id: profile.id, name: profile.name, age: profile.age, height: profile.height, weight: profile.weight, shoeSize: profile.shoeSize, gender: profile.gender, workedSecCategoryStr: profile.workedSecCategoryStr, }; } } navigateTo(PageUrl.MessageChat, { chatId: chat.chatId, initText: !materialMessage, material: materialMessage, jobId: data.id, }); } else { // Show material guide if no resume and no VIP and no free balance if (!productRecord && !productInfo?.isCreateResume && !productInfo?.isPaidVip && !productInfo?.freeBalance) { setShowMaterialGuide(true); return; } // Open integrated dialog - it handles buy + contact internally setShowJobContactDialog(true); } } catch (error) { const e = error as HttpError; const errorCode = e.errorCode; if (errorCode === RESPONSE_ERROR_CODE.INSUFFICIENT_BALANCE) { setErrorTips('今日开聊次数已用完,请明日再来'); } else { Toast.error('请求失败请重试'); } } }, [data, productInfo?.freeBalance, productInfo?.isCreateResume, productInfo?.isPaidVip]); const handleDialogClose = useCallback(() => { setShowJobContactDialog(false); // Refresh data after dialog closes getProductRecord(); }, [getProductRecord]); const handleConfirmPrejob = useCallback( (type: GET_CONTACT_TYPE) => { setShowMaterialGuide(false); if (GET_CONTACT_TYPE.VIP === type) { getProductBalance().then(() => { setShowJobContactDialog(true); }); } }, [getProductBalance] ); // const unAuthedButtonText = useMemo(() => { // if (haveSeen) { // return '查看联系方式'; // } // // if (productInfo?.isPaidVip) { // return '您是会员,可直接查看'; // } // // if (productInfo?.freeBalance) { // return `还剩${productInfo.freeBalance}次查看次数`; // } // // return productInfo?.isCreateResume? '升级会员即可查看': '创建模卡,免费查看'; // }, [productInfo, haveSeen]); const handleRefresh = useCallback(async () => { await getProductBalance(true); }, [getProductBalance]); useEffect(() => { Taro.eventCenter.on(EventName.CREATE_PROFILE, getProductBalance); return () => { Taro.eventCenter.off(EventName.CREATE_PROFILE); }; }, [getProductBalance]); useEffect(() => { getProductBalance(); }, [getProductBalance]); useEffect(() => { getProductRecord(); }, [getProductRecord]); return ( <>
{data.isAuthed ? '在线沟通' : '查看联系方式'} {needPhone ? (
登录后可免费报单
) : !productRecord && (data.isAuthed || productInfo?.content) ? (
{data.isAuthed ? '急招岗位可免费查看' : productInfo?.content}
) : null}
{showJobContactDialog && ( )} {showMaterialGuide && ( setShowMaterialGuide(false)} onConfirm={handleConfirmPrejob} /> )} setErrorTips('')} onClick={() => setErrorTips('')} />
); }; const CompanyFooter = (props: { data: JobDetails }) => { const { data } = props; const [showBuy, setShowBuy, handlePublishJob] = usePublishJob(data.id); const handleClickEdit = useCallback(() => navigateTo(PageUrl.JobPublish, { jobId: data.id }), [data]); return ( <>
setShowBuy(false)}> ); }; export default function JobDetail() { const roleType = useRoleType(); const userInfo = useUserInfo(); const [data, setData] = useState(null); const isOwner = roleType === RoleType.Company && userInfo.userId === data?.userId; const inviteCode = useInviteCode(); const onDev = useCallback(async () => data && copy(data.id), [data]); const handleClickMap = useCallback( (e: React.MouseEvent) => { e.stopPropagation(); if (!data?.jobLocation) { return; } Taro.openLocation({ longitude: Number(data.jobLocation.longitude), latitude: Number(data.jobLocation.latitude), address: data.jobLocation.address, }); }, [data] ); useEffect(() => { const callback = async (jobId: string) => { try { const res = await requestJobDetail(jobId); setData(res); } catch (e) { console.error(e); } }; Taro.eventCenter.on(EventName.JOB_UPDATE, callback); return () => { Taro.eventCenter.off(EventName.JOB_UPDATE, callback); }; }, []); useLoad(async () => { const query = getPageQuery & { c: string; share: string }>(); if (query?.share === 'true') { switchRoleType(RoleType.Anchor); } getInviteCodeFromQueryAndUpdate(query); const jobId = query?.id; if (!jobId) { return; } Taro.eventCenter.trigger(EventName.VIEW_JOB_SUCCESS, jobId); try { const res = await requestJobDetail(jobId); setData(res); } catch (e) { console.error(e); Toast.error('出错了,请重试'); } }); Taro.showShareMenu({ withShareTicket: true, }); useShareAppMessage(() => { if (!data) { return getCommonShareMessage({ inviteCode }); } return { title: getJobTitle(data) || '', path: getJumpUrl(PageUrl.JobDetail, { id: data.id, share: true, c: inviteCode }), }; }); if (!data) { return ; } return (
{getJobTitle(data)}
{EMPLOY_TYPE_TITLE_MAP[data.employType]}
{getJobSalary(data)}
{`${formatDate(data.updated)}更新`}
请注意甄别通告真假,谨防上当
{`发布人:${data.publisher}`}
{data.isAuthed && ( )}
{data.companyName &&
{`公司:${data.companyName}`}
}
{!isOwner && }
职位描述
{(data.tags || []).map((keyword: string, index) => (
{keyword}
))}
{data.sourceText}
{data.jobLocation?.address}
{data.distance && (
{calcDistance(data.distance)}
)} {isValidLocation(data.jobLocation) && (
Toast.error('地图加载错误')} />
)}
{!isOwner && }
{!isOwner && } {isOwner && }
); }