apps/bMiniApp/src/pages/home/index.vue
@@ -114,8 +114,8 @@ page: pageParam, orderInput: [ queryState.orderType === HomeOrderType.Recommend ? { property: 'createdTime', order: EnumPagedListOrder.Desc } : {}, ? { property: 'recommendStatus', order: EnumPagedListOrder.Desc } : { property: 'createdTime', order: EnumPagedListOrder.Desc }, ], }, // keywords: 'string', @@ -127,10 +127,6 @@ // status: 10, releaseStatus: EnumTaskReleaseStatus.InProcess, }; if (queryState.orderType === HomeOrderType.Recommend) { params.recommendStatus = EnumTaskRecommendStatus.Yes; } return taskServices.getTaskInfos(params, { showLoading: false, apps/bMiniApp/src/subpackages/task/publishTask/InnerPage.vue
@@ -285,17 +285,17 @@ form.billingMethod = data.billingMethod; form.serviceFee = data.serviceFee; form.settlementCycle = data.settlementCycle; form.benefits = (data.benefits ?? []).map((item) => item.code); form.benefits = (data.benefits ?? []).map((item) => item.benefitCode); form.ageMinLimit = data.ageMinLimit; form.ageMaxLimit = data.ageMaxLimit; form.genderLimit = data.genderLimit; form.credentialLimits = (data.credentialLimits ?? []).map((item) => item.code); form.credentialLimits = (data.credentialLimits ?? []).map((item) => item.typeCode); form.beginTime = dayjs(data.beginTime).format('YYYY-MM-DD 00:00:00'); form.endTime = dayjs(data.endTime).format('YYYY-MM-DD 23:59:59'); form.addressDetail = data.addressDetail; form.weMapInfo = { provinceName: data.provinceName, cityName: data.cityName, provinceName: data.provinceContent, cityName: data.cityContent, provinceCode: data.provinceCode, cityCode: data.cityCode, latitude: data.latitude, apps/cMiniApp/project.private.config.json
@@ -9,6 +9,13 @@ "miniprogram": { "list": [ { "name": "任务详情", "pathName": "subpackages/task/taskDetail/taskDetail", "query": "id=04c75425-e783-4dbf-0f16-08ddd626b756", "launchMode": "default", "scene": null }, { "name": "城市选择", "pathName": "subpackages/city/citySelect/citySelect", "query": "", apps/cMiniApp/src/hooks/task.ts
@@ -50,8 +50,8 @@ page: pageParam, orderInput: [ queryState.orderType === HomeOrderType.Recommend ? { property: 'createdTime', order: EnumPagedListOrder.Desc } : {}, ? { property: 'recommendStatus', order: EnumPagedListOrder.Desc } : { property: 'createdTime', order: EnumPagedListOrder.Desc }, ], }, keywords: queryState.searchValueTrim, @@ -62,10 +62,6 @@ status: queryMenuState.status, releaseStatus: EnumTaskReleaseStatus.InProcess, }; if (queryState.orderType === HomeOrderType.Recommend) { params.recommendStatus = EnumTaskRecommendStatus.Yes; } return taskServices.getTaskInfos(params, { showLoading: false, apps/cMiniApp/src/pages/home/index.vue
@@ -57,7 +57,7 @@ :key="queryState.orderType" > <template #renderItem="{ item }"> <TaskCard @click="goTaskDetail(item)" /> <TaskCard @click="goTaskDetail(item)" v-bind="item" /> </template> </InfiniteLoading> </PageLayoutWithBg> apps/cMiniApp/src/subpackages/task/components/CompanyDesc.vue
@@ -1,12 +1,12 @@ <template> <div class="taskDetail-company-wrapper"> <div class="taskDetail-company-title-wrapper"> <div class="taskDetail-company-title">宁波人力无忧</div> <div class="taskDetail-company-title">{{ enterpriseName }}</div> <RectRight v-if="showArrow" :size="8" class="taskDetail-company-arrow" /> </div> <div class="taskDetail-company-info"> <img :src="IconSafe" class="safe-company-info-icon" /> <div class="taskDetail-company-info-text">已认证 | 4个岗位在招</div> <div class="taskDetail-company-info-text">已认证 | {{ taskCount }}个岗位在招</div> </div> </div> </template> @@ -21,10 +21,16 @@ type Props = { showArrow?: boolean; enterpriseName?: string; taskCount?: number; /** * TODO 缺少是否已认证 */ }; const props = withDefaults(defineProps<Props>(), { showArrow: true, taskCount: 0, }); </script> apps/cMiniApp/src/subpackages/task/taskDetail/InnerPage.vue
@@ -1,26 +1,38 @@ <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 :src="detail.isCollected ? IconAttentioActive : IconAttention" class="taskDetail-attention-icon" /> </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 :value="detail.serviceFee ?? 0" :unit="BillingMethodEnumUnit[detail.billingMethod]" /> </div> <div class="taskDetail-address-wrapper"> <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> @@ -28,31 +40,44 @@ <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="IconAttentioActive" :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" ></CompanyDesc> </CellChunk> </Cell> <Cell> @@ -84,7 +109,7 @@ <script setup lang="ts"> import Taro from '@tarojs/taro'; import { useQuery } from '@tanstack/vue-query'; import * as flexWorkerServices from '@12333/services/api/FlexWorker'; import * as taskServices from '@12333/services/apiV2/task'; import { useToggle } from 'senin-mini/hooks'; import { TaskPrice, TaskDetailWelfareItem } from '@12333/components'; import IconAttention from '@/assets/task/icon-attention.png'; @@ -96,10 +121,18 @@ import IconLocaltion from '@/assets/task/icon-localtion.png'; import './taskDetail.scss'; import CompanyDesc from '../components/CompanyDesc.vue'; import dayjs from 'dayjs'; import { TaskUtils } from '@12333/utils'; import { EnumSettlementCycleText, BillingMethodEnumUnit } from '@12333/constants'; import { useAccessLogin } from '@/hooks'; defineOptions({ name: 'InnerPage', }); /** * TODO 缺少已报名人数 手机 投诉举报接口 */ const router = Taro.useRouter(); const taskId = router.params?.id ?? ''; @@ -110,32 +143,32 @@ data: detail, refetch, } = useQuery({ queryKey: ['flexWorkerServices/getOrdeForDetail', taskId], queryKey: ['taskServices/getTaskInfo', taskId], queryFn: async () => { return await flexWorkerServices.getOrdeForDetail( return await taskServices.getTaskInfo( { id: taskId }, { 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}`, }); } }); function goCompanyDetail() { const goCompanyDetail = useAccessLogin(() => { Taro.navigateTo({ url: `${RouterPath.companyDetail}?id=${taskId}`, }); } }); </script> packages/components/src/Card/TaskCard.vue
@@ -1,23 +1,29 @@ <template> <div class="task-card-wrapper"> <div class="task-card-title-wrapper"> <div class="task-card-title">{{ taskName }}</div> <div class="task-card-title">{{ name }}</div> <slot name="title-right"> <TaskPrice :value="212" /> <TaskPrice :value="serviceFee ?? 0" :unit="BillingMethodEnumUnit[billingMethod]" /> </slot> </div> <slot> <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"> {{ EnumSettlementCycleText[settlementCycle] }} </div> <div class="task-card-welfare-list-item">{{ TaskUtils.getGenderText(genderLimit) }}</div> <div class="task-card-welfare-list-item">包三餐</div> </div> <div class="task-card-time">上班时间:07:00-15:30</div> <div class="task-card-time"> {{ dayjs(beginTime).format('YYYY年MM月DD日') }}至{{ dayjs(endTime).format('YYYY年MM月DD日') }} </div> </slot> <div class="task-card-footer"> <div class="task-card-left"> <div class="task-card-footer-tag">H</div> <div class="task-card-footer-address">{{ address }}</div> <div class="task-card-footer-address">{{ 'address' }}</div> </div> <div class="task-card-actions" v-if="showActions"> <slot name="actions"> @@ -29,8 +35,24 @@ </template> <script setup lang="ts"> import { EnumBillingMethod, EnumSettlementCycle, EnumTaskCheckReceiveStatus, EnumTaskRecommendStatus, EnumTaskReleaseStatus, EnumTaskSettlementStatus, EnumTaskStatus, EnumUserGender, EnumBillingMethodText, EnumUserGenderText, EnumSettlementCycleText, BillingMethodEnumUnit, } from '@12333/constants'; import TaskPrice from './TaskPrice.vue'; import { CommonTaskCardProps } from './card'; import dayjs from 'dayjs'; import { TaskUtils } from '@12333/utils'; defineOptions({ name: 'TaskCard', @@ -38,9 +60,30 @@ type Props = CommonTaskCardProps & { showActions?: boolean; taskName?: string; address?: string; /** Id */ id?: string; /** 任务名称 */ name: string; /** 任务单号 */ code?: string; billingMethod?: EnumBillingMethod; /** 服务费 */ serviceFee?: number; settlementCycle?: EnumSettlementCycle; genderLimit?: EnumUserGender; /** 报名人数 */ userCount?: number; status?: EnumTaskStatus; /** 任务开始时间 */ beginTime?: string; /** 任务结束时间 */ endTime?: string; releaseStatus?: EnumTaskReleaseStatus; checkReceiveStatus?: EnumTaskCheckReceiveStatus; settlementStatus?: EnumTaskSettlementStatus; recommendStatus?: EnumTaskRecommendStatus; /** 创建时间 */ createdTime?: string; }; const props = withDefaults(defineProps<Props>(), { packages/constants/apiEnum.ts
@@ -125,6 +125,20 @@ AliyunSms = 10, } /** 短信模板类型 */ export enum EnumSmsTemplateType { /**登录 */ Login = 0, /**注册 */ Register = 1, /**修改密码 */ UpdatePassword = 2, /**绑定手机号码 */ BindPhoneNumber = 3, /**修改手机号码 */ UpdatePhoneNumber = 4, } /** 任务结算状态 */ export enum EnumTaskCheckReceiveStatus { /**待验收 */ packages/services/apiV2/auth.ts
@@ -62,3 +62,15 @@ ...(options || {}), }); } /** 发送验证码 POST /api/user/auth/sendVerifyCode */ export async function sendVerifyCode(body: API.SendVerifyCodeCommand, options?: API.RequestConfig) { return request<string>('/api/user/auth/sendVerifyCode', { method: 'POST', headers: { 'Content-Type': 'application/json-patch+json', }, data: body, ...(options || {}), }); } packages/services/apiV2/typings.d.ts
@@ -122,13 +122,6 @@ ids: string[]; } interface DictionaryDataQueryModel { /** 编号 */ code?: string; /** 名称 */ name?: string; } enum EnumBillingMethod { /**按月 */ Month = 10, @@ -240,6 +233,19 @@ enum EnumSmsAccess { /**阿里云短信 */ AliyunSms = 10, } enum EnumSmsTemplateType { /**登录 */ Login = 0, /**注册 */ Register = 1, /**修改密码 */ UpdatePassword = 2, /**绑定手机号码 */ BindPhoneNumber = 3, /**修改手机号码 */ UpdatePhoneNumber = 4, } enum EnumTaskCheckReceiveStatus { @@ -1159,22 +1165,22 @@ serviceFee?: number; settlementCycle?: EnumSettlementCycle; /** 福利 */ benefits?: DictionaryDataQueryModel[]; benefits?: GetTaskInfoQueryResultBenefit[]; /** 年龄范围最小 */ ageMinLimit?: number; /** 年龄范围大 */ ageMaxLimit?: number; genderLimit?: EnumUserGender; /** 资格证书类型 */ credentialLimits?: DictionaryDataQueryModel[]; credentialLimits?: GetTaskInfoQueryResultCredentialLimit[]; /** 任务地点所属省份编号 */ provinceCode?: string; /** 任务地点所属省份 */ provinceName?: string; provinceContent?: string; /** 任务地点所属城市编号 */ cityCode?: string; /** 任务地点所属城市 */ cityName?: string; cityContent?: string; /** 任务地点名称 */ addressName?: string; /** 任务地点详细地址 */ @@ -1191,6 +1197,20 @@ createdTime?: string; /** 是否已收藏 */ isCollected?: boolean; } interface GetTaskInfoQueryResultBenefit { /** 福利编号 */ benefitCode?: string; /** 福利 */ benefitContent?: string; } interface GetTaskInfoQueryResultCredentialLimit { /** 证书类型编号 */ typeCode?: string; /** 证书类型 */ typeContent?: string; } interface GetTaskInfosQuery { @@ -1223,7 +1243,27 @@ /** 服务费 */ serviceFee?: number; settlementCycle?: EnumSettlementCycle; /** 福利 */ benefits?: GetTaskInfoQueryResultBenefit[]; genderLimit?: EnumUserGender; /** 资格证书类型 */ credentialLimits?: GetTaskInfoQueryResultCredentialLimit[]; /** 任务地点所属省份编号 */ provinceCode?: string; /** 任务地点所属省份 */ provinceContent?: string; /** 任务地点所属城市编号 */ cityCode?: string; /** 任务地点所属城市 */ cityContent?: string; /** 任务地点名称 */ addressName?: string; /** 任务地点详细地址 */ addressDetail?: string; /** 经度 */ longitude?: number; /** 纬度 */ latitude?: number; /** 报名人数 */ userCount?: number; status?: EnumTaskStatus; @@ -1600,6 +1640,12 @@ data?: any; } interface SendVerifyCodeCommand { /** 手机号码 */ phoneNumber?: string; templateCode?: EnumSmsTemplateType; } interface SetDictionaryDataIsDisabledCommand { ids?: string[]; /** 是否已禁用 */ packages/utils/index.ts
@@ -14,3 +14,4 @@ export * from './media'; export * from './location'; export * from './encrypt'; export * from './task'; packages/utils/task.ts
New file @@ -0,0 +1,14 @@ import { EnumUserGender, EnumUserGenderText } from '@12333/constants'; export class TaskUtils { static getGenderText(gender: EnumUserGender, allGenderText = '男女不限') { return gender ? EnumUserGenderText[gender] : allGenderText; } static getCredentialLimit(credentialLimits: API.GetTaskInfoQueryResultCredentialLimit[]) { if (credentialLimits?.length > 0) { return credentialLimits[0].typeContent; } return ''; } } packages/utils/tsconfig.json
@@ -7,7 +7,12 @@ "@12333/*": ["../../packages/*"] }, "composite": true, "types": ["node", "@12333/services/api/typings.d.ts", "../../types/api.d.ts"] "types": [ "node", "@12333/services/api/typings.d.ts", "@12333/services/apiV2/typings.d.ts", "../../types/api.d.ts" ] }, "exclude": ["node_modules", "dist"], "references": [{ "path": "../constants" }, { "path": "../services" }, { "path": "../components" }]