diff --git a/package-lock.json b/package-lock.json index 1b542ec..8dc8f55 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,11 +10,12 @@ "dependencies": { "@tailwindcss/vite": "^4.1.18", "@vee-validate/zod": "^4.15.1", - "@vueuse/core": "^14.1.0", + "@vueuse/core": "^14.2.0", "axios": "^1.13.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "crypto-js": "^4.2.0", + "embla-carousel-vue": "^8.6.0", "lucide-vue-next": "^0.562.0", "reka-ui": "^2.8.0", "tailwind-merge": "^3.4.0", @@ -2370,14 +2371,14 @@ } }, "node_modules/@vueuse/core": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.1.0.tgz", - "integrity": "sha512-rgBinKs07hAYyPF834mDTigH7BtPqvZ3Pryuzt1SD/lg5wEcWqvwzXXYGEDb2/cP0Sj5zSvHl3WkmMELr5kfWw==", + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.2.0.tgz", + "integrity": "sha512-tpjzVl7KCQNVd/qcaCE9XbejL38V6KJAEq/tVXj7mDPtl6JtzmUdnXelSS+ULRkkrDgzYVK7EerQJvd2jR794Q==", "license": "MIT", "dependencies": { "@types/web-bluetooth": "^0.0.21", - "@vueuse/metadata": "14.1.0", - "@vueuse/shared": "14.1.0" + "@vueuse/metadata": "14.2.0", + "@vueuse/shared": "14.2.0" }, "funding": { "url": "https://github.com/sponsors/antfu" @@ -2387,14 +2388,18 @@ } }, "node_modules/@vueuse/metadata": { - "version": "14.1.0", + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-14.2.0.tgz", + "integrity": "sha512-i3axTGjU8b13FtyR4Keeama+43iD+BwX9C2TmzBVKqjSHArF03hjkp2SBZ1m72Jk2UtrX0aYCugBq2R1fhkuAQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/@vueuse/shared": { - "version": "14.1.0", + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-14.2.0.tgz", + "integrity": "sha512-Z0bmluZTlAXgUcJ4uAFaML16JcD8V0QG00Db3quR642I99JXIDRa2MI2LGxiLVhcBjVnL1jOzIvT5TT2lqJlkA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/antfu" @@ -2966,6 +2971,35 @@ "dev": true, "license": "ISC" }, + "node_modules/embla-carousel": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", + "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==", + "license": "MIT", + "peer": true + }, + "node_modules/embla-carousel-reactive-utils": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-reactive-utils/-/embla-carousel-reactive-utils-8.6.0.tgz", + "integrity": "sha512-fMVUDUEx0/uIEDM0Mz3dHznDhfX+znCCDCeIophYb1QGVM7YThSWX+wz11zlYwWFOr74b4QLGg0hrGPJeG2s4A==", + "license": "MIT", + "peerDependencies": { + "embla-carousel": "8.6.0" + } + }, + "node_modules/embla-carousel-vue": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-vue/-/embla-carousel-vue-8.6.0.tgz", + "integrity": "sha512-v8UO5UsyLocZnu/LbfQA7Dn2QHuZKurJY93VUmZYP//QRWoCWOsionmvLLAlibkET3pGPs7++03VhJKbWD7vhQ==", + "license": "MIT", + "dependencies": { + "embla-carousel": "8.6.0", + "embla-carousel-reactive-utils": "8.6.0" + }, + "peerDependencies": { + "vue": "^3.2.37" + } + }, "node_modules/enhanced-resolve": { "version": "5.18.4", "license": "MIT", diff --git a/package.json b/package.json index c0dc655..6847a6f 100644 --- a/package.json +++ b/package.json @@ -18,11 +18,12 @@ "dependencies": { "@tailwindcss/vite": "^4.1.18", "@vee-validate/zod": "^4.15.1", - "@vueuse/core": "^14.1.0", + "@vueuse/core": "^14.2.0", "axios": "^1.13.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "crypto-js": "^4.2.0", + "embla-carousel-vue": "^8.6.0", "lucide-vue-next": "^0.562.0", "reka-ui": "^2.8.0", "tailwind-merge": "^3.4.0", diff --git a/public/fast-video.MP4 b/public/fast-video.MP4 new file mode 100644 index 0000000..ff2af2b Binary files /dev/null and b/public/fast-video.MP4 differ diff --git a/src/components/ui/button/index.ts b/src/components/ui/button/index.ts index 5262d70..26e2c55 100644 --- a/src/components/ui/button/index.ts +++ b/src/components/ui/button/index.ts @@ -1,34 +1,37 @@ -import type { VariantProps } from 'class-variance-authority' -import { cva } from 'class-variance-authority' +import type { VariantProps } from "class-variance-authority" +import { cva } from "class-variance-authority" -export { default as Button } from './Button.vue' +export { default as Button } from "./Button.vue" export const buttonVariants = cva( - "inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", { variants: { variant: { - default: 'bg-primary text-primary-foreground hover:bg-primary/90', + default: + "bg-primary text-primary-foreground hover:bg-primary/90", destructive: - 'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60', + "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", outline: - 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50', - secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80', - ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50', - link: 'text-primary underline-offset-4 hover:underline', + "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: + "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", + link: "text-primary underline-offset-4 hover:underline", }, size: { - default: 'h-9 px-4 py-2 has-[>svg]:px-3', - sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5', - lg: 'h-10 rounded-md px-6 has-[>svg]:px-4', - icon: 'size-9', - 'icon-sm': 'size-8', - 'icon-lg': 'size-10', + "default": "h-9 px-4 py-2 has-[>svg]:px-3", + "sm": "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", + "lg": "h-10 rounded-md px-6 has-[>svg]:px-4", + "icon": "size-9", + "icon-sm": "size-8", + "icon-lg": "size-10", }, }, defaultVariants: { - variant: 'default', - size: 'default', + variant: "default", + size: "default", }, }, ) diff --git a/src/components/ui/carousel/Carousel.vue b/src/components/ui/carousel/Carousel.vue new file mode 100644 index 0000000..4575682 --- /dev/null +++ b/src/components/ui/carousel/Carousel.vue @@ -0,0 +1,53 @@ + + + diff --git a/src/components/ui/carousel/CarouselContent.vue b/src/components/ui/carousel/CarouselContent.vue new file mode 100644 index 0000000..bd3db7e --- /dev/null +++ b/src/components/ui/carousel/CarouselContent.vue @@ -0,0 +1,33 @@ + + + diff --git a/src/components/ui/carousel/CarouselItem.vue b/src/components/ui/carousel/CarouselItem.vue new file mode 100644 index 0000000..39df4c6 --- /dev/null +++ b/src/components/ui/carousel/CarouselItem.vue @@ -0,0 +1,24 @@ + + + diff --git a/src/components/ui/carousel/CarouselNext.vue b/src/components/ui/carousel/CarouselNext.vue new file mode 100644 index 0000000..242374f --- /dev/null +++ b/src/components/ui/carousel/CarouselNext.vue @@ -0,0 +1,29 @@ + + + diff --git a/src/components/ui/carousel/CarouselPrevious.vue b/src/components/ui/carousel/CarouselPrevious.vue new file mode 100644 index 0000000..1ce8425 --- /dev/null +++ b/src/components/ui/carousel/CarouselPrevious.vue @@ -0,0 +1,29 @@ + + + diff --git a/src/components/ui/carousel/index.ts b/src/components/ui/carousel/index.ts new file mode 100644 index 0000000..154bfcb --- /dev/null +++ b/src/components/ui/carousel/index.ts @@ -0,0 +1,10 @@ +export { default as Carousel } from "./Carousel.vue" +export { default as CarouselContent } from "./CarouselContent.vue" +export { default as CarouselItem } from "./CarouselItem.vue" +export { default as CarouselNext } from "./CarouselNext.vue" +export { default as CarouselPrevious } from "./CarouselPrevious.vue" +export type { + UnwrapRefCarouselApi as CarouselApi, +} from "./interface" + +export { useCarousel } from "./useCarousel" diff --git a/src/components/ui/carousel/interface.ts b/src/components/ui/carousel/interface.ts new file mode 100644 index 0000000..74eaf36 --- /dev/null +++ b/src/components/ui/carousel/interface.ts @@ -0,0 +1,26 @@ +import type useEmblaCarousel from "embla-carousel-vue" +import type { + EmblaCarouselVueType, +} from "embla-carousel-vue" +import type { HTMLAttributes, UnwrapRef } from "vue" + +type CarouselApi = EmblaCarouselVueType[1] +type UseCarouselParameters = Parameters +type CarouselOptions = UseCarouselParameters[0] +type CarouselPlugin = UseCarouselParameters[1] + +export type UnwrapRefCarouselApi = UnwrapRef + +export interface CarouselProps { + opts?: CarouselOptions + plugins?: CarouselPlugin + orientation?: "horizontal" | "vertical" +} + +export interface CarouselEmits { + (e: "init-api", payload: UnwrapRefCarouselApi): void +} + +export interface WithClassAsProps { + class?: HTMLAttributes["class"] +} diff --git a/src/components/ui/carousel/useCarousel.ts b/src/components/ui/carousel/useCarousel.ts new file mode 100644 index 0000000..32e35ca --- /dev/null +++ b/src/components/ui/carousel/useCarousel.ts @@ -0,0 +1,56 @@ +import type { UnwrapRefCarouselApi as CarouselApi, CarouselEmits, CarouselProps } from "./interface" +import { createInjectionState } from "@vueuse/core" +import emblaCarouselVue from "embla-carousel-vue" +import { onMounted, ref } from "vue" + +const [useProvideCarousel, useInjectCarousel] = createInjectionState( + ({ + opts, + orientation, + plugins, + }: CarouselProps, emits: CarouselEmits) => { + const [emblaNode, emblaApi] = emblaCarouselVue({ + ...opts, + axis: orientation === "horizontal" ? "x" : "y", + }, plugins) + + function scrollPrev() { + emblaApi.value?.scrollPrev() + } + function scrollNext() { + emblaApi.value?.scrollNext() + } + + const canScrollNext = ref(false) + const canScrollPrev = ref(false) + + function onSelect(api: CarouselApi) { + canScrollNext.value = api?.canScrollNext() || false + canScrollPrev.value = api?.canScrollPrev() || false + } + + onMounted(() => { + if (!emblaApi.value) + return + + emblaApi.value?.on("init", onSelect) + emblaApi.value?.on("reInit", onSelect) + emblaApi.value?.on("select", onSelect) + + emits("init-api", emblaApi.value) + }) + + return { carouselRef: emblaNode, carouselApi: emblaApi, canScrollPrev, canScrollNext, scrollPrev, scrollNext, orientation } + }, +) + +function useCarousel() { + const carouselState = useInjectCarousel() + + if (!carouselState) + throw new Error("useCarousel must be used within a ") + + return carouselState +} + +export { useCarousel, useProvideCarousel } diff --git a/src/pages/Home/index.vue b/src/pages/Home/index.vue index d05b120..a230ed3 100644 --- a/src/pages/Home/index.vue +++ b/src/pages/Home/index.vue @@ -37,8 +37,8 @@
- -
+ +

@@ -49,6 +49,11 @@

+
+
+ +
+ 邀请规则
@@ -71,7 +76,22 @@
给您的客户提供专业视角的建议
-
+ +
+ + + + + +
+ + +
@@ -97,6 +117,13 @@ import { useLocalStorage } from '@vueuse/core' import LoginFormModal from './components/LoginFormModal.vue' import Logo from './logo.svg?component' import Group215Icon from './modules3/Group 215.svg?component' +import { + Carousel, + CarouselContent, + CarouselItem, + CarouselNext, + CarouselPrevious, +} from '@/components/ui/carousel' import request from '@/utils/request' import Frame98 from './modules2/Frame 98.png' import Frame99 from './modules2/Frame 99.png' @@ -105,7 +132,15 @@ import Frame101 from './modules2/Frame 101.png' import Frame104 from './modules2/Frame 104.png' import Frame105 from './modules2/Frame 105.png' +import image1 from './modules4/image1.png' +import image2 from './modules4/image2.png' +import image3 from './modules4/image3.png' +import image4 from './modules4/image4.png' +import image5 from './modules4/image5.png' +import image6 from './modules4/image6.png' + const modules2Image = [Frame98, Frame99, Frame100, Frame101, Frame104, Frame105] +const modules4Images = [image1, image2, image3, image4, image5, image6] const route = useRoute() const router = useRouter() diff --git a/src/pages/Home/modules1/Group 235.png b/src/pages/Home/modules1/Group 235.png new file mode 100644 index 0000000..243ace0 Binary files /dev/null and b/src/pages/Home/modules1/Group 235.png differ diff --git a/src/pages/Home/modules1/Group-236.png b/src/pages/Home/modules1/Group-236.png new file mode 100644 index 0000000..86b57b3 Binary files /dev/null and b/src/pages/Home/modules1/Group-236.png differ diff --git a/src/pages/Home/modules4/arrow.svg b/src/pages/Home/modules4/arrow.svg new file mode 100644 index 0000000..9afae9e --- /dev/null +++ b/src/pages/Home/modules4/arrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/pages/Home/modules4/image1.png b/src/pages/Home/modules4/image1.png new file mode 100644 index 0000000..5564a57 Binary files /dev/null and b/src/pages/Home/modules4/image1.png differ diff --git a/src/pages/Home/modules4/image2.png b/src/pages/Home/modules4/image2.png new file mode 100644 index 0000000..4a20a5c Binary files /dev/null and b/src/pages/Home/modules4/image2.png differ diff --git a/src/pages/Home/modules4/image3.png b/src/pages/Home/modules4/image3.png new file mode 100644 index 0000000..24d4619 Binary files /dev/null and b/src/pages/Home/modules4/image3.png differ diff --git a/src/pages/Home/modules4/image4.png b/src/pages/Home/modules4/image4.png new file mode 100644 index 0000000..304abdf Binary files /dev/null and b/src/pages/Home/modules4/image4.png differ diff --git a/src/pages/Home/modules4/image5.png b/src/pages/Home/modules4/image5.png new file mode 100644 index 0000000..c786d07 Binary files /dev/null and b/src/pages/Home/modules4/image5.png differ diff --git a/src/pages/Home/modules4/image6.png b/src/pages/Home/modules4/image6.png new file mode 100644 index 0000000..6184a09 Binary files /dev/null and b/src/pages/Home/modules4/image6.png differ