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