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