zhengyiming
2025-02-12 8ddaa42086bc67dac16ea596d212b79d3b832313
fix: task
13个文件已修改
13个文件已添加
1个文件已删除
760 ■■■■■ 已修改文件
apps/cMiniApp/project.private.config.json 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/app.config.ts 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/assets/task/icon-no-certified.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/components/Chunk/Cell.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/components/Chunk/CellChunk.vue 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/constants/router.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/custom-tab-bar/index.tsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/hooks/index.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/hooks/task.ts 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/pages/home/constants/index.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/pages/home/index.vue 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/pages/task/InnerPage.vue 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/pages/task/task.vue 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/task/companyDetail/companyDetail.config.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/task/companyDetail/companyDetail.vue 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/task/components/CompanyDesc.vue 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/task/components/CompanyInfo.vue 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/task/components/CompanyTaskList.vue 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/task/components/TaskDetailWelfareItem.vue 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/task/taskDetail/InnerPage.vue 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/src/subpackages/task/taskDetail/taskDetail.scss 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/components/src/Calendar/Calendar.vue 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/components/src/Card/MineAgreementSignCard.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/components/src/Card/MyTaskCard.vue 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/components/src/Card/TaskCard.vue 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/components/src/Card/card.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages/components/src/index.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/project.private.config.json
@@ -9,6 +9,20 @@
        "miniprogram": {
            "list": [
                {
                    "name": "任务",
                    "pathName": "pages/task/task",
                    "query": "",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "公司详情",
                    "pathName": "subpackages/task/companyDetail/companyDetail",
                    "query": "id=c4cfe028-23e7-0be8-ee56-3a11e3743b9d",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "任务详情",
                    "pathName": "subpackages/task/taskDetail/taskDetail",
                    "query": "id=c4cfe028-23e7-0be8-ee56-3a11e3743b9d",
apps/cMiniApp/src/app.config.ts
@@ -84,7 +84,11 @@
    },
    {
      root: 'subpackages/task',
      pages: ['taskDetail/taskDetail'],
      pages: ['taskDetail/taskDetail', 'companyDetail/companyDetail'],
    },
    {
      root: 'subpackages/user',
      pages: ['complaint/complaint'],
    },
  ],
  // preloadRule: {
apps/cMiniApp/src/assets/task/icon-no-certified.png
apps/cMiniApp/src/components/Chunk/Cell.vue
@@ -1,6 +1,6 @@
<template>
  <div class="bole-cell-wrapper">
    <div class="cell-title-wrapper">
    <div class="cell-title-wrapper" v-if="showTitle">
      <slot name="title">
        <div :class="titleSize === 'normal' ? 'cell-title' : 'cell-title-large'">{{ title }}</div>
        <slot name="title-right"></slot>
@@ -18,10 +18,12 @@
type Props = {
  title?: string;
  titleSize?: 'large' | 'normal';
  showTitle?: boolean;
};
const props = withDefaults(defineProps<Props>(), {
  titleSize: 'normal',
  showTitle: true,
});
</script>
apps/cMiniApp/src/components/Chunk/CellChunk.vue
New file
@@ -0,0 +1,38 @@
<template>
  <div class="cell-chunk-wrapper">
    <div class="cell-title-wrapper">
      <slot name="title">
        <div :class="titleSize === 'normal' ? 'cell-title' : 'cell-title-large'">{{ title }}</div>
        <slot name="title-right"></slot>
      </slot>
    </div>
    <slot></slot>
  </div>
</template>
<script setup lang="ts">
defineOptions({
  name: 'CellChunk',
});
type Props = {
  title?: string;
  titleSize?: 'large' | 'normal';
};
const props = withDefaults(defineProps<Props>(), {
  titleSize: 'normal',
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.cell-chunk-wrapper {
  margin-bottom: 20px;
  &:last-child {
    margin-bottom: 0;
  }
}
</style>
apps/cMiniApp/src/constants/router.ts
@@ -11,6 +11,7 @@
  editRichContent = '/subpackages/editRichContent/editRichContent',
  taskDetail = '/subpackages/task/taskDetail/taskDetail',
  companyDetail = '/subpackages/task/companyDetail/companyDetail',
  // userInfo = '/subpackages/setting/userInfo/userInfo',
  // setting = '/subpackages/setting/setting/setting',
apps/cMiniApp/src/custom-tab-bar/index.tsx
@@ -128,7 +128,7 @@
          ></TarBarItem>
          <TarBarItem
            text="消息"
            text="任务"
            icon="../assets/tabbar/icon-task.png"
            activeIcon="../assets/tabbar/icon-task-active.png"
            pagePath={TabBarPageRouter.Task}
apps/cMiniApp/src/hooks/index.ts
@@ -3,3 +3,4 @@
export * from './access';
export * from './login';
export * from './authentication';
export * from './task';
apps/cMiniApp/src/hooks/task.ts
New file
@@ -0,0 +1,55 @@
import { useInfiniteLoading } from '@12333/hooks';
import { OrderInputType, Gender } from '@12333/constants';
import * as orderServices from '@12333/services/api/Order';
import _ from 'lodash';
import { trim } from '@12333/utils';
export enum HomeOrderType {
  Recommend = 'Recommend',
  LastShelfTime = 'LastShelfTime',
}
export function useTaskList() {
  const searchValue = ref('');
  const queryState = reactive({
    searchValueTrim: '',
    orderType: HomeOrderType.Recommend,
    gender: '' as any as Gender,
    companyId: '',
  });
  const handleSearch = _.debounce(function () {
    queryState.searchValueTrim = trim(searchValue.value);
  }, 300);
  const { infiniteLoadingProps } = useInfiniteLoading(
    ({ pageParam }) => {
      let params: API.FrontOrderListInput = {
        pageModel: {
          rows: 20,
          page: pageParam,
          orderInput: [
            queryState.orderType === HomeOrderType.Recommend
              ? { property: 'isRecommend', order: OrderInputType.Desc }
              : { property: 'lastShelfTime', order: OrderInputType.Desc },
          ],
        },
      };
      return orderServices.getFrontOrderList(params, {
        showLoading: false,
      });
    },
    {
      queryKey: ['orderServices/getFrontOrderList', queryState],
    }
  );
  return {
    searchValue,
    queryState,
    handleSearch,
    infiniteLoadingProps,
  };
}
apps/cMiniApp/src/pages/home/constants/index.ts
File was deleted
apps/cMiniApp/src/pages/home/index.vue
@@ -64,35 +64,21 @@
</template>
<script setup lang="ts">
import { useUser } from '@/hooks';
import { useUser, useTaskList, HomeOrderType } from '@/hooks';
import { useUserStore } from '@/stores/modules/user';
import { RectDown, Location2 } from '@nutui/icons-vue-taro';
import Taro from '@tarojs/taro';
import { LocationUtils, trim } from '@12333/utils';
import _ from 'lodash';
import IconLogo from '@/assets/home/icon-logo.png';
import { useInfiniteLoading } from '@12333/hooks';
import { OrderInputType, Gender } from '@12333/constants';
import * as orderServices from '@12333/services/api/Order';
import { TaskCard, ProTabs, ProTabPane } from '@12333/components';
import { HomeOrderType } from './constants';
import HomeQueryMenuView from './HomeQueryMenuView.vue';
const { locationCity } = useUser();
const searchValue = ref('');
const queryState = reactive({
  searchValueTrim: '',
  orderType: HomeOrderType.Recommend,
  gender: '' as any as Gender,
});
const handleSearch = _.debounce(function () {
  queryState.searchValueTrim = trim(searchValue.value);
}, 300);
const userStore = useUserStore();
const { searchValue, queryState, handleSearch, infiniteLoadingProps } = useTaskList();
function goCitySelect() {
  Taro.navigateTo({
@@ -106,29 +92,6 @@
  'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
  'https://storage.360buyimg.com/jdc-article/fristfabu.jpg',
]);
const { infiniteLoadingProps } = useInfiniteLoading(
  ({ pageParam }) => {
    let params: API.FrontOrderListInput = {
      pageModel: {
        rows: 20,
        page: pageParam,
        orderInput: [
          queryState.orderType === HomeOrderType.Recommend
            ? { property: 'isRecommend', order: OrderInputType.Desc }
            : { property: 'lastShelfTime', order: OrderInputType.Desc },
        ],
      },
    };
    return orderServices.getFrontOrderList(params, {
      showLoading: false,
    });
  },
  {
    queryKey: ['orderServices/getFrontOrderList', queryState],
  }
);
const selectItem = ref();
apps/cMiniApp/src/pages/task/InnerPage.vue
New file
@@ -0,0 +1,74 @@
<template>
  <Calendar v-model="queryState.date"></Calendar>
  <ProTabs
    v-model="queryState.status"
    name="task-tab"
    :showPaneContent="false"
    class="task-tabs"
    isTransparent
    title-gutter="8"
    title-scroll
  >
    <ProTabPane :title="`待提交`" :pane-key="10"></ProTabPane>
    <ProTabPane :title="`待验收`" :pane-key="20"></ProTabPane>
  </ProTabs>
  <InfiniteLoading
    scrollViewClassName="common-infinite-scroll-list task-list"
    v-bind="infiniteLoadingProps"
    :key="queryState.status"
  >
    <template #renderItem="{ item }">
      <MyTaskCard @click="goSubmitTaskDetail(item)" />
    </template>
  </InfiniteLoading>
</template>
<script setup lang="ts">
import { MyTaskCard, ProTabs, ProTabPane, Calendar } from '@12333/components';
import Taro from '@tarojs/taro';
import { useInfiniteLoading } from '@12333/hooks';
import { OrderInputType } from '@12333/constants';
import * as orderServices from '@12333/services/api/Order';
defineOptions({
  name: 'InnerPage',
});
const queryState = reactive({
  status: 10,
  date: new Date(),
});
const { infiniteLoadingProps } = useInfiniteLoading(
  ({ pageParam }) => {
    let params: API.FrontOrderListInput = {
      pageModel: {
        rows: 20,
        page: pageParam,
        orderInput: [{ property: 'lastShelfTime', order: OrderInputType.Desc }],
      },
    };
    return orderServices.getFrontOrderList(params, {
      showLoading: false,
    });
  },
  {
    queryKey: ['orderServices/getFrontOrderList', queryState],
  }
);
function goSubmitTaskDetail(item: API.FrontOrderList) {
  Taro.navigateTo({
    url: `${RouterPath.taskDetail}?id=${item.id}`,
  });
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
.task-list {
  @include infiniteLoadingInTabBarPage;
}
</style>
apps/cMiniApp/src/pages/task/task.vue
@@ -1,13 +1,13 @@
<template>
  <div>task</div>
  <PageLayoutWithBg class="task-page-wrapper" title="任务">
    <InnerPage />
  </PageLayoutWithBg>
</template>
<script setup lang="ts">
import InnerPage from './InnerPage.vue';
defineOptions({
  name: 'task',
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
</style>
apps/cMiniApp/src/subpackages/task/companyDetail/companyDetail.config.ts
New file
@@ -0,0 +1,3 @@
export default definePageConfig({
  disableScroll: true,
});
apps/cMiniApp/src/subpackages/task/companyDetail/companyDetail.vue
New file
@@ -0,0 +1,66 @@
<template>
  <PageLayoutWithBg class="companyDetail-page-wrapper" title="公司详情" :need-auth="false">
    <LoadingLayout :loading="isLoading" :error="isError" :loadError="refetch">
      <ContentView>
        <CompanyDesc style="background-color: #fff" :showArrow="false"></CompanyDesc>
      </ContentView>
      <ProTabs
        v-model="tab"
        name="companyDetail-tab"
        :showSmile="false"
        class="companyDetail-tabs"
        isTransparent
        title-gutter="8"
        fullHeight
      >
        <ProTabPane :title="`任务`" pane-key="1">
          <CompanyTaskList />
        </ProTabPane>
        <ProTabPane :title="`企业信息`" pane-key="2">
          <CompanyInfo />
        </ProTabPane>
      </ProTabs>
    </LoadingLayout>
  </PageLayoutWithBg>
</template>
<script setup lang="ts">
import Taro from '@tarojs/taro';
import { useQuery } from '@tanstack/vue-query';
import * as orderServices from '@12333/services/api/Order';
import CompanyDesc from '../components/CompanyDesc.vue';
import CompanyTaskList from '../components/CompanyTaskList.vue';
import CompanyInfo from '../components/CompanyInfo.vue';
import { ProTabs, ProTabPane } from '@12333/components';
defineOptions({
  name: 'companyDetail',
});
const router = Taro.useRouter();
const companyId = router.params?.id ?? '';
const tab = ref('1');
const {
  isLoading,
  isError,
  data: detail,
  refetch,
} = useQuery({
  queryKey: ['orderServices/getOrdeForDetail', companyId],
  queryFn: async () => {
    return await orderServices.getOrdeForDetail(
      { id: companyId },
      {
        showLoading: false,
      }
    );
  },
  placeholderData: () => ({} as API.OrderInfoDto),
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
</style>
apps/cMiniApp/src/subpackages/task/components/CompanyDesc.vue
New file
@@ -0,0 +1,80 @@
<template>
  <div class="taskDetail-company-wrapper">
    <div class="taskDetail-company-title-wrapper">
      <div class="taskDetail-company-title">宁波人力无忧</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>
  </div>
</template>
<script setup lang="ts">
import IconSafe from '@/assets/task/icon-safe.png';
import { RectRight } from '@nutui/icons-vue-taro';
defineOptions({
  name: 'CompanyDesc',
});
type Props = {
  showArrow?: boolean;
};
const props = withDefaults(defineProps<Props>(), {
  showArrow: true,
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.taskDetail-company-wrapper {
  padding: 28px 20px;
  background: #f9fbff;
  border-radius: 8px;
  .taskDetail-company-title-wrapper {
    display: flex;
    align-items: center;
    margin-bottom: 24px;
    .taskDetail-company-title {
      font-weight: 500;
      font-size: 28px;
      color: boleGetCssVar('text-color', 'primary');
      line-height: 42px;
      flex: 1;
      min-width: 0;
      @include ellipsis;
    }
    .taskDetail-company-arrow {
      color: boleGetCssVar('text-color', 'secondary');
      margin-left: 10px;
    }
  }
  .taskDetail-company-info {
    display: flex;
    align-items: center;
    .safe-company-info-icon {
      width: 24px;
      height: 24px;
      margin-right: 6px;
    }
    .taskDetail-company-info-text {
      font-size: 24px;
      color: boleGetCssVar('text-color', 'regular');
      line-height: 36px;
      flex: 1;
      min-width: 0;
      @include ellipsis;
    }
  }
}
</style>
apps/cMiniApp/src/subpackages/task/components/CompanyInfo.vue
New file
@@ -0,0 +1,107 @@
<template>
  <ContentScrollView style="background-color: transparent">
    <div v-if="isCertified" class="companyInfo-info-wrapper">
      <div class="companyInfo-info-item">
        <div class="companyInfo-info-item-label">企业名称</div>
        <div class="companyInfo-info-item-content">江西君润商务服务有限公司</div>
      </div>
      <div class="companyInfo-info-item">
        <div class="companyInfo-info-item-label">统一社会信用代码</div>
        <div class="companyInfo-info-item-content">420902197910211010</div>
      </div>
      <div class="companyInfo-info-item">
        <div class="companyInfo-info-item-label">注册资本</div>
        <div class="companyInfo-info-item-content">捌佰万元整</div>
      </div>
      <div class="companyInfo-info-item">
        <div class="companyInfo-info-item-label">企业类型</div>
        <div class="companyInfo-info-item-content">有限责任公司(自然人投资或控股 的法人独资)</div>
      </div>
      <div class="companyInfo-info-item">
        <div class="companyInfo-info-item-label">成立日期</div>
        <div class="companyInfo-info-item-content">2024年11月11日</div>
      </div>
      <div class="companyInfo-info-item">
        <div class="companyInfo-info-item-label">企业地址</div>
        <div class="companyInfo-info-item-content">江西省九江市共青城市xx路xx号xx xxxx</div>
      </div>
      <div class="companyInfo-info-item">
        <div class="companyInfo-info-item-label">经营范围</div>
        <div class="companyInfo-info-item-content">
          我是营业执照上的经营范围信息我 是营业执照上的经营范围信息我是
          营业执照上的经营范围信息我是营 业执照上的经营范围信息我是营业 执照上的经营范围信息
        </div>
      </div>
    </div>
    <div v-else class="company-info-unCertified-wrapper">
      <img :src="IconNoCertified" class="company-info-unCertified-icon" />
      <div class="company-info-unCertified-text">该企业尚未认证</div>
      <div class="company-info-unCertified-text">请谨慎核实招聘信息</div>
    </div>
  </ContentScrollView>
</template>
<script setup lang="ts">
import IconNoCertified from '@/assets/task/icon-no-certified.png';
defineOptions({
  name: 'CompanyInfo',
});
const isCertified = ref(true);
</script>
<style lang="scss">
@import '@/styles/common.scss';
.companyInfo-info-wrapper {
  background: #ffffff;
  border-radius: 12px;
  padding: 72px 28px 108px;
  .companyInfo-info-item {
    display: flex;
    font-weight: 400;
    font-size: 24px;
    line-height: 36px;
    margin-bottom: 24px;
    &:last-child {
      margin-bottom: 0;
    }
    .companyInfo-info-item-label {
      color: boleGetCssVar('text-color', 'secondary');
      margin-right: 54px;
      width: 200px;
      text-align: right;
    }
    .companyInfo-info-item-content {
      flex: 1;
      min-width: 0;
      color: boleGetCssVar('text-color', 'primary');
    }
  }
}
.company-info-unCertified-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 140px;
  .company-info-unCertified-icon {
    width: 320px;
    height: 180px;
    margin-bottom: 8px;
  }
  .company-info-unCertified-text {
    font-weight: 400;
    font-size: 32px;
    color: boleGetCssVar('text-color', 'primary');
    line-height: 48px;
  }
}
</style>
apps/cMiniApp/src/subpackages/task/components/CompanyTaskList.vue
New file
@@ -0,0 +1,29 @@
<template>
  <InfiniteLoading scrollViewClassName="common-infinite-scroll-list" v-bind="infiniteLoadingProps">
    <template #renderItem="{ item }">
      <TaskCard @click="goTaskDetail(item)" />
    </template>
  </InfiniteLoading>
</template>
<script setup lang="ts">
import { useTaskList } from '@/hooks';
import { TaskCard } from '@12333/components';
import Taro from '@tarojs/taro';
defineOptions({
  name: 'CompanyTaskList',
});
const { queryState, infiniteLoadingProps } = useTaskList();
function goTaskDetail(item: API.FrontOrderList) {
  Taro.navigateTo({
    url: `${RouterPath.taskDetail}?id=${item.id}`,
  });
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
</style>
apps/cMiniApp/src/subpackages/task/components/TaskDetailWelfareItem.vue
New file
@@ -0,0 +1,44 @@
<template>
  <div class="taskDetail-welfare-list-item">
    <img :src="IconAttentioActive" class="taskDetail-welfare-list-item-icon" />
    <div class="taskDetail-welfare-list-item-text">高温补贴</div>
  </div>
</template>
<script setup lang="ts">
import IconAttentioActive from '@/assets/task/icon-attention-active.png';
defineOptions({
  name: 'TaskDetailWelfareItem',
});
// type Props = {};
// const props = withDefaults(defineProps<Props>(), {});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.taskDetail-welfare-list-item {
  display: flex;
  align-items: center;
  flex-direction: column;
  width: 25%;
  .taskDetail-welfare-list-item-icon {
    width: 72px;
    height: 72px;
    margin-bottom: 24px;
  }
  .taskDetail-welfare-list-item-text {
    font-weight: 400;
    font-size: 24px;
    color: boleGetCssVar('text-color', 'regular');
    line-height: 36px;
    text-align: center;
    /* @include ellipsis; */
  }
}
</style>
apps/cMiniApp/src/subpackages/task/taskDetail/InnerPage.vue
@@ -21,9 +21,39 @@
          </div>
          <div class="taskDetail-address-info-wrapper">
            <div class="taskDetail-address-info">宁波市鄞州区东钱湖大堰路188号宁波柏悦酒店</div>
            <RectRight :size="6" class="taskDetail-address-info-icon" />
            <RectRight :size="8" class="taskDetail-address-info-icon" />
          </div>
        </div>
      </Cell>
      <Cell :show-title="false">
        <CellChunk title="福利信息">
          <div class="taskDetail-welfare-list">
            <TaskDetailWelfareItem />
            <TaskDetailWelfareItem />
            <TaskDetailWelfareItem />
            <TaskDetailWelfareItem />
            <TaskDetailWelfareItem />
          </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>
            <div class="taskDetail-limit-list-item">
              <div class="taskDetail-limit-list-item-label">性别:</div>
              <div class="taskDetail-limit-list-item-text">不限</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>
          </div>
        </CellChunk>
        <CellChunk title="发布者信息">
          <CompanyDesc @click="goCompanyDetail"></CompanyDesc>
        </CellChunk>
      </Cell>
      <Cell>
        <template #title>
@@ -45,6 +75,7 @@
        :isFlex="false"
        openType="share"
      ></PageFooterAction>
      <PageFooterAction :icon="IconShare" text="手机" :isFlex="false"></PageFooterAction>
      <PageFooterBtn type="primary">报名</PageFooterBtn>
    </PageFooter>
  </LoadingLayout>
@@ -62,6 +93,8 @@
import IconShare from '@/assets/task/icon-share.png';
import IconSafe from '@/assets/task/icon-safe.png';
import './taskDetail.scss';
import TaskDetailWelfareItem from '../components/TaskDetailWelfareItem.vue';
import CompanyDesc from '../components/CompanyDesc.vue';
defineOptions({
  name: 'InnerPage',
@@ -98,4 +131,10 @@
    url: `${RouterPath.complaint}?id=${taskId}`,
  });
}
function goCompanyDetail() {
  Taro.navigateTo({
    url: `${RouterPath.companyDetail}?id=${taskId}`,
  });
}
</script>
apps/cMiniApp/src/subpackages/task/taskDetail/taskDetail.scss
@@ -116,4 +116,32 @@
      display: inline;
    }
  }
  .taskDetail-welfare-list {
    display: flex;
    flex-wrap: wrap;
    row-gap: 24px;
  }
  .taskDetail-limit-list {
    display: flex;
    justify-content: space-between;
    padding: 0 14px;
    .taskDetail-limit-list-item {
      display: flex;
      align-items: center;
      font-size: 24px;
      line-height: 28px;
      .taskDetail-limit-list-item-label {
        color: boleGetCssVar('text-color', 'regular');
      }
      .taskDetail-limit-list-item-text {
        color: boleGetCssVar('text-color', 'primary');
      }
    }
  }
}
packages/components/src/Calendar/Calendar.vue
New file
@@ -0,0 +1,43 @@
<template>
  <div class="bole-calendar-wrapper">
    <div class="bole-calendar-inner">
      <nut-calendar-card v-model="model" class="bole-calendar"></nut-calendar-card>
    </div>
    <div class="bole-calendar-arrow">
      <DownArrow :size="12" />
    </div>
  </div>
</template>
<script setup lang="ts">
import { DownArrow } from '@nutui/icons-vue-taro';
defineOptions({
  name: 'Calendar',
});
// type Props = {};
// const props = withDefaults(defineProps<Props>(), {});
const model = defineModel<Date | Date[]>();
</script>
<style lang="scss">
@import '@/styles/common.scss';
.bole-calendar-wrapper {
  .bole-calendar {
    background-color: transparent;
  }
  .bole-calendar-inner {
    height: 500px;
    overflow: hidden;
  }
  .bole-calendar-arrow {
    display: flex;
    justify-content: center;
  }
}
</style>
packages/components/src/Card/MineAgreementSignCard.vue
@@ -17,15 +17,13 @@
</template>
<script setup lang="ts">
import { CommonTaskCardProps } from './card';
defineOptions({
  name: 'MineAgreementSignCard',
});
type Props = {
  title?: string;
};
const props = withDefaults(defineProps<Props>(), {});
const props = withDefaults(defineProps<CommonTaskCardProps>(), {});
</script>
<style lang="scss">
packages/components/src/Card/MyTaskCard.vue
New file
@@ -0,0 +1,39 @@
<template>
  <TaskCard v-bind="props" :show-actions="false" class="my-task-card-wrapper">
    <template #title-right>
      <RectRight :size="12" class="my-task-card-arrow" />
    </template>
    <div class="my-task-card-time">2025年2月5日 至 2025年3月5日</div>
  </TaskCard>
</template>
<script setup lang="ts">
import TaskCard from './TaskCard.vue';
import { CommonTaskCardProps } from './card';
import { RectRight } from '@nutui/icons-vue-taro';
defineOptions({
  name: 'MyTaskCard',
});
const props = withDefaults(defineProps<CommonTaskCardProps>(), {});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.my-task-card-wrapper {
  .my-task-card-arrow {
    color: boleGetCssVar('text-color', 'primary');
  }
  .my-task-card-time {
    font-weight: 400;
    @include ellipsis;
    font-size: 24px;
    color: boleGetCssVar('text-color', 'primary');
    line-height: 36px;
    margin-bottom: 14px;
  }
}
</style>
packages/components/src/Card/TaskCard.vue
@@ -2,20 +2,24 @@
  <div class="task-card-wrapper">
    <div class="task-card-title-wrapper">
      <div class="task-card-title">客房服务员</div>
      <slot name="title-right">
      <TaskPrice :value="212" />
      </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">包三餐</div>
    </div>
    <div class="task-card-time">上班时间:07:00-15:30</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">宁波雷迪森酒店</div>
      </div>
      <div class="task-card-actions">
      <div class="task-card-actions" v-if="showActions">
        <slot name="actions">
          <nut-button type="primary">报名</nut-button>
        </slot>
@@ -26,16 +30,19 @@
<script setup lang="ts">
import TaskPrice from './TaskPrice.vue';
import { CommonTaskCardProps } from './card';
defineOptions({
  name: 'TaskCard',
});
type Props = {
  title?: string;
type Props = CommonTaskCardProps & {
  showActions?: boolean;
};
const props = withDefaults(defineProps<Props>(), {});
const props = withDefaults(defineProps<Props>(), {
  showActions: true,
});
</script>
<style lang="scss">
packages/components/src/Card/card.ts
New file
@@ -0,0 +1,3 @@
export type CommonTaskCardProps = {
  title?: string;
};
packages/components/src/index.ts
@@ -19,7 +19,9 @@
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 MyTaskCard } from './Card/MyTaskCard.vue';
export { default as TaskPrice } from './Card/TaskPrice.vue';
export { default as QueryMenuView } from './Menu/QueryMenuView.vue';
export { default as QueryMenuItem } from './Menu/QueryMenuItem.vue';
export { default as ProRadio } from './Form/ProRadio.vue';
export { default as Calendar } from './Calendar/Calendar.vue';