wupengfei
2 天以前 b3dc565fe8a341bdb069b8f0feb912cd751a589f
Merge branch 'master' of http://120.26.58.240:8888/r/flexJobMiniApp
1个文件已添加
25个文件已修改
625 ■■■■■ 已修改文件
apps/bMiniApp/project.private.config.json 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/JobDetailContent/JobDetailContent.vue 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/JobDetailContent/components/curriculumView.vue 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/JobDetailContent/components/experienceView.vue 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/pages/home/HomeQueryMenuView.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/pages/home/HomeQueryPositionMenuView.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/pages/home/index.vue 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/flexJob/flexJobDetail/flexJobDetail.vue 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/flexJob/flexJobDetailFromTask/InnerPage.vue 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/flexJobManage/flexJobDetailFromManage/InnerPage.vue 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/flexJobManage/flexJobManage/InnerPage.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/jobApplicationManage/components/SignList.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/task/taskManage/InnerPage.vue 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/auto-imports.d.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/hooks/user.ts 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/curriculum/editMineInfo/InnerPage.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/curriculum/mineCertificateAddOrEdit/InnerPage.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/curriculum/mineDetailedInfo/InnerPage.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/curriculum/mineJobIntention/InnerPage.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/curriculum/mineWorkExperience/InnerPage.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/components/src/Card/FlexJobCard.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/hooks/index.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/hooks/user.ts 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/services/apiV2/enterpriseEmployee.ts 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/services/apiV2/typings.d.ts 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/utils/common.ts 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/project.private.config.json
@@ -9,6 +9,13 @@
        "miniprogram": {
            "list": [
                {
                    "name": "灵工详情",
                    "pathName": "subpackages/flexJob/flexJobDetail/flexJobDetail",
                    "query": "enterpriseEmployeeId=700a3a67-5da5-49d2-a65a-08ddd661238b",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "灵工管理",
                    "pathName": "subpackages/flexJobManage/flexJobManage/flexJobManage",
                    "query": "",
@@ -61,13 +68,6 @@
                    "name": "验收管理",
                    "pathName": "subpackages/task/taskCheck/taskCheck",
                    "query": "",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "灵工详情",
                    "pathName": "subpackages/flexJob/flexJobDetail/flexJobDetail",
                    "query": "id=c4cfe028-23e7-0be8-ee56-3a11e3743b9d",
                    "launchMode": "default",
                    "scene": null
                },
apps/bMiniApp/src/components/JobDetailContent/JobDetailContent.vue
@@ -1,17 +1,28 @@
<template>
  <ContentView style="background-color: transparent" class="job-detail-content">
    <FlexJobTopView size="small" class="job-detail-content-top" />
    <FlexJobTopView
      :avatar="avatar"
      :name="name"
      :age="age"
      :isReal="isReal"
      :gender="gender"
      :personalIdentityContent="personalIdentityContent"
      :educationalBackgroundContent="educationalBackgroundContent"
      :taskCount="taskCount"
      size="small"
      class="job-detail-content-top"
    />
    <div class="job-detail-content-contact-info">
      <div class="job-detail-content-contact-info-item">
        <div class="job-detail-content-contact-info-item-label">手机号:</div>
        <div class="job-detail-content-contact-info-item-text">
          {{ isCollapse ? '13333333333' : '立即联系后可查看' }}
          {{ isCollapse ? contactPhoneNumber : '立即联系后可查看' }}
        </div>
      </div>
      <div class="job-detail-content-contact-info-item">
        <div class="job-detail-content-contact-info-item-label">身份证号:</div>
        <div class="job-detail-content-contact-info-item-text">
          {{ isCollapse ? hiddenIDNumberForEnd6('330902199909123456') : '立即联系后可查看' }}
          {{ isCollapse ? hiddenIDNumberForEnd6(identity) : '立即联系后可查看' }}
        </div>
      </div>
    </div>
@@ -26,7 +37,17 @@
    fullHeight
  >
    <ProTabPane :title="`简历`" pane-key="1">
      <curriculumView />
      <curriculumView
        :userExpectJobs="userExpectJobs"
        :freeTime="freeTime"
        :jobSeekingStatus="jobSeekingStatus"
        :userCredentials="userCredentials"
        :workSeniority="workSeniority"
        :workExperience="workExperience"
        :photos="photos"
        :height="height"
        :weight="weight"
      />
    </ProTabPane>
    <ProTabPane :title="`经历`" pane-key="2">
      <experienceView />
@@ -42,6 +63,7 @@
import { hiddenIDNumberForEnd6 } from '@12333/utils';
import curriculumView from './components/curriculumView.vue';
import experienceView from './components/experienceView.vue';
import { EnumUserGender } from '@12333/constants';
defineOptions({
  name: 'JobDetailContent',
@@ -49,6 +71,32 @@
type Props = {
  isCollapse: boolean;
  avatar?: string;
  name?: string;
  gender?: EnumUserGender;
  age?: number;
  isReal?: boolean;
  personalIdentityContent?: string;
  educationalBackgroundContent?: string;
  taskCount?: number;
  contactPhoneNumber?: string;
  identity?: string;
  userId?: string;
  userExpectJobs?: API.GetUserResumeQueryResultExpectJob[];
  freeTime?: API.EnumPersonalFreeTime;
  jobSeekingStatus?: API.EnumPersonalJobSeekingStatus;
  userCredentials?: API.GetUserResumeQueryResultCredential[];
  workSeniority?: string;
  workExperience?: string;
  photos?: string[];
  /** 身高 */
  height?: number;
  /** 体重 */
  weight?: number;
  taskInfoUsers?: API.GetUserResumeQueryResultExperience[];
};
const tab = ref('1');
apps/bMiniApp/src/components/JobDetailContent/components/curriculumView.vue
@@ -5,18 +5,22 @@
        <div class="curriculum-list">
          <CurriculumViewItem label="期望岗位:">
            <div class="curriculum-position-list">
              <div class="curriculum-position-list-item">客房服务员</div>
              <div class="curriculum-position-list-item">客房服务员</div>
              <div class="curriculum-position-list-item">客房服务员</div>
              <div class="curriculum-position-list-item">客房服务员</div>
              <div class="curriculum-position-list-item">客房员</div>
              <div class="curriculum-position-list-item">客房服务员</div>
              <div class="curriculum-position-list-item">客房服务员</div>
              <div class="curriculum-position-list-item">客房服务员</div>
              <div
                v-for="userExpectJob in userExpectJobs"
                :key="userExpectJob.expectJobCode"
                class="curriculum-position-list-item"
              >
                {{ userExpectJob.expectJobContent }}
              </div>
            </div>
          </CurriculumViewItem>
          <CurriculumViewItem label="空闲时间:" text="不限"> </CurriculumViewItem>
          <CurriculumViewItem label="求职状态:" text="积极找工作"> </CurriculumViewItem>
          <CurriculumViewItem label="空闲时间:" :text="EnumPersonalFreeTimeText[freeTime]">
          </CurriculumViewItem>
          <CurriculumViewItem
            label="求职状态:"
            :text="EnumPersonalJobSeekingStatusText[jobSeekingStatus]"
          >
          </CurriculumViewItem>
        </div>
      </CellChunk>
      <CellChunk title="资格证书">
@@ -25,31 +29,34 @@
          :column-num="3"
          :border="false"
          :gutter="20"
          v-if="list.length > 0"
          v-if="_userCredentials.length > 0"
          class="pro-img-grid"
        >
          <nut-grid-item v-for="(item, index) in list" :key="item" class="pro-img-grid-item">
          <nut-grid-item
            v-for="(item, index) in _userCredentials"
            :key="item"
            class="pro-img-grid-item"
          >
            <div class="pro-img-grid-img-item">
              <PreviewImage :src="item" class="pro-img-grid-img" :urls="list" />
              <PreviewImage :src="item" class="pro-img-grid-img" :urls="_userCredentials" />
            </div>
          </nut-grid-item>
        </nut-grid>
      </CellChunk>
      <CellChunk title="工作经验">
        <CurriculumViewItem label="工作年限:" text="无工作经验,用户自己填写">
        <CurriculumViewItem label="工作年限:" :text="workSeniority ? `${workSeniority}年` : ''">
        </CurriculumViewItem>
        <CurriculumViewItem label="工作经验:" text="客房服务员,用户自己填写">
        </CurriculumViewItem>
        <CurriculumViewItem label="工作经验:" :text="workExperience"> </CurriculumViewItem>
      </CellChunk>
      <CellChunk title="详细信息">
        <CurriculumViewItem
          label="身高:"
          text="175 cm"
          :text="`${height} cm`"
          :label-width="labelWidth"
        ></CurriculumViewItem>
        <CurriculumViewItem
          label="体重:"
          text="80 kg"
          :text="`${weight} kg`"
          :label-width="labelWidth"
        ></CurriculumViewItem>
        <CurriculumViewItem label="个人照片:">
@@ -58,12 +65,12 @@
            :column-num="2"
            :border="false"
            :gutter="20"
            v-if="list.length > 0"
            v-if="_photos.length > 0"
            class="pro-img-grid"
          >
            <nut-grid-item v-for="(item, index) in list" :key="item" class="pro-img-grid-item">
            <nut-grid-item v-for="(item, index) in _photos" :key="item" class="pro-img-grid-item">
              <div class="pro-img-grid-img-item">
                <PreviewImage :src="item" class="pro-img-grid-img" :urls="list" />
                <PreviewImage :src="item" class="pro-img-grid-img" :urls="_photos" />
              </div>
            </nut-grid-item>
          </nut-grid>
@@ -77,19 +84,37 @@
import CurriculumViewItem from './CurriculumViewItem.vue';
import { PreviewImage } from '@12333/components';
import Taro from '@tarojs/taro';
import { EnumPersonalFreeTimeText, EnumPersonalJobSeekingStatusText } from '@12333/constants';
import { setOSSLink } from '@12333/utils';
defineOptions({
  name: 'curriculumView',
});
const labelWidth = Taro.pxTransform(120);
type Props = {
  userExpectJobs?: API.GetUserResumeQueryResultExpectJob[];
  freeTime?: API.EnumPersonalFreeTime;
  jobSeekingStatus?: API.EnumPersonalJobSeekingStatus;
  userCredentials?: API.GetUserResumeQueryResultCredential[];
  workSeniority?: string;
  workExperience?: string;
  photos?: string[];
  /** 身高 */
  height?: number;
  /** 体重 */
  weight?: number;
};
const list = ref([
  'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
  'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
  'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
  'https://storage.360buyimg.com/jdc-article/fristfabu.jpg',
]);
const props = withDefaults(defineProps<Props>(), {
  userExpectJobs: () => [],
  userCredentials: () => [],
  photos: () => [],
});
const _userCredentials = computed(() => props.userCredentials.map((x) => setOSSLink(x.img)));
const _photos = computed(() => props.photos.map((x) => setOSSLink(x)));
const labelWidth = Taro.pxTransform(120);
</script>
<style lang="scss">
apps/bMiniApp/src/components/JobDetailContent/components/experienceView.vue
@@ -1,24 +1,43 @@
<template>
  <ContentScrollView>
    <Cell title="岗位经历">
      <nut-steps direction="vertical" progress-dot :current="3" class="job-detail-content-steps">
        <nut-step title="2024.12.24" content="您的订单已经打包完成,商品已发出"></nut-step>
        <nut-step title="2024.12.24" content="您的订单正在配送途中"></nut-step>
        <nut-step title="2024.12.24">
      <nut-steps
        v-if="taskInfoUsers.length > 0"
        direction="vertical"
        progress-dot
        :current="3"
        class="job-detail-content-steps"
      >
        <nut-step
          v-for="(taskInfoUser, index) in taskInfoUsers"
          :key="index"
          :title="taskInfoUser.signContractTime"
        >
          <template #content>
            <p>收货地址为:</p>
            <p>北京市经济技术开发区科创十一街18号院京东大厦</p>
            <p>在{{ taskInfoUser.enterpriseName }}:</p>
            <p>做过{{ taskInfoUser.name }}</p>
          </template>
        </nut-step>
      </nut-steps>
      <NoData v-else />
    </Cell>
  </ContentScrollView>
</template>
<script setup lang="ts">
import NoData from '../../NoData/NoData.vue';
defineOptions({
  name: 'experienceView',
});
type Props = {
  taskInfoUsers?: API.GetUserResumeQueryResultExperience[];
};
const props = withDefaults(defineProps<Props>(), {
  taskInfoUsers: () => [],
});
</script>
<style lang="scss">
apps/bMiniApp/src/pages/home/HomeQueryMenuView.vue
@@ -9,7 +9,11 @@
        ></ProRadio>
      </QueryMenuItem>
      <QueryMenuItem title="身份">
        <ProRadio v-model="query.identity" :value-enum="identityList" show-all-btn></ProRadio>
        <ProRadio
          v-model="query.personalIdentityCode"
          :value-enum="identityList"
          show-all-btn
        ></ProRadio>
      </QueryMenuItem>
      <QueryMenuItem>
        <template #title>
@@ -66,7 +70,7 @@
const query = defineModel<{
  genderLimit: number | string;
  age: number[];
  identity: string;
  personalIdentityCode: string;
  certificateType: string;
}>('query');
apps/bMiniApp/src/pages/home/HomeQueryPositionMenuView.vue
@@ -1,14 +1,13 @@
<template>
  <QueryMenuView @close="handleReset" @confirm="emit('close')" cancelText="重置">
    <div class="home-query-position-menu-view">
      <PositionSelectView v-model="query.position" />
      <PositionSelectView v-model="query.userExpectJobs" />
    </div>
  </QueryMenuView>
</template>
<script setup lang="ts">
import { QueryMenuView, QueryMenuItem, PositionSelectView } from '@12333/components';
import { GenderText } from '@12333/constants';
defineOptions({
  name: 'HomeQueryPositionMenuView',
@@ -24,11 +23,12 @@
}>();
const query = defineModel<{
  position: string[];
  userExpectJobs: string[];
}>('query');
const DefaultQuery = {
  ...query.value,
  userExpectJobs: [...query.value.userExpectJobs],
};
function handleReset() {
apps/bMiniApp/src/pages/home/index.vue
@@ -33,7 +33,6 @@
      title-gutter="8"
      title-scroll
    >
      <ProTabPane :title="`推荐`" :pane-key="HomeOrderType.Recommend"></ProTabPane>
      <ProTabPane :title="`最新`" :pane-key="HomeOrderType.LastShelfTime"></ProTabPane>
      <template #right>
        <Menu>
@@ -58,7 +57,20 @@
      :key="queryState.orderType"
    >
      <template #renderItem="{ item }">
        <FlexJobCard @click="goFlexJobDetail(item)" :showFooterLeft="false" />
        <FlexJobCard
          :name="item.name"
          :gender="item.gender"
          :age="item.age"
          :isReal="item.isReal"
          :personalIdentityContent="item.personalIdentityContent"
          :educationalBackgroundContent="item.educationalBackgroundContent"
          :taskCount="item.taskCount"
          :avatar="item.avatar"
          :workExperience="item.workExperience"
          :workSeniority="item.workSeniority"
          @click="goFlexJobDetail(item)"
          :showFooterLeft="false"
        />
      </template>
    </InfiniteLoading>
  </PageLayoutWithBg>
@@ -80,12 +92,12 @@
  EnumTaskReleaseStatus,
  EnumUserGender,
} from '@12333/constants';
import * as taskServices from '@12333/services/apiV2/task';
import _ from 'lodash';
import HomeQueryMenuView from './HomeQueryMenuView.vue';
import HomeQueryPositionMenuView from './HomeQueryPositionMenuView.vue';
import IconLocaltion from '@/assets/home/icon-localtion.png';
import { setLocationCity } from '@/utils';
import * as userResumeServices from '@12333/services/apiV2/userResume';
const { locationCity } = useUser();
@@ -100,12 +112,12 @@
const queryMenuState = reactive({
  genderLimit: '' as any as EnumUserGender,
  age: [15, 65],
  identity: '',
  personalIdentityCode: '',
  certificateType: '',
});
const queryPositionState = reactive({
  position: [] as string[],
  userExpectJobs: [] as string[],
});
const queryState = reactive({
@@ -114,32 +126,26 @@
const { infiniteLoadingProps } = useInfiniteLoading(
  ({ pageParam }) => {
    let params: API.GetTaskInfosQuery = {
    let params: API.GetUserResumesQuery = {
      pageModel: {
        rows: 20,
        page: pageParam,
        orderInput: [
          queryState.orderType === HomeOrderType.Recommend
            ? { property: 'recommendStatus', order: EnumPagedListOrder.Desc }
            : { property: 'createdTime', order: EnumPagedListOrder.Desc },
        ],
        orderInput: [{ property: 'createdTime', order: EnumPagedListOrder.Desc }],
      },
      // keywords: 'string',
      // time: '2025-08-08T02:58:58.756Z',
      // cityCode: 'string',
      // settlementCycle: 10,
      // benefitCodes: ['string'],
      genderLimit: queryMenuState.genderLimit,
      // status: 10,
      releaseStatus: EnumTaskReleaseStatus.InProcess,
      userExpectJobs: queryPositionState.userExpectJobs,
      gender: queryMenuState.genderLimit,
      personalIdentityCode: queryMenuState.personalIdentityCode,
      // ageMin: queryMenuState.age[0],
      // ageMax: queryMenuState.age[1],
      userCredentials: queryMenuState.certificateType ? [queryMenuState.certificateType] : null,
    };
    return taskServices.getTaskInfos(params, {
    return userResumeServices.getUserResumes(params, {
      showLoading: false,
    });
  },
  {
    queryKey: ['taskServices/getTaskInfos', queryState, queryMenuState, queryPositionState],
    queryKey: ['userResumeServices/getUserResumes', queryState, queryMenuState, queryPositionState],
  }
);
@@ -167,9 +173,9 @@
  selectPositionItem.value?.toggle?.();
}
function goFlexJobDetail(item: API.GetTaskInfosQueryResultItem) {
function goFlexJobDetail(item: API.GetUserResumesQueryResultItem) {
  Taro.navigateTo({
    url: `${RouterPath.flexJobDetail}?id=${item.id}`,
    url: `${RouterPath.flexJobDetail}?enterpriseEmployeeId=${item.id}`,
  });
}
apps/bMiniApp/src/subpackages/flexJob/flexJobDetail/flexJobDetail.vue
@@ -1,7 +1,30 @@
<template>
  <PageLayoutWithBg class="flexJobDetail-page-wrapper" title="灵工详情" :need-auth="false">
    <LoadingLayout :loading="isLoading" :error="isError" :loadError="refetch">
      <JobDetailContent :isCollapse="isCollapse">
      <JobDetailContent
        :avatar="userResumeInfo.avatar"
        :name="userResumeInfo.name"
        :age="userResumeInfo.age"
        :isReal="userResumeInfo.isReal"
        :gender="userResumeInfo.gender"
        :personalIdentityContent="userResumeInfo.personalIdentityContent"
        :educationalBackgroundContent="userResumeInfo.educationalBackgroundContent"
        :taskCount="userResumeInfo.taskCount"
        :contactPhoneNumber="userResumeInfo.contactPhoneNumber"
        :identity="userResumeInfo.identity"
        :isCollapse="isCollapse"
        :userId="enterpriseEmployeeId"
        :userExpectJobs="userResumeInfo.userExpectJobs"
        :freeTime="userResumeInfo.freeTime"
        :jobSeekingStatus="userResumeInfo.jobSeekingStatus"
        :userCredentials="userResumeInfo.userCredentials"
        :workSeniority="userResumeInfo.workSeniority"
        :workExperience="userResumeInfo.workExperience"
        :photos="userResumeInfo.photos"
        :height="userResumeInfo.height"
        :weight="userResumeInfo.weight"
        :taskInfoUsers="userResumeInfo.taskInfoUsers"
      >
        <template #footer>
          <PageFooterAction
            :icon="IconShare"
@@ -10,12 +33,12 @@
            openType="share"
          ></PageFooterAction>
          <PageFooterAction
            :icon="IconAttentionActive"
            :icon="userResumeInfo.isCollected ? IconAttentionActive : IconAttention"
            text="收藏"
            :isFlex="false"
            @click="handleAttention"
          ></PageFooterAction>
          <PageFooterBtn type="primary" @click="toggle">立即联系</PageFooterBtn>
          <PageFooterBtn type="primary" @click="handleContact">立即联系</PageFooterBtn>
        </template>
      </JobDetailContent>
    </LoadingLayout>
@@ -25,54 +48,47 @@
<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 userResumeServices from '@12333/services/apiV2/userResume';
import IconShare from '@/assets/flexJob/icon-share.png';
import IconAttention from '@/assets/flexJob/icon-attention-lg.png';
import IconAttentionActive from '@/assets/flexJob/icon-attention-lg-active.png';
import { useToggle } from 'senin-mini/hooks';
import { Message } from '@12333/utils';
import { useUserResume } from '@12333/hooks';
import { useAccessLogin } from '@/hooks';
defineOptions({
  name: 'flexJobDetail',
});
const router = Taro.useRouter();
const taskId = router.params?.id ?? '';
const enterpriseEmployeeId = router.params?.enterpriseEmployeeId ?? '';
const {
  isLoading,
  isError,
  data: detail,
  refetch,
} = useQuery({
  queryKey: ['flexWorkerServices/getOrdeForDetail', taskId],
  queryFn: async () => {
    return await flexWorkerServices.getOrdeForDetail(
      { id: taskId },
      {
        showLoading: false,
      }
    );
  },
  placeholderData: () => ({} as API.OrderInfoDto),
const { isLoading, isError, userResumeInfo, refetch } = useUserResume({
  userId: enterpriseEmployeeId,
});
const { isCollapse, toggle } = useToggle();
const handleContact = useAccessLogin(async () => {
  try {
    if (!isCollapse.value) {
      await userResumeServices.contactUserResume({ id: enterpriseEmployeeId });
      toggle();
    }
  } catch (error) {}
});
async function handleAttention() {
  try {
    let params: API.CollectFlexWorkerResumeInput = {
      flexWorkerId: detail.value?.flexWorkerId,
      userResumeId: detail.value?.userResumeId,
    let params: API.CollectUserResumeCommand = {
      id: enterpriseEmployeeId,
      isCollected: !userResumeInfo.value.isCollected,
    };
    let res = await flexWorkerServices.collectFlexWorkerResume(params);
    let res = await userResumeServices.collectUserResume(params);
    if (res) {
      Message.success('收藏成功');
      refetch({ type: 'inactive' });
    }
  } catch (error) {}
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
</style>
apps/bMiniApp/src/subpackages/flexJob/flexJobDetailFromTask/InnerPage.vue
@@ -1,9 +1,36 @@
<template>
  <LoadingLayout :loading="isLoading" :error="isError" :loadError="refetch">
    <JobDetailContent :isCollapse="true">
    <JobDetailContent
      :avatar="userResumeInfo.avatar"
      :name="userResumeInfo.name"
      :age="userResumeInfo.age"
      :isReal="userResumeInfo.isReal"
      :gender="userResumeInfo.gender"
      :personalIdentityContent="userResumeInfo.personalIdentityContent"
      :educationalBackgroundContent="userResumeInfo.educationalBackgroundContent"
      :taskCount="userResumeInfo.taskCount"
      :contactPhoneNumber="userResumeInfo.contactPhoneNumber"
      :identity="userResumeInfo.identity"
      :userId="enterpriseEmployeeId"
      :userExpectJobs="userResumeInfo.userExpectJobs"
      :freeTime="userResumeInfo.freeTime"
      :jobSeekingStatus="userResumeInfo.jobSeekingStatus"
      :userCredentials="userResumeInfo.userCredentials"
      :workSeniority="userResumeInfo.workSeniority"
      :workExperience="userResumeInfo.workExperience"
      :photos="userResumeInfo.photos"
      :height="userResumeInfo.height"
      :weight="userResumeInfo.weight"
      :taskInfoUsers="userResumeInfo.taskInfoUsers"
      :isCollapse="true"
    >
      <template #footer>
        <PageFooterBtn type="primary" plain @click="taskWorkerHireRefuse(10)">谢绝</PageFooterBtn>
        <PageFooterBtn type="primary" @click="taskWorkerHireRefuse(20)">录用</PageFooterBtn>
        <PageFooterBtn type="primary" plain @click="setTaskUserHire(EnumTaskUserHireStatus.Refuse)"
          >谢绝</PageFooterBtn
        >
        <PageFooterBtn type="primary" @click="setTaskUserHire(EnumTaskUserHireStatus.Pass)"
          >录用</PageFooterBtn
        >
      </template>
    </JobDetailContent>
  </LoadingLayout>
@@ -14,33 +41,22 @@
import { useQuery } from '@tanstack/vue-query';
import * as taskUserServices from '@12333/services/apiV2/taskUser';
import { Message } from '@12333/utils';
import { useUserResume } from '@12333/hooks';
import { EnumTaskUserHireStatus } from '@12333/constants';
defineOptions({
  name: 'InnerPage',
});
const router = Taro.useRouter();
const enterpriseEmployeeId = router.params?.enterpriseEmployeeId ?? '';
const id = router.params?.id ?? '';
const {
  isLoading,
  isError,
  data: detail,
  refetch,
} = useQuery({
  queryKey: ['taskServices/getTaskInfo', id],
  queryFn: async () => {
    return await taskServices.getTaskInfo(
      { id: id },
      {
        showLoading: false,
      }
    );
  },
  placeholderData: () => ({} as API.GetTaskInfoQueryResult),
const { isLoading, isError, userResumeInfo, refetch } = useUserResume({
  userId: enterpriseEmployeeId,
});
async function taskWorkerHireRefuse(hireStatus: FlexTaskWorkerHireEnum) {
async function setTaskUserHire(hireStatus: EnumTaskUserHireStatus) {
  try {
    let params: API.SetTaskUserHireCommand = {
      id: id,
@@ -56,7 +72,3 @@
  } catch (error) {}
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
</style>
apps/bMiniApp/src/subpackages/flexJobManage/flexJobDetailFromManage/InnerPage.vue
@@ -1,6 +1,29 @@
<template>
  <LoadingLayout :loading="isLoading" :error="isError" :loadError="refetch">
    <JobDetailContent :isCollapse="true">
    <JobDetailContent
      :avatar="userResumeInfo.avatar"
      :name="userResumeInfo.name"
      :age="userResumeInfo.age"
      :isReal="userResumeInfo.isReal"
      :gender="userResumeInfo.gender"
      :personalIdentityContent="userResumeInfo.personalIdentityContent"
      :educationalBackgroundContent="userResumeInfo.educationalBackgroundContent"
      :taskCount="userResumeInfo.taskCount"
      :contactPhoneNumber="userResumeInfo.contactPhoneNumber"
      :identity="userResumeInfo.identity"
      :userId="enterpriseEmployeeId"
      :userExpectJobs="userResumeInfo.userExpectJobs"
      :freeTime="userResumeInfo.freeTime"
      :jobSeekingStatus="userResumeInfo.jobSeekingStatus"
      :userCredentials="userResumeInfo.userCredentials"
      :workSeniority="userResumeInfo.workSeniority"
      :workExperience="userResumeInfo.workExperience"
      :photos="userResumeInfo.photos"
      :height="userResumeInfo.height"
      :weight="userResumeInfo.weight"
      :taskInfoUsers="userResumeInfo.taskInfoUsers"
      :isCollapse="true"
    >
      <!-- <template #footer>
        <PageFooterBtn type="primary" plain>解约</PageFooterBtn>
        <PageFooterBtn type="primary">签约</PageFooterBtn>
@@ -12,31 +35,17 @@
<script setup lang="ts">
import Taro from '@tarojs/taro';
import { useQuery } from '@tanstack/vue-query';
import * as flexWorkerServices from '@12333/services/api/FlexWorker';
import { useUserResume } from '@12333/hooks';
defineOptions({
  name: 'InnerPage',
});
const router = Taro.useRouter();
const taskId = router.params?.id ?? '';
const enterpriseEmployeeId = router.params?.enterpriseEmployeeId ?? '';
const {
  isLoading,
  isError,
  data: detail,
  refetch,
} = useQuery({
  queryKey: ['flexWorkerServices/getOrdeForDetail', taskId],
  queryFn: async () => {
    return await flexWorkerServices.getOrdeForDetail(
      { id: taskId },
      {
        showLoading: false,
      }
    );
  },
  placeholderData: () => ({} as API.OrderInfoDto),
const { isLoading, isError, userResumeInfo, refetch } = useUserResume({
  userId: enterpriseEmployeeId,
});
</script>
apps/bMiniApp/src/subpackages/flexJobManage/flexJobManage/InnerPage.vue
@@ -102,7 +102,7 @@
function goDetail(item: API.GetEnterpriseEmployeesQueryResultItem) {
  Taro.navigateTo({
    url: `${RouterPath.flexJobDetailFromManage}?userId=${item.id}`,
    url: `${RouterPath.flexJobDetailFromManage}?enterpriseEmployeeId=${item.id}`,
  });
}
apps/bMiniApp/src/subpackages/jobApplicationManage/components/SignList.vue
@@ -22,7 +22,7 @@
          </div>
        </template>
        <template #footerRight>
          <nut-button type="primary" @click="goToJobDetail(item.id)">查看详情</nut-button>
          <nut-button type="primary" @click="goToJobDetail(item)">查看详情</nut-button>
        </template>
      </FlexJobCard>
    </template>
@@ -52,9 +52,9 @@
  id: id,
});
function goToJobDetail(id: string) {
function goToJobDetail(item: API.GetTaskUsersQueryResultItem) {
  Taro.navigateTo({
    url: `${RouterPath.flexJobDetailFromTask}?id=${id}`,
    url: `${RouterPath.flexJobDetailFromTask}?enterpriseEmployeeId=${item.enterpriseEmployeeId}&id=${item.id}`,
  });
}
</script>
apps/bMiniApp/src/subpackages/task/taskManage/InnerPage.vue
@@ -78,11 +78,12 @@
  return infiniteLoadingProps.value?.listData?.pages?.[0]?.objectData?.waitAssignCount ?? 0;
});
function goSubmitTaskDetail(item: API.GetTaskInfosQueryResultItem) {
  Taro.navigateTo({
    url: `${RouterPath.flexJobDetail}?taskId=${item.id}`,
  });
}
//有问题
// function goSubmitTaskDetail(item: API.GetTaskInfosQueryResultItem) {
//   Taro.navigateTo({
//     url: `${RouterPath.taskManage}?taskId=${item.id}`,
//   });
// }
function goBatchTaskList(item: API.GetTaskInfosQueryResultItem, status: EnumTaskUserArrangeStatus) {
  Taro.navigateTo({
apps/cMiniApp/auto-imports.d.ts
@@ -91,7 +91,6 @@
  const useSlots: typeof import('vue')['useSlots']
  const useSwitchTab: typeof import('./src/hooks/router')['useSwitchTab']
  const useTemplateRef: typeof import('vue')['useTemplateRef']
  const useUpdateResume: typeof import('./src/hooks/user')['useUpdateResume']
  const useUser: typeof import('./src/hooks/user')['useUser']
  const useUserResume: typeof import('./src/hooks/user')['useUserResume']
  const watch: typeof import('vue')['watch']
@@ -204,7 +203,6 @@
    readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']>
    readonly useSwitchTab: UnwrapRef<typeof import('./src/hooks/router')['useSwitchTab']>
    readonly useTemplateRef: UnwrapRef<typeof import('vue')['useTemplateRef']>
    readonly useUpdateResume: UnwrapRef<typeof import('./src/hooks/user')['useUpdateResume']>
    readonly useUser: UnwrapRef<typeof import('./src/hooks/user')['useUser']>
    readonly useUserResume: UnwrapRef<typeof import('./src/hooks/user')['useUserResume']>
    readonly watch: UnwrapRef<typeof import('vue')['watch']>
apps/cMiniApp/src/hooks/user.ts
@@ -6,6 +6,7 @@
import { MaybeRef } from 'vue';
import { useRefeshDidShow } from '@12333/hooks/infiniteLoading';
import * as userResumeServices from '@12333/services/apiV2/userResume';
import { useUserResume as useUserResumeHook } from '@12333/hooks';
export function useUser() {
  const userStore = useUserStore();
@@ -97,44 +98,5 @@
export function useUserResume() {
  const { userId } = useUser();
  const { data, refetch } = useQuery({
    queryKey: ['userResumeServices/getUserResume', userId],
    queryFn: async () => {
      return await userResumeServices.getUserResume(
        { userId: userId.value },
        {
          showLoading: false,
        }
      );
    },
    placeholderData: () => ({} as API.GetUserResumeQueryResult),
    enabled: computed(() => !!userId.value),
  });
  return {
    userResumeInfo: data,
    refetch,
  };
}
export function useUpdateResume() {
  const queryClient = useQueryClient();
  const updateUserResumeCredentials = () => {
    return queryClient.invalidateQueries({
      queryKey: ['userResumeServices/getUserResumeCredentials'],
    });
  };
  const updateUserResume = () => {
    return queryClient.invalidateQueries({
      queryKey: ['userResumeServices/getUserResume'],
    });
  };
  return {
    updateUserResumeCredentials,
    updateUserResume,
  };
  return useUserResumeHook({ userId });
}
apps/cMiniApp/src/subpackages/curriculum/editMineInfo/InnerPage.vue
@@ -42,7 +42,7 @@
import { FormRules } from '@nutui/nutui-taro/dist/types/__VUE/form/types';
import { ChooseInputWithPicker, ChooseInputWithAreaPicker } from '@12333/components';
import { convertApi2FormUrlOnlyOne, Message, setOSSLink } from '@12333/utils';
import { useAreaTree, useDictionaryDataSelect } from '@12333/hooks';
import { useAreaTree, useDictionaryDataSelect, useUpdateResume } from '@12333/hooks';
import { AreaType, CategoryCode } from '@12333/constants';
import * as userResumeServices from '@12333/services/apiV2/userResume';
import Taro from '@tarojs/taro';
apps/cMiniApp/src/subpackages/curriculum/mineCertificateAddOrEdit/InnerPage.vue
@@ -67,7 +67,7 @@
import { FormRules } from '@nutui/nutui-taro/dist/types/__VUE/form/types';
import { useQuery, useQueryClient } from '@tanstack/vue-query';
import Taro from '@tarojs/taro';
import { useDictionaryDataSelect } from '@12333/hooks';
import { useDictionaryDataSelect, useUpdateResume } from '@12333/hooks';
import { CategoryCode } from '@12333/constants';
import { convertApi2FormUrlOnlyOne, Message, setOSSLink, FormValidator } from '@12333/utils';
import dayjs from 'dayjs';
apps/cMiniApp/src/subpackages/curriculum/mineDetailedInfo/InnerPage.vue
@@ -29,6 +29,7 @@
<script setup lang="ts">
import { goBack } from '@/utils';
import { NumberInput } from '@12333/components';
import { useUpdateResume } from '@12333/hooks';
import * as userResumeServices from '@12333/services/apiV2/userResume';
import { convertApiPath2Url, Message } from '@12333/utils';
import { FileItem } from '@nutui/nutui-taro/dist/types/__VUE/uploader/type';
apps/cMiniApp/src/subpackages/curriculum/mineJobIntention/InnerPage.vue
@@ -44,7 +44,7 @@
} from '@12333/constants';
import Taro from '@tarojs/taro';
import * as userResumeServices from '@12333/services/apiV2/userResume';
import { useDictionaryDataSelect } from '@12333/hooks';
import { useDictionaryDataSelect, useUpdateResume } from '@12333/hooks';
import { Message } from '@12333/utils';
import { useQuery } from '@tanstack/vue-query';
import { goBack } from '@/utils';
apps/cMiniApp/src/subpackages/curriculum/mineWorkExperience/InnerPage.vue
@@ -16,6 +16,7 @@
<script setup lang="ts">
import { goBack } from '@/utils';
import { useUpdateResume } from '@12333/hooks';
import * as userResumeServices from '@12333/services/apiV2/userResume';
import { Message } from '@12333/utils';
import { useQuery } from '@tanstack/vue-query';
packages/components/src/Card/FlexJobCard.vue
@@ -14,9 +14,7 @@
      {{ workExperience }}
    </div>
    <div class="flexJob-card-done-detail" v-if="showDoneDetail">
      <div class="flexJob-card-done-detail-item">
        {{ workSeniority }}
      </div>
      <div class="flexJob-card-done-detail-item">{{ workSeniority }}年</div>
      <!-- <div class="flexJob-card-done-detail-item">{{ '在「宁波雷迪森酒店」,做过客房服务员' }}</div> -->
    </div>
    <div class="flexJob-card-footer">
packages/hooks/index.ts
@@ -7,3 +7,4 @@
export * from './enterprise';
export * from './task';
export * from './taskUser';
export * from './user';
packages/hooks/user.ts
New file
@@ -0,0 +1,51 @@
import { MaybeRef, computed, unref } from 'vue';
import * as userResumeServices from '@12333/services/apiV2/userResume';
import { useQuery, useQueryClient } from '@tanstack/vue-query';
type UseUserResumeOptions = {
  userId: MaybeRef<string>;
};
export function useUserResume({ userId }: UseUserResumeOptions) {
  const { data, refetch, isLoading, isError } = useQuery({
    queryKey: ['userResumeServices/getUserResume', userId],
    queryFn: async () => {
      return await userResumeServices.getUserResume(
        { userId: unref(userId) },
        {
          showLoading: false,
        }
      );
    },
    placeholderData: () => ({} as API.GetUserResumeQueryResult),
    enabled: computed(() => !!unref(userId)),
  });
  return {
    userResumeInfo: data,
    refetch,
    isLoading,
    isError,
  };
}
export function useUpdateResume() {
  const queryClient = useQueryClient();
  const updateUserResumeCredentials = () => {
    return queryClient.invalidateQueries({
      queryKey: ['userResumeServices/getUserResumeCredentials'],
    });
  };
  const updateUserResume = () => {
    return queryClient.invalidateQueries({
      queryKey: ['userResumeServices/getUserResume'],
    });
  };
  return {
    updateUserResumeCredentials,
    updateUserResume,
  };
}
packages/services/apiV2/enterpriseEmployee.ts
@@ -2,6 +2,21 @@
// @ts-ignore
import { request } from '@/utils/request';
/** 编辑灵工信息 POST /api/user/enterpriseEmployee/editEnterpriseEmployee */
export async function editEnterpriseEmployee(
  body: API.EditEnterpriseEmployeeCommand,
  options?: API.RequestConfig
) {
  return request<string>('/api/user/enterpriseEmployee/editEnterpriseEmployee', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json-patch+json',
    },
    data: body,
    ...(options || {}),
  });
}
/** 查询灵工详情 GET /api/user/enterpriseEmployee/getEnterpriseEmployee */
export async function getEnterpriseEmployee(
  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
@@ -37,3 +52,18 @@
    }
  );
}
/** 导入灵工信息 POST /api/user/enterpriseEmployee/importEnterpriseEmployees */
export async function importEnterpriseEmployees(
  body: API.ImportEnterpriseEmployeesCommand,
  options?: API.RequestConfig
) {
  return request<number>('/api/user/enterpriseEmployee/importEnterpriseEmployees', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json-patch+json',
    },
    data: body,
    ...(options || {}),
  });
}
packages/services/apiV2/typings.d.ts
@@ -243,6 +243,24 @@
    ids: string[];
  }
  interface EditEnterpriseEmployeeCommand {
    /** 灵工Id */
    id?: string;
    /** 姓名 */
    name?: string;
    /** 身份证号 */
    identity?: string;
    /** 手机号 */
    contactPhoneNumber?: string;
    gender?: EnumUserGender;
    /** 年龄 */
    age?: number;
    /** 身份证人像面 */
    identityImg?: string;
    /** 身份证国徽面 */
    identityBackImg?: string;
  }
  enum EnumBillingMethod {
    /**按月 */
    Month = 10,
@@ -2396,6 +2414,8 @@
    releaseStatus?: EnumTaskReleaseStatus;
    recommendStatus?: EnumTaskRecommendStatus;
    checkReceiveStatus?: EnumTaskCheckReceiveStatus;
    /** 是否收藏 */
    isCollected?: boolean;
    pageModel?: PagedListQueryPageModel;
  }
@@ -2670,6 +2690,8 @@
    photos?: string[];
    /** 经历 */
    taskInfoUsers?: GetUserResumeQueryResultExperience[];
    /** 是否已收藏 */
    isCollected?: boolean;
  }
  interface GetUserResumeQueryResultCredential {
@@ -2725,6 +2747,10 @@
    ageMax?: number;
    /** 资格证书编号 */
    userCredentials?: string[];
    /** 是否已收藏 */
    isCollected?: boolean;
    /** 是否已联系 */
    isContacted?: boolean;
    pageModel?: PagedListQueryPageModel;
  }
@@ -2766,6 +2792,8 @@
    workSeniority?: string;
    /** 工作经验 */
    workExperience?: string;
    /** 创建时间 */
    createdTime?: string;
  }
  type GetUserResumeWorkExperienceQuery = Record<string, any>;
@@ -2777,6 +2805,11 @@
    workExperience?: string;
  }
  interface ImportEnterpriseEmployeesCommand {
    /** Excel地址 */
    excelUrl?: string;
  }
  interface LoginCommandCallback {
    /** 用户Id */
    id?: string;
packages/utils/common.ts
@@ -131,5 +131,7 @@
  return list.filter(Boolean).join(separator);
}
export const hiddenIDNumberForEnd6 = (realIDNumber: string) =>
export const hiddenIDNumberForEnd6 = (realIDNumber: string) => {
  if (!realIDNumber) return '';
  realIDNumber.replace(/^(\d+)(.{6})$/, '$1******');
};