产品分类
All checks were successful
Gitea Actions Official-website / deploy-dev (push) Successful in 3s

This commit is contained in:
2026-04-08 14:25:09 +08:00
parent 86cc41b78c
commit 5262ece276
2 changed files with 640 additions and 92 deletions

View File

@@ -1,93 +1,548 @@
{extend name="public/base" /} <!DOCTYPE html>
{block name="style"} <html lang="zh-CN">
<link rel="stylesheet" type="text/css" href="__CSS__/product_category.css" />
{/block} <head>
{block name="main"} <meta charset="UTF-8">
<div class="oricoEGapp"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- banner轮播图 --> <title>ORICO 移动硬盘</title>
{notempty name="focus_image"} <script type="text/javascript">
<div> (function (doc, win)
{volist name="focus_image" id="fi"} {
<a {notempty name="fi.link" }href="{$fi.link}"{/notempty}> var docEl = doc.documentElement;
<img src="{$fi.image}" style="width: 100%;margin-top: 3.5rem;"/> var resizeEvt = 'orientationchange' in win ? 'orientationchange' : 'resize';
</a> var designWidth = 804; // 设计稿宽度
{/volist} var designRemPx = 100; // 设计稿下 1rem 对应 px
</div>
{/notempty} function setRootFontSize ()
<div class="oricoEGapp-catelists"> {
<!-- 二级分类导航 --> var clientWidth = docEl.clientWidth;
<div class="first_list_category"> if (!clientWidth) return;
<div class="scroller">
<ul class="clearfix"> // 计算基础字号
{volist name="list" id="vo"} var fontSize = (clientWidth / designWidth) * designRemPx;
<li>
<a href="{:url('product/subcategory', ['id' => $vo.id])}"> // 限制范围(可选)
<div class="category_list"> fontSize = Math.max(fontSize, 28); // 最小 28px
<p>{$vo.name}</p> fontSize = Math.min(fontSize, 80); // 最大 80px
</div>
</a> docEl.style.fontSize = fontSize + 'px';
</li>
{/volist} // 设置 body 基准,避免继承问题
</ul> doc.body.style.fontSize = '14px';
</div>
</div>
<!-- 二级分类几个产品展示 -->
{volist name="list" id="vo"}
<div class="m_Container">
<div class="product_list_title">
<div class="product_title">{$vo.name}</div>
<a href="{:url('product/subcategory', ['id' => $vo.id])}" class="view_all text_gray">
{:lang_i18n('查看全部')}<span class="icon-Double-Arrow"></span>
</a>
</div>
<div class="product_list">
{notempty name="vo.products"}
<ul>
{volist name="vo.products" id="pro" length="4"}
<li class="img-responsive">
<a href="{:url('product/detail', ['id' => $pro.id])}">
<img src="{:thumb($pro.cover_image)}">
<span class="title">{$pro.name}</span>
<span class="subtitle">{$pro.spu}</span>
</a>
</li>
{/volist}
</ul>
{/notempty}
</div>
</div>
{/volist}
</div>
</div>
{/block}
{block name="script"}
<script type="text/javascript">
// 自定义 navbarscroll 方法
$(function() {
let startX = 0;
let isDragging = false;
let currentLi;
$('.scroller ul li').on('mousedown touchstart', function(e) {
startX = e.type === 'touchstart' ? e.originalEvent.touches[0].clientX : e.clientX;
isDragging = true;
currentLi = $(this);
});
$(document).on('mousemove touchmove', function(e) {
if (isDragging) {
const currentX = e.type === 'touchmove' ? e.originalEvent.touches[0].clientX : e.clientX;
const diffX = currentX - startX;
if (diffX > 20) { // 设定一个最小滑动距离这里设为20像素
// 右滑操作
$('.scroller ul li').removeClass('cur');
currentLi.addClass('cur');
// 这里可以添加更多右滑后要执行的操作,例如显示对应内容
isDragging = false;
} }
setRootFontSize();
win.addEventListener(resizeEvt, setRootFontSize);
doc.addEventListener('DOMContentLoaded', setRootFontSize);
})(document, window);
</script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: sans-serif
} }
});
$(document).on('mouseup touchend', function() { body {
isDragging = false; background: #f5f5f5;
});
}); height: 100vh;
</script> overflow: hidden
{/block} }
.top-box {
width: 100%;
box-sizing: border-box;
padding: 20px 22px;
background: #fff;
}
.top-bar {
display: flex;
align-items: center;
height: 0.82rem;
background: #F1F2F5;
justify-content: space-between;
border-radius: 0.2rem;
padding: 0 16px;
}
.back {
width: 14px;
height: 14px;
color: #333;
cursor: pointer;
display: flex;
align-items: center;
}
.title {
font-size: 0.32rem;
font-weight: 500;
}
/* 主体布局 */
.main {
display: flex;
height: calc(100% - 46px)
}
/* 左侧菜单 */
.sidebar {
width: 114px;
background: #FAFAFA;
overflow-y: auto;
box-sizing: border-box;
}
.sidebar li {
list-style: none;
padding: 24px 0;
text-align: center;
font-size: 0.28rem;
color: #686A70;
cursor: pointer;
}
.sidebar li.active {
color: #004BFA;
background: #fff;
}
/* 右侧内容 */
.content {
flex: 1;
overflow-y: auto;
padding-left: 12px;
background: #fff;
}
.sec-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 24px;
padding-right: 17px;
padding-bottom: 12px;
}
.sec-title {
font-size: 0.28rem;
color: #686A70;
font-weight: 500
}
.sec-arrow {
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
color: #666;
font-size: 20px;
cursor: pointer;
}
/* 横向滚动容器 */
.scroll-box {
display: flex;
gap: 10px;
overflow-x: auto;
scroll-behavior: smooth;
scrollbar-width: none;
}
.scroll-box::-webkit-scrollbar {
display: none
}
.card {
flex-shrink: 0;
background: #FAFAFA;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
display: flex;
flex-direction: column;
align-items: center;
padding-top: 8px;
}
.card-img {
width: 1.52rem;
background: #f1f1f1;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
color: #999;
}
.card-img img {
width: 100%;
}
.card-info {
padding: 8px;
text-align: center
}
.card-name {
font-size: 0.2rem;
width: 1.52rem;
height: auto;
color: #1D1D1F;
line-height: 1.4;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.card-model {
font-size: 0.16rem;
color: #686A70;
margin-top: 4px
}
/* 内容区块默认隐藏 */
.tab-pane {
display: none
}
/* 激活时显示 */
.tab-pane.active {
display: block;
}
</style>
</head>
<body>
<!-- 顶部返回栏(已完全按图纸修改) -->
<div class="top-box">
<div class="top-bar">
<div class="back">
<image src="./img/left.png"></image>
</div>
<div class="title">数据存储</div>
</div>
</div>
<div class="main">
<!-- 左侧导航 -->
<ul class="sidebar">
<li class="nav-item" data-tab="tab1">固态硬盘</li>
<li class="nav-item active" data-tab="tab2">移动硬盘</li>
<li class="nav-item" data-tab="tab3">内存条</li>
<li class="nav-item" data-tab="tab4">NAS</li>
<li class="nav-item" data-tab="tab5">U盘/闪存卡</li>
<li class="nav-item" data-tab="tab6">混合存储</li>
</ul>
<!-- 右侧分区内容 -->
<div class="content">
<!-- 固态硬盘 -->
<div class="tab-pane" id="tab1">
<div class="sec-header">
<div class="sec-title">固态硬盘</div>
<div class="sec-arrow" onclick="scrollNext(this)">
<img src="./img/y.png" alt="">
</div>
</div>
<div class="scroll-box">
<div class="card">
<div class="card-img">
<img src="./img/111.png" alt="">
</div>
<div class="card-info">
<div class="card-name">
<div>M.2 NVMe 固态硬盘</div>
</div>
<div class="card-model">ORICO-SSD1T</div>
</div>
</div>
</div>
</div>
<!-- 移动硬盘(默认显示) -->
<div class="tab-pane active" id="tab2">
<!-- 磁吸移动硬盘 -->
<section class="sec-box">
<div class="sec-header">
<div class="sec-title">磁吸移动硬盘</div>
<div class="sec-arrow" onclick="scrollNext(this)">
<img src="./img/y.png" alt="">
</div>
</div>
<div class="scroll-box">
<div class="card">
<div class="card-img">
<img src="./img/111.png" alt="">
</div>
<div class="card-info">
<div class="card-name">PS5 M.2固态硬盘测试专用九五二七</div>
<div class="card-model">ORICO-e7450</div>
</div>
</div>
<div class="card">
<div class="card-img">
<img src="./img/111.png" alt="">
</div>
<div class="card-info">
<div class="card-name">PS5 M.2固态硬盘</div>
<div class="card-model">ORICO-e7450</div>
</div>
</div>
</div>
</section>
<!-- 桌面移动硬盘 -->
<section>
<div class="sec-header">
<div class="sec-title">桌面移动硬盘</div>
<div class="sec-arrow" onclick="scrollNext(this)"><img src="./img/y.png" alt=""></div>
</div>
<div class="scroll-box">
<div class="card">
<div class="card-img">
<img src="./img/111.png" alt="">
</div>
<div class="card-info">
<div class="card-name">3.5英寸桌面硬盘</div>
<div class="card-model">ORICO-3588</div>
</div>
</div>
</div>
</section>
</div>
<!-- 内存条 -->
<div class="tab-pane" id="tab3">
<div class="sec-header">
<div class="sec-title">内存条</div>
<div class="sec-arrow" onclick="scrollNext(this)"><img src="./img/y.png" alt=""></div>
</div>
<div class="scroll-box">
<div class="card">
<div class="card-img">
<img src="./img/111.png" alt="">
</div>
<div class="card-info">
<div class="card-name">DDR4 16G 内存</div>
<div class="card-model">ORICO-RAM</div>
</div>
</div>
</div>
</div>
<!-- NAS -->
<div class="tab-pane" id="tab4">
<div class="sec-header">
<div class="sec-title">NAS存储</div>
<div class="sec-arrow" onclick="scrollNext(this)"><img src="./img/y.png" alt=""></div>
</div>
<div class="scroll-box">
<div class="card">
<div class="card-img">
<img src="./img/111.png" alt="">
</div>
<div class="card-info">
<div class="card-name">4盘位NAS机箱</div>
<div class="card-model">ORICO-NAS</div>
</div>
</div>
</div>
</div>
<!-- U盘/闪存卡 -->
<div class="tab-pane" id="tab5">
<div class="sec-header">
<div class="sec-title">U盘/闪存卡</div>
<div class="sec-arrow" onclick="scrollNext(this)"><img src="./img/y.png" alt=""></div>
</div>
<div class="scroll-box">
<div class="card">
<div class="card-img">
<img src="./img/111.png" alt="">
</div>
<div class="card-info">
<div class="card-name">高速U盘 128G</div>
<div class="card-model">ORICO-U128</div>
</div>
</div>
</div>
</div>
<!-- 混合存储 -->
<div class="tab-pane" id="tab6">
<div class="sec-header">
<div class="sec-title">混合存储</div>
<div class="sec-arrow" onclick="scrollNext(this)"><img src="./img/y.png" alt=""></div>
</div>
<div class="scroll-box">
<div class="card">
<div class="card-img">
<img src="./img/111.png" alt="">
</div>
<div class="card-info">
<div class="card-name">多功能扩展坞</div>
<div class="card-model">ORICO-DOCK</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// 点击右侧箭头滚动
function scrollNext (el)
{
const box = el.closest('section')?.querySelector('.scroll-box')
|| el.parentElement.nextElementSibling
if (box) box.scrollBy({ left: 150, behavior: 'smooth' })
}
// 左侧Tab切换
const navItems = document.querySelectorAll('.nav-item')
const tabPanes = document.querySelectorAll('.tab-pane')
navItems.forEach(item =>
{
item.addEventListener('click', () =>
{
// 切换左侧激活状态
navItems.forEach(i => i.classList.remove('active'))
item.classList.add('active')
// 切换右侧内容
const target = item.dataset.tab
tabPanes.forEach(p => p.classList.remove('active'))
document.getElementById(target)?.classList.add('active')
})
})
</script>
<style>
/* 全屏侧边菜单 */
.full-menu {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .4);
z-index: 9999;
display: none;
}
.full-menu.show {
display: block;
}
.menu-wrap {
width: 80%;
height: 100%;
background: #fff;
position: relative;
padding: 20px;
overflow-y: auto;
}
.menu-close {
position: absolute;
right: 16px;
top: 16px;
font-size: 20px;
cursor: pointer;
}
.menu-logo {
margin: 30px 0 40px;
}
.menu-logo img {
height: 24px;
}
.menu-item {
padding: 14px 0;
border-bottom: 1px solid #eee;
font-size: 15px;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
}
.menu-item::after {
content: '>';
font-size: 12px;
color: #999;
}
.sub-menu {
padding-left: 16px;
display: none;
}
.sub-menu.show {
display: block;
}
.sub-item {
padding: 10px 0;
font-size: 14px;
color: #666;
}
</style>
<!-- 菜单结构 -->
<div class="full-menu" id="fullMenu">
<div class="menu-wrap">
<div class="menu-close" onclick="closeMenu()">×</div>
<div class="menu-logo">
<img src="./img/log.png" alt="">
</div>
<div class="menu-item" onclick="toggleSub(this)">产品列表
<div class="sub-menu">
<div class="sub-item">数据存储</div>
<div class="sub-item">充电系列</div>
<div class="sub-item">线材配件</div>
</div>
</div>
<div class="menu-item">关于我们</div>
<div class="menu-item">服务支持</div>
<div class="menu-item">联系我们</div>
</div>
</div>
<script>
// 打开菜单
document.querySelector('.nav-img').onclick = function ()
{
document.getElementById('fullMenu').classList.add('show')
}
// 关闭菜单
function closeMenu ()
{
document.getElementById('fullMenu').classList.remove('show')
}
// 展开子菜单
function toggleSub (el)
{
el.querySelector('.sub-menu').classList.toggle('show')
}
</script>
</body>
</html>

View File

@@ -0,0 +1,93 @@
{extend name="public/base" /}
{block name="style"}
<link rel="stylesheet" type="text/css" href="__CSS__/product_category.css" />
{/block}
{block name="main"}
<div class="oricoEGapp">
<!-- banner轮播图 -->
{notempty name="focus_image"}
<div>
{volist name="focus_image" id="fi"}
<a {notempty name="fi.link" }href="{$fi.link}"{/notempty}>
<img src="{$fi.image}" style="width: 100%;margin-top: 3.5rem;"/>
</a>
{/volist}
</div>
{/notempty}
<div class="oricoEGapp-catelists">
<!-- 二级分类导航 -->
<div class="first_list_category">
<div class="scroller">
<ul class="clearfix">
{volist name="list" id="vo"}
<li>
<a href="{:url('product/subcategory', ['id' => $vo.id])}">
<div class="category_list">
<p>{$vo.name}</p>
</div>
</a>
</li>
{/volist}
</ul>
</div>
</div>
<!-- 二级分类几个产品展示 -->
{volist name="list" id="vo"}
<div class="m_Container">
<div class="product_list_title">
<div class="product_title">{$vo.name}</div>
<a href="{:url('product/subcategory', ['id' => $vo.id])}" class="view_all text_gray">
{:lang_i18n('查看全部')}<span class="icon-Double-Arrow"></span>
</a>
</div>
<div class="product_list">
{notempty name="vo.products"}
<ul>
{volist name="vo.products" id="pro" length="4"}
<li class="img-responsive">
<a href="{:url('product/detail', ['id' => $pro.id])}">
<img src="{:thumb($pro.cover_image)}">
<span class="title">{$pro.name}</span>
<span class="subtitle">{$pro.spu}</span>
</a>
</li>
{/volist}
</ul>
{/notempty}
</div>
</div>
{/volist}
</div>
</div>
{/block}
{block name="script"}
<script type="text/javascript">
// 自定义 navbarscroll 方法
$(function() {
let startX = 0;
let isDragging = false;
let currentLi;
$('.scroller ul li').on('mousedown touchstart', function(e) {
startX = e.type === 'touchstart' ? e.originalEvent.touches[0].clientX : e.clientX;
isDragging = true;
currentLi = $(this);
});
$(document).on('mousemove touchmove', function(e) {
if (isDragging) {
const currentX = e.type === 'touchmove' ? e.originalEvent.touches[0].clientX : e.clientX;
const diffX = currentX - startX;
if (diffX > 20) { // 设定一个最小滑动距离这里设为20像素
// 右滑操作
$('.scroller ul li').removeClass('cur');
currentLi.addClass('cur');
// 这里可以添加更多右滑后要执行的操作,例如显示对应内容
isDragging = false;
}
}
});
$(document).on('mouseup touchend', function() {
isDragging = false;
});
});
</script>
{/block}