zhengyiming
8 天以前 2b7fccce78fe4d57d73f4cf350cbe16b75a72fd4
fix: 任务详情
1个文件已添加
13个文件已修改
307 ■■■■ 已修改文件
apps/bMiniApp/src/pages/home/index.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/task/publishTask/InnerPage.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/project.private.config.json 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/hooks/task.ts 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/pages/home/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/task/components/CompanyDesc.vue 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/task/taskDetail/InnerPage.vue 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/components/src/Card/TaskCard.vue 61 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/constants/apiEnum.ts 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/services/apiV2/auth.ts 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/services/apiV2/typings.d.ts 68 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/utils/index.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/utils/task.ts 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/utils/tsconfig.json 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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>
          <TaskPrice :value="212" />
            <!-- <div class="task-card-welfare-list-item">
              {{ TaskUtils.getGenderText(detail.genderLimit) }}
            </div> -->
          </div>
          <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">
              <template v-if="detail?.credentialLimits?.length > 0">
              <div class="taskDetail-limit-list-item-label">资格证书:</div>
              <div class="taskDetail-limit-list-item-text">健康证</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" }]