Compare commits
92 Commits
853da3c948
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| a3d2398f83 | |||
| 80291c6a6a | |||
| 1ff3d28ff7 | |||
| 3d7ed2c16b | |||
| ade2c6bea8 | |||
| 2f4b0f8b76 | |||
| 9fcdea0061 | |||
| d7d8e2aa77 | |||
| cfe07c9df5 | |||
| 5eb49defe1 | |||
| 00e8eed191 | |||
| aeec3e4f0d | |||
| 251a13c368 | |||
| 73a51fcffc | |||
| b75a159d70 | |||
| d7cb06f4a9 | |||
| 40d4a41461 | |||
| 84a5e319cb | |||
| 456b2ede8a | |||
| 8daf4d0696 | |||
| 322cfad5d9 | |||
| 2b2dc2021a | |||
| 9b732b19dc | |||
| 654caf58c2 | |||
| 1d62a64014 | |||
| 4447aa4a39 | |||
| 53a317c8cf | |||
| b269e18547 | |||
| 04efd7ef4a | |||
| dc74a1ee10 | |||
| 9b661405c9 | |||
| 1ed900d2b5 | |||
| d6ce8aa2be | |||
| 4b5dae8714 | |||
| cf670b24f8 | |||
| cf1c78c882 | |||
| adef3c1e2e | |||
| 180b5db570 | |||
| a18ff844a4 | |||
| 80d3aa8160 | |||
| d79b418310 | |||
| 816d85a744 | |||
| 2d078033fa | |||
| d430f04b41 | |||
| aaf73a0803 | |||
| 7baac33d0d | |||
| f2f59e9528 | |||
| a9abb16fcb | |||
| 7ff746267b | |||
| bc9f233cb2 | |||
| 2c4eb38495 | |||
| 347ebddb97 | |||
| 93a72c7826 | |||
| 9748a3008e | |||
| 2c20bd2649 | |||
| ff8e23766a | |||
| 81f01e1424 | |||
| b6b5ea5308 | |||
| 62db7e8cb2 | |||
| ba2b343d0a | |||
| 83be5a7c0b | |||
| ce38172cd6 | |||
| 5262ece276 | |||
| 86cc41b78c | |||
| f5a891e00e | |||
| 184e81737e | |||
| eb015c552f | |||
| 685cd53b1a | |||
| 2c3e309d2a | |||
| 49240893b5 | |||
| f4646f1e3a | |||
| 624d7fde2f | |||
| a85f2c1b3a | |||
| 67016c4e9a | |||
| 12bc6aeee7 | |||
| 24e5554bc4 | |||
| c767c20641 | |||
| 2c85df4a98 | |||
| 88a91f3136 | |||
| 5fd603cbc6 | |||
| b92753c822 | |||
| ddd578eb08 | |||
| 1cdd0536b9 | |||
| 9cc6dc3cd9 | |||
| 4d25f6fec8 | |||
| 2764ce3b86 | |||
| 7cb270b313 | |||
| 86ffcb99ac | |||
| c476193002 | |||
| 5643faad94 | |||
| 989f6c25a0 | |||
| 2e5103b19a |
208
LICENSE
Normal file
@@ -0,0 +1,208 @@
|
||||
Apache License
|
||||
|
||||
Version 2.0, January 2004
|
||||
|
||||
http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION,
|
||||
AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and distribution
|
||||
as defined by Sections 1 through 9 of this document.
|
||||
|
||||
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright
|
||||
owner that is granting the License.
|
||||
|
||||
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities
|
||||
that control, are controlled by, or are under common control with that entity.
|
||||
For the purposes of this definition, "control" means (i) the power, direct
|
||||
or indirect, to cause the direction or management of such entity, whether
|
||||
by contract or otherwise, or (ii) ownership of fifty percent (50%) or more
|
||||
of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions
|
||||
granted by this License.
|
||||
|
||||
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including
|
||||
but not limited to software source code, documentation source, and configuration
|
||||
files.
|
||||
|
||||
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation
|
||||
or translation of a Source form, including but not limited to compiled object
|
||||
code, generated documentation, and conversions to other media types.
|
||||
|
||||
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form,
|
||||
made available under the License, as indicated by a copyright notice that
|
||||
is included in or attached to the work (an example is provided in the Appendix
|
||||
below).
|
||||
|
||||
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form,
|
||||
that is based on (or derived from) the Work and for which the editorial revisions,
|
||||
annotations, elaborations, or other modifications represent, as a whole, an
|
||||
original work of authorship. For the purposes of this License, Derivative
|
||||
Works shall not include works that remain separable from, or merely link (or
|
||||
bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version
|
||||
of the Work and any modifications or additions to that Work or Derivative
|
||||
Works thereof, that is intentionally submitted to Licensor for inclusion in
|
||||
the Work by the copyright owner or by an individual or Legal Entity authorized
|
||||
to submit on behalf of the copyright owner. For the purposes of this definition,
|
||||
"submitted" means any form of electronic, verbal, or written communication
|
||||
sent to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems, and
|
||||
issue tracking systems that are managed by, or on behalf of, the Licensor
|
||||
for the purpose of discussing and improving the Work, but excluding communication
|
||||
that is conspicuously marked or otherwise designated in writing by the copyright
|
||||
owner as "Not a Contribution."
|
||||
|
||||
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
||||
of whom a Contribution has been received by Licensor and subsequently incorporated
|
||||
within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of this
|
||||
License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable copyright license to reproduce, prepare
|
||||
Derivative Works of, publicly display, publicly perform, sublicense, and distribute
|
||||
the Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of this License,
|
||||
each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable (except as stated in this section) patent
|
||||
license to make, have made, use, offer to sell, sell, import, and otherwise
|
||||
transfer the Work, where such license applies only to those patent claims
|
||||
licensable by such Contributor that are necessarily infringed by their Contribution(s)
|
||||
alone or by combination of their Contribution(s) with the Work to which such
|
||||
Contribution(s) was submitted. If You institute patent litigation against
|
||||
any entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||
that the Work or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses granted to You
|
||||
under this License for that Work shall terminate as of the date such litigation
|
||||
is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the Work or
|
||||
Derivative Works thereof in any medium, with or without modifications, and
|
||||
in Source or Object form, provided that You meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or Derivative Works a copy
|
||||
of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices stating that
|
||||
You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works that You distribute,
|
||||
all copyright, patent, trademark, and attribution notices from the Source
|
||||
form of the Work, excluding those notices that do not pertain to any part
|
||||
of the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its distribution,
|
||||
then any Derivative Works that You distribute must include a readable copy
|
||||
of the attribution notices contained within such NOTICE file, excluding those
|
||||
notices that do not pertain to any part of the Derivative Works, in at least
|
||||
one of the following places: within a NOTICE text file distributed as part
|
||||
of the Derivative Works; within the Source form or documentation, if provided
|
||||
along with the Derivative Works; or, within a display generated by the Derivative
|
||||
Works, if and wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and do not modify the
|
||||
License. You may add Your own attribution notices within Derivative Works
|
||||
that You distribute, alongside or as an addendum to the NOTICE text from the
|
||||
Work, provided that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and may provide
|
||||
additional or different license terms and conditions for use, reproduction,
|
||||
or distribution of Your modifications, or for any such Derivative Works as
|
||||
a whole, provided Your use, reproduction, and distribution of the Work otherwise
|
||||
complies with the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise, any
|
||||
Contribution intentionally submitted for inclusion in the Work by You to the
|
||||
Licensor shall be under the terms and conditions of this License, without
|
||||
any additional terms or conditions. Notwithstanding the above, nothing herein
|
||||
shall supersede or modify the terms of any separate license agreement you
|
||||
may have executed with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade names,
|
||||
trademarks, service marks, or product names of the Licensor, except as required
|
||||
for reasonable and customary use in describing the origin of the Work and
|
||||
reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or agreed to
|
||||
in writing, Licensor provides the Work (and each Contributor provides its
|
||||
Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied, including, without limitation, any warranties
|
||||
or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness
|
||||
of using or redistributing the Work and assume any risks associated with Your
|
||||
exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory, whether
|
||||
in tort (including negligence), contract, or otherwise, unless required by
|
||||
applicable law (such as deliberate and grossly negligent acts) or agreed to
|
||||
in writing, shall any Contributor be liable to You for damages, including
|
||||
any direct, indirect, special, incidental, or consequential damages of any
|
||||
character arising as a result of this License or out of the use or inability
|
||||
to use the Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all other commercial
|
||||
damages or losses), even if such Contributor has been advised of the possibility
|
||||
of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing the Work
|
||||
or Derivative Works thereof, You may choose to offer, and charge a fee for,
|
||||
acceptance of support, warranty, indemnity, or other liability obligations
|
||||
and/or rights consistent with this License. However, in accepting such obligations,
|
||||
You may act only on Your own behalf and on Your sole responsibility, not on
|
||||
behalf of any other Contributor, and only if You agree to indemnify, defend,
|
||||
and hold each Contributor harmless for any liability incurred by, or claims
|
||||
asserted against, such Contributor by reason of your accepting any such warranty
|
||||
or additional liability. END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following boilerplate
|
||||
notice, with the fields enclosed by brackets "[]" replaced with your own identifying
|
||||
information. (Don't include the brackets!) The text should be enclosed in
|
||||
the appropriate comment syntax for the file format. We also recommend that
|
||||
a file or class name and description of purpose be included on the same "printed
|
||||
page" as the copyright notice for easier identification within third-party
|
||||
archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
See the License for the specific language governing permissions and
|
||||
|
||||
limitations under the License.
|
||||
@@ -366,6 +366,18 @@ class System
|
||||
'url' => (string)url('/index/topic/laptop/index')
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
'id' => 9,
|
||||
'name' => '闪存(SSD)专题',
|
||||
'url' => '',
|
||||
'children' => [
|
||||
[
|
||||
'id' => 101,
|
||||
'name' => '首页',
|
||||
'url' => (string)url('/index/topic/ssd/index')
|
||||
],
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ class SysMallStoreEntranceValidate extends Validate
|
||||
'name' => 'require|max:255',
|
||||
'image' => 'require|max:255',
|
||||
'hover_image' => 'max:255',
|
||||
'link' => 'max:500',
|
||||
'link' => 'url|max:500',
|
||||
'sort' => 'require|integer',
|
||||
'disabled' => 'in:0,1',
|
||||
];
|
||||
@@ -40,6 +40,7 @@ class SysMallStoreEntranceValidate extends Validate
|
||||
'image.require' => '图片不能为空',
|
||||
'image.max' => '图片长度不能超过:rule个字符',
|
||||
'hover_image.max' => '悬浮图长度不能超过:rule个字符',
|
||||
'link.url' => '链接地址必须是有效的URL',
|
||||
'link.max' => '链接地址长度不能超过:rule个字符',
|
||||
'sort.require' => '排序不能为空',
|
||||
'sort.integer' => '排序必须是整数',
|
||||
|
||||
@@ -93,7 +93,7 @@ abstract class Common extends BaseController
|
||||
])
|
||||
->when($with_recommends, function($query) {
|
||||
$query->with(['recommends' => function($query) {
|
||||
$query->field(['id', 'category_id', 'title', 'image', 'desc', 'link'])
|
||||
$query->field(['id', 'category_id', 'title', 'image', 'desc', 'link'])->disabled(false)
|
||||
->order(['sort' => 'asc', 'id' => 'desc']);
|
||||
}]);
|
||||
})
|
||||
@@ -120,7 +120,13 @@ abstract class Common extends BaseController
|
||||
}
|
||||
$children = $this->toTreeAndChunk($categorys, $item['id'], $lv);
|
||||
if (!empty($children)) {
|
||||
$item['children'] = $item['level'] == 1 ? array_chunk($children, 2) : $children;
|
||||
if ($lv == 1) {
|
||||
$item['children'] = array_chunk($children, 2);
|
||||
} else if ($lv == 2) {
|
||||
$item['children'] = array_chunk($children, 3);
|
||||
} else {
|
||||
$item['children'] = $children;
|
||||
}
|
||||
}
|
||||
$ret[] = $item;
|
||||
}
|
||||
|
||||
@@ -267,6 +267,59 @@ class Product extends Common
|
||||
return View::fetch('subcategory');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 单纯分类页
|
||||
*/
|
||||
public function classify()
|
||||
{
|
||||
$pid = request()->param('id/d', 0);
|
||||
|
||||
// 获取当前选中的父分类
|
||||
$parent = ProductCategoryModel::field(['id', 'name'])->find($pid);
|
||||
View::assign('parent', $parent);
|
||||
|
||||
// 获取分类及产品信息
|
||||
$categorys = ProductCategoryModel::field(['id', 'pid', 'name', 'path', 'level'])
|
||||
->language($this->lang_id)
|
||||
->displayed(true)
|
||||
->children($pid)
|
||||
->order(['pid' => 'asc', 'sort' => 'asc', 'id' => 'desc'])
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
// 组装第三级分类所属产品数据
|
||||
$lv3_id_arr = array_column(array_filter($categorys, fn($item)=> $item['level'] === 3), 'id');
|
||||
$products = ProductModel::field([
|
||||
'id',
|
||||
'category_id',
|
||||
'name',
|
||||
'short_name',
|
||||
'cover_image',
|
||||
'spu'
|
||||
])
|
||||
->byCategory($lv3_id_arr)
|
||||
->language($this->lang_id)
|
||||
->enabled(true)
|
||||
->onSale(true)
|
||||
->onShelves(true)
|
||||
->select()
|
||||
->toArray();
|
||||
$product_groups = [];
|
||||
foreach ($products as $product) {
|
||||
$product_groups[$product['category_id']][] = $product;
|
||||
}
|
||||
foreach ($categorys as $key => $category) {
|
||||
if ($category['level'] < 3) continue;
|
||||
$categorys[$key]['products'] = $product_groups[$category['id']] ?? [];
|
||||
}
|
||||
|
||||
$tree = array_to_tree($categorys, $pid);
|
||||
View::assign('categorys', $tree);
|
||||
|
||||
return View::fetch('classify');
|
||||
}
|
||||
|
||||
/**
|
||||
* 产品搜索
|
||||
*/
|
||||
|
||||
52
app/index/controller/TopicSsd.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\index\controller;
|
||||
|
||||
use app\index\model\SysBannerModel;
|
||||
use think\facade\View;
|
||||
|
||||
/**
|
||||
* 专题 - SSD
|
||||
*/
|
||||
class TopicSsd extends Common
|
||||
{
|
||||
/**
|
||||
* 专题 - SSD首页
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$banners = SysBannerModel::with([
|
||||
'items' => function ($query) {
|
||||
$query->withoutField(['sort', 'created_at', 'updated_at', 'deleted_at'])
|
||||
->order(['sort' => 'asc', 'id' => 'desc'])
|
||||
->enabled(true);
|
||||
}
|
||||
])
|
||||
->atPlatform(request()->from)
|
||||
->uniqueLabel([
|
||||
'BANNER_69faaf8582967', // 专题 - 闪存(SSD)首页 - 焦点图
|
||||
'BANNER_69fab1bed8f71', // 专题 - 闪存(SSD)首页 - 产品
|
||||
])
|
||||
->language($this->lang_id)
|
||||
->enabled(true)
|
||||
->order(['sort' => 'asc', 'id' => 'desc'])
|
||||
->select();
|
||||
|
||||
$data = [];
|
||||
if (!$banners->isEmpty()) {
|
||||
$banners_map = [];
|
||||
foreach ($banners as $banner) {
|
||||
$banners_map[$banner->unique_label] = $banner;
|
||||
}
|
||||
|
||||
// 焦点图轮播图
|
||||
$data['top_focus_images'] = data_get($banners_map, 'BANNER_69faaf8582967')?->items->toArray();
|
||||
// 产品
|
||||
$data['products'] = data_get($banners_map, 'BANNER_69fab1bed8f71')?->items->toArray();
|
||||
}
|
||||
View::assign('data', $data);
|
||||
|
||||
return View::fetch('index');
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,9 @@ return [
|
||||
'产品列表' => 'Products',
|
||||
'搜索' => 'Search',
|
||||
'搜索历史' => 'Search History',
|
||||
'请输入搜索关键词' => 'Please enter a search keyword',
|
||||
'搜索记录' => 'Search History',
|
||||
'清空' => 'Clear',
|
||||
'请择地区' => 'SELECT A REGION',
|
||||
'产品' => 'Product',
|
||||
'联系方式' => 'Contact',
|
||||
|
||||
@@ -22,4 +22,9 @@ class ProductCategoryRecommendModel extends ProductCategoryRecommendBaseModel
|
||||
{
|
||||
$query->where($this->getTable() . '.language_id', '=', $language);
|
||||
}
|
||||
|
||||
public function scopeDisabled($query, $disabled = true)
|
||||
{
|
||||
$query->where($this->getTable() . '.disabled', '=', (int)$disabled);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ Route::group('product', function () {
|
||||
Route::get('category/:id', 'Product/category');
|
||||
// 产品分类 - 查看子类
|
||||
Route::get('subcategory/:id', 'Product/subcategory');
|
||||
// 单纯分类页
|
||||
Route::get('classify/:id', 'Product/classify');
|
||||
// 产品详情页
|
||||
Route::get('detail/:id', 'Product/detail');
|
||||
// 产品询盘
|
||||
@@ -117,6 +119,12 @@ Route::group('topic', function () {
|
||||
// 专题 - 笔记本电脑首页
|
||||
Route::get('index', 'TopicLaptop/index');
|
||||
});
|
||||
|
||||
// 专题 - SSD
|
||||
Route::group('ssd', function() {
|
||||
// 专题 - SSD首页
|
||||
Route::get('index', 'TopicSsd/index');
|
||||
});
|
||||
});
|
||||
|
||||
// 数据迁移
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<!-- banner-->
|
||||
<div class="oidx-banner">
|
||||
{notempty name="focus_images"}
|
||||
<div class="swiper-container bannerswiper">
|
||||
<div class="swiper-container bannerswiper" style="background: #fff;">
|
||||
<div class="swiper-wrapper">
|
||||
{volist name="focus_images" id="fi"}
|
||||
<div class="swiper-slide">
|
||||
|
||||
225
app/index/view/mobile/product/classify.html
Normal file
@@ -0,0 +1,225 @@
|
||||
{extend name="public/base" /}
|
||||
|
||||
{block name="style"}
|
||||
<link rel="stylesheet" href="__CSS__/category.css">
|
||||
|
||||
<script type="text/javascript">
|
||||
(function (doc, win) {
|
||||
var docEl = doc.documentElement;
|
||||
var resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
|
||||
|
||||
function setRootFontSize() {
|
||||
var clientWidth = docEl.clientWidth;
|
||||
if (!clientWidth) return;
|
||||
var fontSize = clientWidth / 8.04; // 750px/7.5=100px,375px/7.5=50px
|
||||
// 直接修改内联样式,优先级最高
|
||||
docEl.setAttribute('style', 'font-size: ' + fontSize + 'px !important;');
|
||||
}
|
||||
|
||||
setRootFontSize();
|
||||
win.addEventListener(resizeEvt, setRootFontSize);
|
||||
doc.addEventListener('DOMContentLoaded', setRootFontSize);
|
||||
})(document, window);
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
{/block}
|
||||
|
||||
{block name="main"}
|
||||
<!-- 顶部返回栏(已完全按图纸修改) -->
|
||||
<div class="top-box">
|
||||
<div class="top-bar">
|
||||
<div class="back">
|
||||
<image src="__IMAGES__/left.png"></image>
|
||||
</div>
|
||||
<div class="title">{$parent.name|default=''}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main">
|
||||
<!-- 左侧导航 -->
|
||||
{if condition="!empty($categorys)"}
|
||||
<ul class="sidebar">
|
||||
{volist name="categorys" id="category"}
|
||||
<li class="nav-item {eq name='$key' value='0'}active{/eq}" data-tab="tab{$category.id}">{$category.name}</li>
|
||||
{/volist}
|
||||
<li style="background: #fff;" class="li-bottom"></li>
|
||||
</ul>
|
||||
|
||||
<!-- 右侧分区内容 -->
|
||||
<div class="right-content">
|
||||
{volist name="categorys" id="category"}
|
||||
<div class="tab-pane {eq name='$key' value='0'}active{/eq}" id="tab{$category.id}">
|
||||
{if condition="!empty($category.children)"}
|
||||
{volist name="$category.children" id="child"}
|
||||
<section class="sec-box">
|
||||
<div class="sec-header">
|
||||
<div class="sec-title">{$child.name}</div>
|
||||
<a class="sec-arrow" href="{:url('product/subcategory', ['id' => $child.id])}" target="_self">
|
||||
<img src="__IMAGES__/y.png" alt="">
|
||||
</a>
|
||||
</div>
|
||||
{if condition="!empty($child.products)"}
|
||||
<div class="scroll-box">
|
||||
{volist name="$child.products" id="pro"}
|
||||
<a class="card" href="{:url('product/detail', ['id' => $pro.id])}" style="background: #fff;">
|
||||
<div class="card-img">
|
||||
<img src="{$pro.cover_image}" alt="">
|
||||
</div>
|
||||
<div class="card-info">
|
||||
<div class="card-name">{$pro.name}</div>
|
||||
<div class="card-model">{$pro.spu}</div>
|
||||
</div>
|
||||
</a>
|
||||
{/volist}
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
{/volist}
|
||||
{/if}
|
||||
</div>
|
||||
{/volist}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/block}
|
||||
|
||||
{block name="script"}
|
||||
|
||||
<script>
|
||||
// 点击右侧箭头滚动
|
||||
function scrollNext (el)
|
||||
{
|
||||
const box = el.closest('section')?.querySelector('.scroll-box')
|
||||
|| el.parentElement.nextElementSibling
|
||||
if (box) box.scrollBy({ left: 150, behavior: 'smooth' })
|
||||
}
|
||||
const back = document.querySelector('.back')
|
||||
// 左侧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')
|
||||
})
|
||||
})
|
||||
|
||||
back.addEventListener('click',()=>{
|
||||
window.location.href = document.referrer;
|
||||
})
|
||||
// 更新侧边栏相邻元素的圆角
|
||||
function updateSidebarAdjacentRadius() {
|
||||
const sidebarItems = document.querySelectorAll('.sidebar li');
|
||||
|
||||
// 先移除所有相邻类名
|
||||
sidebarItems.forEach(item => {
|
||||
item.classList.remove('active-prev', 'active-next');
|
||||
});
|
||||
|
||||
// 找到当前激活的项
|
||||
let activeIndex = -1;
|
||||
sidebarItems.forEach((item, index) => {
|
||||
if (item.classList.contains('active')) {
|
||||
activeIndex = index;
|
||||
}
|
||||
});
|
||||
|
||||
// 添加上一个和下一个的类名(使用requestAnimationFrame确保DOM更新)
|
||||
requestAnimationFrame(() => {
|
||||
if (activeIndex > 0) {
|
||||
sidebarItems[activeIndex - 1].classList.add('active-prev');
|
||||
}
|
||||
if (activeIndex < sidebarItems.length - 1) {
|
||||
sidebarItems[activeIndex + 1].classList.add('active-next');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 绑定点击事件
|
||||
document.querySelectorAll('.sidebar li').forEach(item => {
|
||||
item.addEventListener('click', function() {
|
||||
// 移除所有active
|
||||
document.querySelectorAll('.sidebar li').forEach(li => {
|
||||
li.classList.remove('active');
|
||||
});
|
||||
// 添加active
|
||||
this.classList.add('active');
|
||||
// 更新相邻圆角
|
||||
updateSidebarAdjacentRadius();
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
// 页面初始化时调用
|
||||
if (document.querySelector('.sidebar li.active')) {
|
||||
updateSidebarAdjacentRadius();
|
||||
}
|
||||
|
||||
|
||||
// 动态计算 li-bottom 的高度
|
||||
function setLiBottomHeight() {
|
||||
const sidebar = document.querySelector('.sidebar');
|
||||
const liBottom = document.querySelector('.sidebar .li-bottom');
|
||||
const sidebarItems = document.querySelectorAll('.sidebar li:not(.li-bottom)');
|
||||
|
||||
if (!sidebar || !liBottom || sidebarItems.length === 0) return;
|
||||
|
||||
// 计算所有正常li的总高度
|
||||
let totalHeight = 0;
|
||||
sidebarItems.forEach(item => {
|
||||
totalHeight += item.offsetHeight;
|
||||
});
|
||||
|
||||
// 获取sidebar的高度
|
||||
const sidebarHeight = sidebar.offsetHeight;
|
||||
|
||||
// 计算剩余高度
|
||||
const remainingHeight = sidebarHeight - totalHeight;
|
||||
|
||||
// 赋值给 li-bottom
|
||||
if (remainingHeight > 0) {
|
||||
liBottom.style.height = remainingHeight + 'px';
|
||||
} else {
|
||||
liBottom.style.height = '0px';
|
||||
liBottom.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// 页面加载时执行
|
||||
window.addEventListener('load', function() {
|
||||
setLiBottomHeight();
|
||||
});
|
||||
|
||||
// 窗口大小改变时重新计算
|
||||
window.addEventListener('resize', function() {
|
||||
console.log('切换了吗')
|
||||
setLiBottomHeight();
|
||||
});
|
||||
|
||||
// 如果侧边栏内容有动态变化,使用 MutationObserver 监听
|
||||
const observer = new MutationObserver(function() {
|
||||
setLiBottomHeight();
|
||||
});
|
||||
|
||||
// 监听侧边栏变化
|
||||
const sidebar = document.querySelector('.sidebar');
|
||||
if (sidebar) {
|
||||
observer.observe(sidebar, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
attributes: true
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
@@ -1,559 +1,104 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>ORICO 移动硬盘</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: sans-serif
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.mobile-header-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 46px;
|
||||
padding: 0 17px;
|
||||
background: #fff;
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.mobile-header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-img,
|
||||
.nav-search,
|
||||
.nav-lang,
|
||||
.nav-img1,
|
||||
.nav-card {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nav-log {
|
||||
width: 90px;
|
||||
height: 22px;
|
||||
margin-left: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nav-lang {
|
||||
margin: 0 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 下拉菜单 */
|
||||
.nav-dropdown-menu {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
border-top: 1px solid #eee;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 46px;
|
||||
left: 0;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.nav-dropdown-menu.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 所有菜单项统一用 div */
|
||||
.menu-item {
|
||||
margin: 0 22px;
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.menu-item-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
.menu-item-img {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 有子菜单才显示箭头 */
|
||||
.has-child .menu-item-img {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 无子菜单隐藏箭头 */
|
||||
.no-child .menu-item-img {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 箭头旋转 */
|
||||
.has-child.open .menu-item-img {
|
||||
transform: rotate(180deg);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.nav-img1 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sub-menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sub-menu.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sub-item {
|
||||
padding: 0 16px;
|
||||
font-size: 14px;
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
.sub-item:nth-child(1) {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.sub-item a {
|
||||
color: #686A70;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sub-item:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.sub-item-card-img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
aspect-ratio: 358 / 192;
|
||||
}
|
||||
|
||||
.sub-item-card-title {
|
||||
font-size: 16px;
|
||||
color: #1D1D1F;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.sub-item-card-name {
|
||||
font-size: 14px;
|
||||
color: #686A70;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.no-padding {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* ====================== 弹窗样式(不遮盖头部) ====================== */
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
top: 46px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: calc(100% - 46px);
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: none;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
z-index: 98;
|
||||
}
|
||||
|
||||
.modal-overlay.show {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
width: 90%;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 66px 24px 8px 24px;
|
||||
margin-top: 20px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
position: absolute;
|
||||
top: 24px;
|
||||
right: 24px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 写法2:使用 flex 布局实现一行2个 */
|
||||
.modal-items-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.modal-item {
|
||||
width: calc(50% - 16px);
|
||||
|
||||
font-size: 16px;
|
||||
color: #1D1D1F;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.modal-item-img {
|
||||
width: clamp(48px, 17vw, 128px);
|
||||
height: auto;
|
||||
aspect-ratio: 64 / 64;
|
||||
object-fit: contain;
|
||||
display: block;
|
||||
|
||||
}
|
||||
|
||||
.modal-item-title {
|
||||
margin-top: 10px;
|
||||
font-size: 16px;
|
||||
color: #1D1D1F;
|
||||
}
|
||||
|
||||
.modal-item:hover {
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* 语言弹窗样式 - 列表布局 */
|
||||
.lang-modal-content {
|
||||
width: 90%;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 68px 24px;
|
||||
margin-top: 20px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.lang-items-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.lang-item {
|
||||
font-size: 16px;
|
||||
color: #1D1D1F;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.lang-item img {
|
||||
width: 29px;
|
||||
height: 20px;
|
||||
margin-right: 16px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.lang-item:last-child {
|
||||
border-bottom: none;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.lang-item:hover {
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* 搜索弹窗样式 */
|
||||
.search-modal-content {
|
||||
width: 90%;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 68px 24px;
|
||||
margin-top: 20px;
|
||||
position: relative;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.search-input-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 30px;
|
||||
padding-left: 24px;
|
||||
padding-right: 13px;
|
||||
background: #f8f8f8;
|
||||
}
|
||||
|
||||
.search-input-box input {
|
||||
flex: 1;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
font-size: 14px;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.search-input-box input::placeholder {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.search-input-box .search-clear-btn {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
cursor: pointer;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.search-input-box .search-clear-btn:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.search-input-box .search-submit-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.search-history {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.search-history-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.search-history-title {
|
||||
font-size: 14px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.search-history-clear {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.search-history-clear:hover {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.search-history-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.search-history-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.search-history-item:hover {
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
margin-left: -8px;
|
||||
margin-right: -8px;
|
||||
}
|
||||
|
||||
.search-history-item span {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.search-history-item .delete-icon {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
cursor: pointer;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.search-history-item .delete-icon:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.empty-history {
|
||||
text-align: center;
|
||||
padding: 40px 0;
|
||||
font-size: 14px;
|
||||
color: #aaa;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<link rel="stylesheet" href="__CSS__/new_header.css">
|
||||
<header>
|
||||
<div class="mobile-header-box">
|
||||
<div class="mobile-header-left">
|
||||
<img src="./img/nav.png" class="nav-img">
|
||||
<img src="./img/x.png" class="nav-img1">
|
||||
<a href="#" target="_self" style="display: flex; justify-content: center;">
|
||||
<img src="./img/log.png" class="nav-log">
|
||||
<img src="__IMAGES__/header/nav.png" class="nav-img">
|
||||
<img src="__IMAGES__/header/x.png" class="nav-img1">
|
||||
<a href="/" target="_self" style="display: flex; justify-content: center;">
|
||||
<img src="__IMAGES__/logo.png" class="nav-log">
|
||||
</a>
|
||||
</div>
|
||||
<div class="mobile-header-right">
|
||||
<img src="./img/search.png" class="nav-search">
|
||||
<img src="./img/lang.png" class="nav-lang">
|
||||
<img src="./img/card.png" class="nav-card">
|
||||
<img src="__IMAGES__/header/search.png" class="nav-search">
|
||||
<img src="__IMAGES__/header/lang.png" class="nav-lang">
|
||||
<img src="__IMAGES__/header/card.png" class="nav-card">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="nav-dropdown-menu">
|
||||
<div class="nav-dropdown-menu" style="height: 100vh; overflow-y: scroll;-webkit-overflow-scrolling: touch;padding-bottom:9rem;">
|
||||
<!-- 产品列表 - 有子菜单 -->
|
||||
<div class="menu-item has-child">
|
||||
<div class="menu-item-box">
|
||||
<span>产品列表</span>
|
||||
<img src="./img/b.png" class="menu-item-img">
|
||||
<span>{:lang_i18n('产品列表')}</span>
|
||||
<img src="__IMAGES__/header/b.png" class="menu-item-img">
|
||||
</div>
|
||||
<div class="sub-menu">
|
||||
<div class="sub-item"><a href="#" target="_self">数据存储</a></div>
|
||||
<div class="sub-item"><a href="#" target="_self">生活家居</a></div>
|
||||
<div class="sub-item"><a href="#" target="_self">3C配件</a></div>
|
||||
{if condition="!empty($header_categorys)"}
|
||||
<div class="sub-menu" style="overflow-y: auto;">
|
||||
{volist name="header_categorys" id="vo" key="idx"}
|
||||
<div class="sub-item"><a href="{:url('product/classify', ['id' => $vo.id])}" target="_self">{$vo.name}</a></div>
|
||||
{/volist}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- 闪存 - 无子菜单 -->
|
||||
<div class="menu-item no-child" data-link="/flash">
|
||||
{if condition="!empty($header_navigation)"}
|
||||
{volist name="header_navigation" id="nav"}
|
||||
{empty name='nav.children'}
|
||||
<div class="menu-item no-child" data-link="{$nav.link}">
|
||||
{else/}
|
||||
<div class="menu-item has-child" data-link="{$nav.link}">
|
||||
{/empty}
|
||||
<div class="menu-item-box">
|
||||
<span>闪存</span>
|
||||
<img src="./img/b.png" class="menu-item-img">
|
||||
<span>{$nav.name}</span>
|
||||
<img src="__IMAGES__/header/b.png" class="menu-item-img">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 电力 - 有子菜单 -->
|
||||
<div class="menu-item has-child" data-link="">
|
||||
<div class="menu-item-box">
|
||||
<span>电力</span>
|
||||
<img src="./img/b.png" class="menu-item-img">
|
||||
</div>
|
||||
<div class="sub-menu">
|
||||
<div class="sub-item no-padding">
|
||||
<a href="https://orico.cc" target="_self" class="sub-item-card">
|
||||
<img src="./img/s.png" alt="" class="sub-item-card-img">
|
||||
<div class="sub-item-card-title">软件下载</div>
|
||||
<div class="sub-item-card-name">赛博云系统/微链接系统多平台客户端下载</div>
|
||||
{if condition="!empty($nav.children)"}
|
||||
<div class="sub-menu" style="border: none;" >
|
||||
{volist name="nav.children" id="child"}
|
||||
<div class="sub-item no-padding ">
|
||||
<a href="{$child.link}" target="{$child.blank==1?'_blank':'_self'}" class="sub-item-card">
|
||||
<img src="{$child.image}" alt="" class="sub-item-card-img">
|
||||
<div class="sub-item-card-title">{$child.name}</div>
|
||||
<div class="sub-item-card-name">{$child.desc}</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="sub-item no-padding">
|
||||
<a href="https://baidu.com" target="_self" class="sub-item-card">
|
||||
<img src="./img/s.png" alt="" class="sub-item-card-img">
|
||||
<div class="sub-item-card-title">软件下载</div>
|
||||
<div class="sub-item-card-name">赛博云系统/微链接系统多平台客户端下载</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AI PC - 无子菜单 -->
|
||||
<div class="menu-item no-child" data-link="/ai-pc">
|
||||
<div class="menu-item-box">
|
||||
<span>AI PC</span>
|
||||
<img src="./img/b.png" class="menu-item-img">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- NAS - 无子菜单 -->
|
||||
<div class="menu-item no-child" data-link="/nas">
|
||||
<div class="menu-item-box">
|
||||
<span>NAS</span>
|
||||
<img src="./img/b.png" class="menu-item-img">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 技术支持 - 无子菜单 -->
|
||||
<div class="menu-item no-child" data-link="/support">
|
||||
<div class="menu-item-box">
|
||||
<span>技术支持</span>
|
||||
<img src="./img/b.png" class="menu-item-img">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 关于我们 - 无子菜单 -->
|
||||
<div class="menu-item no-child" data-link="/about">
|
||||
<div class="menu-item-box">
|
||||
<span>关于我们</span>
|
||||
<img src="./img/b.png" class="menu-item-img">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 合作加盟 - 无子菜单 -->
|
||||
<div class="menu-item no-child" data-link="/join">
|
||||
<div class="menu-item-box">
|
||||
<span>合作加盟</span>
|
||||
<img src="./img/b.png" class="menu-item-img">
|
||||
{/volist}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/volist}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- ====================== 购物车弹窗 ====================== -->
|
||||
<div class="modal-overlay" id="cartModal">
|
||||
<div class="modal-content">
|
||||
<img src="./img/x.png" class="modal-close">
|
||||
<img src="__IMAGES__/header/x.png" class="modal-close">
|
||||
{if condition="!empty($header_mall_entrance)"}
|
||||
<div class="modal-items-list">
|
||||
<a class="modal-item" href="#" target="_self">
|
||||
<img src="./img/g.png" alt="" class="modal-item-img">
|
||||
<div class="modal-item-title">京东自营旗舰店</div>
|
||||
</a>
|
||||
<a class="modal-item" href="#" target="_self">
|
||||
<img src="./img/g.png" alt="" class="modal-item-img">
|
||||
<div class="modal-item-title">天猫旗舰店</div>
|
||||
</a>
|
||||
<a class="modal-item" href="#" target="_self">
|
||||
<img src="./img/g.png" alt="" class="modal-item-img">
|
||||
<div class="modal-item-title">拼多多旗舰店</div>
|
||||
</a>
|
||||
<a class="modal-item" href="#" target="_self">
|
||||
<img src="./img/g.png" alt="" class="modal-item-img">
|
||||
<div class="modal-item-title">抖音店铺</div>
|
||||
{volist name="header_mall_entrance" id="ma"}
|
||||
{if condition="!empty($ma.link)"}
|
||||
<a class="modal-item" href="{$ma.link}" target="_self">
|
||||
<img src="{$ma.image}" alt="" class="modal-item-img">
|
||||
<div class="modal-item-title">{$ma.name}</div>
|
||||
</a>
|
||||
{else/}
|
||||
<!--悬浮图-->
|
||||
<div class="modal-item" data-link="{$ma.link}" style="cursor: pointer;">
|
||||
<img src="{$ma.image}" alt="" class="modal-item-img">
|
||||
<div class="modal-item-title">{$ma.name}</div>
|
||||
</div>
|
||||
<div class="modal-item" style="display:none">
|
||||
<img src="{$ma.hover_image}" alt="" class="modal-item-img">
|
||||
</div>
|
||||
{/if}
|
||||
{/volist}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ====================== 语言弹窗 ====================== -->
|
||||
<div class="modal-overlay" id="langModal">
|
||||
<div class="lang-modal-content">
|
||||
<img src="./img/x.png" class="modal-close">
|
||||
<img src="__IMAGES__/header/x.png" class="modal-close">
|
||||
<div class="lang-items-list">
|
||||
<a class="lang-item" href="#" target="_self">
|
||||
<img src="https://orico.com.cn/static/common/images/langs/CN.png" />
|
||||
<div>China - Simplified Chinese</div>
|
||||
</a>
|
||||
<a class="lang-item" href="#" target="_self">
|
||||
<img src="https://orico.com.cn/static/common/images/langs/CN.png" />
|
||||
<div>USA - English</div>
|
||||
{volist name="header_languages" id="la"}
|
||||
<a class="lang-item" href="{$la.lang_url}" target="_self">
|
||||
<img src="{$la.lang_icon}" />
|
||||
<div>{$la.country_en_name} - {$la.lang_en_name}</div>
|
||||
</a>
|
||||
{/volist}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -561,17 +106,22 @@
|
||||
<!-- ====================== 搜索弹窗 ====================== -->
|
||||
<div class="modal-overlay" id="searchModal">
|
||||
<div class="search-modal-content">
|
||||
<img src="./img/x.png" class="modal-close">
|
||||
<img src="__IMAGES__/header/x.png" class="modal-close">
|
||||
<div class="search-input-box">
|
||||
<input type="text" placeholder="请输入搜索关键词" id="searchInput">
|
||||
<img src="./img/x.png" alt="清除" class="search-clear-btn" id="searchClearBtn" style="display: none;">
|
||||
<span style="width: 1px; color:#d9d9d9;margin: 0 10px;">|</span>
|
||||
<img src="./img/search.png" alt="搜索" class="search-submit-icon" id="searchSubmit">
|
||||
<input type="text" placeholder="{:lang_i18n('请输入搜索关键词')}" id="searchInput">
|
||||
|
||||
<div class="search-clear-box">
|
||||
<img src="__IMAGES__/header/x.png" alt="{:lang_i18n('清除')}" class="search-clear-btn" id="searchClearBtn" style="display: none;">
|
||||
</div>
|
||||
<!-- <span style="width: 1px; color:#d9d9d9;margin: 0 10px;">|</span> -->
|
||||
<div class="search-submit-box">
|
||||
<img src="__IMAGES__/header/search.png" alt="{:lang_i18n('搜索')}" class="search-submit-icon" id="searchSubmit">
|
||||
</div>
|
||||
</div>
|
||||
<div class="search-history">
|
||||
<div class="search-history-header">
|
||||
<div class="search-history-title">搜索记录</div>
|
||||
<div class="search-history-clear" id="clearAllHistory">清空</div>
|
||||
<div class="search-history-title">{:lang_i18n('搜索记录')}</div>
|
||||
<div class="search-history-clear" id="clearAllHistory">{:lang_i18n('清空')}</div>
|
||||
</div>
|
||||
<div class="search-history-list" id="searchHistoryList">
|
||||
<!-- 搜索记录会动态显示在这里 -->
|
||||
@@ -579,18 +129,89 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<script>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function ()
|
||||
{
|
||||
const navBtn = document.querySelector('.nav-img');
|
||||
const navBtn1 = document.querySelector('.nav-img1');
|
||||
const dropdownMenu = document.querySelector('.nav-dropdown-menu');
|
||||
|
||||
// 禁止body滚动
|
||||
function disableBodyScroll() {
|
||||
document.body.style.overflow = 'hidden';
|
||||
document.body.style.position = 'fixed';
|
||||
document.body.style.top = `-${window.scrollY}px`;
|
||||
document.body.style.width = '100%';
|
||||
}
|
||||
|
||||
// 恢复body滚动
|
||||
function enableBodyScroll() {
|
||||
const scrollY = document.body.style.top;
|
||||
document.body.style.overflow = '';
|
||||
document.body.style.position = '';
|
||||
document.body.style.top = '';
|
||||
document.body.style.width = '';
|
||||
if (scrollY) {
|
||||
window.scrollTo(0, parseInt(scrollY || '0') * -1);
|
||||
}
|
||||
}
|
||||
|
||||
// 复位所有子菜单(关闭并重置滚动位置)
|
||||
function resetAllSubMenus() {
|
||||
let hasOpenMenu = false;
|
||||
document.querySelectorAll('.has-child .sub-menu').forEach(function(subMenu) {
|
||||
if (subMenu.classList.contains('show')) {
|
||||
hasOpenMenu = true;
|
||||
}
|
||||
subMenu.classList.remove('show');
|
||||
// 重置滚动位置到顶部
|
||||
subMenu.scrollTop = 0;
|
||||
});
|
||||
document.querySelectorAll('.has-child').forEach(function(item) {
|
||||
item.classList.remove('open');
|
||||
});
|
||||
|
||||
// 如果没有打开的菜单,恢复body滚动
|
||||
if (!hasOpenMenu) {
|
||||
enableBodyScroll();
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭单个子菜单并重置滚动位置
|
||||
function closeSubMenu(subMenu, menuItem) {
|
||||
if (subMenu) {
|
||||
subMenu.classList.remove('show');
|
||||
subMenu.scrollTop = 0; // 重置滚动位置
|
||||
}
|
||||
if (menuItem) {
|
||||
menuItem.classList.remove('open');
|
||||
}
|
||||
// 检查是否还有其他打开的菜单
|
||||
const anyOpen = document.querySelector('.has-child .sub-menu.show');
|
||||
if (!anyOpen) {
|
||||
enableBodyScroll();
|
||||
}
|
||||
}
|
||||
|
||||
// 打开子菜单
|
||||
function openSubMenu(subMenu, menuItem) {
|
||||
// 禁止body滚动
|
||||
disableBodyScroll();
|
||||
|
||||
subMenu.classList.add('show');
|
||||
menuItem.classList.add('open');
|
||||
// 确保新打开的菜单滚动位置在顶部
|
||||
subMenu.scrollTop = 0;
|
||||
}
|
||||
|
||||
// 打开菜单
|
||||
navBtn.addEventListener('click', function (e)
|
||||
{
|
||||
e.stopPropagation();
|
||||
// 禁止body滚动
|
||||
disableBodyScroll();
|
||||
// 关闭所有弹窗
|
||||
closeAllModals();
|
||||
dropdownMenu.classList.add('show');
|
||||
@@ -598,16 +219,19 @@
|
||||
navBtn1.style.display = 'block';
|
||||
});
|
||||
|
||||
// 关闭菜单
|
||||
// 关闭菜单 - 复位所有子菜单
|
||||
navBtn1.addEventListener('click', function (e)
|
||||
{
|
||||
e.stopPropagation();
|
||||
dropdownMenu.classList.remove('show');
|
||||
navBtn.style.display = 'block';
|
||||
navBtn1.style.display = 'none';
|
||||
|
||||
// 复位所有子菜单到初始状态
|
||||
resetAllSubMenus();
|
||||
});
|
||||
|
||||
// 处理所有菜单项
|
||||
// ====================== 处理所有菜单项(同一时间只展开一个) ======================
|
||||
document.querySelectorAll('.menu-item').forEach(function (item)
|
||||
{
|
||||
const isHasChild = item.classList.contains('has-child');
|
||||
@@ -615,11 +239,33 @@
|
||||
const box = item.querySelector('.menu-item-box');
|
||||
|
||||
if (isHasChild && subMenu) {
|
||||
box.addEventListener('click', function (e)
|
||||
// 移除原有事件,重新绑定(确保只有一个展开)
|
||||
const newBox = box.cloneNode(true);
|
||||
box.parentNode.replaceChild(newBox, box);
|
||||
|
||||
newBox.addEventListener('click', function (e)
|
||||
{
|
||||
e.stopPropagation();
|
||||
subMenu.classList.toggle('show');
|
||||
item.classList.toggle('open');
|
||||
|
||||
// 检查当前是否已展开
|
||||
const isOpen = subMenu.classList.contains('show');
|
||||
|
||||
// 关闭所有其他子菜单并重置滚动位置
|
||||
document.querySelectorAll('.has-child').forEach(function (otherItem) {
|
||||
const otherSubMenu = otherItem.querySelector('.sub-menu');
|
||||
if (otherSubMenu && otherSubMenu !== subMenu) {
|
||||
otherSubMenu.classList.remove('show');
|
||||
otherSubMenu.scrollTop = 0; // 重置滚动位置
|
||||
otherItem.classList.remove('open');
|
||||
}
|
||||
});
|
||||
|
||||
// 切换当前菜单
|
||||
if (!isOpen) {
|
||||
openSubMenu(subMenu, item);
|
||||
} else {
|
||||
closeSubMenu(subMenu, item);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const link = item.getAttribute('data-link');
|
||||
@@ -675,6 +321,8 @@
|
||||
navBtn.style.display = 'block';
|
||||
navBtn1.style.display = 'none';
|
||||
closeAllModals();
|
||||
// 复位所有子菜单
|
||||
resetAllSubMenus();
|
||||
cartModal.classList.add('show');
|
||||
});
|
||||
|
||||
@@ -703,6 +351,8 @@
|
||||
navBtn.style.display = 'block';
|
||||
navBtn1.style.display = 'none';
|
||||
closeAllModals();
|
||||
// 复位所有子菜单
|
||||
resetAllSubMenus();
|
||||
langModal.classList.add('show');
|
||||
});
|
||||
|
||||
@@ -793,7 +443,7 @@
|
||||
itemDiv.className = 'search-history-item';
|
||||
itemDiv.innerHTML = `
|
||||
<span>${escapeHtml(keyword)}</span>
|
||||
<img src="./img/x.png" class="delete-icon" data-keyword="${escapeHtml(keyword)}">
|
||||
<img src="__IMAGES__/header/x.png" class="delete-icon" data-keyword="${escapeHtml(keyword)}">
|
||||
`;
|
||||
itemDiv.addEventListener('click', function (e)
|
||||
{
|
||||
@@ -864,6 +514,8 @@
|
||||
navBtn.style.display = 'block';
|
||||
navBtn1.style.display = 'none';
|
||||
closeAllModals();
|
||||
// 复位所有子菜单
|
||||
resetAllSubMenus();
|
||||
renderSearchHistory();
|
||||
searchModal.classList.add('show');
|
||||
setTimeout(() =>
|
||||
@@ -894,13 +546,14 @@
|
||||
if (keyword && keyword.trim()) {
|
||||
const searchKeyword = keyword.trim();
|
||||
console.log('搜索关键词:', searchKeyword);
|
||||
if (searchKeyword) {
|
||||
addSearchHistory(searchKeyword);
|
||||
alert('搜索: ' + searchKeyword);
|
||||
window.location.href = "{:url('product/search')}?keywords=" + encodeURIComponent(searchKeyword);
|
||||
searchModal.classList.remove('show');
|
||||
searchInput.value = '';
|
||||
searchClearBtn.style.display = 'none';
|
||||
} else {
|
||||
alert('请输入搜索关键词');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -912,13 +565,98 @@
|
||||
|
||||
searchInput.addEventListener('keypress', function (e)
|
||||
{
|
||||
console.log(e,'========e=============')
|
||||
if (e.key === 'Enter' || e.key === 'enter' || e.keyCode === 13) {
|
||||
e.preventDefault();
|
||||
doSearch(searchInput.value);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
// ====================== 添加:点击空白区域关闭所有子菜单 ======================
|
||||
document.addEventListener('click', function(e) {
|
||||
// 如果点击的不是菜单项内部,关闭所有子菜单
|
||||
if (!e.target.closest('.menu-item')) {
|
||||
resetAllSubMenus();
|
||||
}
|
||||
});
|
||||
|
||||
// ====================== 购物车弹窗悬浮图功能 ======================
|
||||
// 处理购物车弹窗中的图片悬浮效果
|
||||
function initCartModalHover() {
|
||||
const modalItems = document.querySelectorAll('#cartModal .modal-item');
|
||||
|
||||
modalItems.forEach(function(item) {
|
||||
// 查找当前item中是否有悬浮图(隐藏的那个)
|
||||
const defaultImg = item.querySelector('.modal-item-img');
|
||||
const hiddenItem = item.nextElementSibling;
|
||||
let hoverImg = null;
|
||||
|
||||
// 检查下一个元素是否是隐藏的悬浮图容器
|
||||
if (hiddenItem && hiddenItem.classList && hiddenItem.classList.contains('modal-item') && hiddenItem.style.display === 'none') {
|
||||
hoverImg = hiddenItem.querySelector('.modal-item-img');
|
||||
}
|
||||
|
||||
// 如果有悬浮图
|
||||
if (hoverImg && defaultImg) {
|
||||
const originalSrc = defaultImg.src;
|
||||
const hoverSrc = hoverImg.src;
|
||||
const link = item.getAttribute('data-link');
|
||||
|
||||
// 移除原有的href,因为需要悬浮图效果
|
||||
item.style.cursor = 'pointer';
|
||||
|
||||
// 鼠标移入:显示悬浮图
|
||||
item.addEventListener('mouseenter', function(e) {
|
||||
e.stopPropagation();
|
||||
defaultImg.src = hoverSrc;
|
||||
});
|
||||
|
||||
// 鼠标移出:恢复普通图
|
||||
item.addEventListener('mouseleave', function(e) {
|
||||
e.stopPropagation();
|
||||
defaultImg.src = originalSrc;
|
||||
});
|
||||
|
||||
// 点击事件:如果有链接就跳转
|
||||
item.addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
if (link && link !== '#') {
|
||||
window.location.href = link;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 没有悬浮图,保持原有链接
|
||||
const link = item.getAttribute('href') || item.getAttribute('data-link');
|
||||
if (link && link !== '#') {
|
||||
item.addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
window.location.href = link;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 在购物车弹窗打开时初始化悬浮图功能
|
||||
const cartModalObserver = new MutationObserver(function(mutations) {
|
||||
mutations.forEach(function(mutation) {
|
||||
if (mutation.attributeName === 'class') {
|
||||
if (cartModal.classList.contains('show')) {
|
||||
setTimeout(function() {
|
||||
initCartModalHover();
|
||||
}, 50);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (cartModal) {
|
||||
cartModalObserver.observe(cartModal, { attributes: true });
|
||||
// 如果弹窗默认是打开的,也初始化一次
|
||||
if (cartModal.classList.contains('show')) {
|
||||
initCartModalHover();
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
<header class="oircoEgapp-head">
|
||||
<div class="headtop">
|
||||
<a href="/"><img src="__IMAGES__/logo.png" class="headerlogimg" /></a>
|
||||
<div class="action-r">
|
||||
<div class="right img-responsive cursor_p">
|
||||
<span class="icon-category cursor_p top-menu-toggle"><i class="icon-menu-svg"></i></span>
|
||||
<span class="icon-keyword cursor_p top-search-toggle"><i class="icon-search-svg"></i></span>
|
||||
<span class="mask-up cursor_p top-country-toggle"><i class="icon-lag-svg"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 顶部菜单-->
|
||||
<div class="top-menu">
|
||||
<div class="it-ct">
|
||||
<div class="it-1"><a href="/">{:lang_i18n('首页')}</a></div>
|
||||
</div>
|
||||
<div class="it-ct">
|
||||
<div class="it-1">
|
||||
<div class="it-1-more">{:lang_i18n('产品列表')}<i class="icon-arrow"></i></div>
|
||||
{notempty name="header_categorys"}
|
||||
{volist name="header_categorys" id="ca"}
|
||||
<div class="it-1-2"><a href="{:url('product/category', ['id' => $ca.id])}">{$ca.name}</a></div>
|
||||
{/volist}
|
||||
{/notempty}
|
||||
</div>
|
||||
</div>
|
||||
{notempty name="header_navigation"}
|
||||
{volist name="header_navigation" id="nav"}
|
||||
<div class="it-ct">
|
||||
<div class="it-1">
|
||||
{empty name="nav.children"}
|
||||
<a href="{$nav.link}">{$nav.name}</a>
|
||||
{else/}
|
||||
<div class="it-1-more">{$nav.name}<i class="icon-arrow"></i></div>
|
||||
{volist name="nav.children" id="ch"}
|
||||
<div class="it-1-2"><a href="{$ch.link}">{$ch.name}</a></div>
|
||||
{/volist}
|
||||
{/empty}
|
||||
</div>
|
||||
</div>
|
||||
{/volist}
|
||||
{/notempty}
|
||||
</div>
|
||||
<!-- 顶部搜索-->
|
||||
<div class="top-search">
|
||||
<div class="marsk-container">
|
||||
<div class="popup-quick">
|
||||
<div class="ac-close float_r "><img src="__IMAGES__/close.png"></div>
|
||||
<div class="search-in">
|
||||
<form action="{:url('product/search')}" method="get">
|
||||
<input type="text" name="keywords" placeholder="{:lang_i18n('产品')} USB 2.0...">
|
||||
<button type="submit" id="search-btnput" class="search-button">{:lang_i18n('搜索')}</button>
|
||||
</form>
|
||||
<div class="title-text">
|
||||
<p><a href="#">{:lang_i18n('搜索历史')}</a></p>
|
||||
<div id="history"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 顶部国家选择-->
|
||||
<div class="top-country">
|
||||
<div class="mask"></div>
|
||||
<div class="action-sheet">
|
||||
<div class="menu-title">
|
||||
<div class="menu-name">{:lang_i18n('请择地区')}</div>
|
||||
<div class="close-icon">
|
||||
<img src="__IMAGES__/close.png">
|
||||
</div>
|
||||
</div>
|
||||
<ul>
|
||||
{volist name="header_languages" id="la"}
|
||||
<li>
|
||||
<a href="{$la.lang_url}" target="_blank">
|
||||
<img src="{$la.lang_icon}">{$la.country_en_name} - {$la.lang_en_name}
|
||||
</a>
|
||||
</li>
|
||||
{/volist}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
// 点击顶部菜单
|
||||
$(".top-menu-toggle").click(function() {
|
||||
$(".top-menu").slideToggle(800);
|
||||
})
|
||||
// 点击一级菜单显示二级菜单
|
||||
$(".it-1-more").on("click", function() {
|
||||
$('.it-1-2').hide();
|
||||
$('.icon-arrow').removeClass('rotate');
|
||||
$(this).siblings('.it-1-2').slideToggle(800);
|
||||
$(this).find('.icon-arrow').addClass('rotate');
|
||||
});
|
||||
//点击搜索
|
||||
$('.top-search-toggle').click(function() {
|
||||
$(".marsk-container").show();
|
||||
})
|
||||
$('.ac-close').click(function() {
|
||||
$(".marsk-container").hide();
|
||||
})
|
||||
// 顶部国家选择
|
||||
$('.top-country-toggle').click(function(){
|
||||
$(".mask,.action-sheet").show();
|
||||
})
|
||||
$('.top-country .close-icon').click(function(){
|
||||
$(".mask,.action-sheet").hide();
|
||||
})
|
||||
|
||||
// 移动端顶部宽度设置和主体内容宽度一致
|
||||
var pageWidth = $('.oricoEGapp').outerWidth();
|
||||
// 设置.header-PC元素的宽度
|
||||
$('.oircoEgapp-head').css('width', pageWidth + 'px');
|
||||
// 可选:监听窗口大小变化,实时更新宽度
|
||||
$(window).resize(function() {
|
||||
var newWidth = $('.oricoEGapp').outerWidth();
|
||||
$('.oircoEgapp-head').css('width', newWidth + 'px');
|
||||
});
|
||||
|
||||
// 回显搜索历史记录
|
||||
history();
|
||||
})
|
||||
|
||||
function history() {
|
||||
var keywords = new URL(window.location.href).searchParams.get('keywords')
|
||||
var history_keywords = localStorage.getItem('header_search_keywords');
|
||||
if (!history_keywords) {
|
||||
history_keywords = [];
|
||||
} else {
|
||||
history_keywords = JSON.parse(history_keywords);
|
||||
}
|
||||
|
||||
// 记录搜索关键词
|
||||
if (keywords) {
|
||||
if (history_keywords.includes(keywords)) {
|
||||
history_keywords.splice(history_keywords.indexOf(keywords), 1);
|
||||
}
|
||||
history_keywords.unshift(keywords);
|
||||
if (history_keywords.length > 3) {
|
||||
history_keywords.pop();
|
||||
}
|
||||
localStorage.setItem('header_search_keywords', JSON.stringify(history_keywords));
|
||||
}
|
||||
|
||||
// 回显搜索历史
|
||||
history_keywords.forEach(function(item) {
|
||||
$('#history').append(
|
||||
$('<a>')
|
||||
.css({
|
||||
'margin-right': '10px'
|
||||
})
|
||||
.attr('href', '{:url("product/search")}?keywords=' + item)
|
||||
.text(item)
|
||||
);
|
||||
});
|
||||
|
||||
return history_keywords;
|
||||
}
|
||||
</script>
|
||||
@@ -48,7 +48,7 @@
|
||||
{block name="main"}
|
||||
{notempty name="data.top_focus_images"}
|
||||
<!-- 顶部轮播 -->
|
||||
<div class="swiper-container auto-swiper-container" style="margin-top:60px;">
|
||||
<div class="swiper-container auto-swiper-container" style="margin-top:42px;">
|
||||
<div class="swiper-wrapper">
|
||||
{volist name="data.top_focus_images" id="tfi"}
|
||||
<div class="swiper-slide auto-swiper-slide">
|
||||
|
||||
@@ -31,15 +31,13 @@
|
||||
<link rel="stylesheet" href="__CSS__/topic_power_prodline/footer.css">
|
||||
|
||||
{/block}
|
||||
{block name="header"}
|
||||
<!-- 重置header头为空 -->
|
||||
{/block}
|
||||
|
||||
{block name="main"}
|
||||
<a class="header" href="/">
|
||||
<!-- <a class="header" href="/">
|
||||
<div class="header-img">
|
||||
<img src="__IMAGES__/logo.png" alt="">
|
||||
</div>
|
||||
</a>
|
||||
</a> -->
|
||||
<!-- 轮播核心容器 -->
|
||||
<div class="swiper-container auto-swiper-container" >
|
||||
{notempty name="data.focus_image"}
|
||||
|
||||
43
app/index/view/mobile/topic_ssd/index.html
Normal file
@@ -0,0 +1,43 @@
|
||||
{extend name="public/base" /}
|
||||
{block name="style"}
|
||||
<link rel="stylesheet" href="__CSS__/topic_laptop/header.css">
|
||||
<link rel="stylesheet" href="__CSS__/topic_laptop/footer.css">
|
||||
<link rel="stylesheet" href="__CSS__/topic_ssd/index.css">
|
||||
<!-- 将rem适配JS移到这里,确保优先执行 -->
|
||||
<script type="text/javascript">
|
||||
(function (doc, win)
|
||||
{
|
||||
var docEl = doc.documentElement;
|
||||
var resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
|
||||
|
||||
function setRootFontSize ()
|
||||
{
|
||||
var clientWidth = docEl.clientWidth;
|
||||
if (!clientWidth) return;
|
||||
var fontSize = clientWidth / 7.5;
|
||||
// 直接修改内联样式,优先级最高
|
||||
docEl.setAttribute('style', 'font-size: ' + fontSize + 'px !important;');
|
||||
}
|
||||
|
||||
setRootFontSize();
|
||||
win.addEventListener(resizeEvt, setRootFontSize);
|
||||
doc.addEventListener('DOMContentLoaded', setRootFontSize);
|
||||
})(document, window);
|
||||
</script>
|
||||
{/block}
|
||||
{block name="main"}
|
||||
<div class="m-sc-main" style="margin-top:42px;">
|
||||
{volist name="data.top_focus_images" id="item"}
|
||||
<a href="{$item.link}" class="m-sc-mt20">
|
||||
<img src="{$item.image}" alt="" class="m-sc-main-img" loading="lazy">
|
||||
</a>
|
||||
{/volist}
|
||||
<div class="m-sc-main-imgs m-sc-mt20 m-sc-mb34">
|
||||
{volist name="data.products" id="item"}
|
||||
<a href="{$item.link}" class="">
|
||||
<img src="{$item.image}" alt="" class="m-sc-main-img1" loading="lazy">
|
||||
</a>
|
||||
{/volist}
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="pageMain">
|
||||
<!-- banner -->
|
||||
{notempty name="focus_images"}
|
||||
<div class="swiper-container bannerswiper">
|
||||
<div class="swiper-container bannerswiper" style="background: #fff;">
|
||||
<div class="swiper-wrapper">
|
||||
{volist name="focus_images" id="focus"}
|
||||
<div class="swiper-slide">
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<div class="orico_Page_category">
|
||||
<!-- banner轮播 -->
|
||||
{notempty name="focus_image"}
|
||||
<div class="opdBanner">
|
||||
<div class="opdBanner" >
|
||||
{volist name="focus_image" id="fi"}
|
||||
<a {notempty name="fi.link" }href="{$fi.link}" {/notempty}>
|
||||
<img src="{$fi.image}" class="opdbannerImg" />
|
||||
|
||||
@@ -1,287 +0,0 @@
|
||||
<header class="header-PC">
|
||||
<div id="header">
|
||||
<!-- LOG -->
|
||||
<div class="nav1">
|
||||
<a href="/">
|
||||
<img src="__IMAGES__/logo.png" />
|
||||
</a>
|
||||
</div>
|
||||
<!--顶部导航栏 -->
|
||||
<div class="nav2">
|
||||
<nav id="booNavigation" class="booNavigation">
|
||||
<ul>
|
||||
{if condition="!empty($header_categorys)"}
|
||||
<li class="navItem">
|
||||
<a href="javascript:void(0);">{:lang_i18n('产品列表')}</a>
|
||||
<img src="__IMAGES__/black-down.png" class="downimg" />
|
||||
<ol class="navItemConten">
|
||||
<!-- 左边子菜单-->
|
||||
<ul class="navItem_cyleft">
|
||||
{volist name="header_categorys" id="vo"}
|
||||
<li class="{$key == 0 ? 'it_active' : ''}">
|
||||
<a href="{:url('product/category', ['id' => $vo.id])}">{$vo.name}</a>
|
||||
</li>
|
||||
{/volist}
|
||||
</ul>
|
||||
<!-- 右边子菜单-->
|
||||
{volist name="header_categorys" id="vo" key="idx"}
|
||||
<div class="navItem_cyright" {eq name="idx" value="1" }style="display: block;"{else/}style="display: none;"{/eq}>
|
||||
{if condition="!empty($vo.children)"}
|
||||
{volist name="vo.children" id="vc"}
|
||||
<dl class="nav_cyrightit">
|
||||
<dt>
|
||||
<a href="{:url('product/subcategory', ['id' => $vc.id])}">{$vc.name}</a>
|
||||
</dt>
|
||||
{if condition="!empty($vc.children)"}
|
||||
{volist name="vc.children" id="vcc"}
|
||||
<dd>
|
||||
<a href="{:url('product/subcategory', ['id' => $vcc.id])}">{$vcc.name}</a>
|
||||
</dd>
|
||||
{/volist}
|
||||
{/if}
|
||||
</dl>
|
||||
{/volist}
|
||||
{/if}
|
||||
</div>
|
||||
{/volist}
|
||||
</ol>
|
||||
</li>
|
||||
{/if}
|
||||
{volist name="header_navigation" id="vo"}
|
||||
<li class="navItem">
|
||||
<a href="{$vo.link}" target="{$vo.blank==1?'_blank':'_self'}">{$vo.name}</a>
|
||||
{if condition="!empty($vo.children)"}
|
||||
<img src="__IMAGES__/black-down.png" class="downimg" />
|
||||
<!--下拉菜单 -->
|
||||
<ol class="navItemConten1">
|
||||
{volist name="vo.children" id="voc"}
|
||||
<li>
|
||||
<a href="{$voc.link}" target="{$voc.blank==1?'_blank':'_self'}">{$voc.name}</a>
|
||||
</li>
|
||||
{/volist}
|
||||
</ol>
|
||||
{/if}
|
||||
</li>
|
||||
{/volist}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<!-- 顶部搜索/国家选择/商店-->
|
||||
<div class="nav3">
|
||||
<img src="__IMAGES__/icon-search.png" id="openModalBtn" class="searchimg" />
|
||||
<div class="choesCountry">
|
||||
<img src="__IMAGES__/icon-language.png" id="countrycheck" class="checkimg" />
|
||||
<!--国家选择 -->
|
||||
<div class="topCountry" id="top-country">
|
||||
<ul>
|
||||
<li class="closec">
|
||||
<span class="closecountrybt">×</span>
|
||||
</li>
|
||||
{volist name="header_languages" id="vo"}
|
||||
<a href="{$vo.lang_url}">
|
||||
<li>
|
||||
<div class="cico">
|
||||
<img src="{$vo.lang_icon}" class="countryimg" />
|
||||
</div>
|
||||
<p class="countryName">{$vo.country_en_name} - {$vo.lang_en_name}</p>
|
||||
</li>
|
||||
</a>
|
||||
{/volist}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{eq name=":cookie('think_lang')" value="en-us"}
|
||||
{notempty name="basic_config['navigation_store_url']['value']"}
|
||||
<a class="storetopbt" href="{$basic_config['navigation_store_url']['value']}" target="_blank">
|
||||
<img src="__IMAGES__/shopico.png" class="storeImgico" />{:lang_i18n('店铺')}
|
||||
</a>
|
||||
{/notempty}
|
||||
{/eq}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 搜索弹框-->
|
||||
<div class="searchmodalMian" id="scmodal">
|
||||
<div class="searchmodalct">
|
||||
<span class="close-btn">×</span>
|
||||
<input type="text" name="keywords" id="serrchinput" autocomplete="off" />
|
||||
<!-- 历史记录 -->
|
||||
<div class="searchhistory">
|
||||
<p class="h_title">{:lang_i18n('搜索记录')}</p>
|
||||
<ul></ul>
|
||||
</div>
|
||||
<div class="popProduct">
|
||||
<p class="h_title">{:lang_i18n('热销产品')}</p>
|
||||
<div class="popmain">
|
||||
{volist name="header_hot_products" id="vo"}
|
||||
<div class="popitem">
|
||||
<a href="{:url('product/detail', ['id' => $vo.id])}"><img src="{:thumb($vo.cover_image)}" class="popimg" /></a>
|
||||
<div class="productName">{$vo.name}</div>
|
||||
<div class="produc-dec">{$vo.short_name}</div>
|
||||
</div>
|
||||
{/volist}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
$('.header-PC #header .navItem>a').each(function(idx, item) {
|
||||
var _item = $(item);
|
||||
_item.removeClass('active');
|
||||
if (_item.attr('href') && compareUrls(location.href, _item.get(0).href)) {
|
||||
_item.addClass('active').siblings();
|
||||
}
|
||||
});
|
||||
|
||||
// 比较两个URL是否相等(支持只有path的情况,并处理有无.html后缀的情况)
|
||||
function compareUrls(url1, url2) {
|
||||
// 如果输入的是相对路径,添加当前域名
|
||||
if (!url1.startsWith('http')) {
|
||||
url1 = window.location.origin + (url1.startsWith('/') ? '' : '/') + url1;
|
||||
}
|
||||
if (!url2.startsWith('http')) {
|
||||
url2 = window.location.origin + (url2.startsWith('/') ? '' : '/') + url2;
|
||||
}
|
||||
|
||||
// 将两个URL转换为URL对象
|
||||
const urlObj1 = new URL(url1);
|
||||
const urlObj2 = new URL(url2);
|
||||
|
||||
// 获取路径名并移除末尾的斜杠
|
||||
let path1 = urlObj1.pathname.replace(/\/$/, '');
|
||||
let path2 = urlObj2.pathname.replace(/\/$/, '');
|
||||
|
||||
// 移除.html后缀
|
||||
path1 = path1.replace(/\.html$/, '');
|
||||
path2 = path2.replace(/\.html$/, '');
|
||||
|
||||
// 比较处理后的路径
|
||||
return path1 === path2;
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
// 搜索历史记录处理
|
||||
function history(keywords) {
|
||||
var history = localStorage.getItem('header_search_keywords');
|
||||
if (!history) {
|
||||
history = [];
|
||||
} else {
|
||||
history = JSON.parse(history);
|
||||
}
|
||||
// 记录搜索关键词
|
||||
if (keywords) {
|
||||
if (history.includes(keywords)) {
|
||||
history.splice(history.indexOf(keywords), 1);
|
||||
}
|
||||
history.unshift(keywords);
|
||||
if (history.length > 3) {
|
||||
history.pop();
|
||||
}
|
||||
localStorage.setItem('header_search_keywords', JSON.stringify(history));
|
||||
return history;
|
||||
}
|
||||
|
||||
// 回显搜索历史记录
|
||||
history.forEach(function (item) {
|
||||
$('.searchhistory ul').append('<li><a href="{:url(\'product/search\')}?keywords=' + item + '">' + item + '</a></li>');
|
||||
});
|
||||
|
||||
return history;
|
||||
}
|
||||
|
||||
// 封装一个函数用于处理鼠标悬停显示和隐藏内容
|
||||
function handleHover($element, $content) {
|
||||
// 同时支持鼠标悬停和点击事件
|
||||
$element
|
||||
.mouseenter(function () {
|
||||
$content.stop(true, true).slideDown(60);
|
||||
})
|
||||
.mouseleave(function () {
|
||||
$content.stop(true, true).slideUp(60);
|
||||
})
|
||||
.click(function (e) {
|
||||
// 阻止链接默认跳转(如果有链接的话)
|
||||
if ($content.is(':visible')) {
|
||||
$content.stop(true, true).slideUp(60);
|
||||
} else {
|
||||
$content.stop(true, true).slideDown(60);
|
||||
}
|
||||
// 防止点击事件冒泡到a标签
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
|
||||
// 处理产品列表的下拉菜单
|
||||
var $firstNav = $('.navItem').eq(0);
|
||||
if ($firstNav.find('.navItemConten').length) {
|
||||
handleHover($firstNav, $firstNav.find('.navItemConten'));
|
||||
}
|
||||
|
||||
// 鼠标移入左侧子菜单切换显示
|
||||
$('.navItem_cyleft li').mouseenter(function () {
|
||||
$(this).addClass('it_active').siblings().removeClass('it_active');
|
||||
$('.navItem_cyright').hide();
|
||||
$('.navItem_cyright').eq($(this).index()).show();
|
||||
});
|
||||
|
||||
// 动态处理所有带有navItemConten1的导航项
|
||||
$('.navItem').each(function () {
|
||||
var $this = $(this);
|
||||
var $dropdown = $this.find('.navItemConten1');
|
||||
// 只给有下拉菜单的导航项绑定事件
|
||||
if ($dropdown.length) {
|
||||
handleHover($this, $dropdown);
|
||||
}
|
||||
});
|
||||
|
||||
// 点击搜索
|
||||
$('#openModalBtn').click(function () {
|
||||
$('#scmodal').toggle();
|
||||
});
|
||||
$('.close-btn').click(function () {
|
||||
$('#scmodal').hide();
|
||||
});
|
||||
|
||||
// 点击空白处关闭下拉菜单
|
||||
$(document).click(function () {
|
||||
$('.navItemConten, .navItemConten1, #top-country').slideUp(60);
|
||||
});
|
||||
|
||||
// 防止下拉菜单内部点击触发空白处关闭事件
|
||||
$('.navItemConten, .navItemConten1, #top-country').click(function (e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
// 搜索历史记录回显
|
||||
history();
|
||||
|
||||
// 执行搜索
|
||||
$('#serrchinput').keydown(function (event) {
|
||||
if (event.originalEvent.keyCode == 13) {
|
||||
var keywords = $(this).val();
|
||||
if (keywords == '') {
|
||||
return false;
|
||||
}
|
||||
// 记录搜索关键词
|
||||
history(keywords);
|
||||
|
||||
// 跳转到搜索页面
|
||||
window.location.href = "{:url('product/search')}" + '?keywords=' + keywords;
|
||||
}
|
||||
});
|
||||
|
||||
// 点击选择国家
|
||||
$('#countrycheck').click(function (e) {
|
||||
$('#top-country').toggle();
|
||||
e.stopPropagation();
|
||||
});
|
||||
$('.closecountrybt').click(function () {
|
||||
$('#top-country').hide();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -1,6 +1,6 @@
|
||||
{extend name="public/base" /}
|
||||
{block name="style"}
|
||||
<!--<link rel="stylesheet" href="__CSS__/topic_laptop/header.css">-->
|
||||
<link rel="stylesheet" href="__CSS__/topic_laptop/header.css">
|
||||
<link rel="stylesheet" href="__CSS__/before-after.min.css">
|
||||
<link rel="stylesheet" href="__CSS__/topic_laptop/swiper.css">
|
||||
<link rel="stylesheet" href="__CSS__/topic_laptop/footer.css">
|
||||
@@ -52,7 +52,7 @@
|
||||
{/block}
|
||||
{block name="main"}
|
||||
{notempty name="data.top_focus_images"}
|
||||
<div class="swiper-container auto-swiper-container" style="margin-top:60px;">
|
||||
<div class="swiper-container auto-swiper-container">
|
||||
<div class="swiper-wrapper">
|
||||
{volist name="data.top_focus_images" id="tfi"}
|
||||
<div class="swiper-slide auto-swiper-slide">
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
{/block}
|
||||
{block name="main"}
|
||||
<!-- 轮播核心容器 -->
|
||||
<div class="swiper-container auto-swiper-container" >
|
||||
<div class="swiper-container auto-swiper-container">
|
||||
{notempty name="data.focus_image"}
|
||||
<div class="swiper-wrapper">
|
||||
{volist name="data.focus_image" id="fo"}
|
||||
|
||||
44
app/index/view/pc/topic_ssd/index.html
Normal file
@@ -0,0 +1,44 @@
|
||||
{extend name="public/base" /}
|
||||
{block name="style"}
|
||||
<link rel="stylesheet" href="__CSS__/topic_laptop/header.css">
|
||||
<link rel="stylesheet" href="__CSS__/topic_laptop/footer.css">
|
||||
<link rel="stylesheet" href="__CSS__/topic_ssd/index.css">
|
||||
<script type="text/javascript">
|
||||
(function (doc, win)
|
||||
{
|
||||
var docEl = doc.documentElement;
|
||||
var resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
|
||||
var designWidth = 2560;
|
||||
var designRemPx = 100;
|
||||
function setRootFontSize ()
|
||||
{
|
||||
var clientWidth = docEl.clientWidth;
|
||||
if (!clientWidth) return;
|
||||
var fontSize = (clientWidth / designWidth) * designRemPx;
|
||||
fontSize = Math.max(fontSize, 20);
|
||||
fontSize = Math.min(fontSize, designRemPx);
|
||||
docEl.style.fontSize = fontSize + 'px';
|
||||
}
|
||||
|
||||
setRootFontSize();
|
||||
win.addEventListener(resizeEvt, setRootFontSize);
|
||||
doc.addEventListener('DOMContentLoaded', setRootFontSize);
|
||||
})(document, window);
|
||||
</script>
|
||||
{/block}
|
||||
{block name="main"}
|
||||
<div class="sc-main">
|
||||
{volist name="data.top_focus_images" id="item"}
|
||||
<a href="{$item.link}" class="sc-mt20">
|
||||
<img src="{$item.image}" alt="" class="sc-main-img" loading="lazy">
|
||||
</a>
|
||||
{/volist}
|
||||
<div class="sc-main-imgs sc-mt20 sc-mb-78">
|
||||
{volist name="data.products" id="item"}
|
||||
<a href="{$item.link}" class="">
|
||||
<img src="{$item.image}" alt="" class="sc-main-img1" loading="lazy">
|
||||
</a>
|
||||
{/volist}
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
@@ -6,7 +6,7 @@
|
||||
align-items: center;
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
padding-top: 50px;
|
||||
padding-top: 46px;
|
||||
}
|
||||
|
||||
.iotb_bgw {
|
||||
|
||||
246
public/static/index/mobile/css/category.css
Normal file
@@ -0,0 +1,246 @@
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: sans-serif;
|
||||
font-size: inherit !important;
|
||||
/* font-size:100% !important; */
|
||||
}
|
||||
|
||||
body {
|
||||
background: #f5f5f5;
|
||||
font-size: inherit !important;
|
||||
/* font-size:100% !important; */
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
max-width: 100vw !important;
|
||||
|
||||
}
|
||||
|
||||
.top-box {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 20px 22px;
|
||||
background: #fff;
|
||||
margin-top: 46px;
|
||||
/* border-bottom: 1px solid #f0f0f0; */
|
||||
box-shadow: 0 2px 8px rgba(217, 217, 217, 0.2);
|
||||
}
|
||||
|
||||
.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: 0.28rem;
|
||||
height: 0.28rem;
|
||||
color: #333;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.back img {
|
||||
width: 0.28rem;
|
||||
height: 0.28rem;
|
||||
}
|
||||
.title {
|
||||
font-size: 0.32rem !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 主体布局 */
|
||||
.main {
|
||||
display: flex;
|
||||
height: calc(100% - 46px);
|
||||
margin-top:0.018rem;
|
||||
}
|
||||
|
||||
/* 左侧菜单 #FAFAFA;*/
|
||||
.sidebar {
|
||||
width: 114px;
|
||||
background:#fafafa;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.sidebar li {
|
||||
list-style: none;
|
||||
padding: 24px 16px;
|
||||
text-align: center;
|
||||
font-size: 0.28rem !important;
|
||||
color:#686A70; /* #686A70;*/
|
||||
cursor: pointer;
|
||||
background:#fff;
|
||||
/* 分别控制上下圆角的过渡 */
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
transition: border-radius 1s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.sidebar li.active {
|
||||
color: #004BFA;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
|
||||
.sidebar li.active-prev {
|
||||
border-bottom-right-radius: 0.17rem !important;
|
||||
}
|
||||
|
||||
.sidebar li.active-next {
|
||||
border-top-right-radius: 0.17rem !important;
|
||||
}
|
||||
/* 右侧内容 */
|
||||
.right-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding-left: 12px;
|
||||
background: #fafafa;
|
||||
/* padding-bottom: 100px; */
|
||||
|
||||
}
|
||||
|
||||
.right-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding-left: 12px;
|
||||
background: #fafafa;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 在底部添加占位元素 */
|
||||
.right-content::after {
|
||||
content: '';
|
||||
display: block;
|
||||
height: 80px; /* 根据需要调整 */
|
||||
width: 100%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 最后一个元素底部留白 */
|
||||
.sec-box:last-child {
|
||||
margin-bottom: 80px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.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 !important;
|
||||
color: #686A70;
|
||||
font-weight: 500
|
||||
}
|
||||
|
||||
.sec-arrow {
|
||||
width: 0.28rem;
|
||||
height: 0.28rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #666;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.sec-arrow img {
|
||||
width: 0.28rem;
|
||||
height: 0.28rem;
|
||||
}
|
||||
/* 横向滚动容器 */
|
||||
.scroll-box {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
overflow-x: auto;
|
||||
scroll-behavior: smooth;
|
||||
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.scroll-box::-webkit-scrollbar {
|
||||
display: none
|
||||
}
|
||||
|
||||
.right-card {
|
||||
flex-shrink: 0;
|
||||
background: #fff;
|
||||
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 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
padding-left: 19px;
|
||||
padding-right: 19px;
|
||||
|
||||
}
|
||||
.card-img {
|
||||
width: 1.52rem;
|
||||
background: #f1f1f1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #999;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.card-img img {
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
.card-info {
|
||||
|
||||
text-align: center;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.card-name {
|
||||
font-size: 0.2rem !important;
|
||||
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 !important;
|
||||
color: #686A70;
|
||||
margin-top: 4px
|
||||
}
|
||||
|
||||
/* 内容区块默认隐藏 */
|
||||
.tab-pane {
|
||||
display: none
|
||||
}
|
||||
|
||||
/* 激活时显示 */
|
||||
.tab-pane.active {
|
||||
display: block;
|
||||
|
||||
}
|
||||
@@ -156,7 +156,7 @@
|
||||
align-items: center;
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
padding-top: 50px;
|
||||
padding-top: 46px;
|
||||
}
|
||||
|
||||
.iotb_bgw {
|
||||
|
||||
@@ -156,7 +156,7 @@
|
||||
align-items: center;
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
padding-top: 50px;
|
||||
padding-top: 46px;
|
||||
}
|
||||
|
||||
.iotb_bgw {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.oricoEGapp .oricoEGapp-index .oidx-banner {
|
||||
margin-top: 3.5rem;
|
||||
margin-top: 46px;
|
||||
z-index: 9;
|
||||
}
|
||||
.oricoEGapp .oricoEGapp-index .oidx-banner .swiper-container {
|
||||
|
||||
457
public/static/index/mobile/css/new_header.css
Normal file
@@ -0,0 +1,457 @@
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.mobile-header-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 46px;
|
||||
padding: 0 17px;
|
||||
background: #fff;
|
||||
/* position: relative; */
|
||||
position: fixed;
|
||||
top:0;
|
||||
left:0;
|
||||
z-index: 100;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mobile-header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-img,
|
||||
.nav-search,
|
||||
.nav-lang,
|
||||
.nav-img1,
|
||||
.nav-card {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nav-log {
|
||||
width: 90px;
|
||||
height: 22px;
|
||||
margin-left: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nav-lang {
|
||||
margin: 0 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 下拉菜单 */
|
||||
.nav-dropdown-menu {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
border-top: 1px solid #eee;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 46px;
|
||||
left: 0;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.nav-dropdown-menu.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 所有菜单项统一用 div */
|
||||
.menu-item {
|
||||
margin: 0 22px;
|
||||
font-size: 15px !important;
|
||||
color: #333;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.menu-item-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
.menu-item-img {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 有子菜单才显示箭头 */
|
||||
.has-child .menu-item-img {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 无子菜单隐藏箭头 */
|
||||
.no-child .menu-item-img {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 箭头旋转 */
|
||||
.has-child.open .menu-item-img {
|
||||
transform: rotate(180deg);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.nav-img1 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* .sub-menu {
|
||||
display: none;
|
||||
} */
|
||||
.sub-menu {
|
||||
display: none;
|
||||
/* height: 100vh; */
|
||||
/* overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
-webkit-overflow-scrolling: touch; */
|
||||
}
|
||||
|
||||
/* .sub-menu-overflow {
|
||||
max-height: calc(100vh - 180px);
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
} */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.sub-menu.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sub-item {
|
||||
padding: 0 16px;
|
||||
font-size: 14px !important;
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
.sub-item:nth-child(1) {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.sub-item a {
|
||||
color: #686A70;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sub-item:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.sub-item-card-img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
aspect-ratio: 358 / 192;
|
||||
}
|
||||
|
||||
.sub-item-card-title {
|
||||
font-size: 16px !important;
|
||||
color: #1D1D1F;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.sub-item-card-name {
|
||||
font-size: 14px !important;
|
||||
color: #686A70;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.no-padding {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* ====================== 弹窗样式(不遮盖头部) ====================== */
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
top: 46px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: calc(100% - 46px);
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: none;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
z-index: 98;
|
||||
}
|
||||
|
||||
.modal-overlay.show {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
width: 90%;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 66px 24px 8px 24px;
|
||||
margin-top: 20px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
position: absolute;
|
||||
top: 24px;
|
||||
right: 24px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 写法2:使用 flex 布局实现一行2个 */
|
||||
.modal-items-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.modal-item {
|
||||
width: calc(50% - 16px);
|
||||
|
||||
font-size: 16px !important;
|
||||
color: #1D1D1F;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.modal-item-img {
|
||||
width: clamp(48px, 17vw, 128px);
|
||||
height: auto;
|
||||
aspect-ratio: 64 / 64;
|
||||
object-fit: contain;
|
||||
display: block;
|
||||
|
||||
}
|
||||
|
||||
.modal-item-title {
|
||||
margin-top: 10px;
|
||||
font-size: 16px !important;
|
||||
color: #1D1D1F;
|
||||
}
|
||||
|
||||
.modal-item:hover {
|
||||
/* background-color: #f5f5f5; */
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* 语言弹窗样式 - 列表布局 */
|
||||
.lang-modal-content {
|
||||
width: 90%;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 68px 24px;
|
||||
margin-top: 20px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.lang-items-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.lang-item {
|
||||
font-size: 16px !important;
|
||||
color: #1D1D1F;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.lang-item img {
|
||||
width: 29px;
|
||||
height: 20px;
|
||||
margin-right: 16px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.lang-item:last-child {
|
||||
border-bottom: none;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.lang-item:hover {
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* 搜索弹窗样式 */
|
||||
.search-modal-content {
|
||||
width: 90%;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 68px 24px;
|
||||
margin-top: 20px;
|
||||
position: relative;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.search-input-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 30px;
|
||||
padding-left: 24px;
|
||||
/* padding-right: 13px; */
|
||||
background: #f8f8f8;
|
||||
}
|
||||
|
||||
.search-input-box input {
|
||||
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
font-size: 14px !important;
|
||||
padding: 10px 0;
|
||||
flex:1;
|
||||
}
|
||||
|
||||
.search-input-box input::placeholder {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.search-input-box .search-clear-btn {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
cursor: pointer;
|
||||
opacity: 0.6;
|
||||
|
||||
}
|
||||
.search-clear-box {
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
/* .search-clear-btn {
|
||||
border-right: 1px solid #eee;
|
||||
} */
|
||||
.search-input-box .search-clear-btn:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.search-input-box .search-submit-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.search-submit-box {
|
||||
border-left: 1px solid #d9d9d9;
|
||||
padding-left:10px;
|
||||
padding-right: 13px;
|
||||
max-height: 18px;
|
||||
}
|
||||
.search-history {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.search-history-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.search-history-title {
|
||||
font-size: 14px !important;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.search-history-clear {
|
||||
font-size: 12px !important;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.search-history-clear:hover {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.search-history-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.search-history-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.search-history-item:hover {
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
margin-left: -8px;
|
||||
margin-right: -8px;
|
||||
}
|
||||
|
||||
.search-history-item span {
|
||||
font-size: 14px !important;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.search-history-item .delete-icon {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
cursor: pointer;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.search-history-item .delete-icon:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.empty-history {
|
||||
text-align: center;
|
||||
padding: 40px 0;
|
||||
font-size: 14px !important;
|
||||
color: #aaa;
|
||||
}
|
||||
.mobile-header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
/* 产品列表的子菜单不需要滚动 */
|
||||
.menu-item:first-child .sub-menu {
|
||||
max-height: none !important;
|
||||
overflow-y: visible !important;
|
||||
}
|
||||
|
||||
/* 其他导航的子菜单使用JS动态设置高度
|
||||
.has-child:not(:first-child) .sub-menu {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
} */
|
||||
@@ -2,7 +2,7 @@
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 3.4rem;
|
||||
margin-top:46px;
|
||||
}
|
||||
.oricoEGapp-newarrival .ona-topimg {
|
||||
max-width: 100%;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/* max-height: 900px; */
|
||||
min-height: 300px;
|
||||
position: relative;
|
||||
margin-top:60px;
|
||||
margin-top:46px;
|
||||
|
||||
}
|
||||
/* 轮播项 - 填充容器高度 */
|
||||
|
||||
65
public/static/index/mobile/css/topic_ssd/index.css
Normal file
@@ -0,0 +1,65 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
html {
|
||||
width: 100% !important;
|
||||
overflow-x: hidden;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
max-width: 100vw !important;
|
||||
}
|
||||
body {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
overflow-x: hidden;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
max-width: 100vw !important;
|
||||
}
|
||||
.m-sc-main {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.m-sc-main-img {
|
||||
width: 100%;
|
||||
/* max-width: 2560px; */
|
||||
}
|
||||
|
||||
.m-sc-mt20 {
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
.m-sc-mt20:first-child {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
.m-sc-mb34 {
|
||||
margin-bottom: 0.34rem;
|
||||
}
|
||||
.m-sc-main-imgs {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 0.1rem;
|
||||
list-style: none;
|
||||
/* 去除列表样式(如果有) */
|
||||
}
|
||||
|
||||
.m-sc-main-imgs a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.m-sc-main-img1 {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
/* 保持比例 */
|
||||
display: block;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 356 B |
|
Before Width: | Height: | Size: 520 B After Width: | Height: | Size: 991 B |
|
Before Width: | Height: | Size: 868 B After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 205 B After Width: | Height: | Size: 211 B |
|
Before Width: | Height: | Size: 514 B After Width: | Height: | Size: 1021 B |
|
Before Width: | Height: | Size: 326 B After Width: | Height: | Size: 521 B |
BIN
public/static/index/mobile/images/left.png
Normal file
|
After Width: | Height: | Size: 271 B |
BIN
public/static/index/mobile/images/y.png
Normal file
|
After Width: | Height: | Size: 301 B |
1029
public/static/index/pc/css/header.css
Normal file
@@ -17,7 +17,6 @@
|
||||
width: 100%;
|
||||
height: auto;
|
||||
position: relative;
|
||||
margin-top: 3.75rem;
|
||||
}
|
||||
|
||||
.orico_Page_index .pageMain .bannerswiper .swiper-slide img {
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
flex-direction: column;
|
||||
padding: 2.5rem 0 1.375rem 0;
|
||||
position: relative;
|
||||
margin-top: 3%;
|
||||
/* margin-top: 3%; */
|
||||
}
|
||||
.orico_Page_prdetail .oriprdetail .product_address {
|
||||
width: 70%;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
}
|
||||
.orico_Page_subcategory .pageMain {
|
||||
width: 85%;
|
||||
padding: 7.5rem 0 10px;
|
||||
padding: 54px 0 10px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -1,406 +1,13 @@
|
||||
@charset "UTF-8";
|
||||
/* 全局文字最小尺寸兜底 */
|
||||
.header-PC {
|
||||
width: 100%;
|
||||
|
||||
height: 60px;
|
||||
background: #fff;
|
||||
.header {
|
||||
max-width: 100% !important;
|
||||
width: 100% !important;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
|
||||
}
|
||||
.header-PC * {
|
||||
min-font-size: 16px !important; /* 强制最小16px */
|
||||
box-sizing: border-box;
|
||||
.header-nav-outer {
|
||||
max-width: 1920px;
|
||||
width: 100%;
|
||||
margin:auto 0 !important;
|
||||
}
|
||||
|
||||
.header-PC #header {
|
||||
margin: 0 auto;
|
||||
height: 60px; /* 0.6rem*100=60px */
|
||||
max-width: var(--max-width);
|
||||
/* position: fixed;
|
||||
top: 0; */
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
z-index: 999;
|
||||
background: white;
|
||||
color: black;
|
||||
width: 100%;
|
||||
font-size: 16px; /* 基础字号16px */
|
||||
}
|
||||
.header-PC #header .nav1 {
|
||||
position: relative;
|
||||
width: 20%;
|
||||
}
|
||||
.header-PC #header .nav1 img {
|
||||
width: 45%;
|
||||
margin-left: 40%;
|
||||
}
|
||||
.header-PC #header .nav2 {
|
||||
position: relative;
|
||||
width: 60%;
|
||||
}
|
||||
.header-PC #header .nav2 .navItem {
|
||||
font-size: 16px; /* 强制16px */
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
width: 12.5%;
|
||||
height: 60px; /* 0.6rem*100=60px */
|
||||
text-align: center;
|
||||
float: left;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
-webkit-transition: all 0.5s ease;
|
||||
}
|
||||
.header-PC #header .nav2 .navItem a {
|
||||
padding-right: 5px; /* 0.05rem*100=5px */
|
||||
padding-left: 20px; /* 0.2rem*100=20px */
|
||||
text-decoration: none;
|
||||
word-break: keep-all;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-wrap: break-word;
|
||||
text-wrap: nowrap;
|
||||
font-size: 16px; /* 确保16px */
|
||||
}
|
||||
.header-PC #header .nav2 .navItem .downimg {
|
||||
height: 12px; /* 0.12rem*100=12px */
|
||||
}
|
||||
.header-PC #header .nav2 .navItem .navItemConten {
|
||||
width: 100%;
|
||||
z-index: 999;
|
||||
background-color: #f2f2f2;
|
||||
max-height: 660px; /* 6.6rem*100=660px */
|
||||
box-shadow: 3px 5px 60px -20px #88909a; /* 0.03/0.05/0.6/-0.2rem 转px */
|
||||
position: fixed;
|
||||
border: 1px solid lightgray;
|
||||
top: 60px; /* 0.6rem*100=60px */
|
||||
transition: max-height 0.5s ease-out, opacity 0.5s ease-out;
|
||||
left: 0;
|
||||
display: none;
|
||||
font-size: 16px; /* 基础字号16px */
|
||||
}
|
||||
.header-PC #header .nav2 .navItem .navItemConten .navItem_cyleft {
|
||||
float: left;
|
||||
text-align: center;
|
||||
width: 20%;
|
||||
max-height: 660px; /* 6.6rem*100=660px */
|
||||
font-size: 16px; /* 强制16px */
|
||||
}
|
||||
.header-PC #header .nav2 .navItem .navItemConten .navItem_cyleft li {
|
||||
cursor: pointer;
|
||||
zoom: 1;
|
||||
clear: both;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
.header-PC #header .nav2 .navItem .navItemConten .navItem_cyleft li a {
|
||||
line-height: 44px; /* 0.44rem*100=44px */
|
||||
color: #656a6d;
|
||||
font-size: 16px; /* 确保16px */
|
||||
}
|
||||
.header-PC #header .nav2 .navItem .navItemConten .navItem_cyleft li a:hover {
|
||||
color: #004bfa;
|
||||
}
|
||||
.header-PC #header .nav2 .navItem .navItemConten .navItem_cyleft li.it_active {
|
||||
border-color: #dddddd;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.header-PC #header .nav2 .navItem .navItemConten .navItem_cyright {
|
||||
max-height: 660px; /* 6.6rem*100=660px */
|
||||
min-height: 460px; /* 4.6rem*100=460px */
|
||||
overflow-y: auto;
|
||||
border-left: 1px solid #dddddd;
|
||||
font-weight: normal;
|
||||
background-color: #fff;
|
||||
margin: 0 auto;
|
||||
box-shadow: -3px 0 0px #f3f3f3; /* -0.03rem*100=-3px */
|
||||
text-align: left;
|
||||
}
|
||||
.header-PC #header .nav2 .navItem .navItemConten .navItem_cyright .nav_cyrightit dt {
|
||||
font-size: 16px; /* 原0.14rem=14px → 提升至16px */
|
||||
line-height: 16px; /* 0.16rem*100=16px */
|
||||
margin-inline-start: 20px; /* 0.2rem*100=20px */
|
||||
font-weight: 600;
|
||||
border-bottom: 1px solid rgba(225, 225, 225, 0.5);
|
||||
padding-bottom: 13px; /* 0.13rem*100=13px */
|
||||
padding-top: 16px; /* 0.16rem*100=16px */
|
||||
}
|
||||
.header-PC #header .nav2 .navItem .navItemConten .navItem_cyright .nav_cyrightit dt img {
|
||||
height: 16px; /* 0.16rem*100=16px */
|
||||
max-width: 100%;
|
||||
}
|
||||
.header-PC #header .nav2 .navItem .navItemConten .navItem_cyright .nav_cyrightit dt a {
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
word-break: keep-all;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-wrap: break-word;
|
||||
text-wrap: nowrap;
|
||||
font-size: 16px; /* 确保16px */
|
||||
}
|
||||
.header-PC #header .nav2 .navItem .navItemConten .navItem_cyright .nav_cyrightit dd {
|
||||
font-size: 16px; /* 原0.14rem=14px → 提升至16px */
|
||||
line-height: 40px; /* 0.4rem*100=40px */
|
||||
padding-top: 0vw;
|
||||
font-weight: 100;
|
||||
display: inline-block;
|
||||
margin-right: 3%;
|
||||
margin-inline-start: 40px; /* 0.4rem*100=40px */
|
||||
}
|
||||
.header-PC #header .nav2 .navItem .navItemConten .navItem_cyright .nav_cyrightit dd a {
|
||||
font-size: 16px; /* 确保16px */
|
||||
}
|
||||
.header-PC #header .nav2 .navItem .navItemConten .navItem_cyright .nav_cyrightit dd a:hover {
|
||||
color: #004bf9;
|
||||
font-weight: 600;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
-webkit-transition: all 0.2s linear;
|
||||
}
|
||||
.header-PC #header .nav2 .navItem .navItemConten.active {
|
||||
max-height: 660px; /* 6.6rem*100=660px */
|
||||
opacity: 1;
|
||||
}
|
||||
.header-PC #header .nav2 .navItem .navItemConten1 {
|
||||
background-color: #fff;
|
||||
color: black;
|
||||
position: absolute;
|
||||
top: 60px; /* 0.6rem*100=60px */
|
||||
left: 20px; /* 0.2rem*100=20px */
|
||||
width: auto;
|
||||
height: auto;
|
||||
z-index: 9999;
|
||||
border-radius: 5px; /* 0.05rem*100=5px */
|
||||
box-shadow: 0 0 1px 0 #88909a; /* 0.01rem*100=1px */
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 8px 0; /* 0.08rem*100=8px */
|
||||
font-size: 16px; /* 基础字号16px */
|
||||
}
|
||||
.header-PC #header .nav2 .navItem .navItemConten1 li {
|
||||
color: #fff;
|
||||
float: left;
|
||||
text-align: center;
|
||||
line-height: 24px; /* 0.24rem*100=24px */
|
||||
padding: 8px 32px; /* 0.08/0.32rem*100=8/32px */
|
||||
display: list-item;
|
||||
}
|
||||
.header-PC #header .nav2 .navItem .navItemConten1 li a {
|
||||
cursor: pointer;
|
||||
padding-left: 0;
|
||||
white-space: nowrap;
|
||||
font-size: 16px; /* 确保16px */
|
||||
}
|
||||
.header-PC #header .nav2 .navItem > a.active,
|
||||
.header-PC #header .nav2 .navItem .navItemConten1 li a:hover {
|
||||
color: #004bfa;
|
||||
}
|
||||
.header-PC #header .nav3 {
|
||||
position: relative;
|
||||
width: 20%;
|
||||
background-color: transparent;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
font-size: 16px; /* 基础字号16px */
|
||||
}
|
||||
.header-PC #header .nav3 .searchimg {
|
||||
margin-left: 10%;
|
||||
}
|
||||
.header-PC #header .nav3 .storetopbt {
|
||||
background: #004cfa;
|
||||
color: #fff;
|
||||
padding: 0 15px; /* 0.15rem*100=15px */
|
||||
border-radius: 20px; /* 0.2rem*100=20px */
|
||||
height: 38px; /* 0.38rem*100=38px */
|
||||
line-height: 40px; /* 0.4rem*100=40px */
|
||||
margin-left: 15%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 16px; /* 强制16px */
|
||||
}
|
||||
.header-PC #header .nav3 .storetopbt .storeImgico {
|
||||
width: 20px; /* 0.2rem*100=20px */
|
||||
margin-right: 8px; /* 0.08rem*100=8px */
|
||||
}
|
||||
.header-PC #header .nav3 .choesCountry {
|
||||
position: relative;
|
||||
margin-left: 15%;
|
||||
display: flex;
|
||||
}
|
||||
.header-PC #header .nav3 .choesCountry .topCountry {
|
||||
display: none;
|
||||
width: 340px; /* 3.4rem*100=340px */
|
||||
background-color: white;
|
||||
/* position: fixed; */
|
||||
position: absolute;
|
||||
right: -150px;
|
||||
top: 50px; /* 0.8rem*100=80px */
|
||||
border-radius: 15px; /* 0.15rem*100=15px */
|
||||
box-shadow: 2px 2px 10px 1px #88909a; /* 0.02/0.02/0.1/0.01rem 转px */
|
||||
font-size: 16px; /* 基础字号16px */
|
||||
}
|
||||
.header-PC #header .nav3 .choesCountry .topCountry li {
|
||||
width: 100%;
|
||||
height: 50px; /* 0.5rem*100=50px */
|
||||
line-height: 50px; /* 0.5rem*100=50px */
|
||||
text-align: center;
|
||||
display: flex;
|
||||
}
|
||||
.header-PC #header .nav3 .choesCountry .topCountry li .countryName {
|
||||
width: 70%;
|
||||
text-align: left;
|
||||
margin-left: 10px; /* 0.1rem*100=10px */
|
||||
font-size: 16px; /* 强制16px */
|
||||
}
|
||||
.header-PC #header .nav3 .choesCountry .topCountry li .cico {
|
||||
width: 18%;
|
||||
margin-left: 0;
|
||||
}
|
||||
.header-PC #header .nav3 .choesCountry .topCountry li .cico .countryimg {
|
||||
margin-left: 0;
|
||||
margin-left: 20px; /* 0.2rem*100=20px */
|
||||
margin-top: 15px; /* 0.15rem*100=15px */
|
||||
vertical-align: top;
|
||||
}
|
||||
.header-PC #header .nav3 .choesCountry .topCountry li.closec {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: end;
|
||||
height: 30px; /* 0.3rem*100=30px */
|
||||
}
|
||||
.header-PC #header .nav3 .choesCountry .topCountry .closecountrybt {
|
||||
color: #aaa;
|
||||
margin-top: -5px; /* 0.05rem*100=5px */
|
||||
cursor: pointer;
|
||||
height: 20px; /* 0.2rem*100=20px */
|
||||
width: 20px; /* 0.2rem*100=20px */
|
||||
margin-right: 10px; /* 0.1rem*100=10px */
|
||||
font-size: 16px; /* 确保关闭按钮文字16px */
|
||||
}
|
||||
.header-PC .searchmodalMian {
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
z-index: 998;
|
||||
display: none;
|
||||
}
|
||||
.header-PC .searchmodalMian .searchmodalct {
|
||||
background-color: #fff;
|
||||
padding: 20px; /* 0.2rem*100=20px */
|
||||
border-radius: 20px; /* 0.2rem*100=20px */
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); /* 0.04/0.08rem 转px */
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
position: fixed;
|
||||
right: 2%;
|
||||
width: 33%;
|
||||
top: 80px; /* 0.8rem*100=80px */
|
||||
height: 80%;
|
||||
overflow-y: auto;
|
||||
z-index: 998;
|
||||
font-size: 16px; /* 基础字号16px */
|
||||
}
|
||||
.header-PC .searchmodalMian .searchmodalct .close-btn {
|
||||
color: #aaa;
|
||||
float: right;
|
||||
font-size: 24px; /* 0.24rem*100=24px */
|
||||
cursor: pointer;
|
||||
}
|
||||
.header-PC .searchmodalMian .searchmodalct #serrchinput {
|
||||
margin-left: 10%;
|
||||
margin-top: 5%;
|
||||
width: 80%;
|
||||
height: 44px; /* 0.44rem*100=44px */
|
||||
border: 1px solid grey;
|
||||
border-radius: 22px; /* 0.22rem*100=22px */
|
||||
background-position: 95% 50%;
|
||||
padding-left: 5%;
|
||||
font-size: 16px; /* 输入框文字16px */
|
||||
}
|
||||
.header-PC .searchmodalMian .searchmodalct .searchhistory,
|
||||
.header-PC .searchmodalMian .searchmodalct .popProduct {
|
||||
margin-top: 5%;
|
||||
margin-left: 10%;
|
||||
width: 80%;
|
||||
display: flex;
|
||||
position: relative;
|
||||
}
|
||||
.header-PC .searchmodalMian .searchmodalct .searchhistory .h_title,
|
||||
.header-PC .searchmodalMian .searchmodalct .popProduct .h_title {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 1%;
|
||||
font-size: 16px; /* 保持16px */
|
||||
color: #989898;
|
||||
}
|
||||
.header-PC .searchmodalMian .searchmodalct .searchhistory ul,
|
||||
.header-PC .searchmodalMian .searchmodalct .popProduct ul {
|
||||
margin-top: 10%;
|
||||
margin-left: 1%;
|
||||
}
|
||||
.header-PC .searchmodalMian .searchmodalct .popProduct .popmain{
|
||||
width: 100%;
|
||||
}
|
||||
.header-PC .searchmodalMian .searchmodalct .searchhistory .popmain,
|
||||
.header-PC .searchmodalMian .searchmodalct .popProduct .popmain {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.header-PC .searchmodalMian .searchmodalct .searchhistory .popmain .popitem,
|
||||
.header-PC .searchmodalMian .searchmodalct .popProduct .popmain .popitem {
|
||||
text-align: center;
|
||||
margin-top: 7%;
|
||||
margin-left: 1%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
width: 30%;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
.header-PC .searchmodalMian .searchmodalct .searchhistory .popmain .popitem .popimg,
|
||||
.header-PC .searchmodalMian .searchmodalct .popProduct .popmain .popitem .popimg {
|
||||
width: 115px; /* 1.15rem*100=115px */
|
||||
height: 115px; /* 1.15rem*100=115px */
|
||||
margin: 0 auto;
|
||||
}
|
||||
.header-PC .searchmodalMian .searchmodalct .searchhistory .popmain .popitem .productName,
|
||||
.header-PC .searchmodalMian .searchmodalct .popProduct .popmain .popitem .productName {
|
||||
font-weight: 600;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 16px; /* 原0.128rem=12.8px → 提升至16px */
|
||||
margin-top: 10%;
|
||||
}
|
||||
.header-PC .searchmodalMian .searchmodalct .popProduct .popmain .popitem .productName
|
||||
{
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
font-size: 16px; /* 原14px → 提升至16px */
|
||||
}
|
||||
.header-PC .searchmodalMian .searchmodalct .popProduct .popmain .popitem .produc-dec{
|
||||
font-size: 16px; /* 原10px → 提升至16px */
|
||||
color: #000000;
|
||||
margin-top: 1%;
|
||||
}
|
||||
@@ -9,13 +9,6 @@ body {
|
||||
overflow-x: hidden;
|
||||
scroll-behavior: smooth !important;
|
||||
-webkit-overflow-scrolling: touch !important;
|
||||
/* padding: 0 !important;
|
||||
margin:0 !important; */
|
||||
/* max-width:100% !important;
|
||||
width: 100vw !important;
|
||||
margin:0 auto; */
|
||||
/* max-width:100vw !important */
|
||||
/* margin:0 auto !important; */
|
||||
}
|
||||
/* 当视口宽度大于1920px时生效 */
|
||||
@media screen and (min-width: 1920px) {
|
||||
@@ -39,7 +32,3 @@ body {
|
||||
transform 1.2s ease-in-out,
|
||||
visibility 1.2s ease-in-out;
|
||||
}
|
||||
/* 18-19号防卡顿:延迟19号动画 */
|
||||
/* [data-order="19"] {
|
||||
transition: all 0.3s ease-out 0.2s !important;
|
||||
} */
|
||||
|
||||
@@ -63,12 +63,12 @@ a {
|
||||
width: 100%;
|
||||
height: clamp(2.5rem, 5vw, 15rem);
|
||||
}
|
||||
.header {
|
||||
/* .header {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
height: 60px;
|
||||
}
|
||||
.header-img {
|
||||
} */
|
||||
/* .header-img {
|
||||
margin: 0 auto;
|
||||
width: 90%;
|
||||
display: flex;
|
||||
@@ -76,4 +76,4 @@ a {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
|
||||
}
|
||||
} */
|
||||
|
||||
68
public/static/index/pc/css/topic_ssd/index.css
Normal file
@@ -0,0 +1,68 @@
|
||||
|
||||
html {
|
||||
width: 100%;
|
||||
}
|
||||
body {
|
||||
/* width: 100vw;
|
||||
height: 100vh; */
|
||||
background: #fff;
|
||||
overflow-x: hidden;
|
||||
scroll-behavior: smooth !important;
|
||||
-webkit-overflow-scrolling: touch !important;
|
||||
}
|
||||
/* 当视口宽度大于1920px时生效 */
|
||||
@media screen and (min-width: 1920px) {
|
||||
/* 这里写你的样式 */
|
||||
body {
|
||||
max-width:100% !important;
|
||||
width: 100vw !important;
|
||||
}
|
||||
|
||||
}
|
||||
.sc-main {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 2560px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sc-main-img {
|
||||
width: 100%;
|
||||
max-width: 2560px;
|
||||
}
|
||||
.sc-mt20:first-child {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
.sc-mt20 {
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
.sc-mb-78 {
|
||||
margin-bottom: 0.78rem;
|
||||
}
|
||||
.sc-main-imgs {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 0.2rem;
|
||||
list-style: none;
|
||||
/* 去除列表样式(如果有) */
|
||||
}
|
||||
|
||||
.sc-main-imgs a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sc-main-img1 {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
/* 保持比例 */
|
||||
display: block;
|
||||
}
|
||||
BIN
public/static/index/pc/images/g1.png
Normal file
|
After Width: | Height: | Size: 379 B |
BIN
public/static/index/pc/images/gm.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
public/static/index/pc/images/l1.png
Normal file
|
After Width: | Height: | Size: 868 B |
BIN
public/static/index/pc/images/s1.png
Normal file
|
After Width: | Height: | Size: 578 B |
@@ -147,46 +147,6 @@ class ImageMigrator:
|
||||
# 确保paramiko已导入
|
||||
ensure_paramiko()
|
||||
|
||||
# 连接目标服务器(必须为SSH)
|
||||
if self.target_config.is_local():
|
||||
print("错误: 目标服务器必须为SSH服务器,不能是本地目录")
|
||||
return False
|
||||
|
||||
self.target_client = paramiko.SSHClient()
|
||||
self.target_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
if self.verbose:
|
||||
print(
|
||||
f"连接到目标服务器: {self.target_config.host}:{self.target_config.port}"
|
||||
)
|
||||
|
||||
if self.target_config.key_file:
|
||||
key = paramiko.RSAKey.from_private_key_file(self.target_config.key_file)
|
||||
|
||||
self.target_client.connect(
|
||||
hostname=self.target_config.host,
|
||||
port=self.target_config.port,
|
||||
username=self.target_config.username,
|
||||
pkey=key,
|
||||
)
|
||||
else:
|
||||
self.target_client.connect(
|
||||
hostname=self.target_config.host,
|
||||
port=self.target_config.port,
|
||||
username=self.target_config.username,
|
||||
password=self.target_config.password,
|
||||
)
|
||||
|
||||
self.target_sftp = self.target_client.open_sftp()
|
||||
|
||||
# 检查SFTP服务器的工作目录
|
||||
if self.verbose:
|
||||
try:
|
||||
cwd = self.target_sftp.getcwd()
|
||||
print(f"DEBUG: 目标SFTP服务器当前工作目录: {cwd}")
|
||||
except Exception as e:
|
||||
print(f"DEBUG: 无法获取目标SFTP服务器工作目录: {e}")
|
||||
|
||||
# 连接源服务器(如果是SSH类型)
|
||||
if not self.source_config.is_local():
|
||||
self.source_client = paramiko.SSHClient()
|
||||
@@ -218,11 +178,61 @@ class ImageMigrator:
|
||||
|
||||
self.source_sftp = self.source_client.open_sftp()
|
||||
|
||||
# 检查SFTP服务器的工作目录
|
||||
if self.verbose:
|
||||
try:
|
||||
cwd = self.source_sftp.getcwd()
|
||||
print(f"DEBUG: 源SFTP服务器当前工作目录: {cwd}")
|
||||
except Exception as e:
|
||||
print(f"DEBUG: 无法获取源SFTP服务器工作目录: {e}")
|
||||
|
||||
# 连接目标服务器(如果为SSH)
|
||||
if not self.target_config.is_local():
|
||||
self.target_client = paramiko.SSHClient()
|
||||
self.target_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
if self.verbose:
|
||||
print(
|
||||
f"连接到目标服务器: {self.target_config.host}:{self.target_config.port}"
|
||||
)
|
||||
|
||||
if self.target_config.key_file:
|
||||
key = paramiko.RSAKey.from_private_key_file(
|
||||
self.target_config.key_file
|
||||
)
|
||||
|
||||
self.target_client.connect(
|
||||
hostname=self.target_config.host,
|
||||
port=self.target_config.port,
|
||||
username=self.target_config.username,
|
||||
pkey=key,
|
||||
)
|
||||
else:
|
||||
self.target_client.connect(
|
||||
hostname=self.target_config.host,
|
||||
port=self.target_config.port,
|
||||
username=self.target_config.username,
|
||||
password=self.target_config.password,
|
||||
)
|
||||
|
||||
self.target_sftp = self.target_client.open_sftp()
|
||||
|
||||
# 检查SFTP服务器的工作目录
|
||||
if self.verbose:
|
||||
try:
|
||||
cwd = self.target_sftp.getcwd()
|
||||
print(f"DEBUG: 目标SFTP服务器当前工作目录: {cwd}")
|
||||
except Exception as e:
|
||||
print(f"DEBUG: 无法获取目标SFTP服务器工作目录: {e}")
|
||||
|
||||
if self.verbose:
|
||||
source_type = (
|
||||
"本地目录" if self.source_config.is_local() else "SSH服务器"
|
||||
)
|
||||
print(f"连接成功! 源: {source_type}, 目标: SSH服务器")
|
||||
target_type = (
|
||||
"本地目录" if self.target_config.is_local() else "SSH服务器"
|
||||
)
|
||||
print(f"连接成功! 源: {source_type}, 目标: {target_type}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
@@ -718,7 +728,7 @@ def read_image_paths(image_list_file: str) -> List[str]:
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="从本地目录或SSH服务器迁移图片到远程SSH服务器,保持相对路径结构",
|
||||
description="本地目录之间迁移图片,本地目录或SSH服务器迁移图片到远程SSH服务器,保持相对路径结构",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
示例:
|
||||
@@ -756,8 +766,7 @@ def main():
|
||||
parser.add_argument(
|
||||
"--source-type",
|
||||
choices=["local", "ssh"],
|
||||
default="local",
|
||||
help="源服务器类型: local(本地目录) 或 ssh(SSH服务器),默认: local",
|
||||
help="源服务器类型: local(本地目录) 或 ssh(SSH服务器)",
|
||||
)
|
||||
parser.add_argument("--source-host", help="源服务器地址(仅SSH类型需要)")
|
||||
parser.add_argument(
|
||||
@@ -772,6 +781,11 @@ def main():
|
||||
parser.add_argument("--source-dir", help="源服务器图片基础目录")
|
||||
|
||||
# 目标服务器选项
|
||||
parser.add_argument(
|
||||
"--target-type",
|
||||
choices=["local", "ssh"],
|
||||
help="目标服务器类型: local(本地目录) 或 ssh(SSH服务器)",
|
||||
)
|
||||
parser.add_argument("--target-host", help="目标服务器地址")
|
||||
parser.add_argument(
|
||||
"--target-port", type=int, default=22, help="目标服务器端口(默认: 22)"
|
||||
@@ -859,11 +873,15 @@ def main():
|
||||
|
||||
# 构建目标服务器配置
|
||||
target_config_data = config.get("target", {})
|
||||
target_config_data["type"] = "ssh" # 目标必须是SSH
|
||||
|
||||
ssh_config = target_config_data.get("ssh", {})
|
||||
|
||||
# 命令行参数覆盖配置文件
|
||||
if args.target_type:
|
||||
target_config_data["type"] = args.target_type
|
||||
|
||||
# 命令行参数覆盖配置文件
|
||||
if args.target_type == "ssh" or target_config_data.get("type") == "ssh":
|
||||
ssh_config = target_config_data.get("ssh", {})
|
||||
|
||||
if args.target_host:
|
||||
ssh_config["host"] = args.target_host
|
||||
if args.target_port:
|
||||
@@ -877,13 +895,6 @@ def main():
|
||||
|
||||
target_config_data["ssh"] = ssh_config
|
||||
|
||||
# 设置基础目录
|
||||
if args.target_dir:
|
||||
target_config_data["base_dir"] = args.target_dir
|
||||
elif "base_dir" not in target_config_data:
|
||||
print("错误: 必须指定目标服务器图片基础目录 (--target-dir)")
|
||||
sys.exit(1)
|
||||
|
||||
# 检查必要的目标SSH参数
|
||||
if not ssh_config.get("host"):
|
||||
print("错误: 必须指定目标服务器地址 (--target-host)")
|
||||
@@ -891,6 +902,16 @@ def main():
|
||||
if not ssh_config.get("username"):
|
||||
print("错误: 必须指定目标服务器用户名 (--target-user)")
|
||||
sys.exit(1)
|
||||
else:
|
||||
# 本地类型,不需要SSH配置
|
||||
target_config_data.pop("ssh", None)
|
||||
|
||||
# 设置基础目录
|
||||
if args.target_dir:
|
||||
target_config_data["base_dir"] = args.target_dir
|
||||
elif "base_dir" not in target_config_data:
|
||||
print("错误: 必须指定目标服务器图片基础目录 (--target-dir)")
|
||||
sys.exit(1)
|
||||
|
||||
# 创建服务器配置对象
|
||||
try:
|
||||
|
||||