Procházet zdrojové kódy

Merge branch 'main' of https://github.com/omnia96/designer-hub

Jake před 5 měsíci
rodič
revize
379f3b20c4

+ 7 - 4
packages/app/src/components/button-evo.vue

@@ -5,7 +5,7 @@ import { omit } from 'radash'
 interface ComponentProps {
   block?: boolean
   color?: string
-  size?: 'lg'
+  size?: 'lg' | 'md' | 'sm'
 }
 const props = withDefaults(
   defineProps<{ customClass?: string; skew?: boolean } & ComponentProps>(),
@@ -19,16 +19,19 @@ const buttonProps = computed(() => omit(props, ['color']))
 const btnClass = computed(
   () => `${btnThemeClass[props.color] || `before:bg-[--color] after:bg-[--color]`}`,
 )
-const height = computed(() => ({ lg: '2.75rem' })[props.size] || '2.75rem')
+const height = computed(() => ({ lg: '2.75rem', md: '2.1875rem' })[props.size] || '2.75rem')
 </script>
 <template>
   <button
     class="left-skew relative bg-transparent hover:bg-transparent h-[--evo-btn-height]!"
-    :class="`${btnClass}`"
+    :class="`${btnClass} ${{ md: 'pl-7! pr-3.5!' }[size] || ''}`"
     :style="{ '--color': color, '--evo-btn-height': height }"
     :block="block"
   >
-    <div class="w-full h-full flex items-center justify-center relative z-1 c-white">
+    <div
+      class="w-full h-full flex items-center justify-center relative z-1 c-white"
+      :class="`${{ md: 'text-sm' }[size] || ''}`"
+    >
       <slot></slot>
     </div>
   </button>

+ 39 - 45
packages/app/src/components/hot-activity-item.vue

@@ -1,5 +1,13 @@
 <script lang="ts" setup>
+import dayjs from 'dayjs'
+import { Activity, StudyTour } from '../core/libs/models'
 import TiltedButton from './tilted-button.vue'
+import ActivityCountDown from '@/pages/home/components/activity-count-down.vue'
+import ButtonEvo from './button-evo.vue'
+import { useRouter } from '../core/utils/router'
+
+withDefaults(defineProps<{ options?: StudyTour | Activity; type?: 'studyTour' | 'activity' }>(), {})
+const router = useRouter()
 </script>
 <template>
   <view class="relative w-full box-border">
@@ -16,30 +24,38 @@ import TiltedButton from './tilted-button.vue'
     </view>
     <view class="absolute left-0 right-0 top-1 bottom-6 z-1 p-3.5">
       <view class="w-full h-full flex flex-col justify-between">
-        <wd-img
-          custom-class="ms-1.5"
-          src="/static/svgs/unnamed.svg"
-          width="105px"
-          mode="widthFix"
-        ></wd-img>
+        <div class="flex justify-between">
+          <wd-img
+            custom-class="ms-1.5"
+            src="/static/svgs/unnamed.svg"
+            width="105px"
+            mode="widthFix"
+          ></wd-img>
+          <div></div>
+        </div>
+
         <!-- <view class="flex"></view> -->
         <div class="w-[321px] h-[88px] relative">
           <div class="w-[94px] h-3 left-[185px] top-[64px] absolute">
             <div
-              class="left-0 top-0 absolute text-black/40 text-sm font-normal font-['PingFang_SC'] leading-[34px]"
+              class="left-0 top-0 absolute text-black/40 text-sm font-normal font-['PingFang_SC'] leading-[34px] flex items-center"
             >
-              07.15 08.10
+              <!-- 07.15 08.10 -->
+              {{ dayjs(options?.studyStartTime || options?.planStudyStartTime).format('MM.DD') }}
+              <wd-icon name="play" size="22px"></wd-icon>
+              {{ dayjs(options?.studyEndTime || options?.planStudyEndTime).format('MM.DD') }}
             </div>
           </div>
           <wd-img
             custom-class="w-[110px] h-[88px] left-0 top-0 absolute rounded-[10px] overflow-hidden vertical-bottom"
-            src="https://via.placeholder.com/110x88"
+            :src="options?.thumbnailUrl"
             mode="scaleToFill"
           />
           <div
             class="w-[202px] left-[119px] top-0 absolute text-black text-base font-normal font-['PingFang_SC'] leading-relaxed"
           >
-            活动预告 | 日本研学·东京艺术大学设计游学
+            <!-- 活动预告 | 日本研学·东京艺术大学设计游学 -->
+            {{ options?.name }}
           </div>
           <div
             class="left-[119px] top-[64px] absolute text-black/40 text-sm font-normal font-['PingFang_SC'] leading-[34px]"
@@ -48,42 +64,20 @@ import TiltedButton from './tilted-button.vue'
           </div>
         </div>
         <view class="flex items-center justify-between mb-1.5">
-          <view
-            class="flex items-center text-black/40 text-sm font-normal font-['PingFang_SC'] leading-[34px]"
-          >
-            距结束还剩
-            <view
-              class="w-4 h-4 bg-black/90 rounded flex-col justify-center items-center gap-2.5 inline-flex mx-1.5"
-            >
-              <view
-                class="text-white text-[10px] font-normal font-['PingFang_SC'] leading-[10.18px]"
-              >
-                05
-              </view>
-            </view>
-            天
-            <div
-              class="w-4 h-4 bg-black/90 rounded flex-col justify-center items-center gap-2.5 inline-flex mx-1.5"
+          <ActivityCountDown
+            :start-at="options?.applyStartTime"
+            :end-at="options?.applyEndTime"
+          ></ActivityCountDown>
+          <div>
+            <ButtonEvo
+              size="md"
+              @click="
+                router.push(`/pages/home/activity/detail/index?id=${options?.id}&type=${type}`)
+              "
             >
-              <div
-                class="text-white text-[10px] font-normal font-['PingFang_SC'] leading-[10.18px]"
-              >
-                05
-              </div>
-            </div>
-            时
-            <div
-              class="w-4 h-4 bg-black/90 rounded flex-col justify-center items-center gap-2.5 inline-flex mx-1.5"
-            >
-              <div
-                class="text-white text-[10px] font-normal font-['PingFang_SC'] leading-[10.18px]"
-              >
-                05
-              </div>
-            </div>
-            分
-          </view>
-          <tilted-button>立即报名</tilted-button>
+              立即报名
+            </ButtonEvo>
+          </div>
         </view>
       </view>
     </view>

+ 13 - 3
packages/app/src/components/hot-activity.vue

@@ -1,9 +1,11 @@
 <script lang="ts" setup>
 import HotActivityItem from './hot-activity-item.vue'
 
+withDefaults(defineProps<{ items?: any[] }>(), { items: () => [] })
 const swiperList = [{}]
 const item = ref()
 
+const current = ref(0)
 onMounted(() => {
   console.log('mounted')
   nextTick(() => {
@@ -13,10 +15,18 @@ onMounted(() => {
 })
 </script>
 <template>
-  <swiper class="h-60">
-    <template v-for="it of swiperList" :key="it.id">
+  <swiper class="h-60" @change="(e) => (current = e.detail.current)">
+    <template v-for="it of items" :key="it.id">
       <swiper-item class="h-60">
-        <HotActivityItem ref="item"></HotActivityItem>
+        <HotActivityItem ref="item" :options="it.data" :type="it.type"></HotActivityItem>
+        <div class="absolute top-5 right-4 flex gap-1">
+          <template v-for="(it, i) in items" :key="i">
+            <div
+              class="w-1 h-1 rounded-full"
+              :class="`${current === i ? 'bg-white' : 'bg-white/40'}`"
+            ></div>
+          </template>
+        </div>
       </swiper-item>
     </template>
   </swiper>

+ 8 - 0
packages/app/src/components/moment-item.vue

@@ -10,6 +10,7 @@ import { likeActived, likeBlack } from '@designer-hub/assets/src/icons'
 import { NetImages } from '../core/libs/net-images'
 import { currRoute } from '../utils'
 import { usePermissions } from '../composables/permissions'
+import { levelsByLevel } from '@/core/libs/levels'
 
 const props = withDefaults(
   defineProps<{
@@ -97,6 +98,13 @@ onMounted(async () => {
           />
         </view>
         <view class="">{{ props.options.stylistName }}</view>
+        <div v-if="levelsByLevel[options?.member?.level]?.badge">
+          <wd-img
+            width="63"
+            height="18.6"
+            :src="levelsByLevel[options?.member?.level]?.badge"
+          ></wd-img>
+        </div>
         <view class="flex-1"></view>
         <view>{{ beforeNow(dayjs(props.options.createTime).toDate()) }}</view>
       </view>

+ 2 - 0
packages/app/src/components/page-helper-evo.vue

@@ -0,0 +1,2 @@
+<script setup lang="ts"></script>
+<template><div></div></template>

+ 6 - 0
packages/app/src/core/libs/levels.ts

@@ -1,4 +1,7 @@
 import { group } from 'radash'
+import memberSilver from '@designer-hub/assets/src/libs/assets/memberSilver'
+import memberGold from '@designer-hub/assets/src/libs/assets/memberGold'
+import memberPlatinum from '@designer-hub/assets/src/libs/assets/memberPlatinum'
 
 export const levels = [
   {
@@ -8,16 +11,19 @@ export const levels = [
   },
   {
     level: 2,
+    badge: memberSilver,
     bgImg:
       'https://image.zhuchaohui.com/zhucaohui/77b6712b1cab7e769b630010be01eceec6cdd27f6947777b5a805e3cbf077db4.png',
   },
   {
     level: 3,
+    badge: memberGold,
     bgImg:
       'https://image.zhuchaohui.com/zhucaohui/60811dfd5c5a4fa7502cfc2ff3db188849d4f9363849420ba72e32c03f20eca5.png',
   },
   {
     level: 4,
+    badge: memberPlatinum,
     bgImg:
       'https://image.zhuchaohui.com/zhucaohui/77b6712b1cab7e769b630010be01eceec6cdd27f6947777b5a805e3cbf077db4.png',
   },

+ 2 - 3
packages/app/src/pages/home/activity/detail/index.vue

@@ -305,9 +305,8 @@ onLoad(async (query: { id: string; type: 'activity' | 'studyTour' }) => {
       <div
         v-if="tab === 0"
         class="text-justify text-[#c1c1c1] text-base font-normal font-['PingFang_SC'] leading-relaxed"
-      >
-        {{ data['activityDesc'] }}
-      </div>
+        v-html="data['activityDesc']"
+      ></div>
       <div v-if="tab === 1 && 'studyTravelList' in data">
         <template v-for="(it, i) in data.studyTravelList" :key="i">
           <div class="flex flex-col gap-6">

+ 7 - 4
packages/app/src/pages/home/components/register-card.vue

@@ -3,7 +3,7 @@ import Card from '@/components/card.vue'
 import { Activity, DictType, StudyTour } from '../../../core/libs/models'
 import dayjs from 'dayjs'
 import TiltedButton from '@/components/tilted-button.vue'
-import { getActivitySignups, getByDictType } from '../../../core/libs/requests'
+import { getActivitySignups } from '../../../core/libs/requests'
 import { NetImages } from '../../../core/libs/net-images'
 import { useRouter } from '../../../core/utils/router'
 import { getActivityStatusButtonText, getActivityStatusText } from '../../../core/utils/common'
@@ -17,7 +17,6 @@ const { data: signups, run: setSignups } = useRequest(
   () => getActivitySignups({ activityId: props.options!.id.toString() }),
   { initialData: { list: [], total: 0 } },
 )
-// const {} = useRequest(() => getByDictType(DictType))
 onMounted(async () => {
   await setSignups()
 })
@@ -60,7 +59,7 @@ onMounted(async () => {
           </div>
           <view class="flex items-center">
             <div class="text-white/60 text-sm font-normal font-['PingFang_SC'] leading-[34px]">
-              游学时间:
+              活动时间:
             </div>
             <div
               class="text-white/60 text-base font-normal font-['PingFang_SC'] leading-[34px] flex items-center gap-1"
@@ -77,7 +76,11 @@ onMounted(async () => {
           <div
             class="text-justify text-white/60 text-sm font-normal font-['PingFang_SC'] leading-relaxed"
           >
-            等级限制:{{ options?.memberLevel }}
+            等级限制:{{
+              options?.memberLevel
+                ?.map((it) => options?.levelsByMemberLevel[String(it)]?.memberLevelName)
+                ?.join('、')
+            }}
           </div>
           <view class="flex items-center justify-between">
             <view class="flex items-end">

+ 25 - 11
packages/app/src/pages/home/index.vue

@@ -17,9 +17,11 @@ import HomeBanner from './components/home-banner.vue'
 import useRequest from '../../hooks/useRequest'
 import Menus from './components/menus.vue'
 import {
+  getActivities,
   getCircles,
   getMyStudyTours,
   getSetIndexConfigs,
+  getStudyTours,
   shareCircle,
 } from '../../core/libs/requests'
 import { logo } from '../../core/libs/svgs'
@@ -36,6 +38,8 @@ import ButtonEvo from '@/components/button-evo.vue'
 import ImgBtnEvo from '@/components/img-btn-evo.vue'
 import SectionHeading from '@/components/section-heading.vue'
 import dayjs from 'dayjs'
+import { sort } from 'radash'
+import { Activity, StudyTour } from '../../core/libs/models'
 
 defineOptions({
   name: 'Home',
@@ -51,8 +55,11 @@ const { data: indexConfigsData, run: setIndexConfigsData } = useRequest(
 const { data: studyTours, run: setStudyTours } = useRequest(() => getMyStudyTours(), {
   initialData: [],
 })
+// const {} = useRequest(() =>)
 const swiperData = ref<{ data: any }[]>()
 const swiperCurrent = ref(0)
+const hotActivities =
+  ref<{ type: 'studyTour' | 'activity'; data: StudyTour & Activity; startAt: string | number }[]>()
 const currentStudyTour = computed(() =>
   studyTours.value.find(
     (it) => dayjs(it.studyStartTime).isBefore(dayjs()) && dayjs(it.studyEndTime).isAfter(dayjs()),
@@ -73,20 +80,27 @@ const handleLike = async (options) => {
   })
   pageHelperRef.value?.refresh()
 }
+const setHotActivities = async () => {
+  const res = await Promise.all([
+    getStudyTours({ headRecommend: 1 }).then((res) =>
+      res.data.list.map((it) => ({ type: 'studyTour', data: it, startAt: it.applyStartTime })),
+    ),
+    getActivities({ headRecommend: 1 }).then((res) =>
+      res.data.list.map((it) => ({ type: 'activity', data: it, startAt: it.applyStartTime })),
+    ),
+  ])
+  console.log(sort(res.flat(), (it) => it.startAt))
+  hotActivities.value = sort(res.flat(), (it) => it.startAt) as any
+}
 onShow(async () => {
   pageHelperRef.value?.refresh()
   // await setStudyTours()
   // setStudyTours()
 })
 onLoad(async () => {
-  await setIndexConfigsData()
-  await setStudyTours()
-  console.log(
-    studyTours.value.map((it) => [
-      dayjs(it.studyStartTime).format('YYYY-MM-DD HH:mm'),
-      dayjs(it.studyEndTime).format('YYYY-MM-DD HH:mm'),
-    ]),
-  )
+  await Promise.all([setIndexConfigsData(), setStudyTours(), setHotActivities()])
+  // await setIndexConfigsData()
+  // await setStudyTours()
   swiperData.value = indexConfigsData.value.list.map((it) => ({
     data: it,
   }))
@@ -178,9 +192,9 @@ onShareAppMessage(async ({ from, target }) => {
         <ButtonEvo color="red" size="lg">敌无命</ButtonEvo>
       </div> -->
       <menus></menus>
-      <!-- <view class="my-6 mx-3.5">
-        <HotActivity></HotActivity>
-      </view> -->
+      <view class="my-6 mx-3.5">
+        <HotActivity :items="hotActivities"></HotActivity>
+      </view>
       <view v-if="features.about" class="my-6 mx-3.5" @click="toAbout()">
         <Card>
           <div class="flex items-center gap-2">

+ 28 - 12
packages/app/src/pages/home/offline-activity/index.vue

@@ -11,7 +11,12 @@
 import SectionHeading from '@/components/section-heading.vue'
 import Card from '@/components/card.vue'
 import OfflineActivityItem from '../components/offline-activity-item.vue'
-import { getAllCategories, getContents, getActivities } from '../../../core/libs/requests'
+import {
+  getAllCategories,
+  getContents,
+  getActivities,
+  getAppMemberLevelConfigs,
+} from '../../../core/libs/requests'
 import { strip, leaderboardText } from '@designer-hub/assets/src/assets/svgs'
 import { NetImages } from '../../../core/libs/net-images'
 import RegisterCard from '../components/register-card.vue'
@@ -32,6 +37,21 @@ const { data, run: setData } = useRequest(
     initialData: { list: [] },
   },
 )
+const { data: activities, run: setActivities } = useRequest(
+  () => getActivities({ headRecommend: 1 }),
+  {
+    initialData: { list: [] },
+  },
+)
+const { data: levels, run: setLevels } = useRequest(() => getAppMemberLevelConfigs(), {
+  initialData: [],
+})
+const levelsByMemberLevel = computed(() =>
+  levels.value.reduce((acc, item) => {
+    acc[item.memberLevel] = item
+    return acc
+  }, {}),
+)
 const setContentCategory = (index) => {
   contentCategory.value = categories.value.find(({ id }) => id === 2)?.children[index].id.toString()
 }
@@ -42,7 +62,7 @@ const handleTabChange = ({ index }) => {
 onMounted(async () => {
   await setCategories()
   setContentCategory(tab.value)
-  await setData()
+  await Promise.all([setActivities(), setData(), setLevels()])
 })
 </script>
 
@@ -54,17 +74,13 @@ onMounted(async () => {
       path="/pages/home/offline-activity/list/index"
       end-text="查看全部"
     ></section-heading>
-    <PageHelper :request="getActivities" :query="{ headRecommend: 1 }">
-      <template #default="{ source }">
-        <swiper class="aspect-[0.75/1] rounded-[20px] overflow-hidden">
-          <template v-for="(it, i) in source.list" :key="i">
-            <swiper-item>
-              <RegisterCard :options="it"></RegisterCard>
-            </swiper-item>
-          </template>
-        </swiper>
+    <swiper class="aspect-[0.75/1] rounded-[20px] overflow-hidden">
+      <template v-for="(it, i) in activities.list" :key="i">
+        <swiper-item>
+          <RegisterCard :options="{ ...it, levelsByMemberLevel }"></RegisterCard>
+        </swiper-item>
       </template>
-    </PageHelper>
+    </swiper>
     <card custom-class="">
       <div class="my-7.5 text-black text-xl font-normal font-['PingFang_SC'] leading-[10.18px]">
         筑巢荟-活动营

+ 2 - 2
packages/app/src/pages/home/schedule/index.vue

@@ -28,7 +28,7 @@ const currentStudyTour = computed(() =>
   ),
 )
 const schedules = computed(() =>
-  group(currentStudyTour.value.studyTravelDOList, (it) =>
+  group(currentStudyTour.value?.studyTravelDOList, (it) =>
     dayjs(it?.travelTime).format('YYYY-MM-DD'),
   ),
 )
@@ -140,7 +140,7 @@ onMounted(() => {
         </template>
       </template>
     </view>
-    <BottomAppBar fixed>
+    <BottomAppBar fixed placeholder>
       <div
         class="p-3.5 bg-white/90 rounded-2xl backdrop-blur-[20px] bottom-4 left-0 right-0 flex items-center justify-between gap-1"
       >

+ 1 - 2
packages/app/src/pages/home/study-tour/index.vue

@@ -66,8 +66,7 @@ onMounted(async () => {
         </div>
       </template>
     </div>
-    <!-- <PageHelper :request="getActivities" :query="{ headRecommend: 1 }">
-      <template #default="{ source }"> -->
+
     <template v-if="studyTours.list.length">
       <swiper class="aspect-[0.75/1] rounded-[20px] overflow-hidden">
         <template v-for="(it, i) in studyTours.list" :key="i">

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 13 - 0
packages/assets/src/assets/member-gold.svg


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 13 - 0
packages/assets/src/assets/member-platinum.svg


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 13 - 0
packages/assets/src/assets/member-silver.svg


+ 2 - 0
packages/assets/src/libs/assets/memberGold.ts

@@ -0,0 +1,2 @@
+import memberGold from '../../assets/member-gold.svg' 
+ export default memberGold

+ 2 - 0
packages/assets/src/libs/assets/memberPlatinum.ts

@@ -0,0 +1,2 @@
+import memberPlatinum from '../../assets/member-platinum.svg' 
+ export default memberPlatinum

+ 2 - 0
packages/assets/src/libs/assets/memberSilver.ts

@@ -0,0 +1,2 @@
+import memberSilver from '../../assets/member-silver.svg' 
+ export default memberSilver

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů