Browse Source

feat: 项目详情;导航栏

songzhen 3 months ago
parent
commit
1568a52f2e

+ 4 - 0
src/app.vue

@@ -8,6 +8,7 @@
 
 <script setup>
 const themeVars = reactive({
+  primaryColor: "#FD9A00",
   buttonPrimaryBackground: "#22C2A0",
   buttonPrimaryBorderColor: "#22C2A0",
   searchPadding: "0px",
@@ -15,5 +16,8 @@ const themeVars = reactive({
   dividerContentPadding: "0",
   dividerMargin: "0",
   dividerVerticalMargin: "0",
+  dropdownMenuTitleActiveTextColor: "#ff9300",
+  treeSelectItemActiveColor: "#ff9300",
+  sidebarSelectedBorderColor: "#ff9300",
 });
 </script>

BIN
src/assets/img/navbar/menu_profile.png


+ 6 - 2
src/components/Home/Banner.vue

@@ -1,6 +1,10 @@
 <template>
-  <van-swipe :autoplay="3000" :show-indicators="false">
-    <van-swipe-item class="" v-for="item in bannerList" :key="item.id">
+  <van-swipe
+    :autoplay="3000"
+    :show-indicators="false"
+    class="rounded-xl overflow-hidden"
+  >
+    <van-swipe-item v-for="item in bannerList" :key="item.id">
       <img
         class="object-cover w-full aspect-[1920/697] rounded-xl"
         :src="item.imgUrlsAfterConvert[0]"

+ 26 - 12
src/components/NavigationBar/LeftMenu.vue

@@ -65,6 +65,9 @@ import menu_tickets from "@/assets/img/navbar/menu_tickets.png";
 import menu_travel_note from "@/assets/img/navbar/menu_travel_note.png";
 import menu_travel_project from "@/assets/img/navbar/menu_travel_project.png";
 import menu_visa from "@/assets/img/navbar/menu_visa.png";
+import menu_profile from "@/assets/img/navbar/menu_profile.png";
+
+const visible = defineModel("visible");
 
 const authStore = useAuthStore();
 const { token } = storeToRefs(authStore);
@@ -72,15 +75,21 @@ const { token } = storeToRefs(authStore);
 const userInfoStore = useUserInfoStore();
 const { userInfo } = storeToRefs(userInfoStore);
 
-const needLoginMenus = [
-  {
-    title: "写游记",
-    icon: menu_create_note,
-    to: "/note-create",
-  },
-];
+const menuData = ref([]);
 
-const menuData = reactive([
+const writeNoteMenu = {
+  title: "写游记",
+  icon: menu_create_note,
+  to: "/note-create",
+};
+
+const profileMenu = {
+  title: "我的",
+  icon: menu_profile,
+  to: "/profile",
+};
+
+const fixedMenuData = [
   {
     title: "首页",
     icon: menu_travel_home,
@@ -121,14 +130,17 @@ const menuData = reactive([
   //   icon: menu_tickets,
   //   to: "/labour",
   // },
-]);
+];
 
 watch(
   token,
   (val) => {
-    if (!val) return;
-    userInfoStore.getUserInfo();
-    menuData.splice(1, 0, ...needLoginMenus);
+    if (!val) {
+      menuData.value = fixedMenuData;
+    } else {
+      userInfoStore.getUserInfo();
+      menuData.value = [...fixedMenuData, writeNoteMenu, profileMenu];
+    }
   },
   {
     immediate: true,
@@ -136,6 +148,7 @@ watch(
 );
 
 function handleClickMenu(item) {
+  visible.value = false;
   navigateTo({
     path: item.to,
   });
@@ -147,6 +160,7 @@ function handleLogout() {
   } finally {
     authStore.cleanToken();
     navigateTo("/");
+    visible.value = false;
   }
 }
 </script>

+ 9 - 11
src/components/NavigationBar/index.vue

@@ -1,7 +1,9 @@
 <template>
-  <div class="h-60 bg-white justify-between w-full fixed z-[999]">
+  <div
+    class="h-50 bg-white justify-between w-full fixed z-[999] border-b box-border"
+  >
     <NuxtLink to="/" class="absolute top-1/2 -translate-y-1/2 left-15">
-      <img src="~/assets/img/logo.png" class="h-40 object-contain" />
+      <img src="~/assets/img/logo.png" class="h-36 object-contain" />
     </NuxtLink>
     <div
       class="absolute right-15 top-1/2 -translate-y-1/2"
@@ -15,7 +17,11 @@
       position="left"
       :style="{ height: '100%', width: '70%' }"
     >
-      <NavigationBarLeftMenu v-if="isMenuShow" @on-hide="isMenuShow = false" />
+      <NavigationBarLeftMenu
+        v-if="isMenuShow"
+        v-model:visible="isMenuShow"
+        @on-hide="isMenuShow = false"
+      />
     </van-popup>
   </div>
 </template>
@@ -28,14 +34,6 @@ function handleClickMenu() {
 }
 
 const route = useRoute();
-
-watch(
-  route,
-  () => {
-    isMenuShow.value = false;
-  },
-  { deep: true }
-);
 </script>
 
 <style lang="scss" scoped></style>

+ 11 - 1
src/components/TravelProjectDetail/BookInfo.vue

@@ -5,7 +5,13 @@
       @click="showCalendarPicker = true"
       class="h-40 rounded-full border-[2px] px-15 mt-10 border-[#f7f7f7] flex items-center justify-between"
     >
-      <span>出发:{{ startDate }}</span>
+      <span class="flex items-center space-x-10">
+        <span>出发:{{ startDate }}</span>
+        <span class="text-[#FF2222]"
+          >{{ calendarData[startDate]?.adultPrice || "???"
+          }}{{ detailData.priceUnit }}</span
+        >
+      </span>
       <span
         class="iconfont icon-caret-down text-primary"
         style="font-size: 24px"
@@ -90,6 +96,10 @@ const props = defineProps({
     type: Object,
     default: () => {},
   },
+  detailData: {
+    type: Object,
+    default: () => ({}),
+  },
 });
 
 const startDate = defineModel("startDate");

+ 7 - 1
src/components/TravelProjectDetail/BottomBar.vue

@@ -3,7 +3,9 @@
     class="fixed bottom-0 px-20 left-0 right-0 h-70 z-50 bg-white shadow-[0px_2px_14px_1px_rgba(0,0,0,0.12)] flex justify-center items-center"
   >
     <span class="text-black-6">总价:</span>
-    <span class="text-[#FF2222] text-3xl font-semibold">¥{{ totalPrice }}</span>
+    <span class="text-[#FF2222] text-3xl font-semibold"
+      >{{ totalPrice }}{{ detailData.priceUnit }}</span
+    >
     <van-button
       @click="$emit('onOk')"
       class="flex-1"
@@ -26,6 +28,10 @@ defineProps({
     default: "",
   },
   loading: Boolean,
+  detailData: {
+    type: Object,
+    default: () => ({}),
+  },
 });
 defineEmits(["onOk"]);
 </script>

+ 1 - 1
src/layouts/default.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="">
     <NavigationBar />
-    <div class="pt-60">
+    <div class="pt-50">
       <slot></slot>
     </div>
     <!-- <Footer /> -->

+ 27 - 0
src/middleware/auth.global.js

@@ -0,0 +1,27 @@
+export default defineNuxtRouteMiddleware((to, from) => {
+  if (import.meta.server) return;
+
+  const authStore = useAuthStore();
+  const { token } = storeToRefs(authStore);
+
+  if (token.value) return;
+
+  if (to.fullPath.includes("/profile")) {
+    return navigateTo("/login", {
+      replace: true,
+      query: {
+        redirect: to.fullPath,
+      },
+    });
+  }
+
+  if (to.fullPath.includes("/note-create")) {
+    return navigateTo("/login", {
+      replace: true,
+      query: {
+        redirect: to.fullPath,
+      },
+    });
+  }
+  return;
+});

+ 2 - 1
src/pages/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="bg-[#F1F1F1]">
+  <div class="bg-[#F1F1F1] mt-10">
     <div class="px-15 bg-white pb-15">
       <HomeBanner />
       <HomeTravelMenu class="mt-10" />
@@ -12,6 +12,7 @@
       <HomeHotTravelProjects />
       <HomeHotCountry class="mt-30" />
     </div>
+    <Footer />
   </div>
 </template>
 

+ 2 - 2
src/pages/profile/index.vue

@@ -4,7 +4,7 @@
       class="h-250 relative w-full bg-[url('~/assets/img/profile/profile_banner.png')] bg-no-repeat bg-cover"
     >
       <div class="absolute left-20 bottom-10">
-        <div class="flex items-center space-x-10">
+        <NuxtLink to="/profile/userInfo" class="flex items-center space-x-10">
           <van-image
             :src="userInfo.headImageUrl"
             width="75px"
@@ -15,7 +15,7 @@
           <span class="text-2xl font-semibold text-white">
             {{ userInfo.showName }}</span
           >
-        </div>
+        </NuxtLink>
         <div class="text-xl text-white font-semibold mt-15">
           个性签名:{{ userInfo.personalSign || "暂未填写" }}
         </div>

+ 1 - 1
src/pages/profile/userInfo.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="bg-[#f8f8f8] pt-30">
+  <div class="bg-[#f8f8f8] pt-20">
     <van-form>
       <van-cell-group inset>
         <van-field name="uploader" label="头像">

+ 2 - 0
src/pages/t/[id].client.vue

@@ -11,6 +11,7 @@
         v-model:adultNumber="bookInfo.adultNumber"
         v-model:childrenNumber="bookInfo.childrenNumber"
         :calendar-data="calendarData"
+        :detail-data="detailData"
       />
       <TravelProjectDetailSellingPoint
         v-if="detailData?.sellingPoint"
@@ -22,6 +23,7 @@
     </div>
     <TravelProjectDetailBottomBar
       :total-price="totalPrice"
+      :detail-data="detailData"
       :loading="submitLoading"
       @onOk="handleSubmit"
     />

+ 7 - 6
src/pages/travel-projects/index.client.vue

@@ -1,15 +1,12 @@
 <template>
   <div class="">
-    <van-sticky :offset-top="60">
+    <van-sticky :offset-top="50">
       <van-dropdown-menu ref="menuRef">
         <van-dropdown-item :title="currentAreaFilterLabel" ref="areaFilterRef">
           <van-tree-select
+            height="340px"
             v-model:active-id="activeCountryId"
             v-model:main-active-index="activeAreaIndex"
-            style="
-              --van-tree-select-item-active-color: #ff9300;
-              --van-tree-select-nav-background: #ff9300;
-            "
             :items="areaOptions"
             @click-nav="handleAreaClick"
             @click-item="handleCountryClick"
@@ -133,4 +130,8 @@ onMounted(() => {
 });
 </script>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+:deep(.van-tree-select__item) {
+  font-weight: normal;
+}
+</style>