提交 7eaffc3a authored 作者: 李郝虎's avatar 李郝虎

feat:封装搜索组件中ing

上级 d4b8b274
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<div id="app"> <div id="app">
<div class="pro-wrapper"> <div class="pro-wrapper">
<div class="home-page"> <div class="home-page">
<div class="navbar"> <!-- <div class="navbar">
<div class="nav-content"> <div class="nav-content">
<div class="nav-left"> <div class="nav-left">
<div class="icon"> <div class="icon">
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
<div class="bottom-line" v-if="homeActiveTitleIndex === index"></div> <div class="bottom-line" v-if="homeActiveTitleIndex === index"></div>
</div> </div>
</div> </div>
</div> </div>
<div class="nav-right"> <div class="nav-right">
<div class="search-box"> <div class="search-box">
...@@ -49,8 +50,8 @@ ...@@ -49,8 +50,8 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div> -->
<NavBarV2/>
<div class="main-container"> <div class="main-container">
<router-view /> <router-view />
</div> </div>
......
<template>
<div class="navbarV2">
<div class="nav-content">
<div class="nav-left" :class="{ 'flex-start': isShowSearchBar }">
<div class="icon">
<img v-show="!isShowSearchBar" src="@/assets/icons/overview/logo.png" alt="" />
<img v-show="isShowSearchBar" src="@/assets/icons/overview/logo-white.png" alt="" />
</div>
<SearchBar v-show="isShowSearchBar" />
<div class="title-box" v-show="!isShowSearchBar">
<!-- <div class="title-box" v-if="false"> -->
<div
class="title"
v-for="(item, index) in homeTitleList"
:key="index"
@mouseenter="handleShowMenu(index, true)"
@mouseleave="handleShowMenu(index, false)"
@click="handleClickTitle(item)"
>
<div class="text" :class="{ textActive: homeActiveTitleIndex === index }">
{{ item.name }}
</div>
<div class="bottom-line" v-if="homeActiveTitleIndex === index"></div>
</div>
</div>
</div>
<div class="nav-right">
<div class="info-box" @click="handleClickToolBox">
<div class="mail">
<img src="@/assets/icons/overview/mail.png" alt="" />
</div>
<div class="user">
<img src="@/assets/icons/overview/user.png" alt="" />
</div>
<div class="name">{{ "管理员" }}</div>
</div>
</div>
<div class="menu-box" v-if="isShowMenu" @mouseenter="handleHoverMenu(true)" @mouseleave="handleHoverMenu(false)">
<div class="menu-content">
<div class="menu-item" v-for="(item, index) in menuList" :key="index" @click="handleToModule(item)">
<div class="icon">
<img :src="item.icon" alt="" />
</div>
<div class="title">{{ item.title }}</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed, onMounted, watchEffect } from "vue";
import { useRouter } from "vue-router";
import { useRoute } from "vue-router";
import { getPersonType } from "@/api/common/index";
import Menu1 from "@/assets/icons/overview/menu1.png";
import Menu2 from "@/assets/icons/overview/menu2.png";
import Menu3 from "@/assets/icons/overview/menu3.png";
import Menu4 from "@/assets/icons/overview/menu4.png";
import Menu5 from "@/assets/icons/overview/menu5.png";
import Menu6 from "@/assets/icons/overview/menu6.png";
import Menu7 from "@/assets/icons/overview/menu7.png";
import Menu8 from "@/assets/icons/overview/menu8.png";
import Menu9 from "@/assets/icons/overview/menu9.png";
import Menu10 from "@/assets/icons/overview/menu10.png";
import Menu11 from "@/assets/icons/overview/menu11.png";
import Menu12 from "@/assets/icons/overview/menu12.png";
import { ElMessage } from "element-plus";
import { useWrittingAsstaintStore } from "@/stores/writtingAsstaintStore";
const store = useWrittingAsstaintStore();
let isShowSearchBar = computed(() => {
return store.isShowSearchBar;
});
const router = useRouter();
const personTypeList = ref([]);
// 获取人物类别
const handleGetPersonType = async () => {
try {
const res = await getPersonType();
console.log("res", res);
if (res.code === 200) {
personTypeList.value = res.data;
} else {
personTypeList.value = [];
}
window.sessionStorage.setItem("personTypeList", JSON.stringify(personTypeList.value));
} catch (error) {}
};
// 概览页标题列表
const homeTitleList = ref([
{
name: "中美科技博弈",
path: "/ZMOverView",
disabled: false
},
{
name: "主要国家科技动向感知",
path: "",
disabled: true
},
{
name: "主要国家竞争科技安全",
path: "",
disabled: true
}
]);
const homeActiveTitleIndex = ref(0);
const isShowMenu = ref(false);
const handleShowMenu = (index, isShow) => {
if (index === 0) {
isShowMenu.value = isShow;
}
};
const handleHoverMenu = isShow => {
isShowMenu.value = isShow;
};
const menuList = ref([
{
title: "中美科技博弈概览",
icon: Menu1,
path: "/ZMOverView"
},
{
title: "科技法案",
icon: Menu2,
path: "/billHome"
},
{
title: "科技政令",
icon: Menu3,
path: "/decree"
},
{
title: "美国科技智库",
icon: Menu4,
path: "/thinkTank"
},
{
title: "出口管制",
icon: Menu5,
path: "/exportControl"
},
{
title: "科研合作限制",
icon: Menu6,
path: "/cooperationRestrictions"
},
{
title: "投融资限制",
icon: Menu7,
path: "/finance"
},
{
title: "市场准入限制",
icon: Menu8,
path: "/marketAccessRestrictions"
},
{
title: "规则限制",
icon: Menu9,
path: "/ruleRestrictions"
},
{
title: "美国科技人物观点",
icon: Menu10,
path: "/technologyFigures"
},
{
title: "美国主要创新主体动向",
icon: Menu11,
path: "/innovationSubject"
},
{
title: "美国科研资助体系",
icon: Menu12,
path: "/scientificFunding"
}
]);
const handleToModule = item => {
const curRoute = router.resolve({
path: item.path
});
window.open(curRoute.href, "_blank");
};
const searchText = ref("");
const handleSearch = () => {
const curRoute = router.resolve({
path: "/searchResults",
query: {
searchText: searchText.value
}
});
window.open(curRoute.href, "_blank");
};
const handleClickTitle = item => {
if (item.name === "主要国家科技动向感知" || item.name === "主要国家竞争科技安全") {
ElMessage.warning("当前功能正在开发中,敬请期待!");
}
};
const handleClickToolBox = () => {
ElMessage.warning("当前功能正在开发中,敬请期待!");
};
onMounted(() => {
handleGetPersonType();
});
</script>
<style lang="scss" scoped>
.navbarV2 {
width: 100%;
// height: 64px;
border-bottom: 1px solid rgba(234, 236, 238, 1);
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: linear-gradient(180deg, rgba(246, 250, 255, 0.8) 0%, rgba(255, 255, 255, 0.8) 100%);
padding: 12px 0;
.nav-content {
width: 1600px;
margin: 0 auto;
display: flex;
justify-content: space-between;
position: relative;
align-items: flex-start;
.nav-left {
display: flex;
align-items: center;
&.flex-start {
align-items: flex-start;
.icon {
flex-shrink: 0;
width: 48px;
height: 48px;
border-radius: 50%;
background: rgb(5, 95, 194);
display: flex;
align-items: center;
justify-content: center;
img {
width: 29px;
height: 30px;
}
}
}
.icon {
width: 29px;
height: 30px;
margin-right: 17px;
img {
width: 100%;
height: 100%;
}
}
.title-box {
display: flex;
gap: 30px;
.title {
cursor: pointer;
position: relative;
&:hover {
.text {
color: var(--color-main-active);
}
}
.text {
color: rgba(59, 65, 75, 1);
font-family: YouSheBiaoTiHei;
font-style: Regular;
font-size: 30px;
font-weight: 400;
letter-spacing: 0px;
}
.textActive {
color: var(--color-main-active);
}
.bottom-line {
position: absolute;
bottom: -15px;
width: 90%;
height: 20px;
margin-top: 9px;
&::after {
display: block;
content: "";
width: 50%;
height: 4px;
background: var(--color-main-active);
position: absolute;
bottom: 2px;
left: 0;
right: 0;
margin: 0 auto;
}
}
}
}
}
.nav-right {
display: flex;
justify-content: flex-end;
gap: 21px;
.info-box {
display: flex;
justify-content: flex-end;
align-items: center;
.mail {
width: 32px;
height: 32px;
margin-right: 14px;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
}
.user {
width: 32px;
height: 32px;
margin-right: 11px;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
}
.name {
width: 48px;
height: 30px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-style: Regular;
font-size: 16px;
font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
}
}
}
.menu-box {
position: absolute;
z-index: 999999;
width: 713px;
height: 413px;
top: 52px;
left: 0;
box-sizing: border-box;
border: 1px solid rgba(255, 255, 255, 1);
border-radius: 10px;
backdrop-filter: blur(30px);
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 0.8);
.menu-content {
width: 562px;
height: 348px;
margin-top: 8px;
margin-left: 72px;
display: flex;
flex-wrap: wrap;
.menu-item {
margin-top: 36px;
width: 280px;
height: 24px;
display: flex;
cursor: pointer;
&:hover {
.title {
color: var(--color-main-active);
font-size: 20px;
}
}
.icon {
width: 24px;
height: 24px;
img {
width: 100%;
height: 100%;
}
}
.title {
margin-left: 16px;
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-style: Bold;
font-size: 18px;
font-weight: 700;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
}
}
}
}
}
}
</style>
<template>
<div class="search-box">
<div class="search-header-container">
<div class="home-main-header-center">
<el-input
v-model="store.searchBillText"
@keyup.enter="handleSearch"
style="width: 680px; height: 100%"
:placeholder="store.searchData.placeholder"
/>
<div class="search">
<div class="search-icon">
<img src="@/assets/icons/search-icon.png" alt="" />
</div>
<div class="search-text" @click="handleSearch">搜索</div>
</div>
</div>
<div class="home-main-header-btn-box">
<div class="btn" @click="handleToPosi('position1')">
<div class="btn-text">{{ "最新动态" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div>
</div>
<div class="btn" @click="handleToPosi('position2')">
<div class="btn-text">{{ "资讯要闻" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div>
</div>
<div class="btn" @click="handleToPosi('position3')">
<div class="btn-text">{{ "数据总览" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div>
</div>
<div class="btn" @click="handleToPosi('position4')">
<div class="btn-text">{{ "资源库" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, ref, computed, onUnmounted, nextTick, watch, watchEffect } from "vue";
import router from "@/router/index";
import { useWrittingAsstaintStore } from "@/stores/writtingAsstaintStore";
const store = useWrittingAsstaintStore();
const handleSearch = () => {
window.sessionStorage.setItem("curTabName", `搜索-${store.searchBillText}`);
const curRoute = router.resolve({
path: "/searchResults",
query: {
searchText: store.searchBillText,
areaName: "法案"
}
});
window.open(curRoute.href, "_blank");
};
let containerRef = computed(() => store.searchData.containerRef);
const handleToPosi = id => {
const element = document.getElementById(id);
if (element && containerRef.value) {
// 2. 使用 nextTick 等待 DOM 布局(如高度切换)完成后再进行坐标计算
nextTick(() => {
const containerRect = containerRef.value.getBoundingClientRect();
const elementRect = element.getBoundingClientRect();
// 使用 getBoundingClientRect 计算元素相对于容器顶部的绝对距离
const top = elementRect.top - containerRect.top + containerRef.value.scrollTop;
containerRef.value.scrollTo({
top: top,
behavior: "smooth"
});
});
}
};
</script>
<style lang="scss" scoped>
.search-box {
width: 100%;
// background: #fff;
// box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
.search-header-container {
width: 100%;
margin: 0 auto;
// padding: 16px 0px 16px 0px;
}
.home-main-header-center {
// margin-top: 20px;
// margin-left: 200px;
width: 800px;
height: 48px;
border-radius: 10px;
// box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
border: 1px solid var(--color-primary-35);
background: rgba(255, 255, 255, 1);
box-sizing: border-box;
padding: 1px;
position: relative;
&:hover {
border: 1px solid var(--color-main-active);
}
.search {
position: absolute;
right: -1px;
top: 0px;
width: 120px;
height: 46px;
border-radius: 10px;
background: var(--color-main-active);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
.search-icon {
width: 18px;
height: 18px;
img {
width: 100%;
height: 100%;
}
}
.search-text {
margin-left: 8px;
height: 22px;
color: #fff;
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 22px;
}
}
}
.home-main-header-btn-box {
margin-top: 16px;
// margin-left: 200px;
display: flex;
gap: 16px;
.btn {
display: flex;
align-items: center;
gap: 9px;
width: 140px;
height: 36px;
border: 1px solid #aed6ff;
box-sizing: border-box;
border-radius: 24px;
background: #e7f3ff;
cursor: pointer;
position: relative;
&:hover {
background: #cae3fc;
}
.btn-text {
width: 80px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 400;
line-height: 48px;
margin-left: 24px;
text-align: center;
}
.btn-icon {
position: absolute;
top: 10px;
right: 19px;
width: 6px;
height: 12px;
img {
width: 100%;
height: 100%;
}
}
}
}
}
</style>
<template>
<div class="search" v-show="!isShow">
<div class="search-main">
<input v-model="store.searchBillText" :placeholder="placeholder" @keyup.enter="handleSearch" class="search-input" />
<div class="search-btn" @click="handleSearch">
<img src="@/assets/icons/search-icon.png" alt />
搜索
</div>
</div>
<div class="search-center" v-if="countInfo.length">
<div class="search-item" v-for="info in countInfo">
<div class="search-item-num">{{ info.count }}</div>
<div class="search-item-name">{{ info.name }}</div>
</div>
</div>
<div class="search-bottom">
<div class="btn" @click="handleToPosi('position1')">
<div class="btn-text">最新动态</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
<div class="btn" @click="handleToPosi('position2')">
<div class="btn-text">咨询要闻</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
<div class="btn" @click="handleToPosi('position3')">
<div class="btn-text">数据总览</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
<div class="btn" @click="handleToPosi('position4')">
<div class="btn-text">资源库</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, nextTick, watchEffect } from "vue";
import { useContainerScroll } from "@/hooks/useScrollShow";
import { useRouter } from "vue-router";
import { useWrittingAsstaintStore } from "@/stores/writtingAsstaintStore";
const store = useWrittingAsstaintStore();
const router = useRouter();
let { countInfo, containerRef, placeholder, areaName } = defineProps({
countInfo: {
type: Array,
default: () => []
},
containerRef: {
type: Object,
default: {}
},
placeholder: {
type: String,
default: "123"
},
areaName: {
type: String,
default: "法案"
}
});
const handleSearch = () => {
window.sessionStorage.setItem("curTabName", `搜索-${store.searchBillText}`);
if (!areaName) return;
const curRoute = router.resolve({
path: "/searchResults",
query: {
searchText: store.searchBillText,
areaName: areaName
}
});
window.open(curRoute.href, "_blank");
};
let homeMainRef = ref(containerRef);
const { isShow } = useContainerScroll(homeMainRef);
watchEffect(() => {
if (isShow.value) {
homeMainRef.value.classList.add("scroll-main");
} else {
homeMainRef.value.classList.remove("scroll-main");
}
store.changeIsShowSearchBar(isShow.value);
});
store.setSearchData({ placeholder, areaName,containerRef:homeMainRef });
// 锚点跳转
const handleToPosi = id => {
const element = document.getElementById(id);
if (element && homeMainRef.value) {
// 如果当前还未显示吸顶搜索栏,先强制切换状态以稳定布局
if (!isShow.value) {
isShow.value = true;
}
// 使用 nextTick 确保 DOM 状态更新(高度变化生效)后再计算
nextTick(() => {
const containerRect = homeMainRef.value.getBoundingClientRect();
const elementRect = element.getBoundingClientRect();
// 使用 getBoundingClientRect 计算元素相对于容器顶部的绝对距离,不受嵌套布局影响
const top = elementRect.top - containerRect.top + homeMainRef.value.scrollTop;
homeMainRef.value.scrollTo({
top: top,
behavior: "smooth"
});
});
}
};
</script>
<style lang="scss" scoped>
.search {
width: 960px;
height: 168px;
margin: 0 auto 68px auto;
.search-center {
width: 688px;
height: 48px;
margin: 0 auto;
margin-top: 36px;
display: flex;
justify-content: space-between;
.search-item {
width: 120px;
height: 57px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
.search-item-num {
font-family: Microsoft YaHei;
font-style: Bold;
font-size: 36px;
font-weight: 700;
line-height: 22px;
letter-spacing: 0px;
text-align: center;
color: rgba(5, 95, 194, 1);
}
.search-item-name {
font-family: Microsoft YaHei;
font-style: Regular;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: center;
color: rgba(95, 101, 108, 1);
}
}
}
.search-main {
display: flex;
padding-right: 3px;
align-items: center;
justify-content: space-between;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
width: 960px;
height: 48px;
background-color: rgba(255, 255, 255, 0.65);
border-radius: 10px;
border: 1px solid #fff;
&:hover {
border: 1px solid var(--color-main-active);
}
.search-input {
border: none;
outline: none;
width: 838px;
height: 48px;
background-color: transparent;
font-size: 14px;
padding: 12px 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 22px;
color: rgba(59, 65, 75, 1);
&::placeholder {
color: #a8abb2;
}
}
.search-btn {
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
width: 120px;
height: 46px;
margin-right: -3px;
border-radius: 8px;
background-color: rgb(5, 95, 194);
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 22px;
color: #fff;
img {
width: 18px;
height: 18px;
margin-right: 8px;
}
}
}
.search-bottom {
width: 688px;
height: 48px;
margin: 0 auto;
margin-top: 36px;
display: flex;
justify-content: space-between;
// gap: 16px;
.btn {
display: flex;
align-items: center;
gap: 9px;
width: 160px;
height: 48px;
border: 1px solid #aed6ff;
box-sizing: border-box;
border-radius: 24px;
background: #e7f3ff;
cursor: pointer;
position: relative;
&:hover {
background: #cae3fc;
}
.btn-text {
width: 80px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 400;
line-height: 48px;
margin-left: 36px;
text-align: center;
}
.btn-icon {
position: absolute;
top: 16px;
right: 19px;
width: 6px;
height: 12px;
img {
width: 100%;
height: 100%;
}
}
}
}
}
</style>
...@@ -28,6 +28,7 @@ export function useContainerScroll(containerRef, options = {}) { ...@@ -28,6 +28,7 @@ export function useContainerScroll(containerRef, options = {}) {
lastScrollTop.value = currentScrollTop lastScrollTop.value = currentScrollTop
ticking.value = false ticking.value = false
} }
const handleScroll = () => { const handleScroll = () => {
...@@ -42,6 +43,7 @@ export function useContainerScroll(containerRef, options = {}) { ...@@ -42,6 +43,7 @@ export function useContainerScroll(containerRef, options = {}) {
} }
onMounted(() => { onMounted(() => {
console.log('containerRef', containerRef)
const container = containerRef.value const container = containerRef.value
if (container) { if (container) {
container.addEventListener('scroll', handleScroll, { passive: true }) container.addEventListener('scroll', handleScroll, { passive: true })
......
...@@ -42,7 +42,15 @@ export const useWrittingAsstaintStore = defineStore('writtingAsstaint', { ...@@ -42,7 +42,15 @@ export const useWrittingAsstaintStore = defineStore('writtingAsstaint', {
], ],
// 内部控制器 // 内部控制器
abortController: null abortController: null,
isShowSearchBar: false,
searchBillText:'',
searchData:{
placeholder:'',
areaName:'',
containerRef:null
},
}), }),
getters: { getters: {
...@@ -60,7 +68,15 @@ export const useWrittingAsstaintStore = defineStore('writtingAsstaint', { ...@@ -60,7 +68,15 @@ export const useWrittingAsstaintStore = defineStore('writtingAsstaint', {
toggleEditMode() { toggleEditMode() {
this.isEditMode = !this.isEditMode this.isEditMode = !this.isEditMode
}, },
// 设置navbar是否显示搜索框
changeIsShowSearchBar(value){
this.isShowSearchBar = value
},
setSearchData({placeholder,areaName,containerRef}){
this.searchData.placeholder = placeholder
this.searchData.areaName = areaName
this.searchData.containerRef = containerRef
},
resetGenerateState() { resetGenerateState() {
this.isGenerating = false; this.isGenerating = false;
this.isShowProcess = false; this.isShowProcess = false;
......
<template> <template>
<div class="home-wrapper"> <div class="home-wrapper">
<div class="search-header" v-show="isShow"> <div class="search-header" v-show="false">
<div class="search-header-container"> <div class="search-header-container">
<div class="home-main-header-center"> <div class="home-main-header-center">
<el-input <el-input
v-model="searchBillText" v-model="searchBillText"
...@@ -46,7 +45,7 @@ ...@@ -46,7 +45,7 @@
</div> </div>
</div> </div>
<div class="home-box" :class="{ scrollHomeBox: isShow }" ref="containerRef"> <div class="home-box" :class="{ scrollHomeBox: isShow }" ref="containerRef">
<div class="home-top-bg"></div> <div class="home-top-bg"></div>
<!-- <div class="home-header" v-show="!isShow"> <!-- <div class="home-header" v-show="!isShow">
<div class="header-left"> <div class="header-left">
...@@ -57,7 +56,13 @@ ...@@ -57,7 +56,13 @@
</div> </div>
</div> --> </div> -->
<div class="home-main"> <div class="home-main">
<div class="home-main-header"> <SearchContainer
v-if="containerRef"
placeholder="搜索科技法案"
:containerRef="containerRef"
areaName="法案"
/>
<div class="home-main-header" v-if="false">
<div class="home-main-header-center" v-show="!isShow"> <div class="home-main-header-center" v-show="!isShow">
<el-input <el-input
v-model="searchBillText" v-model="searchBillText"
...@@ -395,7 +400,7 @@ ...@@ -395,7 +400,7 @@
}" }"
> >
<el-empty v-if="!box5HasData" description="暂无数据" :image-size="100" /> <el-empty v-if="!box5HasData" description="暂无数据" :image-size="100" />
<div v-else id="box5Chart" style="width: 100%; height: 100%;"></div> <div v-else id="box5Chart" style="width: 100%; height: 100%"></div>
</div> </div>
</div> </div>
<div class="box6"> <div class="box6">
...@@ -1875,8 +1880,9 @@ onUnmounted(() => { ...@@ -1875,8 +1880,9 @@ onUnmounted(() => {
.scrollHomeBox { .scrollHomeBox {
height: calc(100% - 144px); height: calc(100% - 144px);
} }
.home-top-bg{ .home-top-bg {
background: url("./assets/images/background.png"),linear-gradient(180.00deg, rgba(229, 241, 254, 1) 0%,rgba(246, 251, 255, 0) 30%); background:
url("./assets/images/background.png"), linear-gradient(180deg, rgba(229, 241, 254, 1) 0%, rgba(246, 251, 255, 0) 30%);
background-size: 100% 100%; background-size: 100% 100%;
position: absolute; position: absolute;
width: 100%; width: 100%;
...@@ -1916,7 +1922,7 @@ onUnmounted(() => { ...@@ -1916,7 +1922,7 @@ onUnmounted(() => {
box-sizing: border-box; box-sizing: border-box;
padding: 1px; padding: 1px;
position: relative; position: relative;
border: 1px solid rgba(255,255,255,1); border: 1px solid rgba(255, 255, 255, 1);
&:hover { &:hover {
border: 1px solid var(--color-main-active); border: 1px solid var(--color-main-active);
} }
......
<template> <template>
<div class="coop-page"> <div class="coop-page">
<!-- 吸顶简易搜索框 --> <div class="main-content" ref="homeMainRef">
<div class="search-header" v-show="isShow">
<div class="home-main-header-center">
<input v-model="input" class="search-input" placeholder="搜索规则限制" />
<div class="search-btn-small" @click="handleSearch">
<div class="search-icon">
<img src="./assets/icons/search-icon.png" alt />
</div>
<div class="search-text">搜索</div>
</div>
</div>
<div class="home-main-header-btn-box">
<div class="btn" @click="handleToPosi('position1')">
<div class="btn-text">最新动态</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
<div class="btn" @click="handleToPosi('position2')">
<div class="btn-text">咨询要闻</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
<div class="btn" @click="handleToPosi('position3')">
<div class="btn-text">数据总览</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
<div class="btn" @click="handleToPosi('position4')">
<div class="btn-text">资源库</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
</div>
</div>
<!-- 面包屑 -->
<!-- <div class="breadcrumb" v-show="!isShow">
<div class="header-left">
<HeaderMenu></HeaderMenu>
</div>
<div class="header-right">
<headerInfo curTitleName="规则限制"></headerInfo>
</div>
</div> -->
<!-- 主页面 -->
<div class="main-content" ref="homeMainRef" :class="{ 'scroll-main': isShow }">
<!-- 搜索栏部分 --> <!-- 搜索栏部分 -->
<div class="search" v-show="!isShow"> <SearchContainer
<div class="search-main"> v-if="homeMainRef"
<input v-model="input" placeholder="搜索规则限制" class="search-input" /> :countInfo="statCountInfo"
<div class="search-btn"> placeholder="搜索规则限制"
<img src="./assets/icons/search-icon.png" alt /> :containerRef="homeMainRef"
搜索 areaName=""
</div> />
</div>
<div class="search-center">
<div class="search-item">
<div class="search-item-num">{{ statCountInfo.AOCOUNT }}</div>
<div class="search-item-name">规则限制政令</div>
</div>
<div class="search-item">
<div class="search-item-num">{{ statCountInfo.ENTITYCOUNT }}</div>
<div class="search-item-name">规则限制实体</div>
</div>
<div class="search-item">
<div class="search-item-num">{{ statCountInfo.ACTACOUNT }}</div>
<div class="search-item-name">排华科技联盟</div>
</div>
<div class="search-item">
<div class="search-item-num">{{ statCountInfo.COUNTRYCOUNT }}</div>
<div class="search-item-name">排华国家数量</div>
</div>
</div>
<div class="search-bottom">
<div class="btn" @click="handleToPosi('position1')">
<div class="btn-text">最新动态</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
<div class="btn" @click="handleToPosi('position2')">
<div class="btn-text">咨询要闻</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
<div class="btn" @click="handleToPosi('position3')">
<div class="btn-text">数据总览</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
<div class="btn" @click="handleToPosi('position4')">
<div class="btn-text">资源库</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
</div>
</div>
<!-- 最新动态 --> <!-- 最新动态 -->
<div class="newdata" id="position1"> <div class="newdata" id="position1">
<com-title title="最新动态" /> <com-title title="最新动态" />
...@@ -146,69 +51,86 @@ import dataSub from "./components/dataSub/index.vue"; ...@@ -146,69 +51,86 @@ import dataSub from "./components/dataSub/index.vue";
import resLib from "./components/resLib/index.vue"; import resLib from "./components/resLib/index.vue";
import HeaderMenu from "@/components/headerMenu.vue"; import HeaderMenu from "@/components/headerMenu.vue";
import headerInfo from "@/components/headerInfo.vue"; import headerInfo from "@/components/headerInfo.vue";
import { useContainerScroll } from "@/hooks/useScrollShow"; // import { useContainerScroll } from "@/hooks/useScrollShow";
import { getStatCount } from '@/api/ruleRestriction/index.js' import { getStatCount } from "@/api/ruleRestriction/index.js";
// 搜索框 // 搜索框
const input = ref(""); const input = ref("");
const homeMainRef = ref(null); const homeMainRef = ref(null);
const { isShow } = useContainerScroll(homeMainRef); // const { isShow } = useContainerScroll(homeMainRef);
const router = useRouter(); const router = useRouter();
const statCountInfo = ref({}) const statCountInfo = ref([]);
// const
const getStatCountInfo = async () => { const getStatCountInfo = async () => {
try { try {
const res = await getStatCount(); const res = await getStatCount();
if (res && res.code === 200) { if (res && res.code === 200) {
// console.log('----getStatCountInfo', res.data) // console.log('----getStatCountInfo', res.data)
statCountInfo.value = res.data statCountInfo.value = [
} {
} catch (error) { name: "规则限制政令",
console.error("获取首页统计接口失败:", error); count: res.data.AOCOUNT
} },
} {
name: "规则限制实体",
count: res.data.ENTITYCOUNT
},
{
name: "排华科技联盟",
count: res.data.ACTACOUNT
},
{
name: "排华国家数量",
count: res.data.COUNTRYCOUNT
}
];
}
} catch (error) {
console.error("获取首页统计接口失败:", error);
}
};
// 搜索功能 // 搜索功能
const handleSearch = () => { const handleSearch = () => {
console.log("搜索内容:", input.value); console.log("搜索内容:", input.value);
}; };
// 锚点跳转 // 锚点跳转
const handleToPosi = id => { const handleToPosi = id => {
const element = document.getElementById(id); const element = document.getElementById(id);
if (element && homeMainRef.value) { if (element && homeMainRef.value) {
// 如果当前还未显示吸顶搜索栏,先强制切换状态以稳定布局 // 如果当前还未显示吸顶搜索栏,先强制切换状态以稳定布局
if (!isShow.value) { if (!isShow.value) {
isShow.value = true; isShow.value = true;
} }
// 使用 nextTick 确保 DOM 状态更新(高度变化生效)后再计算 // 使用 nextTick 确保 DOM 状态更新(高度变化生效)后再计算
nextTick(() => { nextTick(() => {
const containerRect = homeMainRef.value.getBoundingClientRect(); const containerRect = homeMainRef.value.getBoundingClientRect();
const elementRect = element.getBoundingClientRect(); const elementRect = element.getBoundingClientRect();
// 使用 getBoundingClientRect 计算元素相对于容器顶部的绝对距离,不受嵌套布局影响 // 使用 getBoundingClientRect 计算元素相对于容器顶部的绝对距离,不受嵌套布局影响
const top = elementRect.top - containerRect.top + homeMainRef.value.scrollTop; const top = elementRect.top - containerRect.top + homeMainRef.value.scrollTop;
homeMainRef.value.scrollTo({ homeMainRef.value.scrollTo({
top: top, top: top,
behavior: "smooth" behavior: "smooth"
}); });
}); });
} }
}; };
// 返回首页 // 返回首页
const handleBackHome = () => { const handleBackHome = () => {
router.push({ router.push({
path: "/overview" path: "/overview"
}); });
}; };
onMounted(async () => { onMounted(async () => {
await getStatCountInfo() await getStatCountInfo();
}) });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
......
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论