feat(buyer): 统一全站页面顶部为现代TopBar与SearchHeader,支持商品/店铺双模搜索与占位词规范

This commit is contained in:
pikachu1995@126.com
2026-10-29 17:05:53 +08:00
parent d113f5c553
commit 5973d43b9d
15 changed files with 579 additions and 181 deletions

View File

@@ -1,7 +1,7 @@
<template>
<div class="goods-detail-page">
<BaseHeader></BaseHeader>
<Search></Search>
<TopBar></TopBar>
<SearchHeader></SearchHeader>
<div class="shop-item-path">
<div class="shop-nav-container">
<el-breadcrumb>
@@ -44,7 +44,8 @@ import { ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import { Message } from "@/utils/message";
import storage from "@/plugins/storage.js";
import Search from "@/components/Search";
import TopBar from '@/components/indexDecorate/components/TopBar.vue';
import SearchHeader from '@/components/indexDecorate/components/SearchHeader.vue';
import ShowGoods from "@/components/goodsDetail/ShowGoods";
import empty from "@/components/empty/Main";
import ShowGoodsDetail from "@/components/goodsDetail/ShowGoodsDetail";

View File

@@ -1,7 +1,7 @@
<template>
<div class="wrapper">
<BaseHeader></BaseHeader>
<Search @search="handleSearch"></Search>
<TopBar></TopBar>
<SearchHeader @search="handleSearch"></SearchHeader>
<div class="container">
<!-- 商品筛选栏 -->
@@ -115,6 +115,8 @@ import { ArrowDown, ArrowUp } from '@element-plus/icons-vue';
import GoodsClassNav from "@/components/nav/GoodsClassNav";
import GoodsThumb from "@/components/goods/GoodsThumb.vue";
import * as apiGoods from "@/api/goods";
import TopBar from '@/components/indexDecorate/components/TopBar.vue';
import SearchHeader from '@/components/indexDecorate/components/SearchHeader.vue';
const route = useRoute();
const router = useRouter();

View File

@@ -22,16 +22,21 @@
</el-dialog>
<!-- 固定头部 -->
<hover-search class="hover-search" :class="{show: topSearchShow}"></hover-search>
<hover-search class="hover-search" :class="{show: topSearchShow}" :options="searchHeaderOptions"></hover-search>
<!-- 顶部广告 -->
<FixedTopPage :data="topAdvert" v-if="!isVersion2"></FixedTopPage>
<!-- 头部 包括登录,我的订单等 -->
<BaseHeader v-if="!hasComponentInV2('topBar')"></BaseHeader>
<!-- 搜索框、logo -->
<Search v-if="!hasComponentInV2('searchHeader')"></Search>
<div class="index-main">
<!-- 商品分类 + 楼层装修(同一宽度容器,保证与分类栏左缘对齐) -->
<cateNav :showAlways="true" v-if="!isVersion2 && showNav" :large="carouselLarge" :opacity="carouselOpacity"></cateNav>
<!-- Version 2 页面装修:全宽自由响应容器,由各行独立配置 rowStyle.width(如 100%、1920、1400、1200)实现全宽或精准居中 -->
<div v-if="isVersion2" class="v2-index-main">
<model-form :data="modelFormData"></model-form>
</div>
<!-- Version 1 历史旧版:保持 1200px 传统固定容器与分类栏 -->
<div v-else class="index-main">
<cateNav :showAlways="true" v-if="showNav" :large="carouselLarge" :opacity="carouselOpacity"></cateNav>
<model-form :data="modelFormData"></model-form>
</div>
<!-- 底部栏 -->
@@ -74,6 +79,19 @@ const isVersion2 = computed(() => {
return modelFormData.value?.version === 2 || modelFormData.value?.version === '2.0';
});
const searchHeaderOptions = computed(() => {
if (!Array.isArray(modelFormData.value?.list)) return {};
for (const row of modelFormData.value.list) {
if (Array.isArray(row.components)) {
const target = row.components.find(c => c && c.type === 'searchHeader');
if (target?.options) {
return target.options;
}
}
}
return {};
});
const hasComponentInV2 = (type) => {
if (!isVersion2.value || !Array.isArray(modelFormData.value?.list)) return false;
return modelFormData.value.list.some(r => r.components && r.components.some(c => c.type === type));
@@ -240,6 +258,11 @@ onUnmounted(() => {
.container {
@include sub_background_color($light_background_color);
}
.v2-index-main {
width: 100%;
position: relative;
box-sizing: border-box;
}
</style>
<style>
.hover-search {
@@ -250,7 +273,8 @@ onUnmounted(() => {
position: fixed;
top: 0;
z-index: 9999;
box-shadow:0 0 10px 2px rgb(90 90 90 / 60%);
box-shadow: 0 4px 16px rgba(15, 23, 42, 0.08);
border-bottom: 1px solid #f1f5f9;
transition: 0.35s;
}
.show {

View File

@@ -1,8 +1,8 @@
<template>
<div class="merchant">
<BaseHeader/>
<TopBar></TopBar>
<!-- 搜索栏 -->
<Search :storeId="storeMsg.storeId || $route.query.id" @search="search"></Search>
<SearchHeader @search="search"></SearchHeader>
<div class="store-head">
<div class="store-head-main">
<div class="shop-info">
@@ -129,7 +129,8 @@ import {
isStoreCollection,
} from "@/api/member";
import {goodsList as goodsListApi} from "@/api/goods";
import Search from "@/components/Search";
import TopBar from '@/components/indexDecorate/components/TopBar.vue';
import SearchHeader from '@/components/indexDecorate/components/SearchHeader.vue';
import ModelForm from "@/components/indexDecorate/ModelForm";
import storage from "@/plugins/storage";
import {getFloorStoreData} from "@/api/index.js";

View File

@@ -1,7 +1,7 @@
<template>
<div class="not-found-page">
<BaseHeader></BaseHeader>
<Search :show-tag="false"></Search>
<TopBar></TopBar>
<SearchHeader :options="{ showHotWords: false }"></SearchHeader>
<div class="not-found">
<h1>页面不存在</h1>
<p>你访问的地址没有对应页面</p>
@@ -12,6 +12,9 @@
</template>
<script setup>
import TopBar from '@/components/indexDecorate/components/TopBar.vue';
import SearchHeader from '@/components/indexDecorate/components/SearchHeader.vue';
defineOptions({ name: "NotFound" });
</script>

View File

@@ -1,7 +1,7 @@
<template>
<div>
<BaseHeader></BaseHeader>
<Search></Search>
<TopBar></TopBar>
<SearchHeader></SearchHeader>
<!-- 添加成功提示 -->
<div class="add-info-box-container">
@@ -50,6 +50,8 @@ export default {
<script setup>
import { onMounted, ref } from "vue";
import TopBar from '@/components/indexDecorate/components/TopBar.vue';
import SearchHeader from '@/components/indexDecorate/components/SearchHeader.vue';
import { useRoute } from "vue-router";
const route = useRoute();

View File

@@ -1,7 +1,7 @@
<template>
<div>
<BaseHeader></BaseHeader>
<Search></Search>
<TopBar></TopBar>
<SearchHeader></SearchHeader>
<div class="container width_1200">
<h1 class="page-title">文章帮助中心</h1>
@@ -50,6 +50,8 @@
<script setup>
import { onMounted, reactive, ref } from 'vue'
import TopBar from '@/components/indexDecorate/components/TopBar.vue';
import SearchHeader from '@/components/indexDecorate/components/SearchHeader.vue';
import { useRoute } from 'vue-router'
import { articleCateList, articleDetail, articleList as fetchArticleList } from '@/api/common.js'

View File

@@ -1,7 +1,7 @@
<template>
<div style="background:#fff;">
<BaseHeader></BaseHeader>
<Search style="border-bottom:2px solid red;"></Search>
<TopBar></TopBar>
<SearchHeader></SearchHeader>
<div class="base-width cate-container">
<el-breadcrumb>
<el-breadcrumb-item to="/">首页</el-breadcrumb-item>
@@ -106,7 +106,8 @@ export default {
import { ref, computed, onMounted, nextTick } from "vue";
import { useRoute, useRouter } from "vue-router";
import { Message } from "@/utils/message";
import Search from "@/components/Search";
import TopBar from '@/components/indexDecorate/components/TopBar.vue';
import SearchHeader from '@/components/indexDecorate/components/SearchHeader.vue';
import { addCartGoods } from "@/api/cart.js";
import { pointGoodsDetail } from "@/api/promotion";
import {

View File

@@ -1,7 +1,7 @@
<template>
<div class="point-mall">
<BaseHeader></BaseHeader>
<Search></Search>
<TopBar></TopBar>
<SearchHeader></SearchHeader>
<cateNav></cateNav>
<h3 class="promotion-decorate">积分商品</h3>
<el-select @select="selectCate" size="small" class="cate-select-con" v-model="cateId">
@@ -46,6 +46,8 @@
</template>
<script setup>
import { onMounted, reactive, ref } from "vue";
import TopBar from '@/components/indexDecorate/components/TopBar.vue';
import SearchHeader from '@/components/indexDecorate/components/SearchHeader.vue';
import { useRoute, useRouter } from "vue-router";
import { pointGoods, pointGoodsCategory } from "@/api/promotion.js";