|
|
@@ -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>
|