|  |  |  | 
|---|
|  |  |  | <template> | 
|---|
|  |  |  | <LoadingLayout :loading="isLoading" :error="isError" :loadError="refetch"> | 
|---|
|  |  |  | <ContentScrollView style="background-color: transparent"> | 
|---|
|  |  |  | <Cell :title="'客房服务员'" titleSize="large"> | 
|---|
|  |  |  | <Cell :title="detail?.name ?? ''" titleSize="large"> | 
|---|
|  |  |  | <template #title-right> | 
|---|
|  |  |  | <img :src="IconAttentioActive" class="taskDetail-attention-icon" /> | 
|---|
|  |  |  | <img | 
|---|
|  |  |  | v-if="from === 'apply'" | 
|---|
|  |  |  | :src="detail.isCollected ? IconAttentioActive : IconAttention" | 
|---|
|  |  |  | class="taskDetail-attention-icon" | 
|---|
|  |  |  | @click="handleAttention" | 
|---|
|  |  |  | /> | 
|---|
|  |  |  | <div | 
|---|
|  |  |  | v-if="from === 'sign'" | 
|---|
|  |  |  | :style="{ color: GetPersonalApplyTaskInfosQueryStatusColor[detail.applyButton] }" | 
|---|
|  |  |  | > | 
|---|
|  |  |  | {{ GetTaskInfoQueryResultApplyButtonText[detail.applyButton] }} | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | <div | 
|---|
|  |  |  | v-if="from === 'hire'" | 
|---|
|  |  |  | :style="{ color: GetPersonalHireTaskInfosQueryStatusColor[detail.hireButton] }" | 
|---|
|  |  |  | > | 
|---|
|  |  |  | {{ GetTaskInfoQueryResultHireButtonText[detail.hireButton] }} | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | <div v-if="from === 'cancel'" :style="{ color: '#999999' }">已取消</div> | 
|---|
|  |  |  | </template> | 
|---|
|  |  |  | <div class="taskDetail-time">2025年2月5日 至 2025年3月5日</div> | 
|---|
|  |  |  | <div class="taskDetail-time"> | 
|---|
|  |  |  | {{ dayjs(detail?.beginTime).format('YYYY年MM月DD日') }} 至 | 
|---|
|  |  |  | {{ dayjs(detail?.endTime).format('YYYY年MM月DD日') }} | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | <div class="task-card-welfare-wrapper"> | 
|---|
|  |  |  | <div class="task-card-welfare-list"> | 
|---|
|  |  |  | <div class="task-card-welfare-list-item">日结</div> | 
|---|
|  |  |  | <div class="task-card-welfare-list-item">男女不限</div> | 
|---|
|  |  |  | <div class="task-card-welfare-list-item">包三餐</div> | 
|---|
|  |  |  | <div class="task-card-welfare-list-item"> | 
|---|
|  |  |  | {{ EnumSettlementCycleText[detail.settlementCycle] }} | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | <!-- <div class="task-card-welfare-list-item"> | 
|---|
|  |  |  | {{ TaskUtils.getGenderText(detail.genderLimit) }} | 
|---|
|  |  |  | </div> --> | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | <TaskPrice :value="212" /> | 
|---|
|  |  |  | <TaskPrice | 
|---|
|  |  |  | v-if="detail.releaseStatus !== EnumTaskReleaseStatus.Stopped" | 
|---|
|  |  |  | :value="toThousand(detail.serviceFee ?? 0)" | 
|---|
|  |  |  | :unit="BillingMethodEnumUnit[detail.billingMethod]" | 
|---|
|  |  |  | /> | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | <div class="taskDetail-address-wrapper"> | 
|---|
|  |  |  | <div class="taskDetail-address-wrapper" @click="goMap"> | 
|---|
|  |  |  | <div class="taskDetail-address-title-wrapper"> | 
|---|
|  |  |  | <img :src="IconLocaltion" class="taskDetail-address-title-icon" /> | 
|---|
|  |  |  | <div class="taskDetail-address-title">宁波柏悦酒店</div> | 
|---|
|  |  |  | <div class="taskDetail-address-title">{{ detail?.addressName ?? '' }}</div> | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | <div class="taskDetail-address-info-wrapper"> | 
|---|
|  |  |  | <div class="taskDetail-address-info">宁波市鄞州区东钱湖大堰路188号宁波柏悦酒店</div> | 
|---|
|  |  |  | <div class="taskDetail-address-info">{{ detail?.addressDetail ?? '' }}</div> | 
|---|
|  |  |  | <RectRight :size="8" class="taskDetail-address-info-icon" /> | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | 
|---|
|  |  |  | <Cell :show-title="false"> | 
|---|
|  |  |  | <CellChunk title="福利信息"> | 
|---|
|  |  |  | <div class="taskDetail-welfare-list"> | 
|---|
|  |  |  | <TaskDetailWelfareItem :icon="IconAttentioActive" text="高温补贴" /> | 
|---|
|  |  |  | <TaskDetailWelfareItem :icon="IconAttentioActive" text="高温补贴" /> | 
|---|
|  |  |  | <TaskDetailWelfareItem :icon="IconAttentioActive" text="高温补贴" /> | 
|---|
|  |  |  | <TaskDetailWelfareItem :icon="IconAttentioActive" text="高温补贴" /> | 
|---|
|  |  |  | <TaskDetailWelfareItem :icon="IconAttentioActive" text="高温补贴" /> | 
|---|
|  |  |  | <TaskDetailWelfareItem | 
|---|
|  |  |  | v-for="benefit in detail.benefits" | 
|---|
|  |  |  | :key="benefit.benefitCode" | 
|---|
|  |  |  | :icon="setOSSLink(benefit.benefitField2)" | 
|---|
|  |  |  | :text="benefit.benefitContent" | 
|---|
|  |  |  | /> | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | </CellChunk> | 
|---|
|  |  |  | <CellChunk title="报名条件"> | 
|---|
|  |  |  | <div class="taskDetail-limit-list"> | 
|---|
|  |  |  | <div class="taskDetail-limit-list-item"> | 
|---|
|  |  |  | <div class="taskDetail-limit-list-item-label">年龄:</div> | 
|---|
|  |  |  | <div class="taskDetail-limit-list-item-text">18-45岁</div> | 
|---|
|  |  |  | <div class="taskDetail-limit-list-item-text"> | 
|---|
|  |  |  | {{ detail.ageMinLimit ?? 0 }}-{{ detail.ageMaxLimit ?? 0 }}岁 | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | <div class="taskDetail-limit-list-item"> | 
|---|
|  |  |  | <div class="taskDetail-limit-list-item-label">性别:</div> | 
|---|
|  |  |  | <div class="taskDetail-limit-list-item-text">不限</div> | 
|---|
|  |  |  | <div class="taskDetail-limit-list-item-text"> | 
|---|
|  |  |  | {{ TaskUtils.getGenderText(detail.genderLimit) }} | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | <div class="taskDetail-limit-list-item"> | 
|---|
|  |  |  | <div class="taskDetail-limit-list-item-label">资格证书:</div> | 
|---|
|  |  |  | <div class="taskDetail-limit-list-item-text">健康证</div> | 
|---|
|  |  |  | <template v-if="detail?.credentialLimits?.length > 0"> | 
|---|
|  |  |  | <div class="taskDetail-limit-list-item-label">资格证书:</div> | 
|---|
|  |  |  | <div class="taskDetail-limit-list-item-text"> | 
|---|
|  |  |  | {{ TaskUtils.getCredentialLimit(detail?.credentialLimits) }} | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | </template> | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | </CellChunk> | 
|---|
|  |  |  | <CellChunk title="发布者信息"> | 
|---|
|  |  |  | <CompanyDesc @click="goCompanyDetail"></CompanyDesc> | 
|---|
|  |  |  | <CompanyDesc | 
|---|
|  |  |  | @click="goCompanyDetail" | 
|---|
|  |  |  | :enterpriseName="detail?.enterpriseName ?? ''" | 
|---|
|  |  |  | :taskCount="detail?.taskCount ?? 0" | 
|---|
|  |  |  | :isReal="detail?.isReal ?? false" | 
|---|
|  |  |  | ></CompanyDesc> | 
|---|
|  |  |  | </CellChunk> | 
|---|
|  |  |  | </Cell> | 
|---|
|  |  |  | <Cell title="任务描述"> | 
|---|
|  |  |  | <div class="safe-cell-content">{{ detail?.description ?? '' }}</div> | 
|---|
|  |  |  | </Cell> | 
|---|
|  |  |  | <Cell> | 
|---|
|  |  |  | <template #title> | 
|---|
|  |  |  | 
|---|
|  |  |  | :isFlex="false" | 
|---|
|  |  |  | openType="share" | 
|---|
|  |  |  | ></PageFooterAction> | 
|---|
|  |  |  | <PageFooterAction :icon="IconPhone" text="手机" :isFlex="false"></PageFooterAction> | 
|---|
|  |  |  | <PageFooterBtn type="primary">报名(5人已报名)</PageFooterBtn> | 
|---|
|  |  |  | <PageFooterAction | 
|---|
|  |  |  | :icon="IconPhone" | 
|---|
|  |  |  | text="手机" | 
|---|
|  |  |  | :isFlex="false" | 
|---|
|  |  |  | @click="handleCall" | 
|---|
|  |  |  | ></PageFooterAction> | 
|---|
|  |  |  | <PageFooterBtn | 
|---|
|  |  |  | v-if="from === 'sign' && !!detail?.applyButton" | 
|---|
|  |  |  | type="primary" | 
|---|
|  |  |  | :disabled="detail?.applyButton === GetTaskInfoQueryResultApplyButton.WaitHire" | 
|---|
|  |  |  | @click="handleSign" | 
|---|
|  |  |  | > | 
|---|
|  |  |  | {{ GetTaskInfoQueryResultApplyButtonText[detail.applyButton] }} | 
|---|
|  |  |  | </PageFooterBtn> | 
|---|
|  |  |  | <PageFooterBtn | 
|---|
|  |  |  | v-if=" | 
|---|
|  |  |  | from === 'hire' && | 
|---|
|  |  |  | !( | 
|---|
|  |  |  | detail?.checkReceiveMethod === EnumTaskCheckReceiveMethod.CheckIn && | 
|---|
|  |  |  | detail?.hireButton === GetTaskInfoQueryResultHireButton.ApplyCheckReceive | 
|---|
|  |  |  | ) | 
|---|
|  |  |  | " | 
|---|
|  |  |  | type="primary" | 
|---|
|  |  |  | :disabled="detail?.hireButton !== GetTaskInfoQueryResultHireButton.ApplyCheckReceive" | 
|---|
|  |  |  | @click="handleHire" | 
|---|
|  |  |  | > | 
|---|
|  |  |  | {{ GetTaskInfoQueryResultHireButtonText[detail.hireButton] }} | 
|---|
|  |  |  | </PageFooterBtn> | 
|---|
|  |  |  | <template v-if="from === 'apply'"> | 
|---|
|  |  |  | <PageFooterBtn | 
|---|
|  |  |  | v-if="detail?.releaseStatus === EnumTaskReleaseStatus.InProcess" | 
|---|
|  |  |  | type="primary" | 
|---|
|  |  |  | @click="handleApply" | 
|---|
|  |  |  | :disabled="!!detail?.hireStatus" | 
|---|
|  |  |  | >{{ `报名(${detail?.applyCount ?? 0}人已报名)` }}</PageFooterBtn | 
|---|
|  |  |  | > | 
|---|
|  |  |  |  | 
|---|
|  |  |  | <PageFooterBtn v-if="detail.releaseStatus === EnumTaskReleaseStatus.Stopped" color="#999999" | 
|---|
|  |  |  | >已停止</PageFooterBtn | 
|---|
|  |  |  | > | 
|---|
|  |  |  | </template> | 
|---|
|  |  |  | </PageFooter> | 
|---|
|  |  |  | </LoadingLayout> | 
|---|
|  |  |  | </template> | 
|---|
|  |  |  | 
|---|
|  |  |  | <script setup lang="ts"> | 
|---|
|  |  |  | import Taro from '@tarojs/taro'; | 
|---|
|  |  |  | import { useQuery } from '@tanstack/vue-query'; | 
|---|
|  |  |  | import * as orderServices from '@12333/services/api/Order'; | 
|---|
|  |  |  | import * as taskServices from '@12333/services/apiV2/task'; | 
|---|
|  |  |  | import * as taskUserServices from '@12333/services/apiV2/taskUser'; | 
|---|
|  |  |  | import * as enterpriseEmployeeServices from '@12333/services/apiV2/enterpriseEmployee'; | 
|---|
|  |  |  | import { useToggle } from 'senin-mini/hooks'; | 
|---|
|  |  |  | import { TaskPrice, TaskDetailWelfareItem } from '@12333/components'; | 
|---|
|  |  |  | import IconAttention from '@/assets/task/icon-attention.png'; | 
|---|
|  |  |  | 
|---|
|  |  |  | import IconLocaltion from '@/assets/task/icon-localtion.png'; | 
|---|
|  |  |  | import './taskDetail.scss'; | 
|---|
|  |  |  | import CompanyDesc from '../components/CompanyDesc.vue'; | 
|---|
|  |  |  | import dayjs from 'dayjs'; | 
|---|
|  |  |  | import { TaskUtils, toThousand, setOSSLink, Message } from '@12333/utils'; | 
|---|
|  |  |  | import { | 
|---|
|  |  |  | EnumSettlementCycleText, | 
|---|
|  |  |  | BillingMethodEnumUnit, | 
|---|
|  |  |  | EnumTaskReleaseStatus, | 
|---|
|  |  |  | GetPersonalApplyTaskInfosQueryStatusColor, | 
|---|
|  |  |  | GetTaskInfoQueryResultApplyButtonText, | 
|---|
|  |  |  | GetPersonalHireTaskInfosQueryStatusColor, | 
|---|
|  |  |  | GetTaskInfoQueryResultHireButtonText, | 
|---|
|  |  |  | GetTaskInfoQueryResultHireButton, | 
|---|
|  |  |  | GetTaskInfoQueryResultApplyButton, | 
|---|
|  |  |  | EnumTaskCheckReceiveMethod, | 
|---|
|  |  |  | } from '@12333/constants'; | 
|---|
|  |  |  | import { useAccessLogin } from '@/hooks'; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | defineOptions({ | 
|---|
|  |  |  | name: 'InnerPage', | 
|---|
|  |  |  | }); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * TODO 缺少 投诉举报接口 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | const { userDetail } = useUser(); | 
|---|
|  |  |  | const router = Taro.useRouter(); | 
|---|
|  |  |  | const taskId = router.params?.id ?? ''; | 
|---|
|  |  |  | const id = router.params?.id ?? ''; | 
|---|
|  |  |  | const from = router.params?.from ?? ''; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const { | 
|---|
|  |  |  | isLoading, | 
|---|
|  |  |  | 
|---|
|  |  |  | data: detail, | 
|---|
|  |  |  | refetch, | 
|---|
|  |  |  | } = useQuery({ | 
|---|
|  |  |  | queryKey: ['orderServices/getOrdeForDetail', taskId], | 
|---|
|  |  |  | queryKey: ['taskServices/getTaskInfo', id], | 
|---|
|  |  |  | queryFn: async () => { | 
|---|
|  |  |  | return await orderServices.getOrdeForDetail( | 
|---|
|  |  |  | { id: taskId }, | 
|---|
|  |  |  | return await taskServices.getTaskInfo( | 
|---|
|  |  |  | { id: id }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | showLoading: false, | 
|---|
|  |  |  | } | 
|---|
|  |  |  | ); | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | placeholderData: () => ({} as API.OrderInfoDto), | 
|---|
|  |  |  | placeholderData: () => ({} as API.GetTaskInfoQueryResult), | 
|---|
|  |  |  | onSuccess(data) { | 
|---|
|  |  |  | if (data.isExistTradeChatRecord) setTrue(); | 
|---|
|  |  |  | // if (data.isExistTradeChatRecord) setTrue(); | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | }); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const { isCollapse, setTrue } = useToggle(); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | function goComplaint() { | 
|---|
|  |  |  | const goComplaint = useAccessLogin(() => { | 
|---|
|  |  |  | Taro.navigateTo({ | 
|---|
|  |  |  | url: `${RouterPath.complaint}?id=${taskId}`, | 
|---|
|  |  |  | url: `${RouterPath.complaint}?id=${id}`, | 
|---|
|  |  |  | }); | 
|---|
|  |  |  | }); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const goCompanyDetail = useAccessLogin(() => { | 
|---|
|  |  |  | if (detail.value.enterpriseId) { | 
|---|
|  |  |  | Taro.navigateTo({ | 
|---|
|  |  |  | url: `${RouterPath.companyDetail}?id=${detail.value.enterpriseId}`, | 
|---|
|  |  |  | }); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const handleApply = useAccessReal( | 
|---|
|  |  |  | async () => { | 
|---|
|  |  |  | try { | 
|---|
|  |  |  | let params: API.ApplyTaskCommand = { | 
|---|
|  |  |  | ids: [id], | 
|---|
|  |  |  | }; | 
|---|
|  |  |  | let res = await taskUserServices.applyTask(params); | 
|---|
|  |  |  | if (res) { | 
|---|
|  |  |  | Message.success('报名成功'); | 
|---|
|  |  |  | refetch({ type: 'inactive' }); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } catch (error) {} | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { message: '实名成功后才可报名,请前往实名认证' } | 
|---|
|  |  |  | ); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const handleAttention = useAccessLogin(async () => { | 
|---|
|  |  |  | try { | 
|---|
|  |  |  | // await Message.confirm({ | 
|---|
|  |  |  | //   message: `确定${detail.value?.isCollected ? '取消收藏' : '收藏'}吗?`, | 
|---|
|  |  |  | // }); | 
|---|
|  |  |  | let params: API.CollectTaskCommand = { | 
|---|
|  |  |  | ids: [id], | 
|---|
|  |  |  | isCollect: !detail.value?.isCollected, | 
|---|
|  |  |  | }; | 
|---|
|  |  |  | let res = await taskUserServices.collectTask(params); | 
|---|
|  |  |  | if (res) { | 
|---|
|  |  |  | refetch({ type: 'inactive' }); | 
|---|
|  |  |  | // Message.success('操作成功', { | 
|---|
|  |  |  | //   onClosed() { | 
|---|
|  |  |  | //     refetch({ type: 'inactive' }); | 
|---|
|  |  |  | //   }, | 
|---|
|  |  |  | // }); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } catch (error) {} | 
|---|
|  |  |  | }); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const handleCall = useAccessLogin(() => { | 
|---|
|  |  |  | if (detail.value.contactPhoneNumber) { | 
|---|
|  |  |  | Taro.makePhoneCall({ | 
|---|
|  |  |  | phoneNumber: detail.value.contactPhoneNumber, | 
|---|
|  |  |  | }); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | function handleHire() { | 
|---|
|  |  |  | Taro.navigateTo({ | 
|---|
|  |  |  | url: `${RouterPath.taskSubmitCheck}?id=${id}`, | 
|---|
|  |  |  | }); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | const handleSign = useAccessReal(() => { | 
|---|
|  |  |  | Taro.navigateTo({ | 
|---|
|  |  |  | url: `${RouterPath.mineAgreementSignDetail}?id=${detail.value?.enterpriseEmployeeId}`, | 
|---|
|  |  |  | }); | 
|---|
|  |  |  | }); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | function goMap() { | 
|---|
|  |  |  | Taro.openLocation({ | 
|---|
|  |  |  | latitude: detail.value?.latitude, | 
|---|
|  |  |  | longitude: detail.value?.longitude, | 
|---|
|  |  |  | scale: 18, | 
|---|
|  |  |  | }); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | function goCompanyDetail() { | 
|---|
|  |  |  | Taro.navigateTo({ | 
|---|
|  |  |  | url: `${RouterPath.companyDetail}?id=${taskId}`, | 
|---|
|  |  |  | }); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | Taro.useDidShow(() => { | 
|---|
|  |  |  | refetch(); | 
|---|
|  |  |  | }); | 
|---|
|  |  |  | </script> | 
|---|