product/beenFactory

This commit is contained in:
WindowBird 2025-10-23 17:23:26 +08:00
parent 3884974e68
commit b8dbf781e8
24 changed files with 139 additions and 347 deletions

View File

@ -24,6 +24,9 @@ export default defineAppConfig({
}
}
}
},
colors: {
primary: 'brand',
}
}
})

View File

@ -1,6 +1,20 @@
@import "tailwindcss";
@import "@nuxt/ui";
@theme static {
--color-brand-50: #EFFDF5;
--color-brand-100: #D9FBE8;
--color-brand-200: #B3F5D1;
--color-brand-300: #75EDAE;
--color-brand-400: #00DC82;
--color-brand-500: #00A666;
--color-brand-600: #00A666;
--color-brand-700: #007F45;
--color-brand-800: #016538;
--color-brand-900: #0A5331;
--color-brand-950: #052E16;
}
/*:root {*/
/* --ui-container: var(--container-4xl);*/

View File

@ -4,13 +4,9 @@ import type {NavigationMenuItem} from '@nuxt/ui'
const items: NavigationMenuItem[] = [
{
label: '电话:15280659990',
},
{
label: '邮箱:564737095@qq.com',
},
{
label: '地址:福建省福鼎市太姥山镇海埕路13号',

View File

@ -7,14 +7,14 @@ const items = computed<NavigationMenuItem[]>(() => [{
label: '首页',
to: '/',
icon: 'i-lucide-book-open',
active: route.path.startsWith('/')
// active: route.path.startsWith('')
}, {
label: '产品与服务',
icon: 'i-lucide-box',
active: route.path.startsWith('/docs/components'),
active: route.path.startsWith('/product'),
children: [
{label: '智慧蜂场建设', to: '/hive'},
{label: '智慧蜂场建设', to: '/product/beenfactory'},
{label: '智能蜂箱研制', to: '/hive'},
{label: '质量安全溯源', to: '/hive'},
{label: '蜂产业大数据', to: '/sensors'},

View File

@ -1,76 +0,0 @@
<script setup lang="ts">
const colorMode = useColorMode()
const nextTheme = computed(() => (colorMode.value === 'dark' ? 'light' : 'dark'))
const switchTheme = () => {
colorMode.preference = nextTheme.value
}
const startViewTransition = (event: MouseEvent) => {
if (!document.startViewTransition) {
switchTheme()
return
}
const x = event.clientX
const y = event.clientY
const endRadius = Math.hypot(
Math.max(x, window.innerWidth - x),
Math.max(y, window.innerHeight - y)
)
const transition = document.startViewTransition(() => {
switchTheme()
})
transition.ready.then(() => {
const duration = 600
document.documentElement.animate(
{
clipPath: [
`circle(0px at ${x}px ${y}px)`,
`circle(${endRadius}px at ${x}px ${y}px)`
]
},
{
duration: duration,
easing: 'cubic-bezier(.76,.32,.29,.99)',
pseudoElement: '::view-transition-new(root)'
}
)
})
}
</script>
<template>
<ClientOnly>
<UButton
:aria-label="`Switch to ${nextTheme} mode`"
:icon="`i-lucide-${nextTheme === 'dark' ? 'sun' : 'moon'}`"
color="neutral"
variant="ghost"
size="sm"
class="rounded-full"
@click="startViewTransition"
/>
<template #fallback>
<div class="size-4" />
</template>
</ClientOnly>
</template>
<style>
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
::view-transition-new(root) {
z-index: 9999;
}
::view-transition-old(root) {
z-index: 1;
}
</style>

View File

@ -1,28 +0,0 @@
<script setup lang="ts">
defineProps<{
image: {
src: string
alt: string
}
index: number
}>()
</script>
<template>
<div
class="bg-white p-2 flex flex-col drop-shadow-2xl transition-transform duration-300 ease-in-out hover:scale-105 hover:rotate-0 hover:z-10"
:class="[
index % 2 === 0 ? '-rotate-5' : 'rotate-5',
index % 2 === 0 ? 'hover:-translate-x-4' : 'hover:translate-x-4'
]"
>
<img
:src="image.src"
:alt="image.alt"
class="size-32 object-cover"
>
<span class="w-32 text-xs text-black font-serif font-medium text-center mt-2">
{{ image.alt }}
</span>
</div>
</template>

View File

@ -0,0 +1,28 @@
<!-- components/TitleSection.vue -->
<template>
<view class="flex flex-col items-center">
<view class="text-sm mt-4 lg:mt-20 text-primary font-bold">
{{ subtitle }}
</view>
<view class="text-4xl my-6 font-bold">
{{ title }}
</view>
<view class="text-xl lg:mx-32 mx-6 mb-6 text-muted">
利用物联网人工智能等技术集成蜂箱数据采集硬件设备及数据管理系统协助养蜂人员远程实时获取监控蜂箱内部环境减少频繁开箱操作同时提供
预警功能辅助养殖决策推动从传统经验养蜂到智能化养蜂转型提高管理效率根据不同需求分为基础版标准版高级版三种产品
</view>
</view>
</template>
<script setup>
defineProps({
title: {
type: String,
default: '默认标题'
},
subtitle: {
type: String,
default: '默认副标题'
}
})
</script>

View File

@ -1,12 +1,13 @@
<!-- components/TitleSection.vue -->
<template>
<view class="flex flex-col items-center">
<view class="text-sm mt-4 lg:mt-32 text-primary font-bold">
<view class="text-sm mt-4 lg:mt-20 text-primary font-bold">
{{ subtitle }}
</view>
<view class="text-4xl my-6 font-bold">
{{ title }}
</view>
</view>
</template>

View File

@ -1,61 +0,0 @@
<script lang="ts" setup>
import type { IndexCollectionItem } from '@nuxt/content'
defineProps<{
page: IndexCollectionItem
}>()
const { data: posts } = await useAsyncData('index-blogs', () =>
queryCollection('blog').order('date', 'DESC').limit(3).all()
)
if (!posts.value) {
throw createError({ statusCode: 404, statusMessage: 'blogs posts not found', fatal: true })
}
</script>
<template>
<UPageSection
:description="page.blog.description"
:title="page.blog.title"
:ui="{
container: 'px-0 !pt-0 sm:gap-6 lg:gap-8',
title: 'text-left text-xl sm:text-xl lg:text-2xl font-medium',
description: 'text-left mt-2 text-sm sm:text-md lg:text-sm text-muted'
}"
>
<UBlogPosts
class="gap-4 lg:gap-y-4"
orientation="vertical"
>
<UBlogPost
v-for="(post, index) in posts"
:key="index"
:to="post.path"
:ui="{
root: 'group relative lg:items-start lg:flex ring-0 hover:ring-0',
body: '!px-0',
header: 'hidden'
}"
orientation="horizontal"
v-bind="post"
variant="naked"
>
<template #footer>
<UButton
class="px-0 gap-0"
label="Read Article"
size="xs"
variant="link"
>
<template #trailing>
<UIcon
class="size-4 text-primary transition-all opacity-0 group-hover:translate-x-1 group-hover:opacity-100"
name="i-lucide-arrow-right"
/>
</template>
</UButton>
</template>
</UBlogPost>
</UBlogPosts>
</UPageSection>
</template>

View File

@ -1,64 +0,0 @@
<script setup lang="ts">
import type { IndexCollectionItem } from '@nuxt/content'
const props = defineProps<{
page: IndexCollectionItem
}>()
const items = computed(() => {
return props.page.faq?.categories.map((faq) => {
return {
label: faq.title,
key: faq.title.toLowerCase(),
questions: faq.questions
}
})
})
const ui = {
root: 'flex items-center gap-4 w-full',
list: 'relative flex bg-transparent dark:bg-transparent gap-2 px-0',
indicator: 'absolute top-[4px] duration-200 ease-out focus:outline-none rounded-lg bg-elevated/60',
trigger: 'px-3 py-2 rounded-lg hover:bg-muted/50 data-[state=active]:text-highlighted data-[state=inactive]:text-muted',
label: 'truncate'
}
</script>
<template>
<UPageSection
:title="page.faq.title"
:description="page.faq.description"
:ui="{
container: 'px-0 !pt-0 gap-4 sm:gap-4',
title: 'text-left text-xl sm:text-xl lg:text-2xl font-medium',
description: 'text-left mt-2 text-sm sm:text-md lg:text-sm text-muted'
}"
>
<UTabs
:items
orientation="horizontal"
:ui
>
<template #content="{ item }">
<UAccordion
trailing-icon="lucide:plus"
:items="item.questions"
:unmount-on-hide="false"
:ui="{
item: 'border-none',
trigger: 'mb-2 border-0 group px-4 transform-gpu rounded-lg bg-elevated/60 will-change-transform hover:bg-muted/50 text-base',
trailingIcon: 'group-data-[state=closed]:rotate-0 group-data-[state=open]:rotate-135 text-base text-muted'
}"
>
<template #body="{ item: _item }">
<MDC
:value="_item.content"
unwrap="p"
class="px-4"
/>
</template>
</UAccordion>
</template>
</UTabs>
</UPageSection>
</template>

View File

@ -1,42 +0,0 @@
<script lang="ts" setup>
import type { IndexCollectionItem } from '@nuxt/content'
defineProps<{
page: IndexCollectionItem
}>()
</script>
<template>
<UPageSection
:ui="{
container: 'px-0 !pt-0'
}"
>
<UCarousel
v-slot="{ item }"
:autoplay="{ delay: 4000 }"
:items="page.testimonials"
:ui="{
viewport: '-mx-4 sm:-mx-12 lg:-mx-16 bg-elevated/50 max-w-(--ui-container)'
}"
dots
loop
>
<UPageCTA
:description="item.quote"
:ui="{
container: 'sm:py-12 lg:py-12 sm:gap-8',
description: '!text-base text-balance before:content-[open-quote] before:text-5xl lg:before:text-7xl before:inline-block before:text-dimmed before:absolute before:-ml-6 lg:before:-ml-10 before:-mt-2 lg:before:-mt-4 after:content-[close-quote] after:text-5xl lg:after:text-7xl after:inline-block after:text-dimmed after:absolute after:mt-1 lg:after:mt-0 after:ml-1 lg:after:ml-2'
}"
class="rounded-none"
variant="naked"
>
<UUser
class="justify-center"
size="xl"
v-bind="item.author"
/>
</UPageCTA>
</UCarousel>
</UPageSection>
</template>

View File

@ -1,57 +0,0 @@
<script setup lang="ts">
import type { IndexCollectionItem } from '@nuxt/content'
defineProps<{
page: IndexCollectionItem
}>()
</script>
<template>
<UPageSection
:title="page.experience.title"
:ui="{
container: '!p-0 gap-4 sm:gap-4',
title: 'text-left text-xl sm:text-xl lg:text-2xl font-medium',
description: 'mt-2'
}"
>
<template #description>
<div class="flex flex-col gap-2">
<Motion
v-for="(experience, index) in page.experience.items"
:key="index"
:initial="{ opacity: 0, transform: 'translateY(20px)' }"
:while-in-view="{ opacity: 1, transform: 'translateY(0)' }"
:transition="{ delay: 0.4 + 0.2 * index }"
:in-view-options="{ once: true }"
class="text-muted flex items-center text-nowrap gap-2"
>
<p class="text-sm">
{{ experience.date }}
</p>
<USeparator />
<ULink
class="flex items-center gap-1"
:to="experience.company.url"
target="_blank"
>
<span class="text-sm">
{{ experience.position }}
</span>
<div
class="inline-flex items-center gap-1"
:style="{ color: experience.company.color }"
>
<span class="font-medium">{{ experience.company.name }}</span>
<UIcon :name="experience.company.logo" />
</div>
</ULink>
</Motion>
</div>
</template>
</UPageSection>
</template>
<style scoped>
</style>

View File

@ -0,0 +1,65 @@
<script lang="ts" setup>
import TitleDescription from "~/components/TitleDescription.vue";
const cardItems = ref([
{
title: "蜂场环境气象监测站",
description: "为养蜂人员提供的一套蜂场整体环境数据实时获取、监测及软硬件工具,用户不需到现场频繁开箱,可随时远程了解整个蜂场实时环境或历史信息,管理省时又省心。",
image: "/img/product/beenFactory/product1.png"
},
{
title: "智能全景视频监控站",
description: "利用智能全景视频监控站实现对蜂场物资和周边环境的高清视频远程监控,支持远程视频查看及自动预警。",
image: "/img/product/beenFactory/product2.png"
},
{
title: "蜂场环境远程控制系统",
description: "智能全景视频监控站和蜂场环境气象监测站的配套软件,帮助用户实现对蜂场环境信息的远程实时自动获取、巡检及预警,辅助精准养殖。",
image: "/img/product/beenFactory/product3.png"
},
{
title: "智能蜂箱",
description: "为蜂农提供蜜蜂养殖场所的同时,还可实现对蜂箱内部环境的远程实时监控管理,便于用户快速了解蜂箱环境、蜂群活动及产蜜情况。",
image: "/img/product/beenFactory/product4.png"
},
{
title: "蜜源地调查",
description: "通过对蜂场周边环境进行自动化巡视,准确掌握蜜源地分布情况,确保蜂场周边蜜源充足。",
image: "/img/product/beenFactory/product5.png"
}
])
</script>
<template>
<img alt="" class="w-max" src="/img/product/beenFactory/banner.png">
<TitleDescription
subtitle="SERVICE INTRODUCTION"
title="服务简介"
/>
<UPageCTA
v-for="(item, index) in cardItems"
:key="index"
:description="item.description"
:reverse="index % 2 == 0"
:title="item.title"
:ui="{
title: 'font-semibold text-lg text-primary',
}"
orientation="horizontal"
>
<img
:src="item.image"
alt="Illustration"
class="w-full rounded-lg"
height="364"
width="320"
>
</UPageCTA>
</template>

View File

@ -0,0 +1,13 @@
<script lang="ts" setup>
</script>
<template>
<Upage>
<ProductBeenFactoryHero/>
</Upage>
</template>
<style scoped>
</style>

View File

@ -1,13 +1,13 @@
export default defineNuxtConfig({
compatibilityDate: '2025-07-15',
devtools: { enabled: true },
modules: ['@nuxt/eslint', '@nuxt/ui', '@nuxt/image'],
css: ['~/assets/css/main.css'],
fonts: {
providers: {
google: false, // 禁用 Google Fonts
googleicons: false // 禁用 Google Icons
}
},
compatibilityDate: '2025-07-15',
devtools: {enabled: true},
modules: ['@nuxt/eslint', '@nuxt/ui', '@nuxt/image'],
css: ['~/assets/css/main.css'],
fonts: {
providers: {
google: false, // 禁用 Google Fonts
googleicons: false // 禁用 Google Icons
}
},
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 948 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB