feat: 新首页的搭建
This commit is contained in:
148
src/components/AiTabSwitch/index.vue
Normal file
148
src/components/AiTabSwitch/index.vue
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
<template>
|
||||||
|
<view class="ai-tab-wrapper">
|
||||||
|
<view class="tab-container">
|
||||||
|
<view class="tab-item is-left" :class="{ 'active': modelValue === 0 }" @tap="handleSwitch(0)">
|
||||||
|
<view class="tab-content">
|
||||||
|
<text class="tab-text">探索发现</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="tab-item is-right" :class="{ 'active': modelValue === 1 }" @tap="handleSwitch(1)">
|
||||||
|
<view class="tab-content">
|
||||||
|
<text class="tab-text">AI伴游</text>
|
||||||
|
<view v-if="showDot" class="status-dot"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: { type: Number, default: 0 },
|
||||||
|
showDot: { type: Boolean, default: true }
|
||||||
|
});
|
||||||
|
const emit = defineEmits(['update:modelValue', 'change']);
|
||||||
|
|
||||||
|
const handleSwitch = (i) => {
|
||||||
|
emit('update:modelValue', i);
|
||||||
|
emit('change', i);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.ai-tab-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
background-color: #61D68B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-container {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 48px;
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
/* 基础容器不做裁切,交给内部 Item */
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
height: 48px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 选中态提升层级,压住对方的交汇线 */
|
||||||
|
.tab-item.active {
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
/* 未选中样式:半透明渐变 */
|
||||||
|
background: rgba(0, 0, 0, 0.05);
|
||||||
|
transition: background 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item.active .tab-content {
|
||||||
|
/* 选中样式:纯白 */
|
||||||
|
background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #F0F8F3 75.52%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-text {
|
||||||
|
font-size: 15px;
|
||||||
|
color: rgba(255, 255, 255, 0.95);
|
||||||
|
z-index: 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item.active .tab-text {
|
||||||
|
color: #2E312F;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------- 核心:异形路径优化 ------------------- */
|
||||||
|
|
||||||
|
/* 路径逻辑:
|
||||||
|
1. H 指令缩短,让出更多空间给交汇处。
|
||||||
|
2. C 指令(贝塞尔曲线)的终点设在高度 48 的位置,确保底部平齐不留空隙。
|
||||||
|
3. 通过 margin-right/left 让两个形状在中心高度(24px)处重叠。
|
||||||
|
*/
|
||||||
|
|
||||||
|
.is-left {
|
||||||
|
margin-right: -14px;
|
||||||
|
/* 减小重叠宽度,使形状更精巧 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-left .tab-content {
|
||||||
|
/* 路径:左侧顶满 -> 顶部直线 -> 在中间开始向下弯曲 -> 底部平齐拉回 */
|
||||||
|
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='3 0 180 48' preserveAspectRatio='none'%3E%3Cpath d='M0,0 H140 C155,0 160,12 165,24 C170,36 175,48 185,48 H0 V0 Z' fill='black'/%3E%3C/svg%3E");
|
||||||
|
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='3 0 180 48' preserveAspectRatio='none'%3E%3Cpath d='M0,0 H140 C155,0 160,12 165,24 C170,36 175,48 185,48 H0 V0 Z' fill='black'/%3E%3C/svg%3E");
|
||||||
|
-webkit-mask-size: 100% 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-right {
|
||||||
|
margin-left: -14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-right .tab-content {
|
||||||
|
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 48' preserveAspectRatio='none'%3E%3Cpath d='M180,0 H40 C25,0 20,12 15,24 C10,36 5,48 -5,48 H180 V0 Z' fill='black'/%3E%3C/svg%3E");
|
||||||
|
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 48' preserveAspectRatio='none'%3E%3Cpath d='M180,0 H40 C25,0 20,12 15,24 C10,36 5,48 -5,48 H180 V0 Z' fill='black'/%3E%3C/svg%3E");
|
||||||
|
-webkit-mask-size: 100% 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------- 选中态的渐变边框 ------------------- */
|
||||||
|
|
||||||
|
.tab-item.active::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 15;
|
||||||
|
pointer-events: none;
|
||||||
|
/* 360deg 渐变 */
|
||||||
|
background: linear-gradient(0deg, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-left.active::after {
|
||||||
|
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='3 0 180 48' preserveAspectRatio='none'%3E%3Cpath d='M0.5,47.5 V0.5 H140 C155,0.5 160,12.5 165,24.5 C170,36.5 175,47.5 184.5,47.5' fill='none' stroke='black' stroke-width='1.2'/%3E%3C/svg%3E");
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-right.active::after {
|
||||||
|
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 48' preserveAspectRatio='none'%3E%3Cpath d='M179.5,47.5 V0.5 H40 C25,0.5 20,12.5 15,24.5 C10,36.5 5,47.5 -4.5,47.5' fill='none' stroke='black' stroke-width='1.2'/%3E%3C/svg%3E");
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-dot {
|
||||||
|
width: 7px;
|
||||||
|
height: 7px;
|
||||||
|
background-color: #26D46C;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-left: 5px;
|
||||||
|
transform: translateY(-8px);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
14
src/pages/Discovery/index.vue
Normal file
14
src/pages/Discovery/index.vue
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<template>
|
||||||
|
<AiTabSwitch v-model="tabIndex" :list="['探索发现', 'AI伴游']" @change="handleChange" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from "vue";
|
||||||
|
import AiTabSwitch from "@/components/AiTabSwitch/index.vue";
|
||||||
|
|
||||||
|
const tabIndex = ref(0);
|
||||||
|
|
||||||
|
const handleChange = (i) => {
|
||||||
|
console.log("切换:", i);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
20
src/pages/Home/components/HomeNavBar.vue
Normal file
20
src/pages/Home/components/HomeNavBar.vue
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<template>
|
||||||
|
<view class="border-box h-44 flex flex-items-center pl-12 pr-12">
|
||||||
|
<uni-icons type="bars" size="24" color="#333" @click="showDrawer" />
|
||||||
|
<view class="w-24 h-24"></view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, defineExpose } from "vue";
|
||||||
|
|
||||||
|
const show = ref(false);
|
||||||
|
|
||||||
|
const showDrawer = () => uni.$emit("SHOW_DRAWER");
|
||||||
|
|
||||||
|
defineExpose({ show });
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
||||||
75
src/pages/Home/index.vue
Normal file
75
src/pages/Home/index.vue
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
<template>
|
||||||
|
<view class="relative flex flex-col h-screen">
|
||||||
|
<view class="absolute top-0 left-0 w-full z-10" :style="{ paddingTop: statusBarHeight + 'px' }">
|
||||||
|
<HomeNavBar />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="content relative flex-1">
|
||||||
|
<view class="relative">
|
||||||
|
<image class="w-full" src="https://images.unsplash.com/photo-1506744038136-46273834b3fb?w=800&q=80"
|
||||||
|
mode="widthFix" />
|
||||||
|
<view class="absolute bottom-0 left-0 right-0 w-full head-content ">
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<AiTabSwitch v-model="tabIndex" :list="['探索发现', 'AI伴游']" @change="handleChange" />
|
||||||
|
|
||||||
|
<view>
|
||||||
|
<view class="absolute top-0 left-0 w-full h-full flex flex-col items-center justify-center">
|
||||||
|
<text class="font-size-24 font-bold color-white mb-4">欢迎来到AI助手</text>
|
||||||
|
<text class="font-size-16 color-white mb-8">您的智能聊天伴侣,随时为您提供帮助</text>
|
||||||
|
<view class="flex space-x-4">
|
||||||
|
<view class="px-6 py-2 bg-green-500 text-white rounded-lg">开始聊天</view>
|
||||||
|
<view class="px-6 py-2 bg-gray-300 text-gray-700 rounded-lg">了解更多</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { onLoad } from "@dcloudio/uni-app";
|
||||||
|
|
||||||
|
import HomeNavBar from "./components/HomeNavBar.vue";
|
||||||
|
|
||||||
|
import AiTabSwitch from "@/components/AiTabSwitch/index.vue";
|
||||||
|
|
||||||
|
|
||||||
|
const tabIndex = ref(0);
|
||||||
|
|
||||||
|
const handleChange = (i) => {
|
||||||
|
console.log("切换:", i);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// 导航栏相关
|
||||||
|
const statusBarHeight = ref(20);
|
||||||
|
|
||||||
|
/// =============生命周期函数↓================
|
||||||
|
onLoad(() => {
|
||||||
|
uni.getSystemInfo({
|
||||||
|
success: (res) => {
|
||||||
|
statusBarHeight.value = res.statusBarHeight || 20;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.head-content {
|
||||||
|
background: red;
|
||||||
|
height: 104px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="w-full h-screen bg-liner">
|
<view class="w-full h-screen bg-liner">
|
||||||
<ChatMainList />
|
<Home />
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 日历组件 -->
|
<!-- 日历组件 -->
|
||||||
@@ -29,6 +29,7 @@ import ChatMainList from "../ChatMain/ChatMainList/index.vue";
|
|||||||
import MoreService from "../ChatModule/MoreService/index.vue";
|
import MoreService from "../ChatModule/MoreService/index.vue";
|
||||||
import DrawerSection from "../DrawerSection/index.vue";
|
import DrawerSection from "../DrawerSection/index.vue";
|
||||||
import Calender from "@/components/Calender/index.vue";
|
import Calender from "@/components/Calender/index.vue";
|
||||||
|
import Home from "../Home/index.vue";
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
|
||||||
@@ -83,4 +84,8 @@ onUnmounted(() => {
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped>
|
||||||
|
.top {
|
||||||
|
margin-top: 150px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user