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 ProductJobDialog from '@/components/product-dialog/job'; 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 { CollectEventName, 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 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 store from '@/store'; import { cacheJobId } from '@/store/actions'; import { JobDetails } from '@/types/job'; import { IMaterialMessage } from '@/types/message'; import { switchRoleType } from '@/utils/app'; import { copy, logWithPrefix } from '@/utils/common'; import { collectEvent, reportEvent } from '@/utils/event'; import { getJobSalary, getJobTitle, postPublishJob, 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 { isNeedCreateMaterial } 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 [dialogVisible, setDialogVisible] = useState(false); const [showMaterialGuide, setShowMaterialGuide] = useState(false); const handleClickContact = useCallback(async () => { log('handleClickContact'); if (!data) { return; } reportEvent(ReportEventId.CLICK_JOB_CONTACT); try { const needCreateMaterial = await isNeedCreateMaterial(); if (data.sourcePlat !== 'bl') { if (needCreateMaterial) { const result = await requestProductUseRecord(ProductType.VIP, { jobId: data.id }); if (!result) { const [time, isPaidVip] = await requestProductBalance(ProductType.VIP); if (time <= 0 || !isPaidVip) { setShowMaterialGuide(true); return; } } } } if (data.isAuthed) { const toUserId = data.userId; if (isChatWithSelf(toUserId)) { Toast.error('不能与自己聊天'); return; } const chat = await postCreateChat(toUserId); let materialMessage: null | IMaterialMessage = null; if (!needCreateMaterial) { 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 { setDialogVisible(true); } } catch (error) { const e = error as HttpError; const errorCode = e.errorCode; if (errorCode === RESPONSE_ERROR_CODE.INSUFFICIENT_BALANCE) { setErrorTips('今日开聊次数已用完,请明日再来'); } else { Toast.error('请求失败请重试'); } } }, [data]); const handleDialogHidden = useCallback(() => { setDialogVisible(false); }, []); const handleConfirmPrejob = useCallback((type: GET_CONTACT_TYPE) => { setShowMaterialGuide(false); if (GET_CONTACT_TYPE.VIP === type) { setDialogVisible(true); } }, []); return ( <>
{data.isAuthed ? '在线沟通' : '立即联系'}
{dialogVisible && } {showMaterialGuide && ( setShowMaterialGuide(false)} onConfirm={handleConfirmPrejob} /> )} setErrorTips('')} onClick={() => setErrorTips('')} />
); }; const CompanyFooter = (props: { data: JobDetails }) => { const { data } = props; const [showBuy, setShowBuy] = useState(false); const userInfo = useUserInfo(); const handleClickEdit = useCallback(() => navigateTo(PageUrl.JobPublish, { jobId: data.id }), [data]); const handlePublishJob = useCallback(async () => { try { if (userInfo.bossAuthStatus !== CertificationStatusType.Success) { store.dispatch(cacheJobId(data.id)); navigateTo(PageUrl.CertificationStart); return; } Taro.showLoading(); await postPublishJob(data.id); Taro.eventCenter.trigger(EventName.COMPANY_JOB_PUBLISH_CHANGED); setShowBuy(false); Toast.success('发布成功'); Taro.hideLoading(); } catch (error) { Taro.hideLoading(); const e = error as HttpError; const errorCode = e.errorCode; const errorMsg = e.info?.() || e.message; collectEvent(CollectEventName.PUBLISH_OPEN_JOB_FAILED, { jobId: data.id, error: e.info?.() || e.message }); if (errorCode === RESPONSE_ERROR_CODE.INSUFFICIENT_BALANCE) { Toast.info('您购买的产品已耗尽使用次数'); setShowBuy(true); } else if (errorCode === RESPONSE_ERROR_CODE.BOSS_VIP_EXPIRED) { Toast.info('该通告已到期,请创建新通告', 3000); } else { Toast.error(errorMsg || '发布失败请重试', 3000); } console.error(e); } }, [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('出错了,请重试'); } }); 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 && }
); }