Explorar o código

Merge branch 'master' of http://8.152.4.3:3000/yp_web/yoe-shop-web

hurx hai 1 día
pai
achega
d47ada12c2
Modificáronse 57 ficheiros con 2360 adicións e 197 borrados
  1. BIN=BIN
      src/assets/jd/banner_green_ad.png
  2. BIN=BIN
      src/assets/jd/banner_industrial.png
  3. BIN=BIN
      src/assets/jd/banner_office.png
  4. BIN=BIN
      src/assets/jd/banner_welfare.png
  5. BIN=BIN
      src/assets/jd/brand_logo_1.png
  6. BIN=BIN
      src/assets/jd/brand_logo_2.png
  7. BIN=BIN
      src/assets/jd/prod_it.png
  8. BIN=BIN
      src/assets/jd/prod_lifestyle.png
  9. BIN=BIN
      src/assets/jd/prod_light.png
  10. BIN=BIN
      src/assets/jd/prod_lock.png
  11. BIN=BIN
      src/assets/jd/prod_office.png
  12. BIN=BIN
      src/assets/jd/prod_rags.png
  13. BIN=BIN
      src/assets/jd/scene_cooling.png
  14. BIN=BIN
      src/assets/jd/scene_marketing.png
  15. BIN=BIN
      src/assets/jd/scene_stationery.png
  16. BIN=BIN
      src/assets/jd/scene_teambuilding.png
  17. BIN=BIN
      src/assets/jd/user_avatar.png
  18. 2 3
      src/layout/components/header.vue
  19. 1 1
      src/layout/components/nav.vue
  20. 6 0
      src/permission.ts
  21. 1 0
      src/types/components.d.ts
  22. 1 1
      src/views/greg/index.vue
  23. 1 1
      src/views/home/index-fuli.vue
  24. 4 3
      src/views/home/index.vue
  25. 125 0
      src/views/home/jdcomponents/JDBanner.vue
  26. 331 0
      src/views/home/jdcomponents/JDBannerCards.vue
  27. 201 0
      src/views/home/jdcomponents/JDCategory.vue
  28. 235 0
      src/views/home/jdcomponents/JDFooter.vue
  29. 258 0
      src/views/home/jdcomponents/JDHeader.vue
  30. 296 0
      src/views/home/jdcomponents/JDProducts.vue
  31. 137 0
      src/views/home/jdcomponents/JDScene.vue
  32. 375 0
      src/views/home/jdcomponents/JDUserPanel.vue
  33. 86 0
      src/views/home/jdcomponents/jd-repro.css
  34. 0 1
      src/views/home/pccomponents/pages/activity.vue
  35. 12 1
      src/views/home/pccomponents/pages/advert.vue
  36. 2 1
      src/views/home/pccomponents/pages/article.vue
  37. 6 3
      src/views/home/pccomponents/pages/brand.vue
  38. 17 13
      src/views/home/pccomponents/pages/discover.vue
  39. 3 0
      src/views/home/pccomponents/pages/floor.vue
  40. 4 3
      src/views/home/pccomponents/pages/goods.vue
  41. 16 5
      src/views/home/pccomponents/pages/goodsList.vue
  42. 9 6
      src/views/home/pccomponents/pages/head.vue
  43. 2 1
      src/views/home/pccomponents/pages/imageCube.vue
  44. 14 2
      src/views/home/pccomponents/pages/navigation.vue
  45. 1 1
      src/views/index.vue
  46. 102 61
      src/views/item/index.vue
  47. 9 5
      src/views/login.vue
  48. 5 4
      src/views/plan/guide.vue
  49. 4 3
      src/views/plan/index.vue
  50. 33 31
      src/views/plan/project.vue
  51. 5 3
      src/views/plan_info/guide.vue
  52. 5 2
      src/views/plan_info/index.vue
  53. 3 1
      src/views/plan_info/procure.vue
  54. 3 2
      src/views/plan_info/project.vue
  55. 3 2
      src/views/search/brand.vue
  56. 36 31
      src/views/search/index.vue
  57. 6 6
      src/views/search/special.vue

BIN=BIN
src/assets/jd/banner_green_ad.png


BIN=BIN
src/assets/jd/banner_industrial.png


BIN=BIN
src/assets/jd/banner_office.png


BIN=BIN
src/assets/jd/banner_welfare.png


BIN=BIN
src/assets/jd/brand_logo_1.png


BIN=BIN
src/assets/jd/brand_logo_2.png


BIN=BIN
src/assets/jd/prod_it.png


BIN=BIN
src/assets/jd/prod_lifestyle.png


BIN=BIN
src/assets/jd/prod_light.png


BIN=BIN
src/assets/jd/prod_lock.png


BIN=BIN
src/assets/jd/prod_office.png


BIN=BIN
src/assets/jd/prod_rags.png


BIN=BIN
src/assets/jd/scene_cooling.png


BIN=BIN
src/assets/jd/scene_marketing.png


BIN=BIN
src/assets/jd/scene_stationery.png


BIN=BIN
src/assets/jd/scene_teambuilding.png


BIN=BIN
src/assets/jd/user_avatar.png


+ 2 - 3
src/layout/components/header.vue

@@ -34,9 +34,8 @@
         </div>
         <div v-if="!userInfo.user" class="header-text end" @click="onPath('/login')" style="cursor: pointer">请登录</div>
         <div v-if="!userInfo.user" class="header-text hig" @click="onPath('/breg')">免费注册</div>
-        <div v-if="route.path == '/indexEnterprise'" class="header-text" @click="onPath('/')">切换到个人</div>
-        <!-- onPath('/indexEnterprise') -->
-        <div v-else class="header-text" @click="goEnterprise">切换到企业</div>
+        <!-- <div v-if="route.path == '/indexEnterprise'" class="header-text" @click="onPath('/')">切换到个人</div>
+        <div v-else class="header-text" @click="goEnterprise">切换到企业</div> -->
         <div class="header-text" @click="onPath('/order/orderManage')">我的订单</div>
         <div v-if="userInfo.user && userInfo.user.userSonType != 4" class="header-text" @click="onPath('/enterprise/companyInfo')">会员中心</div>
         <div class="header-text" @click="onPath('/theme?id=1')">人才招聘</div>

+ 1 - 1
src/layout/components/nav.vue

@@ -241,7 +241,7 @@ const leaveClassify = () => {
         right: 0;
         left: 234px;
         // width: 966px;
-        height: 100%;
+        height: 540px;
         border: 1px solid var(--el-color-primary);
         background-color: #ffffff;
         overflow-y: auto;

+ 6 - 0
src/permission.ts

@@ -63,6 +63,12 @@ function getDomainHomePath(site: string, station: ReturnType<typeof stationStore
     }
   }
 
+  // 新增:当 userSonType 为 '3' 时,优先跳转到 /indexEnterprise(如果允许)
+  const userStore = useUserStore();
+  if (userStore.userInfo?.user.userSonType === '3' && allowedPaths.includes('/indexEnterprise')) {
+    return '/indexEnterprise';
+  }
+
   // 新增:根据 diyConfig 配置判断 /index、/indexMro、/indexFuli
   const diyConfig = station.diyState || [];
 

+ 1 - 0
src/types/components.d.ts

@@ -43,6 +43,7 @@ declare module 'vue' {
     ElFormItem: typeof import('element-plus/es')['ElFormItem']
     ElIcon: typeof import('element-plus/es')['ElIcon']
     ElImage: typeof import('element-plus/es')['ElImage']
+    ElImageViewer: typeof import('element-plus/es')['ElImageViewer']
     ElInput: typeof import('element-plus/es')['ElInput']
     ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
     ElMenu: typeof import('element-plus/es')['ElMenu']

+ 1 - 1
src/views/greg/index.vue

@@ -241,7 +241,7 @@
     <div class="pay-foot" v-if="nextNum != 4">
       <div class="foot-bos">
         <el-button @click="previousStep" v-if="nextNum == 2" class="bnt1">返回上一步</el-button>
-        <el-button @click="nextStep" class="bnt2" type="primary" :loading="loading">{{ nextNum == 2 ? '提交并完成注册' : '下一步' }}</el-button>
+        <el-button v-if="nextNum != 3" @click="nextStep" class="bnt2" type="primary" :loading="loading">{{ nextNum == 2 ? '提交并完成注册' : '下一步' }}</el-button>
       </div>
     </div>
     <el-dialog

+ 1 - 1
src/views/home/index-fuli.vue

@@ -118,7 +118,7 @@ const getHead = async () => {
 // 场景采购
 getRecommendAdList({}).then((res) => {
   if (res.code == 200) {
-    imageCubeData.value.imageHeight = 182;
+    imageCubeData.value.aspectRatio = 292.5 / 183;
     imageCubeData.value.number = 4;
     imageCubeData.value.gap = 10;
     imageCubeData.value.imageTopRounded = 5;

+ 4 - 3
src/views/home/index.vue

@@ -5,11 +5,11 @@
 
     <!-- 热门方案 -->
     <indexTitle :datas="hotTitle"></indexTitle>
-    <navigation v-if="hotList.length > 0" :datas="hotList"></navigation>
+    <navigation v-if="hotList.length > 0" :datas="hotList" :row="{ aspectRatio: 170 / 112, imageHeight: 112 }"></navigation>
 
     <!-- 场景采购 -->
     <indexTitle :datas="sceneTitle"></indexTitle>
-    <imageCube v-if="sceneList.length > 0" :datas="sceneList"></imageCube>
+    <imageCube v-if="sceneList.length > 0" :datas="sceneList" :row="{ aspectRatio: 232 / 300 }"></imageCube>
 
     <!-- 大牌推荐 -->
     <indexTitle :datas="bigbrandTitle"></indexTitle>
@@ -24,7 +24,7 @@
 
     <!-- 采购指南 -->
     <indexTitle :datas="procureTitle"></indexTitle>
-    <advert v-if="procureList.length > 0" :row="{ navlList: procureList, styleType: 1 }"></advert>
+    <advert v-if="procureList.length > 0" :row="{ navlList: procureList, styleType: 1, aspectRatio: 393 / 220 }"></advert>
 
     <!-- 循环-商品楼层 -->
     <div v-for="(item1, index1) in homeList" :key="index1">
@@ -144,6 +144,7 @@ const getHead = async () => {
           show: true
         });
       });
+      // headData.value.advertList.push( headData.value.advertList[0]);
     }
 
     const datas5 = await getYouYiZiXunPage({});

+ 125 - 0
src/views/home/jdcomponents/JDBanner.vue

@@ -0,0 +1,125 @@
+<template>
+  <div class="banner-flex w flex">
+    <!-- 侧边条 -->
+    <div class="side-deco" v-if="isLargeScreen">
+      企业专享低至5折 <i></i>
+    </div>
+
+    <!-- 轮播图 -->
+    <div class="slider-box" :style="{ flex: isLargeScreen ? '0 0 540px' : '1' }">
+      <img src="https://img14.360buyimg.com/babel/jfs/t1/181519/33/23577/253912/628f3a38E7b53940c/7c703080e72c8334.jpg" />
+    </div>
+
+    <!-- 复合网格 -->
+    <div class="mini-grid flex-1">
+      <div class="grid-wrap">
+        <div class="g-item subsidy">
+          <div class="g-h">企业购×百亿补贴 <span>先享后付</span></div>
+          <div class="g-p-list flex">
+            <div class="g-p" v-for="i in 4" :key="i">
+              <img src="https://img10.360buyimg.com/n1/s200x200_jfs/t1/192131/28/13600/171542/611a1b5aE3c869e5d/13e007802874102d.jpg" />
+              <p>¥69.9</p>
+            </div>
+          </div>
+        </div>
+        <div class="g-item rank">
+          <div class="g-h">企业榜单 <span>同行买</span></div>
+          <div class="g-rank-list flex">
+             <div class="r-i flex-1" v-for="i in 2" :key="i">
+               <img src="https://img13.360buyimg.com/n1/s200x200_jfs/t1/175027/2/13627/184131/611a1b7eEc1248c8b/09c3d4f4e2f4f4f4.jpg" />
+               <p>电脑榜</p>
+             </div>
+          </div>
+        </div>
+        <div class="g-item store">
+          <div class="g-h">品牌好店 <span>送E卡</span></div>
+          <div class="store-inner flex-column flex-center">
+             <img src="https://img12.360buyimg.com/imagetools/jfs/t1/143521/1/32579/6255/63f8582bEcf959247/e16d443900331003.png" style="width:50px" />
+             <p style="font-size:12px; margin-top:5px">Apple自营店</p>
+          </div>
+        </div>
+        <div class="g-item new">
+          <div class="g-h">京东新品 <span>美的新鲜</span></div>
+          <div class="new-list flex">
+             <div class="n-p flex-1" v-for="i in 2" :key="i">
+               <img src="https://img10.360buyimg.com/n1/s200x200_jfs/t1/170942/37/13844/145826/611a1a7aE5e899b82/6e0f8087c0a6b9a9.jpg" />
+             </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 用户面板 -->
+    <div class="user-wrap" v-if="isLargeScreen">
+      <div class="u-top flex-column flex-center">
+         <img src="https://img11.360buyimg.com/imagetools/jfs/t1/143521/1/32579/6255/63f8582bEcf959247/e16d443900331003.png" class="avatar" />
+         <p class="name">Hi, 欢迎访问</p>
+         <div class="u-btns flex">
+            <button class="b-login">登录</button>
+            <button class="b-reg">注册</button>
+         </div>
+      </div>
+      <div class="u-tools">
+         <p class="t-h">企业工作台</p>
+         <div class="t-grid">
+            <div class="t-i" v-for="i in 8" :key="i">
+               <i></i>
+               <span>工具{{i}}</span>
+            </div>
+         </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted, onUnmounted } from 'vue';
+const isLargeScreen = ref(window.innerWidth >= 1600);
+const check = () => isLargeScreen.value = window.innerWidth >= 1600;
+onMounted(() => window.addEventListener('resize', check));
+onUnmounted(() => window.removeEventListener('resize', check));
+</script>
+
+<style scoped>
+.banner-flex { height: 460px; margin: 10px auto; gap: 10px; }
+
+.side-deco { width: 56px; background: #34C759; border-radius: 12px; writing-mode: vertical-lr; color: #fff; font-weight: bold; font-size: 18px; text-align: center; display: flex; align-items: center; justify-content: center; letter-spacing: 4px; }
+
+.slider-box { border-radius: 12px; overflow: hidden; background: #eee; }
+.slider-box img { width: 100%; height: 100%; object-fit: cover; }
+
+.mini-grid { }
+.grid-wrap { height: 100%; display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; gap: 10px; }
+.g-item { background: #fff; border-radius: 12px; padding: 12px; display: flex; flex-direction: column; }
+.g-h { font-weight: bold; font-size: 14px; margin-bottom: 10px; }
+.g-h span { color: #FF9500; font-size: 12px; float: right; font-weight: normal; }
+
+.g-p-list { gap: 5px; flex: 1; }
+.g-p { flex: 1; text-align: center; }
+.g-p img { width: 100%; border-radius: 4px; }
+.g-p p { color: #E1251B; font-size: 12px; font-weight: bold; }
+
+.g-rank-list { gap: 10px; flex: 1; }
+.r-i { background: #F7F8FA; border-radius: 6px; padding: 5px; text-align: center; }
+.r-i img { width: 100%; border-radius: 4px; }
+.r-i p { font-size: 11px; margin-top: 3px; }
+
+.user-wrap { width: 230px; background: #fff; border-radius: 12px; padding: 15px; }
+.avatar { width: 50px; height: 50px; border-radius: 25px; }
+.name { margin-top: 10px; font-weight: bold; }
+.u-btns { margin-top: 15px; gap: 10px; }
+.u-btns button { padding: 4px 15px; border-radius: 12px; border: none; font-size: 12px; cursor: pointer; }
+.b-login { background: #E1251B; color: #fff; }
+.b-reg { background: #333; color: #e5d790; }
+
+.u-tools { margin-top: 20px; }
+.t-h { font-weight: bold; font-size: 13px; margin-bottom: 10px; }
+.t-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
+.t-i { text-align: center; font-size: 11px; color: #666; }
+.t-i i { display: block; width: 24px; height: 24px; background: #f4f4f4; border-radius: 50%; margin: 0 auto 5px; }
+
+@media screen and (max-width: 1599px) {
+  .banner-flex { height: auto; min-height: 400px; }
+  .grid-wrap { grid-template-rows: auto; }
+}
+</style>

+ 331 - 0
src/views/home/jdcomponents/JDBannerCards.vue

@@ -0,0 +1,331 @@
+<template>
+  <div class="central-ads">
+    <!-- 上半部分 -->
+    <div class="top-row flex">
+      <!-- 智能选品 Banner (多图轮播) -->
+      <div class="slider-box" @mouseenter="stopAuto" @mouseleave="startAuto">
+        <div class="slider-list flex" :style="{ transform: `translateX(-${currentIdx * 100}%)` }">
+          <div class="slider-item" v-for="(slide, i) in bannerSlides" :key="i">
+            <img :src="slide.img" class="banner-img" />
+            <div class="slider-content">
+              <h1>{{ slide.h1 }}</h1>
+              <h2>{{ slide.h2 }}</h2>
+              <p>{{ slide.p }}</p>
+            </div>
+          </div>
+        </div>
+        <div class="ai-logo">
+           <span>A</span><span>i</span>
+        </div>
+        <div class="dots">
+          <span
+            v-for="(_, i) in bannerSlides"
+            :key="i"
+            :class="{ active: currentIdx === i }"
+            @click="currentIdx = i"
+          ></span>
+        </div>
+      </div>
+
+      <!-- 百亿补贴 -->
+      <div class="subsidy-box card-base">
+        <div class="c-header flex-between">
+          <span class="title">企业购×百亿补贴</span>
+          <span class="tag">先采后付 享底价</span>
+        </div>
+        <div class="p-list flex">
+          <div class="p-mini">
+             <img src="@/assets/jd/prod_it.png" />
+             <p class="price"><span>¥</span>69.9</p>
+          </div>
+          <div class="p-mini">
+             <img src="@/assets/jd/prod_office.png" />
+             <p class="price"><span>¥</span>84.8</p>
+          </div>
+          <div class="p-mini">
+             <img src="@/assets/jd/prod_lifestyle.png" />
+             <p class="price"><span>¥</span>139.9</p>
+          </div>
+          <div class="p-mini">
+             <img src="@/assets/jd/prod_it.png" />
+             <p class="price"><span>¥</span>1749</p>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 下半部分 -->
+    <div class="bottom-row flex">
+       <!-- 企采榜单 -->
+       <div class="card-base b-item">
+         <div class="c-header flex-between">
+           <span class="title">企采榜单</span>
+           <span class="tag-orange">同行都在买</span>
+         </div>
+         <div class="rank-list flex">
+            <div class="r-i">
+               <div class="r-title yellow-t">办公电脑榜<i class="arr"> &gt;</i></div>
+               <img src="@/assets/jd/prod_it.png" />
+               <span class="sold">已售1543件</span>
+            </div>
+            <div class="r-i">
+               <div class="r-title red-t">文具榜<i class="arr"> &gt;</i></div>
+               <img src="@/assets/jd/prod_office.png" />
+               <span class="sold">已售2.3万件</span>
+            </div>
+         </div>
+       </div>
+
+       <!-- 品牌好店 -->
+       <div class="card-base b-item">
+         <div class="c-header flex-between">
+           <span class="title">品牌好店</span>
+           <span class="tag-orange">返2000元E卡</span>
+         </div>
+         <div class="brand-box flex">
+            <div class="brand-i">
+              <img src="@/assets/jd/brand_logo_1.png" class="logo" />
+              <p class="name">鲁花京东自营旗舰店</p>
+              <span class="btn btn-red">品质保障</span>
+            </div>
+            <div class="brand-i">
+              <img src="@/assets/jd/brand_logo_2.png" class="logo" />
+              <p class="name">金龙鱼京东自营旗舰</p>
+              <span class="btn btn-red">热销品牌</span>
+            </div>
+         </div>
+       </div>
+
+       <!-- 企业精选 -->
+       <div class="card-base b-item">
+         <div class="c-header flex-between">
+           <span class="title">企业精选</span>
+           <span class="tag-gray">品牌专供 库存足</span>
+         </div>
+         <div class="p-list flex">
+            <div class="p-mini">
+               <img src="@/assets/jd/prod_it.png" />
+               <p class="price"><span>¥</span>10740 <span class="badge-blue">企业价</span></p>
+            </div>
+            <div class="p-mini">
+               <img src="@/assets/jd/prod_lifestyle.png" />
+               <p class="price"><span>¥</span>877</p>
+            </div>
+         </div>
+       </div>
+
+       <!-- 京东新品 -->
+       <div class="card-base b-item">
+         <div class="c-header flex-between">
+           <span class="title">企业购×京东新品</span>
+           <span class="tag-orange">美的新鲜</span>
+         </div>
+         <div class="p-list flex">
+            <div class="p-mini">
+               <img src="@/assets/jd/prod_lifestyle.png" />
+               <p class="price"><span>¥</span>7188</p>
+            </div>
+            <div class="p-mini">
+               <img src="@/assets/jd/prod_office.png" />
+               <p class="price"><span>¥</span>34.9</p>
+            </div>
+         </div>
+       </div>
+    </div>
+  </div>
+</template>
+<script setup>
+import { ref, onMounted, onUnmounted } from 'vue';
+
+const currentIdx = ref(0);
+const bannerSlides = [
+  { h1: '智能选品', h2: '让采购更高效', p: '需求清单极速匹配', img: '@/assets/jd/prod_it.png' }, // Use it as default or generate dedicated
+  { h1: '办公大促', h2: '职场焕新季', p: '精选文具低至5折', img: '@/assets/jd/banner_office.png' },
+  { h1: '工业采买', h2: '正品低价保障', p: '专业工具 一站购齐', img: '@/assets/jd/banner_industrial.png' },
+  { h1: '员工福利', h2: '温情定制礼', p: '打造有温度的职场', img: '@/assets/jd/banner_welfare.png' }
+];
+
+let timer = null;
+const startAuto = () => {
+  timer = setInterval(() => {
+    currentIdx.value = (currentIdx.value + 1) % bannerSlides.length;
+  }, 4000);
+};
+const stopAuto = () => {
+  if (timer) clearInterval(timer);
+};
+
+onMounted(() => startAuto());
+onUnmounted(() => stopAuto());
+</script>
+
+<style scoped>
+.central-ads {
+  display: flex;
+  flex-direction: column;
+  gap: 12px;
+  height: 100%;
+}
+
+.top-row {
+  height: 190px;
+  gap: 12px;
+}
+
+.bottom-row {
+  flex: 1;
+  gap: 12px;
+}
+
+.slider-box {
+  flex: 5.5;
+  background: #187AF2;
+  border-radius: 8px;
+  position: relative;
+  overflow: hidden;
+  cursor: pointer;
+}
+
+.slider-list {
+  width: 100%;
+  height: 100%;
+  transition: transform 0.5s ease-in-out;
+}
+
+.slider-item {
+  min-width: 100%;
+  height: 100%;
+  position: relative;
+  background: #187AF2;
+}
+
+.banner-img {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  opacity: 0.7;
+}
+
+.slider-content {
+  position: absolute;
+  left: 32px;
+  top: 36px;
+  color: #fff;
+  z-index: 5;
+}
+
+.slider-content h1 { font-size: 26px; font-weight: normal; margin-bottom: 2px; letter-spacing: 1px; }
+.slider-content h2 { font-size: 26px; font-weight: 800; margin-bottom: 16px; letter-spacing: 1px; }
+.slider-content p { font-size: 13px; font-weight: 500; opacity: 0.9; }
+
+.ai-logo {
+  position: absolute;
+  right: 60px;
+  top: 20px;
+  font-family: Arial, sans-serif;
+  font-weight: 900;
+  display: flex;
+  align-items: baseline;
+  text-shadow: 0 10px 20px rgba(0,0,0,0.2);
+}
+.ai-logo span:first-child { font-size: 110px; color: #fff; background: linear-gradient(180deg, #E2F1FF, #FFFFFF); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
+.ai-logo span:last-child { font-size: 80px; color: #66B2FF; margin-left: 5px; }
+
+.dots {
+  position: absolute;
+  bottom: 16px;
+  left: 32px;
+  display: flex;
+  gap: 6px;
+}
+.dots span { display: block; width: 6px; height: 6px; background: rgba(255,255,255,0.4); border-radius: 50%; }
+.dots span.active { width: 14px; background: #fff; border-radius: 3px; }
+
+.subsidy-box {
+  flex: 4.5;
+}
+
+.card-base {
+  background: #F8F9FA; /* 与侧边分类背景色相同 */
+  border-radius: 8px;
+  padding: 16px;
+  display: flex;
+  flex-direction: column;
+  transition: transform 0.2s, box-shadow 0.2s;
+  cursor: pointer;
+  box-shadow: 0 1px 4px rgba(0,0,0,0.02);
+}
+.card-base:hover {
+  transform: translateY(-2px);
+  box-shadow: 0 6px 16px rgba(0,0,0,0.08);
+}
+
+.b-item {
+  flex: 1;
+}
+
+.c-header {
+  margin-bottom: 12px;
+  align-items: baseline;
+}
+
+.title {
+  font-weight: 800;
+  font-size: 16px;
+  color: #000;
+}
+
+.tag { font-size: 12px; color: #D46B08; font-weight: bold; }
+.tag-orange { font-size: 11px; color: #D46B08; }
+.tag-gray { font-size: 11px; color: #8C8C8C; }
+
+.p-list {
+  flex: 1;
+  gap: 12px;
+}
+
+.p-mini {
+  flex: 1;
+  text-align: center;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+}
+
+.p-mini img {
+  width: 90%;
+  margin: 0 auto 6px;
+}
+
+.price {
+  color: #E1251B;
+  font-size: 16px;
+  font-weight: bold;
+}
+.price span { font-size: 12px; font-weight: normal; margin-right: 1px; }
+
+.badge-blue {
+  background: #1890FF;
+  color: #fff;
+  font-size: 10px;
+  padding: 1px 4px;
+  border-radius: 2px;
+  font-weight: normal;
+  vertical-align: middle;
+}
+
+.rank-list { gap: 12px; flex: 1; }
+.r-i { flex: 1; background: #fff; border-radius: 6px; display: flex; flex-direction: column; justify-content: space-between; position: relative; }
+.r-title { position: absolute; top: -10px; left: 50%; transform: translateX(-50%); padding: 2px 10px; border-radius: 12px; font-size: 11px; font-weight: bold; white-space: nowrap; z-index: 2; }
+.yellow-t { background: #FFF3E0; color: #E65100; }
+.red-t { background: #FFEBEE; color: #C62828; }
+.r-title .arr { font-style: normal; font-size: 9px; opacity: 0.8; }
+.r-i img { width: 80%; margin: 15px auto 5px; }
+.sold { font-size: 11px; font-weight: bold; color: #E1251B; background: #FFF0F0; border-radius: 0 0 6px 6px; padding: 4px 0; text-align: center; width: 100%; }
+
+.brand-box { gap: 12px; flex: 1; }
+.brand-i { flex: 1; text-align: center; display: flex; flex-direction: column; align-items: center; justify-content: space-between; }
+.logo { width: 50px; height: 50px; margin-top: 5px; }
+.name { font-size: 11px; color: #1890FF; white-space: nowrap; transform: scale(0.9); }
+.btn-red { font-size: 11px; color: #E1251B; border: 1px solid #E1251B; padding: 2px 8px; border-radius: 12px; margin-bottom: 5px; }
+</style>

+ 201 - 0
src/views/home/jdcomponents/JDCategory.vue

@@ -0,0 +1,201 @@
+<template>
+  <div class="cate-menu" @mouseleave="activeIndex = -1">
+    <ul class="cate-list">
+      <li 
+        v-for="(c, i) in categories" 
+        :key="i" 
+        class="cate-item"
+        :class="{ active: activeIndex === i }"
+        @mouseenter="activeIndex = i"
+      >
+        <img :src="c.icon" class="cate-icon" />
+        <a href="#">{{ c.name }}</a>
+      </li>
+    </ul>
+
+    <!-- 巨大悬浮菜单面板 (根据图5精细刻画) -->
+    <div class="category-pop" v-show="activeIndex !== -1">
+       <div class="pop-header flex-between">
+          <div class="pop-tags flex">
+             <span class="p-tag">设备固资</span>
+             <span class="p-tag">职场环境</span>
+             <span class="p-tag">3C数码电子城</span>
+          </div>
+          <div class="pop-logo">
+             <span class="red-t">京东</span><span class="black-t">3C数码</span><br/>
+             <span class="small-t">电脑 | 数码 | 手机 | 图书 | 文具</span>
+          </div>
+       </div>
+
+       <div class="pop-body">
+          <dl class="sub-dl flex">
+             <dt>办公电脑</dt>
+             <dd>
+                <a href="#">台式机</a><a href="#">平板电脑</a><a href="#">显示器</a><a href="#">服务器</a><a href="#">工作站</a><a href="#">一体机</a><a href="#">组装电脑</a><a href="#">游戏本</a><a href="#">设计师本</a><a href="#">笔记本配件</a><a href="#">平板电脑配件</a><a href="#">阅卷机</a><a href="#">办公本</a>
+             </dd>
+          </dl>
+          <dl class="sub-dl flex">
+             <dt>办公打印</dt>
+             <dd>
+                <a href="#">复合机</a><a href="#">打印机</a><a href="#">多功能一体机</a><a href="#">扫描仪</a><a href="#">条码打印机</a><a href="#">碎纸机</a><a href="#">装订机</a><a href="#">高拍仪</a><a href="#">标签打印机</a><a href="#">传真设备</a>
+             </dd>
+          </dl>
+          <dl class="sub-dl flex">
+             <dt>电脑组件</dt>
+             <dd>
+                <a href="#">显示器</a><a href="#">硬盘</a><a href="#">SSD固态硬盘</a><a href="#">机械硬盘</a><a href="#">显卡</a><a href="#">内存</a><a href="#">主板CPU套装</a><a href="#">组装机</a><a href="#">装机配件</a><a href="#">机箱</a><a href="#">刻录机</a><a href="#">光驱</a><a href="#">散热器</a><a href="#">电源</a>
+             </dd>
+          </dl>
+          <dl class="sub-dl flex">
+             <dt>电脑外设</dt>
+             <dd>
+                <a href="#">机柜</a><a href="#">键盘</a><a href="#">扩展坞</a><a href="#">手柄方向盘</a><a href="#">鼠标</a><a href="#">鼠标垫</a><a href="#">移动固态硬盘</a><a href="#">移动机械硬盘</a><a href="#">硬盘盒</a><a href="#">游戏耳机</a><a href="#">游戏机</a><a href="#">游戏软件</a><a href="#">游戏周边</a>
+             </dd>
+          </dl>
+          <dl class="sub-dl flex">
+             <dt>智能会议</dt>
+             <dd>
+                <a href="#">直播设备</a><a href="#">U盘</a><a href="#">UPS电源</a><br/>
+                <a href="#">办公大屏</a><a href="#">投影机</a><a href="#">会议平板</a><a href="#">会议摄像头</a><a href="#">音响</a><a href="#">会议音响</a><a href="#">麦克风</a><a href="#">路由器</a><a href="#">网络机顶盒</a><a href="#">交换机</a><a href="#">网络存储</a><a href="#">网线</a><a href="#">网卡</a><a href="#">话务耳机</a><br/>
+                <a href="#">安防监控</a><a href="#">电动幕布</a><a href="#">网络仪器仪表</a><a href="#">白板</a><a href="#">功放</a><a href="#">电视配件</a><a href="#">回音壁Soundbar</a><a href="#">会议音视频</a><a href="#">手写板</a><a href="#">投影配件</a><a href="#">录音笔</a><a href="#">翻译机</a><a href="#">翻译设备</a>
+             </dd>
+          </dl>
+          <dl class="sub-dl flex">
+             <dt>IT运维</dt>
+             <dd>
+                <a href="#">交换机</a><a href="#">路由器</a><a href="#">网络机顶盒</a><a href="#">网络存储</a><a href="#">网卡</a><a href="#">网线</a><a href="#">网络配件</a><a href="#">网络仪器仪表</a><a href="#">线缆</a><a href="#">普通网络设备</a>
+             </dd>
+          </dl>
+       </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+
+const activeIndex = ref(-1)
+
+// 线条风格 SVG base64 图标
+const iconPC = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2IiBzdHJva2Utd2lkdGg9IjIiPjxyZWN0IHg9IjIiIHk9IjQiIHdpZHRoPSIyMCIgaGVpZ2h0PSIxNCIgcng9IjIiLz48cGF0aCBkPSJNOCAyMmgybS0yIDBsNC00bTQgNGgybS0yIDBsLTQtNCIvPjwvc3ZnPg=='
+const iconAC = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2IiBzdHJva2Utd2lkdGg9IjIiPjxyZWN0IHg9IjIiIHk9IjYiIHdpZHRoPSIyMCIgaGVpZ2h0PSIxMiIgcng9IjIiLz48cGF0aCBkPSJNMiAxMGgyMG0tMTYgNGg0Ii8+PC9zdmc+'
+const iconPrint = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2IiBzdHJva2Utd2lkdGg9IjIiPjxwYXRoIGQ9Ik02IDlWMmgtNHY3bTggMEg0djExaDE2VjltLTYgMTB2LTVoOHY1Ii8+PC9zdmc+'
+const iconTea = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2IiBzdHJva2Utd2lkdGg9IjIiPjxwYXRoIGQ9Ik00IDhoMTJ2OGExIDEgMCAwIDEtMSAxSDVhMSAxIDAgMCAxLTEtMVY4em0xMiAyYTQgNCAwIDAgMSAwIDhoLTJtLTItMTh2NG0tNCAwdjQiLz48L3N2Zz4='
+const iconPhone = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2IiBzdHJva2Utd2lkdGg9IjIiPjxyZWN0IHg9IjUiIHk9IjIiIHdpZHRoPSIxNCIgaGVpZ2h0PSIyMCIgcng9IjIiLz48cGF0aCBkPSJNMTIgMThoLjAxIi8+PC9zdmc+'
+const iconMask = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2IiBzdHJva2Utd2lkdGg9IjIiPjxwYXRoIGQ9Ik0xMiAyMmM0LjQgMCA4LTMuNiA4LThzLTMuNi04LTgtOC04IDMuNi04IDhzMy42IDggOCA4em0wIDB2LThtLTQgNGg4Ii8+PC9zdmc+'
+const iconMed = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2IiBzdHJva2Utd2lkdGg9IjIiPjxwYXRoIGQ9Ik0xMiA0djE2bS04LThoMTZtLTQgNGExIDEgMCAxIDEtMiAwIDEgMSAwIDAgMSA0IDB6Ii8+PC9zdmc+'
+const iconCar = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2IiBzdHJva2Utd2lkdGg9IjIiPjxwYXRoIGQ9Ik0xOSA4bDEgNG0tMTYgMGwxLTRoMTJtLTIgMmgybTEgMTB2LTJIM3YybTEwIDBoNG0tNiAwSDRtMTQgMGgydjRINnYtNCIvPjwvc3ZnPg=='
+const iconTent = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2IiBzdHJva2Utd2lkdGg9IjIiPjxwYXRoIGQ9Ik0xMiAzTDIgMjFoMjBtLTEwLTE4bDkgMTguNW0tMTggMGg4Ii8+PC9zdmc+'
+
+const categories = [
+  { name: '办公电脑 / 办公打印 / 电脑组件', icon: iconPC },
+  { name: '室温调节 / 冷藏保鲜 / 办公家具', icon: iconAC },
+  { name: '打印耗材 / 办公文具 / 清洁用品', icon: iconPrint },
+  { name: '茶歇福利 / 个护清洁 / 日用福利', icon: iconTea },
+  { name: '电子数码 / 茗茶酒水 / 美妆护肤', icon: iconPhone },
+  { name: '个人防护 / 清洁用品 / 电动工具', icon: iconMask },
+  { name: '养生茶饮 / 滋补礼盒 / 营养保健', icon: iconMed },
+  { name: '汽车用品 / 车辆养护 / 整车采购', icon: iconCar },
+  { name: '户外装备 / 体育用品 / 工装工服', icon: iconTent }
+];
+</script>
+
+<style scoped>
+.cate-menu { position: relative; width: 100%; height: 100%; z-index: 100; }
+.cate-list { padding: 10px 0; background: #F8F9FA; height: 100%; box-sizing: border-box; }
+
+.cate-item { 
+  height: 40px; 
+  padding: 0 16px; 
+  cursor: pointer; 
+  display: flex; 
+  align-items: center; 
+  position: relative;
+  box-sizing: border-box;
+  border: 1px solid transparent; /* 为红框预留 */
+}
+
+.cate-item.active, .cate-item:hover { 
+  background: #fff; 
+  border-color: #E1251B; /* 四周边框变红 */
+  border-right-color: #fff; /* 右边框变白打通 */
+  z-index: 201; /* 盖在弹窗上方 */
+  width: calc(100% + 1px); /* 向右延伸 1px */
+}
+
+.cate-item.active a, .cate-item:hover a { 
+  color: #E1251B; 
+  font-weight: bold;
+}
+
+.cate-icon {
+  width: 16px;
+  height: 16px;
+  margin-right: 12px;
+  opacity: 0.7;
+}
+
+.cate-item.active .cate-icon {
+  filter: invert(27%) sepia(51%) saturate(2878%) hue-rotate(346deg) brightness(104%) contrast(97%);
+}
+
+.cate-item a { font-size: 14px; color: #333; text-decoration: none; }
+
+/* 右侧巨大弹出层 */
+.category-pop {
+  position: absolute;
+  left: 280px;
+  top: 0;
+  width: 820px;
+  height: 440px;
+  background: #fff;
+  border: 1px solid #E1251B;
+  border-radius: 12px;
+  box-shadow: 4px 6px 20px rgba(0,0,0,0.12);
+  padding: 24px 30px;
+  z-index: 200;
+  box-sizing: border-box;
+}
+
+/* 顶部标签和 Logo */
+.pop-header { margin-bottom: 25px; align-items: flex-end; }
+.pop-tags { gap: 12px; }
+.p-tag { background: #F4F4F4; color: #333; font-size: 12px; padding: 6px 16px; border-radius: 4px; cursor: pointer; }
+.p-tag:hover { background: #E1251B; color: #fff; }
+
+.pop-logo { text-align: right; line-height: 1.2; }
+.red-t { color: #E1251B; font-size: 18px; font-weight: 900; }
+.black-t { color: #000; font-size: 18px; font-weight: 900; }
+.small-t { font-size: 9px; color: #E1251B; letter-spacing: 1px; }
+
+/* 主体列表区域 */
+.sub-dl {
+  margin-bottom: 12px;
+  align-items: flex-start;
+  line-height: 1.8;
+}
+.sub-dl dt {
+  width: 75px;
+  font-weight: bold;
+  font-size: 12px;
+  color: #000;
+  margin-right: 15px;
+  text-align: right;
+  white-space: nowrap;
+}
+.sub-dl dd {
+  flex: 1;
+  display: flex;
+  flex-wrap: wrap;
+  gap: 0 16px;
+}
+.sub-dl dd a {
+  font-size: 12px;
+  color: #8C8C8C;
+  text-decoration: none;
+  white-space: nowrap;
+}
+.sub-dl dd a:hover {
+  color: #E1251B;
+}
+</style>

+ 235 - 0
src/views/home/jdcomponents/JDFooter.vue

@@ -0,0 +1,235 @@
+<template>
+  <div class="jd-footer">
+    <!-- 1. 多快好省 Slogans -->
+    <div class="slogans-wrap">
+      <div class="w slogans">
+        <div class="slogan-item">
+          <div class="s-icon">
+            <svg viewBox="0 0 40 46" width="36" height="36" class="hex-svg">
+               <polygon points="20,2 38,12 38,34 20,44 2,34 2,12" fill="none" stroke="#E1251B" stroke-width="3"></polygon>
+            </svg>
+            <span class="s-txt">多</span>
+          </div>
+          <span class="s-desc">品类齐全,轻松购物</span>
+        </div>
+        <div class="slogan-item">
+          <div class="s-icon">
+            <svg viewBox="0 0 40 46" width="36" height="36" class="hex-svg">
+               <polygon points="20,2 38,12 38,34 20,44 2,34 2,12" fill="none" stroke="#E1251B" stroke-width="3"></polygon>
+            </svg>
+            <span class="s-txt">快</span>
+          </div>
+          <span class="s-desc">多仓直发,极速配送</span>
+        </div>
+        <div class="slogan-item">
+          <div class="s-icon">
+            <svg viewBox="0 0 40 46" width="36" height="36" class="hex-svg">
+               <polygon points="20,2 38,12 38,34 20,44 2,34 2,12" fill="none" stroke="#E1251B" stroke-width="3"></polygon>
+            </svg>
+            <span class="s-txt">好</span>
+          </div>
+          <span class="s-desc">正品行货,精致服务</span>
+        </div>
+        <div class="slogan-item">
+          <div class="s-icon">
+            <svg viewBox="0 0 40 46" width="36" height="36" class="hex-svg">
+               <polygon points="20,2 38,12 38,34 20,44 2,34 2,12" fill="none" stroke="#E1251B" stroke-width="3"></polygon>
+            </svg>
+            <span class="s-txt">省</span>
+          </div>
+          <span class="s-desc">天天低价,畅选无忧</span>
+        </div>
+      </div>
+    </div>
+
+    <!-- 2. 帮助中心目录 -->
+    <div class="help-links-wrap">
+      <div class="w help-links">
+        <dl>
+          <dt>购物指南</dt>
+          <dd><a href="#">购物流程</a></dd>
+          <dd><a href="#">会员介绍</a></dd>
+          <dd><a href="#">生活旅行/团购</a></dd>
+          <dd><a href="#">常见问题</a></dd>
+          <dd><a href="#">大家电</a></dd>
+          <dd><a href="#">联系客服</a></dd>
+        </dl>
+        <dl>
+          <dt>配送方式</dt>
+          <dd><a href="#">上门自提</a></dd>
+          <dd><a href="#">211限时达</a></dd>
+          <dd><a href="#">配送服务查询</a></dd>
+          <dd><a href="#">配送费收取标准</a></dd>
+        </dl>
+        <dl>
+          <dt>支付方式</dt>
+          <dd><a href="#">货到付款</a></dd>
+          <dd><a href="#">在线支付</a></dd>
+          <dd><a href="#">分期付款</a></dd>
+          <dd><a href="#">公司转账</a></dd>
+        </dl>
+        <dl>
+          <dt>售后服务</dt>
+          <dd><a href="#">售后政策</a></dd>
+          <dd><a href="#">价格保护</a></dd>
+          <dd><a href="#">退款说明</a></dd>
+          <dd><a href="#">返修/退换货</a></dd>
+          <dd><a href="#">取消订单</a></dd>
+        </dl>
+        <dl>
+          <dt>特色服务</dt>
+          <dd><a href="#">夺宝岛</a></dd>
+          <dd><a href="#">DIY装机</a></dd>
+          <dd><a href="#">延保服务</a></dd>
+          <dd><a href="#">京东E卡</a></dd>
+          <dd><a href="#">京东通信</a></dd>
+          <dd><a href="#">京东智能</a></dd>
+        </dl>
+      </div>
+    </div>
+
+    <!-- 3. 版权信息与底部认证 -->
+    <div class="w copyright">
+        <p class="links">
+          <a href="#">关于我们</a><span class="sep">|</span>
+          <a href="#">联系我们</a><span class="sep">|</span>
+          <a href="#">联系客服</a><span class="sep">|</span>
+          <a href="#">合作招商</a><span class="sep">|</span>
+          <a href="#">商家帮助</a><span class="sep">|</span>
+          <a href="#">营销中心</a><span class="sep">|</span>
+          <a href="#">手机京东</a><span class="sep">|</span>
+          <a href="#">友情链接</a><span class="sep">|</span>
+          <a href="#">销售联盟</a><span class="sep">|</span>
+          <a href="#">京东社区</a><span class="sep">|</span>
+          <a href="#">风险监测</a><span class="sep">|</span>
+          <a href="#">隐私政策</a><span class="sep">|</span>
+          <a href="#">京东公益</a><span class="sep">|</span>
+          <a href="#">Media & IR</a>
+        </p>
+        <p class="info-text">
+          京公网安备 11000002000088号 <span class="sep">|</span> 京ICP备11041704号 <span class="sep">|</span> ICP <span class="sep">|</span> 互联网药品信息服务资格证编号(京)-经营性-2014-0008 <span class="sep">|</span> 新出发京零 字第大120007号
+        </p>
+        <p class="info-text">
+          互联网出版许可证编号新出网证(京)字150号 <span class="sep">|</span> 出版物经营许可证 <span class="sep">|</span> 网络文化经营许可证京网文[2020]6112-1201号 <span class="sep">|</span> 违法和不良信息举报电话:4006561155
+        </p>
+        <p class="info-text">
+          Copyright © 2004 - 2026 京东JD.COM 版权所有 <span class="sep">|</span> 消费者维权热线:4006067733 <span class="sep">|</span> 经营证照 <span class="sep">|</span> (京)网械平台备字(2018)第00003号 <span class="sep">|</span> 营业执照 <span class="sep">|</span> 增值电信业务经营许可证
+        </p>
+    </div>
+  </div>
+</template>
+
+<style scoped>
+.jd-footer {
+  background: #f4f4f4;
+  padding-top: 30px;
+  padding-bottom: 50px;
+  border-top: 1px solid #e5e5e5;
+  color: #666;
+}
+
+/* slogans */
+.slogans-wrap {
+  border-bottom: 1px solid #dedede;
+}
+.slogans {
+  display: flex;
+  justify-content: center;
+  gap: 120px;
+  padding: 30px 0;
+}
+.slogan-item {
+  display: flex;
+  align-items: center;
+}
+.s-icon {
+  width: 40px;
+  height: 40px;
+  position: relative;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-right: 12px;
+}
+.hex-svg {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+}
+.s-txt {
+  position: relative;
+  z-index: 2;
+  font-size: 18px;
+  font-weight: 800;
+  color: #E1251B;
+}
+.s-desc {
+  font-size: 18px;
+  font-weight: 700;
+  color: #333;
+}
+
+/* help links */
+.help-links-wrap {
+  border-bottom: 1px solid #dedede;
+}
+.help-links {
+  display: flex;
+  justify-content: center;
+  gap: 120px;
+  padding: 20px 0 30px 0;
+}
+.help-links dl {
+  width: 140px;
+}
+.help-links dt {
+  font-size: 14px;
+  font-weight: bold;
+  color: #666;
+  margin-bottom: 12px;
+}
+.help-links dd {
+  margin: 0;
+  padding: 0;
+}
+.help-links dd a {
+  color: #666;
+  font-size: 12px;
+  line-height: 24px;
+  text-decoration: none;
+  transition: color 0.2s;
+}
+.help-links dd a:hover {
+  color: #E1251B;
+}
+
+/* copyright */
+.copyright {
+  text-align: center;
+  padding-top: 20px;
+}
+.copyright .links {
+  margin-bottom: 10px;
+}
+.copyright .links a {
+  color: #666;
+  font-size: 12px;
+  text-decoration: none;
+  transition: color 0.2s;
+}
+.copyright .links a:hover {
+  color: #E1251B;
+}
+.copyright .sep {
+  margin: 0 10px;
+  color: #ccc;
+  font-size: 12px;
+}
+.copyright .info-text {
+  font-size: 12px;
+  color: #999;
+  line-height: 24px;
+  margin: 0;
+}
+</style>

+ 258 - 0
src/views/home/jdcomponents/JDHeader.vue

@@ -0,0 +1,258 @@
+<template>
+  <div class="jd-header">
+    <!-- 顶部窄条 -->
+    <!-- <div class="header-top">
+      <div class="w flex-between">
+        <div class="loc-wrap">
+          <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align: -2px; margin-right: 2px;"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path><circle cx="12" cy="10" r="3"></circle></svg>
+          湖北
+        </div>
+        <ul class="top-nav-links flex">
+          <li>我的订单</li>
+          <li class="spacer"></li>
+          <li>我的工作台</li>
+          <li class="spacer"></li>
+          <li>企业会员</li>
+          <li class="spacer"></li>
+          <li class="red">企业采购</li>
+          <li class="spacer"></li>
+          <li>客户服务</li>
+          <li class="spacer"></li>
+          <li class="hotline">咨询热线 400-028-0000</li>
+        </ul>
+      </div>
+    </div> -->
+
+    <!-- 中间搜索行 -->
+    <div :class="['header-mid-wrap', { 'is-fixed': isFixed }]">
+      <div class="header-mid w flex">
+        <div class="logo-box">
+          <div class="logo-text">优易企业购</div>
+          <p class="logo-desc">省钱 · 省心 · 省时间</p>
+        </div>
+
+        <div class="search-box-wrap flex-1">
+          <div class="search-bar flex">
+            <div class="input-group flex-1 flex">
+              <input type="text" placeholder="企业端午福利" />
+            </div>
+            <button class="search-btn">搜 索</button>
+          </div>
+          <div class="hot-links">
+            <span>企业权益不止5折</span>
+            <span>定制礼盒低至83折</span>
+          </div>
+        </div>
+
+        <div class="header-actions">
+          <div class="btn-keeper">Ai 采购管家</div>
+        </div>
+      </div>
+    </div>
+    <!-- 占位符,防止吸顶时页面跳动 -->
+    <div class="header-placeholder" v-show="isFixed"></div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted, onUnmounted } from 'vue';
+
+const isFixed = ref(false);
+
+const handleScroll = () => {
+  isFixed.value = window.scrollY > 120;
+};
+
+onMounted(() => {
+  window.addEventListener('scroll', handleScroll);
+});
+
+onUnmounted(() => {
+  window.removeEventListener('scroll', handleScroll);
+});
+</script>
+
+<style scoped>
+.jd-header {
+  background: #fff;
+}
+.header-top {
+  height: 32px;
+  background: #e3e4e5;
+  border-bottom: 1px solid #e3e4e5;
+  font-size: 12px;
+  color: #999;
+  line-height: 32px;
+}
+.top-nav-links li {
+  padding: 0 10px;
+  cursor: pointer;
+  transition: color 0.2s;
+}
+.top-nav-links li:hover {
+  color: #e1251b;
+}
+.top-nav-links .spacer {
+  width: 1px;
+  height: 10px;
+  background: #ccc;
+  margin-top: 11px;
+  padding: 0;
+}
+.top-nav-links .red {
+  color: #e1251b;
+  font-weight: bold;
+}
+
+/* 吸顶包裹层 */
+.header-mid-wrap {
+  background: #fff;
+  transition: all 0.2s;
+}
+.header-mid-wrap.is-fixed {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  z-index: 999;
+  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
+  animation: slideDown 0.3s ease-out;
+}
+@keyframes slideDown {
+  from {
+    transform: translateY(-100%);
+  }
+  to {
+    transform: translateY(0);
+  }
+}
+.header-placeholder {
+  height: 100px;
+} /* header-mid 的总高度估算 */
+
+.header-mid {
+  padding: 25px 0 15px;
+  display: flex;
+  align-items: center;
+  justify-content: flex-start;
+  transition: padding 0.2s;
+}
+.is-fixed .header-mid {
+  padding: 25px 0;
+} /* 增加吸顶时的高度,总高度 90px */
+
+.logo-box {
+  width: auto;
+  text-align: center;
+  margin-right: 30px;
+  flex-shrink: 0;
+}
+.logo-text {
+  font-size: 32px;
+  font-weight: 900;
+  color: #e1251b;
+  letter-spacing: 1px;
+  font-family: 'Microsoft YaHei', sans-serif;
+  line-height: 1.2;
+}
+.logo-desc {
+  font-size: 12px;
+  color: #999;
+  margin-top: 5px;
+  letter-spacing: 2px;
+}
+.is-fixed .logo-desc {
+  display: none;
+} /* 吸顶时隐藏副标题 */
+.is-fixed .logo-text {
+  font-size: 26px;
+} /* 吸顶时稍微缩小Logo */
+
+.search-box-wrap {
+  margin: 0;
+  flex: 1;
+  max-width: none;
+  display: flex;
+  flex-direction: column;
+}
+.search-bar {
+  height: 42px;
+  border: 2px solid #e1251b;
+  border-radius: 8px;
+  background: #fff;
+  padding: 2px;
+  box-sizing: border-box;
+}
+.input-group {
+  padding: 0 15px;
+  align-items: center;
+  height: 100%;
+}
+.input-group input {
+  width: 100%;
+  height: 100%;
+  border: none;
+  outline: none;
+  font-size: 14px;
+  color: #333;
+}
+.input-group input::placeholder {
+  color: #999;
+}
+
+.search-btn {
+  width: 84px;
+  height: 100%;
+  background: #e1251b;
+  color: #fff;
+  border: none;
+  font-size: 16px;
+  font-weight: bold;
+  border-radius: 6px;
+  cursor: pointer;
+  transition: background 0.2s;
+  letter-spacing: 2px;
+}
+.search-btn:hover {
+  background: #c81623;
+}
+
+.hot-links {
+  font-size: 12px;
+  color: #999;
+  margin-top: 8px;
+  padding-left: 5px;
+}
+.hot-links span {
+  margin-right: 15px;
+  cursor: pointer;
+}
+.hot-links span:hover {
+  color: #e1251b;
+}
+.is-fixed .hot-links {
+  display: none;
+} /* 吸顶时隐藏热搜词 */
+
+.header-actions {
+  margin-left: 30px;
+  flex-shrink: 0;
+}
+.btn-keeper {
+  height: 40px;
+  line-height: 38px;
+  padding: 0 24px;
+  border: 1px solid #ffcdd2;
+  border-radius: 8px;
+  color: #e1251b;
+  font-size: 14px;
+  font-weight: bold;
+  background: #fff;
+  cursor: pointer;
+  transition: all 0.2s;
+  box-sizing: border-box;
+}
+.btn-keeper:hover {
+  background: #fef0f0;
+}
+</style>

+ 296 - 0
src/views/home/jdcomponents/JDProducts.vue

@@ -0,0 +1,296 @@
+<template>
+  <div class="products-section w">
+    <!-- 顶部滑动的商品分类导航 -->
+    <div class="cat-nav-wrapper">
+      <div class="more-btn prev-btn" v-show="showPrev" @click="slide(-300)">
+        <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
+          <polyline points="15 18 9 12 15 6"></polyline>
+        </svg>
+      </div>
+
+      <div class="cat-nav-list" ref="navListRef" @scroll="checkScroll">
+        <div
+          class="cat-item"
+          v-for="(cat, i) in categories"
+          :key="i"
+          :class="{ active: currentCat === i }"
+          @click="currentCat = i"
+        >
+          <img :src="`/icons/icon_${cat.icon}.svg`" class="cat-img" />
+          <div class="cat-text">
+            <span class="c-t">{{ cat.title }}</span>
+            <span class="c-s">{{ cat.sub }}</span>
+          </div>
+        </div>
+      </div>
+
+      <div class="more-btn next-btn" v-show="showNext" @click="slide(300)">
+        <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
+          <polyline points="9 18 15 12 9 6"></polyline>
+        </svg>
+      </div>
+    </div>
+
+    <!-- 商品列表 -->
+    <div class="product-grid">
+      <div class="p-card" v-for="(p, i) in productsList" :key="i">
+        <div class="p-img-box">
+          <img :src="p.img" @error="handleImgError" />
+        </div>
+        <div class="p-info">
+          <div class="p-name">
+            <span class="tag-zy">自营</span>
+            {{ p.name }}
+          </div>
+          <div class="p-price-row">
+            <span class="p-currency">¥</span>
+            <span class="p-price">{{ p.price }}</span>
+            <span class="p-decimal" v-if="p.dec !== '00'">.{{ p.dec }}</span>
+            <span class="tag-ep">企业价</span>
+          </div>
+          <div class="p-actions">
+            <button class="btn-cart-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="9" cy="21" r="1"></circle><circle cx="20" cy="21" r="1"></circle><path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path></svg></button>
+            <button class="btn-buy">
+              <span class="txt-normal">加入采购清单</span>
+              <span class="txt-hover">注册企业用户可享</span>
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted, computed } from 'vue';
+
+const categories = [
+  { title: '为你推荐', sub: '每日低价 领券', icon: '1' },
+  { title: '新客专享', sub: '精选爆品 低价', icon: '2' },
+  { title: '办公设备', sub: '电脑设备 批量', icon: '12' },
+  { title: '办公耗材', sub: '低价直供 囤货', icon: '13' },
+  { title: '工业生产', sub: '车间工具 规格', icon: '3' },
+  { title: '员工福利', sub: '节日礼盒 一键', icon: '10' },
+  { title: '办公环境', sub: '电器家具 焕新', icon: '7' },
+  { title: '营销礼赠', sub: '客户礼包 特惠', icon: '8' },
+  { title: '员工餐饮', sub: '茶水间 零食', icon: '5' },
+  { title: '个人防护', sub: '劳保用品 齐全', icon: '6' },
+  { title: '企业服务', sub: '工商注册 财税', icon: '4' },
+  { title: '包装耗材', sub: '纸箱胶带 批采', icon: '11' },
+  { title: '商用家电', sub: '空调冰洗 采购', icon: '9' },
+  { title: '安防监控', sub: '门禁摄像头 全', icon: '14' },
+  { title: '五金建材', sub: '管件工具 直供', icon: '15' }
+];
+
+const baseProducts = [
+  { name: '佛山照明 (FSL) LED投光灯 led户外灯室外防水大功率工程广告牌泛光灯', price: '185', dec: '27', img: '@/assets/jd/prod_light.png' },
+  { name: '初工 门锁卧室门锁室内门锁可调节通用门锁免改孔门锁 双孔可调孔距', price: '49', dec: '90', img: '@/assets/jd/prod_lock.png' },
+  { name: '潘洁擦机布 棉布工业擦机抹布 10KG(20斤)吸水吸油抹布40*60cm', price: '113', dec: '00', img: '@/assets/jd/prod_rags.png' },
+  { name: '德力西电气 (DELIXI ELECTRIC) 硬质合金开孔器不锈钢钻头扩孔', price: '18', dec: '79', img: '@/assets/jd/prod_switch.png' },
+  { name: '世达 (SATA) 150件小飞中飞大飞棘轮扳手套筒综合套装工具箱09510', price: '2025', dec: '78', img: '@/assets/jd/prod_toolset.png' },
+  { name: '普达防毒面具全面罩自吸过滤式防毒农药化工防甲苯醋酸等有机气体', price: '116', dec: '60', img: '@/assets/jd/prod_mask.png' },
+  { name: '华为平板电脑 MatePad 11.5英寸 120Hz高刷全面屏 8+128GB WIFI版', price: '1499', dec: '00', img: '@/assets/jd/prod_it.png' },
+  { name: '惠普(HP)打印机 激光打印机 办公商用家用黑白打印机', price: '899', dec: '00', img: '@/assets/jd/prod_office.png' },
+  { name: '福临门 食用油 精炼一级大豆油 5升*4桶/箱(企业专享)', price: '259', dec: '00', img: '@/assets/jd/prod_office.png' },
+  { name: '得力(deli) A4复印纸 70g 500张/包 5包/箱 办公打印纸', price: '129', dec: '00', img: '@/assets/jd/prod_rags.png' },
+  { name: '智能门禁系统 考勤机 打卡机 刷脸指纹密码识别', price: '399', dec: '00', img: '@/assets/jd/prod_lock.png' },
+  { name: '工业级大功率风扇 车间用强力落地扇 降温通风', price: '288', dec: '00', img: '@/assets/jd/prod_light.png' }
+];
+
+baseProducts.forEach(p => {
+  if (!p.img) p.img = '@/assets/jd/prod_office.png';
+});
+
+// 生成更多数据用于测试吸顶
+const productsList = computed(() => {
+  let list = [];
+  for(let i=0; i<3; i++) { // 36 items
+    list = list.concat(baseProducts.map(p => ({...p, id: i + '_' + p.name})));
+  }
+  return list;
+});
+
+const currentCat = ref(0);
+const navListRef = ref(null);
+const showPrev = ref(false);
+const showNext = ref(true);
+
+const checkScroll = () => {
+  if (!navListRef.value) return;
+  const { scrollLeft, scrollWidth, clientWidth } = navListRef.value;
+  showPrev.value = scrollLeft > 0;
+  showNext.value = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 2;
+};
+
+const slide = (amount) => {
+  if (navListRef.value) {
+    navListRef.value.scrollBy({ left: amount, behavior: 'smooth' });
+  }
+};
+
+const defaultImg = 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400"><rect width="100%" height="100%" fill="%23f4f4f4"/><text x="50%" y="50%" font-family="sans-serif" font-size="20" fill="%23ccc" dominant-baseline="middle" text-anchor="middle">暂无图片</text></svg>';
+
+const handleImgError = (e) => {
+  e.target.src = defaultImg;
+  e.target.onerror = null;
+};
+
+onMounted(() => {
+  setTimeout(checkScroll, 100);
+});
+</script>
+
+<style scoped>
+.products-section { margin-top: 24px; background: #fff; border-radius: 12px; margin-bottom: 50px; }
+
+/* 导航栏 (吸顶) */
+.cat-nav-wrapper {
+  background: #fff;
+  position: sticky;
+  top: 90px; /* 对应 header 吸顶后的高度 90px */
+  z-index: 900;
+  display: flex;
+  align-items: center;
+  padding: 0 10px;
+  border-top-left-radius: 12px;
+  border-top-right-radius: 12px;
+}
+
+.cat-nav-list {
+  display: flex;
+  overflow-x: auto;
+  scrollbar-width: none;
+  -ms-overflow-style: none;
+  scroll-behavior: smooth;
+  flex: 1;
+  padding: 16px 0;
+}
+.cat-nav-list::-webkit-scrollbar { display: none; }
+
+.cat-item {
+  display: flex;
+  align-items: center;
+  flex-shrink: 0;
+  padding: 8px 16px;
+  cursor: pointer;
+  border-radius: 8px;
+  margin-right: 8px;
+  transition: all 0.2s;
+}
+.cat-item:hover { background: #f9f9f9; }
+.cat-item.active .c-t, .cat-item.active .c-s { color: #E1251B; }
+
+.cat-img { width: 32px; height: 32px; margin-right: 12px; border-radius: 50%; }
+
+.cat-text { display: flex; flex-direction: column; }
+.c-t { font-size: 15px; font-weight: bold; color: #333; margin-bottom: 2px; }
+.c-s { font-size: 12px; color: #999; }
+
+/* 左右箭头 */
+.more-btn {
+  width: 28px; height: 28px; border-radius: 50%;
+  background: #fff; border: 1px solid #eee; display: flex; align-items: center; justify-content: center;
+  cursor: pointer; color: #666; font-size: 14px; box-shadow: 0 2px 5px rgba(0,0,0,0.05);
+}
+.more-btn:hover { background: #f4f4f4; }
+.prev-btn { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); z-index: 10; }
+.next-btn { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); z-index: 10; margin-left: 0; }
+
+
+/* 商品网格 */
+.product-grid {
+  display: grid;
+  gap: 12px;
+  padding: 0 20px 20px 20px;
+}
+@media screen and (min-width: 1600px) { .product-grid { grid-template-columns: repeat(6, 1fr); } }
+@media screen and (min-width: 1210px) and (max-width: 1599px) { .product-grid { grid-template-columns: repeat(5, 1fr); } }
+@media screen and (max-width: 1209px) { .product-grid { grid-template-columns: repeat(4, 1fr); } }
+
+/* 商品卡片 */
+.p-card {
+  background: #fff;
+  border: 1px solid #f4f4f4;
+  border-radius: 8px;
+  overflow: hidden;
+  transition: all 0.2s;
+  display: flex;
+  flex-direction: column;
+  padding: 12px;
+}
+.p-card:hover { transform: translateY(-4px); box-shadow: 0 8px 24px rgba(0,0,0,0.08); }
+
+.p-img-box {
+  width: 100%;
+  aspect-ratio: 1 / 1;
+  background: #f8f8f8;
+  border-radius: 8px;
+  overflow: hidden;
+  margin-bottom: 12px;
+  position: relative;
+}
+.p-img-box img { width: 100%; height: 100%; object-fit: cover; }
+
+/* 悬停时的透明遮罩 */
+.p-img-box::after {
+  content: '';
+  position: absolute;
+  top: 0; left: 0; right: 0; bottom: 0;
+  background: rgba(0,0,0,0.04);
+  opacity: 0;
+  transition: opacity 0.2s;
+  pointer-events: none;
+}
+.p-card:hover .p-img-box::after { opacity: 1; }
+
+.p-info { flex: 1; display: flex; flex-direction: column; }
+.p-name {
+  font-size: 13px;
+  line-height: 1.4;
+  height: 36px;
+  overflow: hidden;
+  display: -webkit-box;
+  -webkit-line-clamp: 2;
+  -webkit-box-orient: vertical;
+  color: #333;
+  margin-bottom: 10px;
+}
+.tag-zy { background: #E1251B; color: #fff; padding: 0 4px; border-radius: 2px; font-size: 11px; margin-right: 4px; vertical-align: baseline; display: inline-block; }
+
+.p-price-row { color: #E1251B; display: flex; align-items: baseline; margin-bottom: 12px; margin-top: auto; }
+.p-currency { font-size: 12px; font-weight: bold; }
+.p-price { font-size: 20px; font-weight: 800; font-family: tahoma,arial,Microsoft YaHei,Hiragino Sans GB,u5b8bu4f53,sans-serif; }
+.p-decimal { font-size: 12px; font-weight: bold; margin-right: 6px; }
+.tag-ep { font-size: 11px; color: #187AF2; border: 1px solid #187AF2; border-radius: 2px; padding: 0 4px; margin-left: 6px;}
+
+.p-actions { display: flex; gap: 8px; }
+.btn-cart-icon {
+  width: 32px; height: 32px;
+  border: 1px solid #e0e0e0; background: #fff; border-radius: 4px;
+  color: #666; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.2s; flex-shrink: 0;
+}
+.btn-cart-icon:hover { border-color: #E1251B; color: #E1251B; }
+
+.btn-buy {
+  flex: 1; height: 32px;
+  border: 1px solid #e0e0e0; background: #fff; border-radius: 4px;
+  color: #666; font-size: 12px; cursor: pointer; transition: all 0.2s;
+  display: flex; align-items: center; justify-content: center;
+}
+.txt-hover { display: none; font-weight: bold; }
+
+/* 悬停卡片时,按钮直接变为红色,文字改变 */
+.p-card:hover .btn-buy {
+  background: #E1251B;
+  border-color: #E1251B;
+  color: #fff;
+}
+.p-card:hover .txt-normal { display: none; }
+.p-card:hover .txt-hover { display: inline; }
+
+/* 鼠标悬停在按钮本身时,保持红色 */
+.p-card .btn-buy:hover {
+  background: #C81623;
+  border-color: #C81623;
+}
+</style>

+ 137 - 0
src/views/home/jdcomponents/JDScene.vue

@@ -0,0 +1,137 @@
+<template>
+  <div class="scene-integrated w">
+    <div class="scene-inner flex">
+      <!-- 左侧标题区 -->
+      <div class="scene-left">
+        <div class="s-h-group flex">
+          <h3 class="s-main-t">场景解决方案</h3>
+          <span class="s-sub-t">一站全买齐</span>
+        </div>
+        <a href="#" class="enter-pill">
+          进入全场景 <i class="arr-ic"></i>
+        </a>
+      </div>
+
+      <!-- 右侧卡片区 -->
+      <div class="scene-right flex-1">
+        <div class="s-grid-h flex">
+          <div class="s-item-card" v-for="(s, i) in scenes" :key="i">
+            <div class="item-top flex-between">
+              <div class="item-info flex">
+                <p class="item-t">{{ s.title }}</p>
+                <p class="item-d">{{ s.desc }}</p>
+              </div>
+              <div class="item-arrow">
+                <i class="icon-arr"></i>
+              </div>
+            </div>
+            <div class="item-pic">
+              <img :src="s.img" />
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+const scenes = [
+  { title: '耗材采购', desc: '纸墨随买随用', img: '@/assets/jd/scene_stationery.png' },
+  { title: '防暑降温', desc: '守护员工健康', img: '@/assets/jd/scene_cooling.png' },
+  { title: '员工团建', desc: '同心聚力', img: '@/assets/jd/scene_teambuilding.png' },
+  { title: '营销物资', desc: '全场景解决方案', img: '@/assets/jd/scene_marketing.png' }
+];
+</script>
+
+<style scoped>
+.scene-integrated { margin-top: 15px; }
+.scene-inner {
+  background: linear-gradient(90deg, #6BE7B5 0%, #39D696 100%);
+  border-radius: 12px;
+  padding: 14px 20px;
+  align-items: center;
+  min-height: 140px;
+}
+
+.scene-left {
+  width: 380px;
+  color: #fff;
+  padding-right: 20px;
+}
+.s-h-group { align-items: baseline; margin-bottom: 15px; }
+.s-main-t { font-size: 24px; font-weight: 800; white-space: nowrap; }
+.s-sub-t { font-size: 24px; font-weight: 800; opacity: 0.95; margin-left: 12px; white-space: nowrap; }
+
+.enter-pill {
+  display: inline-flex;
+  align-items: center;
+  background: #fff;
+  color: #E1251B;
+  padding: 6px 18px;
+  border-radius: 20px;
+  font-size: 13px;
+  font-weight: bold;
+  text-decoration: none;
+}
+.arr-ic {
+  display: inline-block; width: 12px; height: 12px;
+  background: #E1251B; border-radius: 50%; margin-left: 6px;
+  position: relative;
+}
+.arr-ic::after {
+  content: ''; position: absolute; left: 3px; top: 3px;
+  width: 4px; height: 4px; border-top: 2px solid #fff; border-right: 2px solid #fff;
+  transform: rotate(45deg);
+}
+
+.scene-right { overflow: hidden; }
+.s-grid-h { gap: 10px; }
+
+.s-item-card {
+  flex: 1;
+  background: #E8FBF1; /* Pale green background matching Figure 2 */
+  border-radius: 10px;
+  height: 130px;
+  display: flex;
+  flex-direction: column;
+  overflow: hidden;
+  transition: transform 0.3s;
+}
+.s-item-card:hover { transform: translateY(-3px); }
+
+.item-top { padding: 8px 12px; align-items: center; }
+.item-info { align-items: baseline; gap: 8px; }
+.item-t { font-size: 18px; font-weight: 900; color: #026034; white-space: nowrap; }
+.item-d { font-size: 13px; font-weight: 600; color: #111; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
+
+.item-arrow {
+  width: 16px;
+  height: 16px;
+  background: #34C759;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-shrink: 0;
+}
+.icon-arr {
+  width: 4px; height: 4px;
+  border-top: 2px solid #fff; border-right: 2px solid #fff;
+  transform: rotate(45deg); margin-left: -1px;
+}
+
+.item-pic { flex: 1; overflow: hidden; padding: 0 8px 8px; }
+.item-pic img { width: 100%; height: 100%; object-fit: cover; border-radius: 6px; }
+
+@media screen and (max-width: 1599px) {
+  .scene-left { width: 340px; }
+  .s-main-t { font-size: 20px; }
+  .s-sub-t { font-size: 20px; font-weight: 800; }
+  .s-item-card:nth-child(4) { display: none; } /* 当宽度小于 1600px 时隐藏第4个卡片 */
+}
+
+@media screen and (max-width: 1209px) {
+  .s-item-card:nth-child(3) { display: none; } /* 宽度更小时隐藏第3个卡片 */
+}
+</style>

+ 375 - 0
src/views/home/jdcomponents/JDUserPanel.vue

@@ -0,0 +1,375 @@
+<template>
+  <div class="user-panel">
+    <!-- 顶部极淡粉色渐变背景 -->
+    <div class="top-bg"></div>
+
+    <!-- 用户信息区 -->
+    <div class="u-auth flex">
+      <div class="avatar">
+        <img src="@/assets/jd/user_avatar.png" />
+      </div>
+      <div class="u-info">
+        <p class="name">52k9i2wwed3jx2</p>
+        <p class="links">切换企业账号<span class="divider">|</span>注册</p>
+      </div>
+    </div>
+
+    <!-- 会员卡片 -->
+    <div class="member-card">
+       <div class="c-tag">企业会员</div>
+       <div class="c-main flex-between">
+         <div class="c-left">
+            <div class="c-h">新人福利</div>
+            <p>领3000元采购补贴</p>
+         </div>
+         <div class="c-btn">立即开通 <i class="arr">&gt;</i></div>
+       </div>
+    </div>
+
+    <!-- 会员权益文本 -->
+    <div class="card-benefits">
+       <div class="b-row-1 flex-between">
+          <span>大额免息</span>
+          <span>充值返</span>
+          <span>免费领</span>
+          <span>购卡返</span>
+       </div>
+       <div class="b-row-2 flex-between">
+          <span>账期</span>
+          <span>余额</span>
+          <span>优惠券</span>
+          <span>礼品卡</span>
+       </div>
+    </div>
+
+    <!-- 免息广告条 -->
+    <div class="small-ad flex-center">
+       <div class="fire-icon">
+          <svg viewBox="0 0 1024 1024" width="10" height="10"><path d="M512 0C326.4 200 256 312 256 464c0 141.4 114.6 256 256 256s256-114.6 256-256c0-152-70.4-264-256-464z" fill="#fff"/></svg>
+       </div>
+       <span>申请免息账期 首单立减288</span>
+    </div>
+
+    <!-- 企业工作台 -->
+    <div class="tools-sec relative">
+      <div class="t-h flex-between">
+         <span>企业工作台</span>
+         <i class="icon-more">&gt;</i>
+      </div>
+
+      <!-- 滑动翻页组件 -->
+      <div class="t-slider-wrap">
+        <div class="t-track" :style="{ transform: `translateX(-${currentPage * 100}%)` }">
+
+          <!-- 第 1 页 -->
+          <div class="t-page">
+            <div class="t-grid">
+               <div class="t-i">
+                 <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMzMzIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTE5IDIxSDVDNC40IDIxIDQgMjAuNiA0IDIwVjRDNCAzLjQgNC40IDMgNSAzSDE0TDIwIDlWMjBDMjAgMjAuNiAxOS42IDIxIDE5IDIxWiIvPjxwYXRoIGQ9Ik0xNCAzVjloNiIvPjxwb2x5Z29uIHBvaW50cz0iOSAxMyAxMSAxNSAxNSAxMSA5IDEzIi8+PC9zdmc+" class="t-icon" />
+                 <span>订单中心</span>
+               </div>
+               <div class="t-i">
+                 <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMzMzIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTE0IDJIMlYyMkgxNEwxOCAxOEwxNCAxNFYyWiIvPjxsaW5lIHgxPSI2IiB5MT0iNiIgeDI9IjEwIiB5Mj0iNiIvPjxsaW5lIHgxPSI2IiB5MT0iMTAiIHgyPSIxMCIgeTI9IjEwIi8+PC9zdmc+" class="t-icon" />
+                 <span>发票中心</span>
+               </div>
+               <div class="t-i">
+                 <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMzMzIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTkgMkgxNVY2SDlaTTUgNlYyMkgxOVY2SDVaIi8+PGxpbmUgeDE9IjkiIHkxPSIxMiIgeDI9IjE1IiB5Mj0iMTIiLz48bGluZSB4MT0iOSIgeTE9IjE2IiB4Mj0iMTUiIHkyPSIxNiIvPjwvc3ZnPg==" class="t-icon" />
+                 <span>采购清单</span>
+               </div>
+               <div class="t-i">
+                 <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMzMzIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTEyIDJDOC4xIDIgNSA1LjEgNSA5QzUgMTQuMiAxMiAyMiAxMiAyMiAxMkMxMiAyMiAxOSAxNC4yIDE5IDlDMTkgNS4xIDE1LjkgMiAxMiAyWiIvPjxjaXJjbGUgY3g9IjEyIiBjeT0iOSIgcj0iMiIvPjwvc3ZnPg==" class="t-icon" />
+                 <span>多地下单</span>
+               </div>
+               <div class="t-i">
+                 <div class="badge">返100</div>
+                 <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMzMzIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTUgMThWMTVIN0E1IDUgMCAwIDEgMTIgOUgxMmE1IDUgMCAwIDEgNSA1VjE4SDE3YTIgMiAwIDAgMSAyIDJWMjBIM2EwIDAgMCAwIDEtLS0yVjE4WiIvPjwvc3ZnPg==" class="t-icon" />
+                 <span>达量返</span>
+               </div>
+               <div class="t-i">
+                 <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMzMzIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHJlY3QgeD0iMyIgeT0iNSIgd2lkdGg9IjE4IiBoZWlnaHQ9IjE0IiByeD0iMiIvPjxwYXRoIGQ9Ik03IDlMMTEgMTVNMTUgOVYxNU0xNSA5TDEzIDEySDE3TTEzIDE1SDE3Ii8+PC9zdmc+" class="t-icon" />
+                 <span>智能选品</span>
+               </div>
+               <div class="t-i">
+                 <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMzMzIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTcgMThWMTRIN0E1IDUgMCAwIDEgMTIgOUgxMmE1IDUgMCAwIDEgNSA1VjE4SDE3YTIgMiAwIDAgMSAyIDJWMjBIM2EwIDAgMCAwIDEtLS0yVjE4WiIvPjwvc3ZnPg==" class="t-icon" />
+                 <span>电子合同</span>
+               </div>
+               <div class="t-i">
+                 <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMzMzIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHJlY3QgeD0iMiIgeT0iNiIgd2lkdGg9IjIwIiBoZWlnaHQ9IjEyIiByeD0iMiIvPjxsaW5lIHgxPSI2IiB5MT0iMTIiIHgyPSIxMCIgeTI9IjEyIi8+PC9zdmc+" class="t-icon" />
+                 <span>极速认款</span>
+               </div>
+            </div>
+          </div>
+
+          <!-- 第 2 页 -->
+          <div class="t-page">
+            <div class="t-grid">
+               <div class="t-i">
+                 <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMzMzIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PGNpcmNsZSBjeD0iOSIgY3k9IjIxIiByPSIxIi8+PGNpcmNsZSBjeD0iMjAiIGN5PSIyMSIgcj0iMSIvPjxwYXRoIGQ9Ik0xIDFoNGwyLjY4IDEzLjM5YTIgMiAwIDAgMCAyIDEuNjFoOS43MmEyIDIgMCAwIDAgMi0xLjYxTDIzIDZINiIvPjwvc3ZnPg==" class="t-icon" />
+                 <span>采购报告</span>
+               </div>
+               <div class="t-i">
+                 <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMzMzIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PGxpbmUgeDE9IjEyIiB5MT0iMSIgeDI9IjEyIiB5Mj0iMjMiLz48cGF0aCBkPSJNMTcgNVYzbS0xMCAyeTJoMTAiLz48cGF0aCBkPSJNNSAxNXYyaDEwIi8+PHBhdGggZD0iTTEyIDljLTIuMjEgMC00IDEuNzktNCA0cyAxLjc5IDQgNCA0Ii8+PHBhdGggZD0iTTEyIDE3YzIuMjEgMCA0LTEuNzkgNC00cy0xLjc5LTQtNC00Ii8+PC9zdmc+" class="t-icon" />
+                 <span>对公转账</span>
+               </div>
+               <div class="t-i">
+                 <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMzMzIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTE4IDhWMk0xOCAyMjEtdi02Ii8+PHBhdGggZD0iTTE0IDhWMk0xNCAyMnYtNiIvPjxwYXRoIGQ9Ik0xMCA4VjJNMTAgMjJ2LTYiLz48cGF0aCBkPSJNMjIgMnY4YTUgNSAwIDAgMS01IDVoLTE0YTUgNSAwIDAgMS01LTVWMloiLz48L3N2Zz4=" class="t-icon" />
+                 <span>员工饭卡</span>
+               </div>
+               <div class="t-i">
+                 <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMzMzIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTE0IDJIMlYyMkgxNEwxOCAxOEwxNCAxNFYyWiIvPjxwb2x5Z29uIHBvaW50cz0iNiAxMCA4IDEyIDEyIDgiLz48L3N2Zz4=" class="t-icon" />
+                 <span>计划购</span>
+               </div>
+               <div class="t-i">
+                 <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMzMzIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTUgMTJIMTlNMTEgMThWMk0xNiAybC01IDUtNSA1Ii8+PC9zdmc+" class="t-icon" />
+                 <span>预算管理</span>
+               </div>
+            </div>
+          </div>
+        </div>
+
+        <!-- 滑动按钮 -->
+        <div class="flip-btn prev-btn" v-show="currentPage > 0" @click="currentPage--">
+          <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="#999" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
+            <polyline points="15 18 9 12 15 6"></polyline>
+          </svg>
+        </div>
+        <div class="flip-btn next-btn" v-show="currentPage < 1" @click="currentPage++">
+          <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="#999" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
+            <polyline points="9 18 15 12 9 6"></polyline>
+          </svg>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref } from 'vue';
+
+const currentPage = ref(0);
+</script>
+
+<style scoped>
+.user-panel {
+  background: #fff;
+  height: 100%;
+  border-radius: 12px;
+  position: relative;
+  overflow: hidden;
+  display: flex;
+  flex-direction: column;
+}
+
+/* 顶部极淡粉色渐变背景 */
+.top-bg {
+  position: absolute;
+  top: 0; left: 0; right: 0; height: 120px;
+  background: linear-gradient(to bottom, #FFF5EE, #ffffff);
+  z-index: 0;
+}
+
+/* 内容提升层级 */
+.u-auth, .member-card, .card-benefits, .small-ad, .tools-sec {
+  position: relative;
+  z-index: 1;
+}
+
+.u-auth {
+  padding: 16px 16px 0;
+  align-items: center;
+  margin-bottom: 12px;
+}
+
+.avatar img {
+  width: 48px;
+  height: 48px;
+  border-radius: 50%;
+  border: 2px solid #fff;
+  box-shadow: 0 2px 6px rgba(255,182,193,0.3);
+  margin-right: 12px;
+}
+
+.name {
+  font-weight: bold;
+  font-size: 14px;
+  color: #000;
+}
+
+.links {
+  font-size: 11px;
+  color: #666;
+  margin-top: 4px;
+}
+
+.divider { margin: 0 6px; color: #E0E0E0; }
+
+.member-card {
+  margin: 0 16px;
+  background: linear-gradient(to right, #FDF0DE, #FCE3C5);
+  border-radius: 8px;
+  position: relative;
+  padding: 16px 12px 12px;
+}
+
+.c-tag {
+  position: absolute;
+  top: 0; left: 0;
+  background: #11366F;
+  color: #F8D9A8;
+  font-size: 10px;
+  padding: 2px 8px;
+  border-radius: 8px 0 8px 0;
+  font-weight: bold;
+}
+
+.c-h {
+  font-weight: 800;
+  font-size: 15px;
+  color: #5A3515;
+}
+
+.c-left p {
+  font-size: 11px;
+  color: #7E5124;
+  margin-top: 3px;
+}
+
+.c-btn {
+  font-size: 11px;
+  color: #613C1C;
+  border: 1px solid #7E5124;
+  padding: 3px 8px 3px 10px;
+  border-radius: 12px;
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+}
+.c-btn .arr { font-style: normal; margin-left: 2px; font-family: sans-serif; }
+
+.card-benefits {
+  margin: 12px 16px 8px;
+}
+
+.b-row-1 {
+  font-size: 12px;
+  font-weight: 800;
+  color: #000;
+  padding: 0 4px;
+}
+
+.b-row-2 {
+  font-size: 11px;
+  color: #666;
+  padding: 0 8px;
+  margin-top: 4px;
+}
+
+.small-ad {
+  margin: 0 16px 16px;
+  background: #FFF7F5;
+  font-size: 11px;
+  color: #333;
+  padding: 8px 0;
+  border-radius: 4px;
+}
+
+.fire-icon {
+  width: 14px;
+  height: 14px;
+  background: #E1251B;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-right: 6px;
+}
+
+.tools-sec {
+  padding: 0 16px;
+  flex: 1;
+}
+
+.t-h {
+  font-weight: bold;
+  font-size: 14px;
+  color: #000;
+  margin-bottom: 15px;
+}
+
+.icon-more { font-size: 12px; color: #999; font-style: normal; }
+
+.t-slider-wrap {
+  position: relative;
+  overflow: hidden;
+  width: 100%;
+}
+
+.t-track {
+  display: flex;
+  transition: transform 0.3s ease-in-out;
+}
+
+.t-page {
+  width: 100%;
+  flex-shrink: 0;
+}
+
+.flip-btn {
+  position: absolute;
+  top: 50%;
+  transform: translateY(-50%);
+  width: 20px;
+  height: 20px;
+  background: #fff;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  cursor: pointer;
+  box-shadow: 0 1px 4px rgba(0,0,0,0.15);
+  z-index: 10;
+  transition: background 0.2s;
+}
+.flip-btn:hover { background: #f4f4f4; }
+.prev-btn { left: 4px; }
+.next-btn { right: 4px; }
+
+.t-grid {
+  display: grid;
+  grid-template-columns: repeat(4, 1fr);
+  grid-template-rows: repeat(2, 1fr);
+  gap: 16px 0;
+}
+
+.t-i {
+  text-align: center;
+  font-size: 11px;
+  color: #333;
+  position: relative;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  cursor: pointer;
+}
+
+.t-icon {
+  width: 24px;
+  height: 24px;
+  margin-bottom: 6px;
+  opacity: 0.8;
+}
+
+.badge {
+  position: absolute;
+  top: -8px;
+  right: -2px;
+  background: #FF5A5F;
+  color: #fff;
+  font-size: 9px;
+  padding: 1px 4px;
+  border-radius: 8px 8px 8px 0;
+  z-index: 2;
+  border: 1px solid #fff;
+  transform: scale(0.9);
+}
+</style>

+ 86 - 0
src/views/home/jdcomponents/jd-repro.css

@@ -0,0 +1,86 @@
+/* 京东企业购 最终修复版全局样式 */
+:root {
+  --jd-red: #E1251B;
+  --jd-bg: #F4F4F4;
+  --jd-white: #FFFFFF;
+  --jd-text-3: #333333;
+  --jd-text-6: #666666;
+  --jd-text-9: #999999;
+  --radius-lg: 12px;
+  --radius-sm: 8px;
+}
+
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
+
+body {
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+  background-color: var(--jd-bg);
+  color: var(--jd-text-3);
+  font-size: 14px;
+  -webkit-font-smoothing: antialiased;
+}
+
+ul, ol { list-style: none; }
+a { text-decoration: none; color: inherit; }
+
+/* 核心容器 */
+.w {
+  margin: 0 auto;
+  position: relative;
+}
+
+/* 媒体查询适配容器宽度 */
+@media screen and (min-width: 1600px) {
+  .w { width: 1600px; }
+}
+
+@media screen and (min-width: 1210px) and (max-width: 1599px) {
+  .w { width: 1190px; }
+}
+
+@media screen and (max-width: 1209px) {
+  .w { width: 990px; }
+}
+
+@media screen and (min-width: 1210px) and (max-width: 1599px) {
+  .w { width: 1190px; }
+}
+
+@media screen and (max-width: 1209px) {
+  .w { width: 990px; }
+}
+
+/* Flex 布局工具 */
+.flex { display: flex; }
+.flex-1 { flex: 1; }
+.flex-center { display: flex; align-items: center; justify-content: center; }
+.flex-between { display: flex; align-items: center; justify-content: space-between; }
+.flex-column { display: flex; flex-direction: column; }
+.flex-wrap { flex-wrap: wrap; }
+
+.clearfix::after {
+  content: "";
+  display: block;
+  clear: both;
+}
+
+/* 通用卡片样式 */
+.jd-card {
+  background: var(--jd-white);
+  border-radius: var(--radius-lg);
+  overflow: hidden;
+}
+
+.tag-red {
+  background: var(--jd-red);
+  color: #fff;
+  padding: 0 4px;
+  border-radius: 2px;
+  font-size: 12px;
+  display: inline-block;
+  line-height: 1.4;
+}

+ 0 - 1
src/views/home/pccomponents/pages/activity.vue

@@ -90,7 +90,6 @@ const componentData = props.row || {};
 
 const warpCss = computed(() => {
   let style = '';
-  style += 'position:relative;';
   //背景颜色
   if (componentData.pageStartBgColor) {
     if (componentData.pageStartBgColor && componentData.pageEndBgColor)

+ 12 - 1
src/views/home/pccomponents/pages/advert.vue

@@ -36,7 +36,7 @@
           class="img"
           :src="item.imageUrl ? item.imageUrl : figure"
           :fit="item.imageUrl ? (item.imgType == 1 ? 'fill' : item.imgType == 2 ? 'contain' : 'cover') : 'cover'"
-          :style="componentData.imageRadius ? { borderRadius: componentData.imageRadius + 'px' } : {}"
+          :style="imageCss"
         />
         <div :style="titleCss" class="title zi-hover">{{ item.title || '' }}</div>
         <div :style="subtitleCss" class="mt-[2px] mb-[12px] subtitle ellipsis">{{ item.subtitle || '' }}</div>
@@ -130,6 +130,17 @@ const subtitleCss = computed(() => {
   if (componentData.subtitleSize) style += 'font-size:' + componentData.subtitleSize + 'px;';
   return style;
 });
+
+// 比例
+const imageCss = computed(() => {
+  let style = '';
+  if (componentData.aspectRatio) {
+    style += 'aspect-ratio:' + componentData.aspectRatio + ';';
+    style += 'margin-bottom:15px;height:auto;';
+  }
+  if (componentData.imageRadius) style += 'image-radius:' + componentData.imageRadius + 'px;';
+  return style;
+});
 </script>
 
 <style lang="scss" scoped>

+ 2 - 1
src/views/home/pccomponents/pages/article.vue

@@ -194,7 +194,8 @@ const dataCss = computed(() => {
 
       img {
         width: 100%;
-        height: 165px;
+        aspect-ratio: 292 / 168;
+        // height: 165px;
       }
 
       // flex: 0 0 calc((100% - ${(componentData.number - 1) * 10}px);

+ 6 - 3
src/views/home/pccomponents/pages/brand.vue

@@ -130,8 +130,9 @@ const subtitleCss = computed(() => {
     width: 100%;
 
     .bigBrand-one {
-      width: 230px;
+      // width: 230px;
       height: 340px;
+      aspect-ratio: 230 / 330;
       cursor: pointer;
     }
 
@@ -157,8 +158,10 @@ const subtitleCss = computed(() => {
         justify-content: center;
 
         .img {
-          width: 120px;
-          height: 50px;
+          // width: 120px;
+          width: 80%;
+          aspect-ratio: 120 / 50;
+          // height: 50px;
         }
 
         .bigBrand1 {

+ 17 - 13
src/views/home/pccomponents/pages/discover.vue

@@ -283,8 +283,9 @@ const subtitleCss = computed(() => {
     gap: 10px;
 
     .discover-image {
-      width: 230px;
+      // width: 230px;
       height: 340px;
+      aspect-ratio: 230/342;
       border-radius: 5px;
       cursor: pointer;
     }
@@ -322,8 +323,8 @@ const subtitleCss = computed(() => {
         }
 
         .plan-image {
-          width: 72px;
-          height: 72px;
+          width: 80px;
+          height: 80px;
           margin-right: 10px;
         }
 
@@ -396,7 +397,7 @@ const subtitleCss = computed(() => {
             height: 132.5px;
             border: 1px solid #e5e7eb;
             margin-top: 10px;
-            padding: 25px 10px;
+            padding: 15px 10px;
             display: flex;
             gap: 10px;
             cursor: pointer;
@@ -417,8 +418,9 @@ const subtitleCss = computed(() => {
               }
             }
             .detect-image {
-              height: 72px;
-              width: 72px;
+              height: 100%;
+              // width: 72px;
+              aspect-ratio: 1 / 1;
             }
           }
         }
@@ -430,8 +432,8 @@ const subtitleCss = computed(() => {
           background-color: #ffffff;
           padding: 25px 10px;
           .detect-img {
-            height: 124px;
-            width: 124px;
+            aspect-ratio: 1 / 1;
+            width: 100%;
             margin: 0 auto;
           }
         }
@@ -444,8 +446,9 @@ const subtitleCss = computed(() => {
     gap: 10px;
     margin-top: 10px;
     .discover-tab {
-      width: 230px;
-      height: 310px;
+      // width: 230px;
+      aspect-ratio: 0.7376;
+      // height: 310px;
       background: #ffffff;
       padding: 0 15px 15px 15px;
       border-radius: 5px;
@@ -479,14 +482,15 @@ const subtitleCss = computed(() => {
       flex: 0 0 calc((100% - 270px) / 4);
       width: 0;
       background: #ffffff;
-      height: 310px;
-      padding: 15px 20px;
+      padding: 15px;
       border-radius: 5px;
       cursor: pointer;
       .goods-img {
         width: 100%;
-        height: 190px;
+        aspect-ratio: 1 / 1;
+        // height: 190px;
         border-radius: 5px;
+        margin-bottom: 10px;
       }
       .goods-name {
         width: 100%;

+ 3 - 0
src/views/home/pccomponents/pages/floor.vue

@@ -198,6 +198,9 @@ const btnCss2 = computed(() => {
       flex-wrap: wrap;
       gap: 10px;
       overflow: hidden;
+      &:hover {
+        overflow: auto;
+      }
       .goods-list {
         padding: 15px 10px;
         height: 275px;

+ 4 - 3
src/views/home/pccomponents/pages/goods.vue

@@ -274,7 +274,6 @@ const btnCss2 = computed(() => {
     gap: 10px;
     .goods-list {
       padding: 20px 15px;
-      height: 300px;
       width: 0;
       flex: 0 0 calc((100% - 40px) / 5);
       overflow: hidden;
@@ -282,16 +281,18 @@ const btnCss2 = computed(() => {
       background-color: #ffffff;
       border-radius: 5px;
       .goods-img {
-        width: 180px;
-        height: 180px;
+        width: 100%;
+        aspect-ratio: 1 / 1;
         border-radius: 5px;
         margin: 0 auto;
+        margin-bottom: 10px;
       }
       .itemName {
         font-size: 14px;
         height: 40px;
         overflow: hidden;
         text-overflow: ellipsis;
+        margin-bottom: 10px;
       }
       .memberPrice {
         font-size: 16px;

+ 16 - 5
src/views/home/pccomponents/pages/goodsList.vue

@@ -239,7 +239,10 @@ const tabHigCss = computed(() => {
     width: 100%;
     margin-bottom: 10px;
     padding: 15px;
-    overflow: auto;
+    overflow: hidden;
+    &:hover {
+      overflow: auto;
+    }
     .tab-list {
       flex-shrink: 0;
       cursor: pointer;
@@ -262,23 +265,31 @@ const tabHigCss = computed(() => {
   .goods-bos {
     display: flex;
     gap: 10px;
-    overflow: auto;
+    flex-wrap: wrap;
+    // overflow: hidden;
+    // &:hover {
+    //   overflow: auto;
+    // }
     .goods-list {
       padding: 20px 15px;
-      height: 300px;
+      // height: 300px;
       width: 0;
       flex: 0 0 calc((100% - 40px) / 5);
       overflow: hidden;
       .goods-img {
-        width: 180px;
-        height: 180px;
+        // width: 180px;
+        // height: 180px;
+        width: 100%;
+        aspect-ratio: 1 / 1;
         margin: 0 auto;
+        margin-bottom: 10px;
       }
       .itemName {
         font-size: 14px;
         height: 40px;
         overflow: hidden;
         text-overflow: ellipsis;
+        margin-bottom: 10px;
       }
       .memberPrice {
         font-size: 16px;

+ 9 - 6
src/views/home/pccomponents/pages/head.vue

@@ -159,7 +159,7 @@
             <template v-for="(item, index) in componentData.advertList" :key="index">
               <div class="head-item" v-if="item.show" @click="onPath(item.url)">
                 <el-image
-                  style="width: 100%; height: 100%"
+                  class="img"
                   :src="item.imageUrl ? item.imageUrl : figure"
                   :fit="item.imageUrl ? (item.imgType == 1 ? 'fill' : item.imgType == 2 ? 'contain' : 'cover') : 'cover'"
                 />
@@ -579,8 +579,8 @@ const warpCss = computed(() => {
         overflow: hidden;
 
         &.classify-show {
-          position: relative;
-          z-index: 999;
+          position: absolute;
+          z-index: 9999;
           height: auto;
           min-height: 540px;
           overflow: visible;
@@ -795,9 +795,12 @@ const warpCss = computed(() => {
             cursor: pointer;
             border-radius: 5px;
             overflow: hidden;
+            display: flex;
+            justify-content: center;
+            align-items: center;
 
-            img {
-              width: 100%;
+            .img {
+              aspect-ratio: 244 / 120;
               height: 100%;
             }
           }
@@ -892,7 +895,7 @@ const warpCss = computed(() => {
 
         .real-time {
           width: calc(100% - 20px);
-          // height: 230px;
+          height: 230px;
           border-bottom: 1px solid #e5e7eb;
           margin: 0 10px;
           padding-top: 15px;

+ 2 - 1
src/views/home/pccomponents/pages/imageCube.vue

@@ -81,6 +81,8 @@ const boxCss = computed(() => {
   if (componentData.imageBottomRoundedRounded) style += 'border-bottom-right-radius:' + componentData.imageBottomRoundedRounded + 'px;';
   //高度
   if (componentData.imageHeight) style += 'height:' + componentData.imageHeight + 'px;';
+  //比例
+  if (componentData.aspectRatio) style += 'aspect-ratio:' + componentData.aspectRatio + ';';
   return style;
 });
 </script>
@@ -97,7 +99,6 @@ const boxCss = computed(() => {
     gap: 10px;
     .imageCube-list {
       overflow: hidden;
-      height: 318px;
       flex: 0 0 calc((100% - 40px) / 5);
       .img {
         width: 100%;

+ 14 - 2
src/views/home/pccomponents/pages/navigation.vue

@@ -17,7 +17,7 @@
                 class="img"
                 :src="item.imageUrl ? item.imageUrl : figure"
                 :fit="item.imgType == 1 ? 'fill' : item.imgType == 2 ? 'contain' : 'cover'"
-                :style="componentData.imageRadius ? { borderRadius: componentData.imageRadius + 'px' } : {}"
+                :style="imageCss"
               />
             </div>
           </div>
@@ -38,7 +38,7 @@
           class="img"
           :src="item.imageUrl ? item.imageUrl : figure"
           :fit="item.imgType == 1 ? 'fill' : item.imgType == 2 ? 'contain' : 'cover'"
-          :style="componentData.imageRadius ? { borderRadius: componentData.imageRadius + 'px' } : {}"
+          :style="imageCss"
         />
       </div>
     </div>
@@ -130,6 +130,18 @@ const subtitleCss = computed(() => {
   if (componentData.subtitleSize) style += 'font-size:' + componentData.subtitleSize + 'px;';
   return style;
 });
+
+// 比例
+const imageCss = computed(() => {
+  let style = '';
+  if (componentData.aspectRatio) style += 'aspect-ratio:' + componentData.aspectRatio + ';';
+  if (componentData.imageRadius) style += 'image-radius:' + componentData.imageRadius + 'px;';
+  if (componentData.imageHeight) {
+    style += 'height:' + componentData.imageHeight + 'px;';
+    style += 'width:auto' + ';';
+  }
+  return style;
+});
 </script>
 
 <style lang="scss" scoped>

+ 1 - 1
src/views/index.vue

@@ -1087,7 +1087,7 @@ const onInfo = (res: any) => {
         height: 200px;
       }
       .procure1 {
-        padding: 12px 0 4px 20px;
+        padding: 12px 20px 4px 20px;
         font-weight: 600;
         font-size: 14px;
         color: #101828;

+ 102 - 61
src/views/item/index.vue

@@ -18,7 +18,7 @@
           <div class="carousel-bos">
             <div class="left-carousel" v-if="carousel && carousel.length > 0">
               <div v-for="(item, index) in carousel" :key="index" class="carousel-item" :class="carouselIndex == index ? 'hig' : ''">
-                <img :src="item" @click="onCarousel(1, index)" @mouseenter="onCarousel(1, index)" />
+                <el-image class="carousel-elImg" :src="item" @click="onCarousel(1, index)" @mouseenter="onCarousel(1, index)" />
               </div>
             </div>
             <div class="left-next flex-row-center" @click="onCarousel(2)">
@@ -28,15 +28,18 @@
             </div>
           </div>
           <!-- 中间大图 -->
-          <div class="images-box" @mouseenter="showZoom = true" @mouseleave="showZoom = false" @mousemove="handleMouseMove">
-            <img v-if="carousel && carousel.length > 0" :src="carousel[carouselIndex]" alt="" class="images-img" ref="mainImageRef" />
-            <!-- 新增:放大镜遮罩层 -->
+          <div class="images-box" ref="imageContainerRef" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave" @mousemove="handleMouseMove">
+            <div v-if="carousel && carousel.length > 0" ref="mainImageRef" class="main-image">
+              <el-image :src="carousel[carouselIndex]" alt="" class="images-img" />
+            </div>
+            <!-- <img v-if="carousel && carousel.length > 0" :src="carousel[carouselIndex]" alt="" class="images-img" ref="mainImageRef" /> -->
+            <!-- 放大镜遮罩层 -->
             <div
               v-show="showZoom"
               class="zoom-mask"
               :style="{
-                left: maskPos.x + 'px',
-                top: maskPos.y + 'px'
+                left: maskPosition.x + 'px',
+                top: maskPosition.y + 'px'
               }"
             ></div>
           </div>
@@ -98,7 +101,8 @@
         v-show="showZoom"
         :style="{
           backgroundImage: `url(${carousel[carouselIndex]})`,
-          backgroundPosition: `${bgPos.x} ${bgPos.y}`
+          backgroundSize: zoomScale + '00%',
+          backgroundPosition: bgPosition.x + '% ' + bgPosition.y + '%'
         }"
       ></div>
       <!-- 右边 -->
@@ -205,7 +209,7 @@
           class="data-list"
           @click="onPath('/item?id=' + item.id + '&productNo=' + item.productNo)"
         >
-          <img class="data-img" :src="item.productImage ? item.productImage.split(',')[0] : ''" alt="" />
+          <el-image class="data-img" :src="item.productImage ? item.productImage.split(',')[0] : ''" alt="" />
           <div class="data-title">{{ item.itemName || '' }}</div>
           <div class="money">
             <span class="money1">¥{{ item.memberPrice || '' }}</span>
@@ -261,7 +265,7 @@ import { getRecommendedCategoryProductList } from '@/api/home/index-mro';
 const route = useRoute();
 const id = ref<any>(null);
 const dataInfo = ref<any>({});
-const carousel = ref<any>([figure]);
+const carousel = ref<any>(['']);
 const regionCodes = ref<any>([]);
 const radio = ref<any>(null);
 const favorites = ref<any>([]);
@@ -327,7 +331,7 @@ const getInfo = (res: any) => {
     // 浏览记录
     addProductBrowsingHistory(id.value).then((res) => {});
   }
-  carousel.value = [figure];
+  carousel.value = [''];
   if (res.data && res.data.imageUrl) {
     carousel.value = res.data.imageUrl.split(',');
     if (carousel.value.length > 5) {
@@ -417,54 +421,67 @@ getRecommendedCategoryProductList({}).then((res) => {
   }
 });
 
-// 新增:放大功能相关
+// 新增:放大镜相关响应式数据
 const showZoom = ref(false);
 const mainImageRef = ref<HTMLImageElement | null>(null);
-const bgPos = ref({ x: '0%', y: '0%' });
-// 新增:遮罩层位置
-const maskPos = ref({ x: 0, y: 0 });
+const imageContainerRef = ref<HTMLDivElement | null>(null);
+const maskPosition = ref({ x: 0, y: 0 });
+const bgPosition = ref({ x: 0, y: 0 });
+const zoomScale = ref(2); // 放大倍数
+
+// 新增:鼠标进入图片区域
+const handleMouseEnter = () => {
+  showZoom.value = true;
+};
+
+// 新增:鼠标离开图片区域
+const handleMouseLeave = () => {
+  showZoom.value = false;
+};
 
+// 新增:鼠标移动处理
 const handleMouseMove = (e: MouseEvent) => {
-  if (!mainImageRef.value) return;
+  if (!mainImageRef.value || !imageContainerRef.value || !showZoom.value) return;
 
-  const image = mainImageRef.value;
-  const rect = image.getBoundingClientRect();
+  const containerRect = imageContainerRef.value.getBoundingClientRect();
+  const imageRect = mainImageRef.value.getBoundingClientRect();
 
-  // 获取容器尺寸 (images-box)
-  const width = rect.width;
-  const height = rect.height;
+  // 计算鼠标在容器内的坐标
+  const mouseX = e.clientX - containerRect.left;
+  const mouseY = e.clientY - containerRect.top;
 
-  // 计算鼠标在图片内的相对坐标
-  const x = e.clientX - rect.left;
-  const y = e.clientY - rect.top;
+  // 获取容器和图片的实际尺寸
+  const containerWidth = containerRect.width;
+  const containerHeight = containerRect.height;
+  const imageWidth = imageRect.width;
+  const imageHeight = imageRect.height;
 
-  // 遮罩层尺寸 (假设放大倍数为2,遮罩层大小为容器的一半,即正方形)
-  // 如果希望遮罩层固定大小,可以写死,例如 200px
-  const maskSize = width / 2;
+  // 计算遮罩层尺寸(固定为100px)
+  const maskWidth = 200;
+  const maskHeight = 200;
 
-  // 计算遮罩层左上角的位置 (让鼠标位于遮罩层中心)
-  let maskX = x - maskSize / 2;
-  let maskY = y - maskSize / 2;
+  // 计算遮罩层位置(鼠标在中心)
+  let maskX = mouseX - maskWidth / 2;
+  let maskY = mouseY - maskHeight / 2;
 
-  // 边界限制:确保遮罩层不超出图片范围
-  maskX = Math.max(0, Math.min(maskX, width - maskSize));
-  maskY = Math.max(0, Math.min(maskY, height - maskSize + 60));
+  // 边界限制:允许遮罩层移动到最边缘
+  maskX = Math.max(0, Math.min(maskX, containerWidth - maskWidth));
+  maskY = Math.max(0, Math.min(maskY, containerHeight - maskHeight));
 
   // 更新遮罩层位置
-  maskPos.value = {
+  maskPosition.value = {
     x: maskX,
     y: maskY
   };
 
-  // 计算背景图偏移百分比 (用于右侧放大区域)
-  // 背景图移动的比例 = 遮罩层移动的比例
-  // 注意:这里分母是 (总宽度 - 遮罩宽度),因为背景图移动范围也是这么多
-  const percentX = (maskX / (width - maskSize)) * 100;
-  const percentY = (maskY / (height - maskSize)) * 100;
+  // 计算背景偏移百分比
+  // 注意:这里使用图片实际尺寸而非容器尺寸进行计算
+  const bgX = (maskX / (containerWidth - maskWidth)) * 100;
+  const bgY = (maskY / (containerHeight - maskHeight)) * 100;
 
-  bgPos.value = {
-    x: `${percentX}%`,
-    y: `${percentY}%`
+  bgPosition.value = {
+    x: bgX,
+    y: bgY
   };
 };
 </script>
@@ -505,16 +522,19 @@ const handleMouseMove = (e: MouseEvent) => {
         // 轮播
         .carousel-bos {
           width: 80px;
+          display: flex;
+          flex-direction: column;
 
           @media (min-width: 1600px) {
             width: 112px;
           }
           // 左边的轮播
           .left-carousel {
-            height: 494px;
+            flex: 1;
+            // height: 494px;
             overflow-y: auto;
             @media (min-width: 1600px) {
-              height: 674px;
+              // height: 674px;
             }
 
             .carousel-item {
@@ -537,7 +557,7 @@ const handleMouseMove = (e: MouseEvent) => {
                 border: 1px solid #e7000b;
               }
 
-              img {
+              .carousel-elImg {
                 width: 100%;
                 height: 100%;
               }
@@ -558,15 +578,23 @@ const handleMouseMove = (e: MouseEvent) => {
         // 中间大图
         .images-box {
           width: 645px;
-          height: 540px;
+          height: 645px;
+          // height: 540px;
           border-radius: 5px;
           overflow: hidden;
           position: relative; /* 关键:作为遮罩层的定位父级 */
-          cursor: crosshair; /* 关键:鼠标变成十字准星 */
+          cursor: move; /* 关键:鼠标变成十字准星 */
 
           @media (min-width: 1600px) {
             width: 860px;
-            height: 720px;
+            height: 860px;
+            // height: 720px;
+          }
+
+          .main-image {
+            width: 100%;
+            height: 100%;
+            display: block;
           }
 
           .images-img {
@@ -575,14 +603,14 @@ const handleMouseMove = (e: MouseEvent) => {
             display: block;
           }
 
-          // 新增:遮罩层样式
+          // 修改:遮罩层尺寸调整为容器的一半
           .zoom-mask {
             position: absolute;
-            width: 200px; /* 对应2倍放大,宽高各占50%形成正方形 */
-            height: 200px; /* 如果图片不是正方形,这里可能需要调整以保持正方形,但通常跟随容器比例即可 */
-            background-color: rgba(255, 255, 255, 0.3); /* 半透明白色 */
-            border: 1px solid #ccc; /* 边框 */
-            pointer-events: none; /* 关键:让鼠标事件穿透遮罩层,避免闪烁 */
+            width: 200px; /* 容器宽度的一半 */
+            height: 200px; /* 容器高度的一半 */
+            background-color: rgba(255, 255, 255, 0.3);
+            border: 1px solid #ccc;
+            pointer-events: none;
             z-index: 5;
           }
         }
@@ -632,6 +660,7 @@ const handleMouseMove = (e: MouseEvent) => {
         //商品详情
         .pc-detail {
           width: 100%;
+          overflow-wrap: break-word;
           :deep(img) {
             width: 100%;
             display: block;
@@ -675,11 +704,6 @@ const handleMouseMove = (e: MouseEvent) => {
       right: 0;
       border: 1px solid #e5e7eb;
 
-      // 新增/修改以下属性以实现放大
-      background-repeat: no-repeat;
-      background-size: 200%; // 放大2倍,可根据需求调整为 250% 等
-      background-position: 0 0; // 默认位置
-
       @media (min-width: 1600px) {
         width: 598px;
         height: 720px;
@@ -880,11 +904,22 @@ const handleMouseMove = (e: MouseEvent) => {
         border-radius: 10px;
         padding: 20px 20px 22px 20px;
         cursor: pointer;
+        transition:
+          transform 0.2s ease,
+          box-shadow 0.2s ease;
+
+        &:hover {
+          transform: translateY(-2px);
+          box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+          .data-title {
+            color: #e7000b !important;
+          }
+        }
 
         .data-img {
-          width: 184px;
-          height: 184px;
-          border-radius: 10px;
+          width: 100%;
+          aspect-ratio: 1 / 1;
+          border-radius: 5px;
         }
 
         .data-title {
@@ -892,6 +927,12 @@ const handleMouseMove = (e: MouseEvent) => {
           font-size: 14px;
           color: #101828;
           height: 40px;
+          display: -webkit-box;
+          -webkit-line-clamp: 2;
+          line-clamp: 2; /* 添加标准属性 */
+          -webkit-box-orient: vertical;
+          overflow: hidden;
+          text-overflow: ellipsis;
         }
 
         .money {

+ 9 - 5
src/views/login.vue

@@ -255,39 +255,43 @@ onMounted(() => {
 <style lang="scss" scoped>
 .login {
   height: 100%;
+  min-height: 700px;
   width: 100%;
   background-image: url('@/assets/images/login/login1.png');
   overflow: auto;
   background-position: center center;
   background-repeat: no-repeat;
   background-size: cover;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  padding: 20px 0;
 
   .head {
     width: 185px;
     height: 90px;
-    margin-top: 53px;
     margin-left: 84px;
     cursor: pointer;
   }
 
   .login-info {
     width: 100%;
-    height: 660px;
+    height: 600px;
     background-image: url('@/assets/images/login/login2.png');
     overflow: hidden;
     background-position: center center;
     background-repeat: no-repeat;
     background-size: cover;
-    margin-top: 68px;
+    margin-top: 10px;
     min-width: 1200px;
     padding: 0 5%;
 
     .login-bos {
       width: 520px;
-      height: 510px;
+      height: 420px;
       background: #ffffff;
       border-radius: 30px 30px 30px 30px;
-      padding: 90px 85px 0 85px;
+      padding: 40px 85px 0 85px;
 
       :deep(.el-form-item) {
         margin-bottom: 18px;

+ 5 - 4
src/views/plan/guide.vue

@@ -316,7 +316,7 @@ const handleCurrentChange = (val: number) => {
     .data-list {
       // 计算宽度:每行3个。 (100% - 2个间隙 * 20px) / 3
       width: calc((100% - 40px) / 3);
-      height: 302px;
+      // height: 302px;
       background: #ffffff;
       border-radius: 5px;
       overflow: hidden;
@@ -337,8 +337,9 @@ const handleCurrentChange = (val: number) => {
 
       .data-img {
         width: 100%;
-        height: 200px;
-        object-fit: cover; // 保持图片比例填充
+        // height: 200px;
+        aspect-ratio: 393 / 220;
+        // object-fit: cover; // 保持图片比例填充
       }
 
       .data-box {
@@ -372,7 +373,7 @@ const handleCurrentChange = (val: number) => {
         .text {
           font-size: 14px;
           color: #e7000b;
-          margin-top: auto; // 推到底部
+          margin-top: 15px; // 推到底部
         }
       }
     }

+ 4 - 3
src/views/plan/index.vue

@@ -310,7 +310,7 @@ const onFilter = (item1: any, item2: any) => {
     .data-list {
       // 计算宽度:每行3个。 (100% - 2个间隙 * 20px) / 3
       width: calc((100% - 40px) / 3);
-      height: 302px;
+      // height: 302px;
       background: #ffffff;
       border-radius: 5px;
       overflow: hidden;
@@ -331,7 +331,8 @@ const onFilter = (item1: any, item2: any) => {
 
       .data-img {
         width: 100%;
-        height: 200px;
+        aspect-ratio: 1139 / 641;
+        // height: 200px;
         object-fit: cover; // 保持图片比例填充
       }
 
@@ -366,7 +367,7 @@ const onFilter = (item1: any, item2: any) => {
         .text {
           font-size: 14px;
           color: #e7000b;
-          margin-top: auto; // 推到底部
+          margin-top: 15px; // 推到底部
         }
       }
     }

+ 33 - 31
src/views/plan/project.vue

@@ -195,9 +195,9 @@ const handleCurrentChange = (val: number) => {
     gap: 15px;
     flex-wrap: wrap;
     .project-list {
-      flex: 0 0 calc((100% - 45px) / 3);
+      flex: 0 0 calc((100% - 45px) / 4);
       width: 0;
-      height: 320px;
+      // height: 320px;
       cursor: pointer;
       border-radius: 10px;
       overflow: hidden;
@@ -214,42 +214,44 @@ const handleCurrentChange = (val: number) => {
         }
       }
 
+      .data-img {
+        width: 100%;
+        aspect-ratio: 292 / 168;
+        // height: 180px;
+      }
+
       .project-box {
         width: 100%;
         height: 156px;
         background: #ffffff;
         border-radius: 10px;
-        margin-top: -20px;
-        z-index: 2;
-        position: absolute;
+        margin-top: -10px;
+        // z-index: 2;
+        // position: absolute;
         padding: 20px;
         border: 1px solid #e5e7eb;
-      }
-      .data-img {
-        width: 100%;
-        height: 180px;
-      }
-      .project1 {
-        font-weight: 600;
-        font-size: 16px;
-        color: #101828;
-        margin-bottom: 14px;
-      }
-      .project2 {
-        font-size: 14px;
-        color: #364153;
-        display: -webkit-box;
-        -webkit-line-clamp: 2;
-        line-clamp: 2; /* 添加标准属性 */
-        -webkit-box-orient: vertical;
-        overflow: hidden;
-        text-overflow: ellipsis;
-      }
-      .project-more {
-        text-align: right;
-        font-size: 14px;
-        color: var(--el-color-primary);
-        margin-top: 18px;
+        .project1 {
+          font-weight: 600;
+          font-size: 16px;
+          color: #101828;
+          margin-bottom: 14px;
+        }
+        .project2 {
+          font-size: 14px;
+          color: #364153;
+          display: -webkit-box;
+          -webkit-line-clamp: 2;
+          line-clamp: 2; /* 添加标准属性 */
+          -webkit-box-orient: vertical;
+          overflow: hidden;
+          text-overflow: ellipsis;
+        }
+        .project-more {
+          text-align: right;
+          font-size: 14px;
+          color: var(--el-color-primary);
+          margin-top: 18px;
+        }
       }
     }
   }

+ 5 - 3
src/views/plan_info/guide.vue

@@ -203,7 +203,7 @@ function getRandomElements(arr: any, count: any) {
         gap: 12px 0px;
         .data-list {
           width: 100%;
-          height: 268px;
+          // height: 268px;
           background-color: #ffffff;
           cursor: pointer;
           border-radius: 5px;
@@ -213,6 +213,7 @@ function getRandomElements(arr: any, count: any) {
             box-shadow 0.2s ease;
           display: flex;
           flex-direction: column;
+          padding-bottom: 15px;
 
           &:hover {
             transform: translateY(-2px);
@@ -223,10 +224,11 @@ function getRandomElements(arr: any, count: any) {
           }
           .data-img {
             width: 100%;
-            height: 200px;
+            aspect-ratio: 393 / 220;
+            // height: 200px;
           }
           .procure1 {
-            padding: 12px 0 4px 20px;
+            padding: 12px 20px 4px 20px;
             font-weight: 600;
             font-size: 14px;
             color: #101828;

+ 5 - 2
src/views/plan_info/index.vue

@@ -138,7 +138,8 @@ const onCart = (row: any) => {
     padding-bottom: 30px;
     .solve-img {
       width: 100%;
-      height: 380px;
+      aspect-ratio: 1200 / 360;
+      // height: 380px;
       border-radius: 5px;
     }
 
@@ -188,8 +189,10 @@ const onCart = (row: any) => {
           }
           .data-img {
             width: 100%;
-            height: 184px;
+            aspect-ratio: 1;
+            // height: 184px;
             border-radius: 5px;
+            margin-bottom: 10px;
           }
           .data-title {
             margin-top: 4px;

+ 3 - 1
src/views/plan_info/procure.vue

@@ -160,8 +160,10 @@ const onCart = (row: any) => {
           }
           .data-img {
             width: 100%;
-            height: 184px;
+            aspect-ratio: 1;
+            // height: 184px;
             border-radius: 5px;
+            margin-bottom: 10px;
           }
           .data-title {
             margin-top: 4px;

+ 3 - 2
src/views/plan_info/project.vue

@@ -202,10 +202,11 @@ onBeforeRouteUpdate((to, from, next) => {
           }
           .data-img {
             width: 100%;
-            height: 200px;
+            // height: 200px;
+            aspect-ratio: 292 / 168;
           }
           .procure1 {
-            padding: 12px 0 4px 20px;
+            padding: 12px 20px 15px 20px;
             font-weight: 600;
             font-size: 14px;
             color: #101828;

+ 3 - 2
src/views/search/brand.vue

@@ -261,7 +261,7 @@ onMounted(() => {
 
     .expert-list {
       flex: 0 0 calc((100% - 75px) / 6);
-      height: 140px;
+      // height: 140px;
       background: #ffffff;
       border-radius: 5px;
       padding: 20px;
@@ -280,7 +280,8 @@ onMounted(() => {
 
       .data-img {
         width: 100%;
-        height: 70px;
+        aspect-ratio: 120 / 50;
+        // height: 70px;
       }
 
       .itemName {

+ 36 - 31
src/views/search/index.vue

@@ -134,7 +134,8 @@
     <!-- 商品 -->
     <div class="expert-bos">
       <div v-for="(item, index) in dataList" :key="index" class="expert-list" @click="onPath('/item?id=' + item.id + '&productNo=' + item.productNo)">
-        <img :src="item.productImage" alt="" />
+        <el-image class="data-img" :src="item.productImage" />
+        <!-- <img :src="item.productImage" alt="" /> -->
         <div class="itemName ellipsis">{{ item.itemName || '' }}</div>
         <div class="price">
           <span class="memberPrice">¥{{ item.memberPrice }}</span>
@@ -229,37 +230,41 @@ const getClassify = () => {
     if (res.code == 200) {
       if (type.value == 2 && httpObj.value.mediumCategoryId) {
         res.data.forEach((item1: any) => {
-          item1.children.unshift({
-            label: '全部',
-            id: ''
-          });
-          item1.children.forEach((item2: any) => {
-            if (item2.id == httpObj.value.mediumCategoryId) {
-              httpObj.value.topCategoryId = item1.id;
-              classifyList.value = item1.children;
-            }
-          });
+          if (item1.children && item1.children.length > 0) {
+            item1.children.unshift({
+              label: '全部',
+              id: ''
+            });
+            item1.children.forEach((item2: any) => {
+              if (item2.id == httpObj.value.mediumCategoryId) {
+                httpObj.value.topCategoryId = item1.id;
+                classifyList.value = item1.children;
+              }
+            });
+          }
         });
         getList();
         //获取当前分类下得品牌
         getBrand2();
       } else if (type.value == 3 && httpObj.value.bottomCategoryId) {
         res.data.forEach((item1: any) => {
-          item1.children.forEach((item2: any) => {
-            if (item2.children && item2.children.length > 0) {
-              item2.children.unshift({
-                label: '全部',
-                id: ''
-              });
-              item2.children.forEach((item3: any) => {
-                if (item3.id == httpObj.value.bottomCategoryId) {
-                  httpObj.value.topCategoryId = item1.id;
-                  httpObj.value.mediumCategoryId = item2.id;
-                  classifyList.value = item2.children;
-                }
-              });
-            }
-          });
+          if (item1.children && item1.children.length > 0) {
+            item1.children.forEach((item2: any) => {
+              if (item2.children && item2.children.length > 0) {
+                item2.children.unshift({
+                  label: '全部',
+                  id: ''
+                });
+                item2.children.forEach((item3: any) => {
+                  if (item3.id == httpObj.value.bottomCategoryId) {
+                    httpObj.value.topCategoryId = item1.id;
+                    httpObj.value.mediumCategoryId = item2.id;
+                    classifyList.value = item2.children;
+                  }
+                });
+              }
+            });
+          }
         });
         getList();
         //获取当前分类下得品牌
@@ -467,7 +472,6 @@ onMounted(() => {
     }
   }
   // 商品
-  // 行家精选
   .expert-bos {
     width: 100%;
     display: flex;
@@ -478,20 +482,21 @@ onMounted(() => {
       flex: 0 0 calc((100% - 48px) / 5);
       width: 0;
       // width: 230px;
-      height: 306px;
+      // height: 306px;
       background: #ffffff;
       padding: 20px;
       cursor: pointer;
       border-radius: 5px;
-      img {
+      .data-img {
         width: 100%;
-        height: 190px;
+        aspect-ratio: 1;
+        // height: 190px;
       }
       .itemName {
         font-weight: 400;
         font-size: 14px;
         color: #101828;
-        margin: 27px 0 2px 0;
+        margin: 10px 0 5px 0;
       }
       .price {
         .memberPrice {

+ 6 - 6
src/views/search/special.vue

@@ -74,7 +74,7 @@
     <!-- 商品 -->
     <div class="expert-bos">
       <div v-for="(item, index) in dataList" :key="index" class="expert-list" @click="onPath('/item?id=' + item.id + '&productNo=' + item.productNo)">
-        <img :src="item.productImage" alt="" />
+        <el-image class="data-img" :src="item.productImage" />
         <div class="itemName ellipsis">{{ item.itemName || '' }}</div>
         <div class="price">
           <span class="memberPrice">¥{{ item.memberPrice }}</span>
@@ -277,7 +277,6 @@ onMounted(() => {
     }
   }
   // 商品
-  // 行家精选
   .expert-bos {
     width: 100%;
     display: flex;
@@ -288,20 +287,21 @@ onMounted(() => {
       flex: 0 0 calc((100% - 48px) / 5);
       width: 0;
       // width: 230px;
-      height: 306px;
+      // height: 306px;
       background: #ffffff;
       padding: 20px;
       cursor: pointer;
       border-radius: 5px;
-      img {
+      .data-img {
         width: 100%;
-        height: 190px;
+        aspect-ratio: 1;
+        // height: 190px;
       }
       .itemName {
         font-weight: 400;
         font-size: 14px;
         color: #101828;
-        margin: 27px 0 2px 0;
+        margin: 10px 0 5px 0;
       }
       .price {
         .memberPrice {