wupengfei
2025-02-14 548b9c78ca14b5c3812e9958835dedb78d589454
feat: mine
5个文件已修改
11个文件已添加
582 ■■■■■ 已修改文件
apps/bMiniApp/project.private.config.json 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/app.config.ts 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/flexJob/icon-localtion.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/constants/router.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/pages/workbenches/InnerPage.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/jobApplicationManage/components/JobDetail.vue 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/jobApplicationManage/components/SignList.vue 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/jobApplicationManage/jobApplicationDetail/InnerPage.vue 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/jobApplicationManage/jobApplicationDetail/jobApplicationDetail.config.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/jobApplicationManage/jobApplicationDetail/jobApplicationDetail.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/jobApplicationManage/jobApplicationManage/InnerPage.vue 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/jobApplicationManage/jobApplicationManage/jobApplicationManage.config.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/jobApplicationManage/jobApplicationManage/jobApplicationManage.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/components/assets/components/icon-more.png 补丁 | 查看 | 原始文档 | blame | 历史
packages/components/src/Card/JobApplicationCard.vue 270 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/components/src/index.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/project.private.config.json
@@ -35,6 +35,13 @@
                    "query": "",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "应聘管理",
                    "pathName": "subpackages/jobApplicationManage/jobApplicationManage/jobApplicationManage",
                    "query": "",
                    "launchMode": "default",
                    "scene": null
                }
            ]
        }
apps/bMiniApp/src/app.config.ts
@@ -79,6 +79,13 @@
      pages: ['publishTask/publishTask'],
    },
    {
      root: 'subpackages/jobApplicationManage',
      pages: [
        'jobApplicationManage/jobApplicationManage',
        'jobApplicationDetail/jobApplicationDetail',
      ],
    },
    {
      root: 'subpackages/city',
      pages: ['citySelect/citySelect'],
    },
apps/bMiniApp/src/assets/flexJob/icon-localtion.png
apps/bMiniApp/src/constants/router.ts
@@ -29,4 +29,7 @@
  mineContactRecord = '/subpackages/mine/mineContactRecord/mineContactRecord',
  publishTask = '/subpackages/task/publishTask/publishTask',
  jobApplicationManage = '/subpackages/jobApplicationManage/jobApplicationManage/jobApplicationManage',
  jobApplicationDetail = '/subpackages/jobApplicationManage/jobApplicationDetail/jobApplicationDetail',
}
apps/bMiniApp/src/pages/workbenches/InnerPage.vue
@@ -12,7 +12,7 @@
      <CellChunk title="任务">
        <div class="workbenches-cell-list">
          <TaskDetailWelfareItem :icon="IconPublishTask" text="发布任务" @click="goPublishTask" />
          <TaskDetailWelfareItem :icon="IconPersonManage" text="用人管理" />
          <TaskDetailWelfareItem :icon="IconPersonManage" text="用人管理" @click="goPersonManage" />
        </div>
      </CellChunk>
      <CellChunk title="用人">
@@ -56,6 +56,10 @@
function goPublishTask() {
  goPage(RouterPath.publishTask);
}
function goPersonManage() {
  goPage(RouterPath.jobApplicationManage);
}
</script>
<style lang="scss">
apps/bMiniApp/src/subpackages/jobApplicationManage/components/JobDetail.vue
New file
@@ -0,0 +1,80 @@
<template>
  <LoadingLayout :loading="isLoading" :error="isError" :loadError="refetch">
    <ContentScrollView style="background-color: transparent">
      <Cell :title="'客房服务员'" titleSize="large">
        <div class="taskDetail-time">2025年2月5日 至 2025年3月5日</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>
          <TaskPrice :value="212" />
        </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>
          <div class="taskDetail-address-info-wrapper">
            <div class="taskDetail-address-info">宁波市鄞州区东钱湖大堰路188号宁波柏悦酒店</div>
            <RectRight :size="8" class="taskDetail-address-info-icon" />
          </div>
        </div>
      </Cell>
      <Cell :show-title="false">
        <CellChunk title="福利信息">
          <div class="taskDetail-welfare-list">
            <TaskDetailWelfareItem :icon="IconLocaltion" text="高温补贴" />
            <TaskDetailWelfareItem :icon="IconLocaltion" text="高温补贴" />
            <TaskDetailWelfareItem :icon="IconLocaltion" text="高温补贴" />
            <TaskDetailWelfareItem :icon="IconLocaltion" text="高温补贴" />
            <TaskDetailWelfareItem :icon="IconLocaltion" text="高温补贴" />
          </div>
        </CellChunk>
      </Cell>
    </ContentScrollView>
  </LoadingLayout>
</template>
<script setup lang="ts">
import { useQuery } from '@tanstack/vue-query';
import Taro from '@tarojs/taro';
import * as orderServices from '@12333/services/api/Order';
import IconLocaltion from '@/assets/flexJob/icon-localtion.png';
import { TaskPrice, TaskDetailWelfareItem } from '@12333/components';
defineOptions({
  name: 'JobDetail',
});
// type Props = {};
// const props = withDefaults(defineProps<Props>(), {});
const router = Taro.useRouter();
const taskId = router.params?.id ?? '';
const {
  isLoading,
  isError,
  data: detail,
  refetch,
} = useQuery({
  queryKey: ['orderServices/getOrdeForDetail', taskId],
  queryFn: async () => {
    return await orderServices.getOrdeForDetail(
      { id: taskId },
      {
        showLoading: false,
      }
    );
  },
  placeholderData: () => ({} as API.OrderInfoDto),
  onSuccess(data) {},
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
</style>
apps/bMiniApp/src/subpackages/jobApplicationManage/components/SignList.vue
New file
@@ -0,0 +1,52 @@
<template>
  <InfiniteLoading scrollViewClassName="common-infinite-scroll-list" v-bind="infiniteLoadingProps">
    <template #renderItem="{ item }">
      <FlexJobCard>
        <template #footerLeft>
          <div class="flexJob-card-footer-text">已录用</div>
        </template>
        <template #footerRight>
          <nut-button type="primary">查看详情</nut-button>
        </template>
      </FlexJobCard>
    </template>
  </InfiniteLoading>
</template>
<script setup lang="ts">
import { OrderInputType } from '@12333/constants';
import { useInfiniteLoading } from '@12333/hooks';
import * as orderServices from '@12333/services/api/Order';
import { FlexJobCard } from '@12333/components';
defineOptions({
  name: 'SignList',
});
// type Props = {};
// const props = withDefaults(defineProps<Props>(), {});
const { infiniteLoadingProps } = useInfiniteLoading(
  ({ pageParam }) => {
    let params: API.FrontOrderListInput = {
      pageModel: {
        rows: 20,
        page: pageParam,
        orderInput: [{ property: 'isRecommend', order: OrderInputType.Desc }],
      },
    };
    return orderServices.getFrontOrderList(params, {
      showLoading: false,
    });
  },
  {
    queryKey: ['orderServices/getFrontOrderList'],
  }
);
</script>
<style lang="scss">
@import '@/styles/common.scss';
</style>
apps/bMiniApp/src/subpackages/jobApplicationManage/jobApplicationDetail/InnerPage.vue
New file
@@ -0,0 +1,37 @@
<template>
  <ProTabs
    v-model="tabType"
    name="home-tab"
    class="home-tabs"
    isTransparent
    title-gutter="12"
    full-height
  >
    <ProTabPane :title="`报名列表`" pane-key="1">
      <SignList></SignList>
    </ProTabPane>
    <ProTabPane :title="`岗位详情`" pane-key="2">
      <JobDetail></JobDetail>
    </ProTabPane>
  </ProTabs>
</template>
<script setup lang="ts">
import { ProTabs, ProTabPane } from '@12333/components';
import SignList from '../components/SignList.vue';
import JobDetail from '../components/JobDetail.vue';
defineOptions({
  name: 'InnerPage',
});
const tabType = ref('1');
</script>
<style lang="scss">
@import '@/styles/common.scss';
// .jobApplicationManage-page-wrapper {
// }
</style>
apps/bMiniApp/src/subpackages/jobApplicationManage/jobApplicationDetail/jobApplicationDetail.config.ts
New file
@@ -0,0 +1,3 @@
export default definePageConfig({
  disableScroll: true,
});
apps/bMiniApp/src/subpackages/jobApplicationManage/jobApplicationDetail/jobApplicationDetail.vue
New file
@@ -0,0 +1,17 @@
<template>
  <PageLayoutWithBg class="jobApplicationDetail-page-wrapper" :title="'详情'">
    <InnerPage></InnerPage>
  </PageLayoutWithBg>
</template>
<script setup lang="ts">
import InnerPage from './InnerPage.vue';
defineOptions({
  name: 'jobApplicationDetail',
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
</style>
apps/bMiniApp/src/subpackages/jobApplicationManage/jobApplicationManage/InnerPage.vue
New file
@@ -0,0 +1,79 @@
<template>
  <ProTabs
    v-model="queryState.mineHireType"
    name="home-tab"
    :showPaneContent="false"
    class="home-tabs"
    isTransparent
    title-gutter="12"
    title-scroll
  >
    <ProTabPane :title="`发布中(${1})`" :pane-key="0"></ProTabPane>
    <ProTabPane :title="`已停止(${1})`" :pane-key="10"></ProTabPane>
  </ProTabs>
  <InfiniteLoading
    scrollViewClassName="common-infinite-scroll-list home-list"
    v-bind="infiniteLoadingProps"
  >
    <template #renderItem="{ item }">
      <JobApplicationCard @edit="goEdit" @detail="goDetail"> </JobApplicationCard>
    </template>
  </InfiniteLoading>
</template>
<script setup lang="ts">
import { JobApplicationCard, ProTabs, ProTabPane } from '@12333/components';
import { RouterPath } from '@/constants';
import { useInfiniteLoading } from '@12333/hooks';
import { OrderInputType } from '@12333/constants';
import * as orderServices from '@12333/services/api/Order';
import { TaskStatus } from '@/constants/task';
import Taro from '@tarojs/taro';
defineOptions({
  name: 'InnerPage',
});
const queryState = reactive({
  mineHireType: TaskStatus.All,
});
const { infiniteLoadingProps } = useInfiniteLoading(
  ({ pageParam }) => {
    let params: API.FrontOrderListInput = {
      pageModel: {
        rows: 20,
        page: pageParam,
        orderInput: [{ property: 'isRecommend', order: OrderInputType.Desc }],
      },
    };
    return orderServices.getFrontOrderList(params, {
      showLoading: false,
    });
  },
  {
    queryKey: ['orderServices/getFrontOrderList'],
  }
);
function goPage(routeName: string) {
  Taro.navigateTo({
    url: routeName,
  });
}
function goEdit() {
  goPage(RouterPath.publishTask);
}
function goDetail() {
  goPage(RouterPath.jobApplicationDetail);
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
// .jobApplicationManage-page-wrapper {
// }
</style>
apps/bMiniApp/src/subpackages/jobApplicationManage/jobApplicationManage/jobApplicationManage.config.ts
New file
@@ -0,0 +1,3 @@
export default definePageConfig({
  disableScroll: true,
});
apps/bMiniApp/src/subpackages/jobApplicationManage/jobApplicationManage/jobApplicationManage.vue
New file
@@ -0,0 +1,17 @@
<template>
  <PageLayoutWithBg class="jobApplicationManage-page-wrapper" :title="'应聘管理'">
    <InnerPage></InnerPage>
  </PageLayoutWithBg>
</template>
<script setup lang="ts">
import InnerPage from './InnerPage.vue';
defineOptions({
  name: 'jobApplicationManage',
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
</style>
packages/components/assets/components/icon-more.png
packages/components/src/Card/JobApplicationCard.vue
New file
@@ -0,0 +1,270 @@
<template>
  <div class="job-application-card-wrapper">
    <div class="job-application-card-title-wrapper">
      <div class="job-application-card-title">客房服务员</div>
      <div class="job-application-card-title-more" @click.stop="handleMore">
        <img :src="IconMore" class="more-btn-icon" />
      </div>
    </div>
    <div class="job-application-card-line">
      <div class="job-application-card-time">{{ `${'2025年2月5日'}至${'2025年3月5日'}` }}</div>
      <div class="job-application-card-status">{{ '生效中' }}</div>
    </div>
    <div class="job-application-card-line">
      <div class="job-application-card-company">
        <div class="job-application-card-company-tag">H</div>
        <div class="job-application-card-company-address">宁波雷迪森酒店</div>
      </div>
      <div class="job-application-card-people">{{ `报名人数:${5}` }}</div>
    </div>
    <div class="job-application-card-line">
      <div class="job-application-card-publish-time">{{ `发布日期:${'2022年12月25日'}` }}</div>
      <div class="job-application-card-fee">
        <TaskPrice :value="212" />
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { computed, h } from 'vue';
import IconMore from '../../assets/components/icon-more.png';
import { CommonTaskCardProps } from './card';
import { ActionSheet } from '@nutui/nutui-taro';
import { Portal } from 'senin-mini/components';
import { TaskPrice } from '@12333/components';
defineOptions({
  name: 'JobApplicationCard',
});
enum ManageActions {
  Edit = 1,
  Detail,
  Publish,
  Stop,
  Copy,
  Delete,
}
enum ResourceStatus {
  /**
   * 已驳回
   */
  Reject = -10,
  /**
   * 未提交
   */
  Draft = 10,
  /**
   * 待审核
   */
  WaitAudit = 20,
  /**
   * 进行中
   */
  Running = 30,
  /**
   * 已下架
   */
  OffShelf = 40,
  /**
   * 系统下架
   */
  SystemOffShelf = 50,
}
type Props = CommonTaskCardProps & {
  showActions?: boolean;
  status?: ResourceStatus;
};
const props = withDefaults(defineProps<Props>(), {
  showActions: true,
});
const emit = defineEmits<{
  (e: 'edit'): void;
  (e: 'detail'): void;
  (e: 'publish'): void;
  (e: 'stop'): void;
  (e: 'copy'): void;
  (e: 'delete'): void;
}>();
const menuList = computed(() => {
  let _menuList = [];
  if (props.status !== ResourceStatus.WaitAudit) {
    _menuList.push({
      name: '编辑',
      value: ManageActions.Edit,
    });
  }
  _menuList.push({
    name: '查看详情',
    value: ManageActions.Detail,
  });
  if (props.status === ResourceStatus.OffShelf) {
    _menuList.push({
      name: '发布',
      value: ManageActions.Publish,
    });
  }
  if (props.status === ResourceStatus.Running) {
    _menuList.push({
      name: '停止发布',
      value: ManageActions.Stop,
    });
  }
  if (props.status !== ResourceStatus.WaitAudit) {
    _menuList.push(
      {
        name: '复制',
        value: ManageActions.Copy,
      },
      {
        name: '删除',
        value: ManageActions.Delete,
      }
    );
  }
  return _menuList;
});
function handleMore() {
  Portal.add((key) => {
    return h(
      Portal.Container,
      { keyNumber: key, delayOpen: true },
      {
        default: ({ open, onClose }) =>
          // @ts-ignore
          h(ActionSheet, {
            visible: open.value,
            'onUpdate:visible': () => onClose(),
            menuItems: menuList.value,
            onChoose: (item) => {
              handleEmit(item);
              onClose();
            },
          }),
      }
    );
  });
}
function handleEmit(action: { name: string; value: number }) {
  switch (action.value) {
    case ManageActions.Edit:
      emit('edit');
      break;
    case ManageActions.Detail:
      emit('detail');
      break;
    case ManageActions.Publish:
      emit('publish');
      break;
    case ManageActions.Stop:
      emit('stop');
      break;
    case ManageActions.Copy:
      emit('copy');
      break;
    case ManageActions.Delete:
      emit('delete');
      break;
  }
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
.job-application-card-wrapper {
  padding: 24px 32px;
  margin-bottom: 24px;
  background-color: #fff;
  border-radius: 12px;
  &:last-child {
    margin-bottom: 0;
  }
  .job-application-card-title-wrapper {
    display: flex;
    align-items: center;
    margin-bottom: 30px;
    justify-content: space-between;
    .job-application-card-title {
      @include ellipsis;
      font-size: 30px;
      color: boleGetCssVar('text-color', 'primary');
      line-height: 42px;
      font-weight: bold;
    }
    .job-application-card-title-more {
      flex-shrink: 0;
      .more-btn-icon {
        width: 42px;
        height: 42px;
      }
    }
  }
  .job-application-card-line {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 24px;
    font-size: 24px;
    line-height: 32px;
    &:last-child {
      margin-bottom: 0;
    }
    .job-application-card-time {
      color: boleGetCssVar('text-color', 'regular');
    }
    .job-application-card-company {
      display: inline-flex;
      align-items: center;
      .job-application-card-company-tag {
        width: 32px;
        height: 32px;
        background: #2a9e1b;
        margin-right: 8px;
        border-radius: 8px;
        text-align: center;
        line-height: 32px;
        color: #fff;
        font-size: 22px;
      }
      .job-application-card-company-address {
        font-size: 22px;
        color: boleGetCssVar('text-color', 'regular');
        line-height: 32px;
        flex: 1;
        min-width: 0;
        @include ellipsis;
      }
    }
    .job-application-card-people {
      font-size: 20px;
      color: boleGetCssVar('text-color', 'secondary');
    }
    .job-application-card-publish-time {
      color: boleGetCssVar('text-color', 'regular');
    }
  }
}
</style>
packages/components/src/index.ts
@@ -21,6 +21,7 @@
export { default as Elevator } from './Elevator/Elevator.vue';
export { default as TaskCard } from './Card/TaskCard.vue';
export { default as MineAgreementSignCard } from './Card/MineAgreementSignCard.vue';
export { default as JobApplicationCard } from './Card/JobApplicationCard.vue';
export { default as MyTaskCard } from './Card/MyTaskCard.vue';
export { default as FlexJobCard } from './Card/FlexJobCard.vue';
export { default as TaskPrice } from './Card/TaskPrice.vue';