From d853816c959089a545f57a2980ca3f42fdd20fa1 Mon Sep 17 00:00:00 2001
From: zhengyiming <540361168@qq.com>
Date: 星期二, 11 二月 2025 14:44:33 +0800
Subject: [PATCH] feat: 首页

---
 apps/cMiniApp/src/components/Layout/PageLayoutWithBg.vue |    4 
 apps/cMiniApp/src/components/Menu/MenuItem.vue           |    6 
 packages/components/src/Card/TaskCard.vue                |  131 +++++++++++++++++++++
 apps/cMiniApp/src/assets/tabbar/icon-mine-active.png     |    0 
 packages/components/src/index.ts                         |    1 
 apps/cMiniApp/src/pages/home/index.vue                   |  146 +++++++++++++++++++++---
 apps/cMiniApp/src/components/Searchbar/BlSearchbar.vue   |    5 
 packages/components/src/Card/TaskPrice.vue               |   39 ++++++
 apps/cMiniApp/src/assets/tabbar/icon-task-active.png     |    0 
 apps/cMiniApp/src/pages/home/constants/index.ts          |    4 
 10 files changed, 314 insertions(+), 22 deletions(-)

diff --git a/apps/cMiniApp/src/assets/tabbar/icon-mine-active.png b/apps/cMiniApp/src/assets/tabbar/icon-mine-active.png
index 4170967..8e174e6 100644
--- a/apps/cMiniApp/src/assets/tabbar/icon-mine-active.png
+++ b/apps/cMiniApp/src/assets/tabbar/icon-mine-active.png
Binary files differ
diff --git a/apps/cMiniApp/src/assets/tabbar/icon-task-active.png b/apps/cMiniApp/src/assets/tabbar/icon-task-active.png
index 2844544..7f3906a 100644
--- a/apps/cMiniApp/src/assets/tabbar/icon-task-active.png
+++ b/apps/cMiniApp/src/assets/tabbar/icon-task-active.png
Binary files differ
diff --git a/apps/cMiniApp/src/components/Layout/PageLayoutWithBg.vue b/apps/cMiniApp/src/components/Layout/PageLayoutWithBg.vue
index 414d78b..3706ecb 100644
--- a/apps/cMiniApp/src/components/Layout/PageLayoutWithBg.vue
+++ b/apps/cMiniApp/src/components/Layout/PageLayoutWithBg.vue
@@ -10,8 +10,8 @@
     <template #bg>
       <img :src="OssAssets.common.CommonPageBg" class="common-page-bg" />
     </template>
-    <template #default>
-      <slot />
+    <template #default="{ scrollViewHeight }">
+      <slot :scrollViewHeight="scrollViewHeight" />
     </template>
   </PageLayout>
 </template>
diff --git a/apps/cMiniApp/src/components/Menu/MenuItem.vue b/apps/cMiniApp/src/components/Menu/MenuItem.vue
index acb4a8d..227252d 100644
--- a/apps/cMiniApp/src/components/Menu/MenuItem.vue
+++ b/apps/cMiniApp/src/components/Menu/MenuItem.vue
@@ -53,10 +53,14 @@
   </view>
 </template>
 <script lang="ts">
-import { MenuItemOption } from '@nutui/nutui-taro/dist/types/__VUE/menuitem/type';
 import { Check } from '@nutui/icons-vue-taro';
 import { isArray } from 'lodash';
 
+type MenuItemOption = {
+  text: string;
+  value: number | string;
+};
+
 export default defineComponent({
   name: 'bl-menu-item',
   props: {
diff --git a/apps/cMiniApp/src/components/Searchbar/BlSearchbar.vue b/apps/cMiniApp/src/components/Searchbar/BlSearchbar.vue
index 0c4a669..3e7ee41 100644
--- a/apps/cMiniApp/src/components/Searchbar/BlSearchbar.vue
+++ b/apps/cMiniApp/src/components/Searchbar/BlSearchbar.vue
@@ -25,5 +25,10 @@
 .bole-search-bar {
   padding: 0;
   background-color: transparent;
+
+  .nut-searchbar__search-input {
+    box-shadow: none;
+    border: 1px solid boleGetCssVar('color', 'primary');
+  }
 }
 </style>
diff --git a/apps/cMiniApp/src/pages/home/constants/index.ts b/apps/cMiniApp/src/pages/home/constants/index.ts
new file mode 100644
index 0000000..ff9bf0b
--- /dev/null
+++ b/apps/cMiniApp/src/pages/home/constants/index.ts
@@ -0,0 +1,4 @@
+export enum HomeOrderType {
+  Recommend = 'Recommend',
+  LastShelfTime = 'LastShelfTime',
+}
diff --git a/apps/cMiniApp/src/pages/home/index.vue b/apps/cMiniApp/src/pages/home/index.vue
index daa5593..62093b5 100644
--- a/apps/cMiniApp/src/pages/home/index.vue
+++ b/apps/cMiniApp/src/pages/home/index.vue
@@ -1,31 +1,91 @@
 <template>
-  <PageLayoutWithBg class="index-page-wrapper" :title="'棣栭〉'" :need-auth="false">
+  <PageLayoutWithBg class="index-page-wrapper" :title="''" :need-auth="false">
     <template #left>
       <div class="menu-btn-wrapper menu-logo">
         <img :src="IconLogo" class="logo" />
       </div>
     </template>
-    <div class="home-searchbar-wrapper">
-      <BlSearchbar v-model.trim="searchValue"></BlSearchbar>
+    <div class="home-header">
+      <div class="home-searchbar-wrapper">
+        <div class="searchbar-container">
+          <BlSearchbar v-model.trim="searchValue" placeholder="鎼滅储浠诲姟"></BlSearchbar>
+        </div>
+        <div class="city-btn" @click="goCitySelect">
+          <Location2 :size="16" />
+          <div class="city-btn-text">{{ locationCity }}</div>
+        </div>
+      </div>
+      <div class="home-banner-wrapper">
+        <nut-swiper :auto-play="3000">
+          <nut-swiper-item v-for="(item, index) in list" :key="index">
+            <img :src="item" class="banner-img" draggable="false" />
+          </nut-swiper-item>
+        </nut-swiper>
+      </div>
     </div>
+    <ProTabs
+      v-model="queryState.orderType"
+      name="home-tab"
+      :showPaneContent="false"
+      class="home-tabs"
+      isTransparent
+      title-gutter="12"
+      title-scroll
+    >
+      <ProTabPane :title="`鎺ㄨ崘`" :pane-key="HomeOrderType.Recommend"></ProTabPane>
+      <ProTabPane :title="`鏈�鏂癭" :pane-key="HomeOrderType.LastShelfTime"></ProTabPane>
+      <template #right>
+        <Menu>
+          <MenuItem
+            v-model="queryState.orderByProperty"
+            title="绛涢��"
+            ref="selectItem"
+            :options="[
+              { text: '鎺掑簭', value: 'userId' },
+              { text: '鎸夊叧娉ㄦ椂闂�', value: 'creationTime' },
+            ]"
+          />
+        </Menu>
+      </template>
+    </ProTabs>
+    <InfiniteLoading
+      scrollViewClassName="common-infinite-scroll-list home-list"
+      v-bind="infiniteLoadingProps"
+      :key="queryState.orderType"
+    >
+      <template #renderItem="{ item }">
+        <TaskCard />
+      </template>
+    </InfiniteLoading>
   </PageLayoutWithBg>
 </template>
 
 <script setup lang="ts">
 import { useUser } from '@/hooks';
 import { useUserStore } from '@/stores/modules/user';
-import { RectDown } from '@nutui/icons-vue-taro';
+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 } from '@12333/constants';
+import * as orderServices from '@12333/services/api/Order';
+import { TaskCard, ProTabs, ProTabPane } from '@12333/components';
+import { HomeOrderType } from './constants';
 
 const { locationCity } = useUser();
+
+Taro.usePageScroll(() => {
+  console.log('11', 11);
+});
 
 const searchValue = ref('');
 
 const queryState = reactive({
   searchValueTrim: '',
+  orderType: HomeOrderType.Recommend,
+  orderByProperty: 'userId',
 });
 
 const handleSearch = _.debounce(function () {
@@ -39,13 +99,36 @@
     url: RouterPath.citySelect,
   });
 }
-// onMounted(async () => {
-//   if (!isSetMatchMakingIdentity.value) {
-//     Taro.navigateTo({
-//       url: RouterPath.toggleMatchMakingIdentity,
-//     });
-//   }
-// });
+
+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 { 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],
+  }
+);
 </script>
 
 <style lang="scss">
@@ -61,19 +144,44 @@
     }
   }
 
-  .city-btn {
+  .home-searchbar-wrapper {
+    padding: 32px 0;
     display: flex;
-    align-items: center;
 
-    .city-btn-text {
-      max-width: 200px;
-      @include ellipsis;
-      margin-right: 12px;
+    .searchbar-container {
+      flex: 1;
+      min-width: 0;
+    }
+
+    .city-btn {
+      display: flex;
+      align-items: center;
+      padding-left: 36px;
+      color: boleGetCssVar('text-color', 'primary');
+
+      .city-btn-text {
+        max-width: 200px;
+        @include ellipsis;
+        margin-left: 12px;
+        font-size: 30px;
+      }
     }
   }
 
-  .home-searchbar-wrapper {
-    padding: 32px 0;
+  .home-banner-wrapper {
+    .banner-img {
+      width: 100%;
+      height: 260px;
+      object-fit: cover;
+    }
   }
+
+  .home-header {
+    padding: 0 boleGetCssVar('size', 'body-padding-h');
+  }
+}
+
+.home-list {
+  @include infiniteLoadingInTabBarPage;
 }
 </style>
diff --git a/packages/components/src/Card/TaskCard.vue b/packages/components/src/Card/TaskCard.vue
new file mode 100644
index 0000000..01186b3
--- /dev/null
+++ b/packages/components/src/Card/TaskCard.vue
@@ -0,0 +1,131 @@
+<template>
+  <div class="task-card-wrapper">
+    <div class="task-card-title-wrapper">
+      <div class="task-card-title">瀹㈡埧鏈嶅姟鍛�</div>
+      <TaskPrice />
+    </div>
+    <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>
+    <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">
+        <slot name="actions">
+          <nut-button type="primary">鎶ュ悕</nut-button>
+        </slot>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import TaskPrice from './TaskPrice.vue';
+
+defineOptions({
+  name: 'TaskCard',
+});
+
+type Props = {
+  title?: string;
+};
+
+const props = withDefaults(defineProps<Props>(), {});
+</script>
+
+<style lang="scss">
+@import '@/styles/common.scss';
+
+.task-card-wrapper {
+  padding: 24px 32px;
+  margin-bottom: 24px;
+  background-color: #fff;
+  border-radius: 12px;
+
+  &:last-child {
+    margin-bottom: 0;
+  }
+
+  .task-card-title-wrapper {
+    display: flex;
+    align-items: center;
+    margin-bottom: 14px;
+
+    .task-card-title {
+      flex: 1;
+      min-width: 0;
+      @include ellipsis;
+      font-size: 30px;
+      color: boleGetCssVar('text-color', 'primary');
+      line-height: 42px;
+    }
+  }
+
+  .task-card-welfare-list {
+    display: flex;
+    flex-wrap: wrap;
+    row-gap: 6px;
+    column-gap: 18px;
+    margin-bottom: 8px;
+
+    .task-card-welfare-list-item {
+      font-size: 24px;
+      color: #ff7d00;
+      line-height: 36px;
+    }
+  }
+
+  .task-card-time {
+    font-size: 24px;
+    color: boleGetCssVar('text-color', 'secondary');
+    line-height: 36px;
+    margin-bottom: 6px;
+  }
+
+  .task-card-footer {
+    display: flex;
+    align-items: center;
+
+    .task-card-left {
+      flex: 1;
+      min-width: 0;
+      display: flex;
+      align-items: center;
+
+      .task-card-footer-tag {
+        width: 32px;
+        height: 32px;
+        background: #2a9e1b;
+        margin-right: 8px;
+        border-radius: 8px;
+        text-align: center;
+        line-height: 32px;
+        color: #fff;
+        font-size: 22px;
+      }
+
+      .task-card-footer-address {
+        font-size: 22px;
+        color: boleGetCssVar('text-color', 'secondary');
+        line-height: 36px;
+        flex: 1;
+        min-width: 0;
+        @include ellipsis;
+      }
+    }
+
+    .task-card-actions {
+      --nut-button-default-font-size: 24px;
+
+      .nut-button {
+        height: 26px;
+      }
+    }
+  }
+}
+</style>
diff --git a/packages/components/src/Card/TaskPrice.vue b/packages/components/src/Card/TaskPrice.vue
new file mode 100644
index 0000000..b359093
--- /dev/null
+++ b/packages/components/src/Card/TaskPrice.vue
@@ -0,0 +1,39 @@
+<template>
+  <div class="task-price">
+    <div class="task-price-decimal">55</div>
+    <div class="task-price-unit">鍏�/灏忔椂</div>
+  </div>
+</template>
+
+<script setup lang="ts">
+defineOptions({
+  name: 'TaskPrice',
+});
+
+type Props = {
+  value?: number;
+};
+
+const props = withDefaults(defineProps<Props>(), {});
+</script>
+
+<style lang="scss">
+@import '@/styles/common.scss';
+
+.task-price {
+  display: flex;
+  align-items: flex-end;
+  color: boleGetCssVar('color', 'primary');
+
+  .task-price-decimal {
+    font-size: 32px;
+    line-height: 40px;
+    margin-right: 8px;
+  }
+
+  .task-price-unit {
+    font-size: 20px;
+    line-height: 32px;
+  }
+}
+</style>
diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts
index 8eb0c39..5a0bf6e 100644
--- a/packages/components/src/index.ts
+++ b/packages/components/src/index.ts
@@ -17,3 +17,4 @@
 export { default as AutoWidthImage } from './Image/AutoWidthImage.vue';
 export { default as AreaTreeSelect } from './AreaTreeSelect/AreaTreeSelect.vue';
 export { default as Elevator } from './Elevator/Elevator.vue';
+export { default as TaskCard } from './Card/TaskCard.vue';

--
Gitblit v1.9.1