Compare commits
102 Commits
3664861ef0
...
v1.3.3
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 | |||
| 853da3c948 | |||
| a68499255d | |||
| 23f9a8fc9a | |||
| 29abb5e230 | |||
| 8a9d66f5d3 | |||
| 90b4bccbcf | |||
| 4c592d9347 | |||
| ebe1c3015e | |||
| 9584b81729 | |||
| 8577877f83 | |||
| be26f2d75b | |||
| 863fdda9a5 | |||
| a1c7ae62ba | |||
| 49240893b5 | |||
| 61728434d3 | |||
| 5736d09dbe | |||
| f4646f1e3a | |||
| 5b3e505e9b | |||
| 624d7fde2f | |||
| a85f2c1b3a | |||
| 7ec97c39a7 | |||
| 67016c4e9a | |||
| 69c3634731 | |||
| 12bc6aeee7 | |||
| 2ca25e083e | |||
| df37a7c00d | |||
| 11e2c4f457 | |||
| edfc27b06a | |||
| fdc9064739 | |||
| 55a75b56b1 | |||
| 005457e13e | |||
| 24e5554bc4 | |||
| c767c20641 | |||
| 2c85df4a98 | |||
| 88a91f3136 | |||
| 5fd603cbc6 | |||
| b92753c822 | |||
| ddd578eb08 | |||
| 1cdd0536b9 | |||
| 9cc6dc3cd9 | |||
| 4d25f6fec8 | |||
| 2764ce3b86 | |||
| 7cb270b313 | |||
| 86ffcb99ac | |||
| c476193002 | |||
| 5643faad94 | |||
| 989f6c25a0 | |||
| 2e5103b19a |
3
.gitignore
vendored
@@ -23,3 +23,6 @@ public/.well-known
|
|||||||
/.settings
|
/.settings
|
||||||
/.buildpath
|
/.buildpath
|
||||||
/.project
|
/.project
|
||||||
|
|
||||||
|
CLAUDE.md
|
||||||
|
/skills
|
||||||
|
|||||||
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.
|
||||||
@@ -201,15 +201,16 @@ class ReceiveProductSync
|
|||||||
throw new \Exception('产品创建失败');
|
throw new \Exception('产品创建失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strtotime($product['updated_at']) < strtotime($data['created_at'])) {
|
// 注释更新同步,防止tco同步修改官网手动调整数据
|
||||||
$product->spu = $data['spu'];
|
// else if (strtotime($product['updated_at']) < strtotime($data['created_at'])) {
|
||||||
$product->name = $data['name'];
|
// $product->spu = $data['spu'];
|
||||||
$product->category_id = $product_category['id'];
|
// $product->name = $data['name'];
|
||||||
$product->status = Operate_Of_ReceiveSync::Disable == $data['operate'] ? -1 : 1;
|
// $product->category_id = $product_category['id'];
|
||||||
if (!$product->save()) {
|
// $product->status = Operate_Of_ReceiveSync::Disable == $data['operate'] ? -1 : 1;
|
||||||
throw new \Exception('产品更新失败');
|
// if (!$product->save()) {
|
||||||
}
|
// throw new \Exception('产品更新失败');
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $th) {
|
||||||
return error(sprintf('%s %s:%d', $th->getMessage(), $th->getFile(), $th->getLine()));
|
return error(sprintf('%s %s:%d', $th->getMessage(), $th->getFile(), $th->getLine()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,7 +91,6 @@ class Banner
|
|||||||
|
|
||||||
$banner = SysBannerModel::withoutField([
|
$banner = SysBannerModel::withoutField([
|
||||||
'at_page',
|
'at_page',
|
||||||
'unique_label',
|
|
||||||
'language_id',
|
'language_id',
|
||||||
'created_at',
|
'created_at',
|
||||||
'updated_at',
|
'updated_at',
|
||||||
@@ -142,6 +141,7 @@ class Banner
|
|||||||
'name',
|
'name',
|
||||||
'desc',
|
'desc',
|
||||||
'recommend',
|
'recommend',
|
||||||
|
'unique_label',
|
||||||
'at_platform' => 'pc',
|
'at_platform' => 'pc',
|
||||||
'status' => 1
|
'status' => 1
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ class NavigationItem
|
|||||||
'id',
|
'id',
|
||||||
'pid',
|
'pid',
|
||||||
'name',
|
'name',
|
||||||
|
'desc',
|
||||||
|
'image',
|
||||||
'nav_id',
|
'nav_id',
|
||||||
'sort',
|
'sort',
|
||||||
'status',
|
'status',
|
||||||
@@ -93,7 +95,9 @@ class NavigationItem
|
|||||||
'pid',
|
'pid',
|
||||||
'nav_id',
|
'nav_id',
|
||||||
'name',
|
'name',
|
||||||
|
'desc',
|
||||||
'icon',
|
'icon',
|
||||||
|
'image',
|
||||||
'link_to' => 'custom',
|
'link_to' => 'custom',
|
||||||
'link',
|
'link',
|
||||||
'sort',
|
'sort',
|
||||||
@@ -121,7 +125,9 @@ class NavigationItem
|
|||||||
'pid',
|
'pid',
|
||||||
'nav_id',
|
'nav_id',
|
||||||
'name',
|
'name',
|
||||||
|
'desc',
|
||||||
'icon',
|
'icon',
|
||||||
|
'image',
|
||||||
'link_to',
|
'link_to',
|
||||||
'link',
|
'link',
|
||||||
'sort',
|
'sort',
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ class Product
|
|||||||
])
|
])
|
||||||
->bypk(request()->param('id'))
|
->bypk(request()->param('id'))
|
||||||
->find()
|
->find()
|
||||||
->bindAttr('category', ['category_name'])
|
?->bindAttr('category', ['category_name'])
|
||||||
->hidden(['category']);
|
->hidden(['category']);
|
||||||
if (empty($product)) {
|
if (empty($product)) {
|
||||||
return error('产品不存在');
|
return error('产品不存在');
|
||||||
|
|||||||
203
app/admin/controller/v1/ProductCategoryRecommend.php
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\v1;
|
||||||
|
|
||||||
|
use app\admin\model\v1\ProductCategoryRecommendModel;
|
||||||
|
use app\admin\validate\v1\ProductCategoryRecommendValidate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品分类推荐管理控制器
|
||||||
|
*/
|
||||||
|
class ProductCategoryRecommend
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 分页列表
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$param = request()->get([
|
||||||
|
'keywords',
|
||||||
|
'category_name',
|
||||||
|
'page/d' => 1,
|
||||||
|
'size/d' => 10
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
$data = ProductCategoryRecommendModel::withJoin(['category' => function($query) use ($param) {
|
||||||
|
if (!empty($param['category_name'])) {
|
||||||
|
$query->where('category.name', 'like', '%' . $param['category_name'] . '%');
|
||||||
|
}
|
||||||
|
}])
|
||||||
|
->withSearch(['keywords'], ['keywords' => $param['keywords']??null])
|
||||||
|
->language(request()->lang_id)
|
||||||
|
->order(['sort' => 'asc', 'id' => 'desc'])
|
||||||
|
->paginate([
|
||||||
|
'list_rows' => $param['size'],
|
||||||
|
'page' => $param['page'],
|
||||||
|
])
|
||||||
|
->bindAttr('category', ['category_name' => 'name'])
|
||||||
|
->hidden(['category', 'language_id', 'updated_at', 'deleted_at'])
|
||||||
|
?->each(function($item) {
|
||||||
|
// 列表页面图片输出缩略图
|
||||||
|
if (!empty($item['image'])) {
|
||||||
|
$item['image'] = thumb($item['image']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return success('获取成功', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出Excel
|
||||||
|
*/
|
||||||
|
public function export()
|
||||||
|
{
|
||||||
|
$schema = [
|
||||||
|
'id' => 'ID',
|
||||||
|
'image' => '图片',
|
||||||
|
'category_name' => '分类名称',
|
||||||
|
'desc' => '产品介绍',
|
||||||
|
'link' => '链接地址',
|
||||||
|
'sort' => '排序',
|
||||||
|
'disabled' => '状态',
|
||||||
|
'created_at' => '添加时间'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 获取导出数据
|
||||||
|
$data = $this->getProductCategoryRecommendData();
|
||||||
|
|
||||||
|
// 导出
|
||||||
|
return xlsx_writer($data, $schema, '产品推荐列表' . date('YmdHis'));
|
||||||
|
}
|
||||||
|
// 获取要导出的推荐记录数据
|
||||||
|
private function getProductCategoryRecommendData()
|
||||||
|
{
|
||||||
|
$server = request()->server();
|
||||||
|
$image_host = $server['REQUEST_SCHEME'] . "://" . $server['SERVER_NAME'] . '/';
|
||||||
|
$param = request()->get(['keywords']);
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
return ProductCategoryRecommendModel::withJoin(['category' => function($query) use ($param) {
|
||||||
|
if (!empty($param['category_name'])) {
|
||||||
|
$query->where('category.name', 'like', '%' . $param['category_name'] . '%');
|
||||||
|
}
|
||||||
|
}])
|
||||||
|
->withSearch(['keywords'], ['keywords' => $param['keywords']??null])
|
||||||
|
->language(request()->lang_id)
|
||||||
|
->order(['sort' => 'asc', 'id' => 'desc'])
|
||||||
|
->select()
|
||||||
|
->bindAttr('category', ['category_name' => 'name'])
|
||||||
|
->hidden(['category', 'language_id', 'updated_at', 'deleted_at'])
|
||||||
|
?->each(function($item) use($image_host) {
|
||||||
|
// 拼接完整图片URL
|
||||||
|
if (!empty($item['image'])) {
|
||||||
|
$item['image'] = url_join($image_host, $item['image']);
|
||||||
|
}
|
||||||
|
// 状态
|
||||||
|
$item['disabled'] = $item['disabled'] == 1 ? '禁用' : '启用';
|
||||||
|
})
|
||||||
|
->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详细数据
|
||||||
|
*/
|
||||||
|
public function read()
|
||||||
|
{
|
||||||
|
$id = request()->param('id/d');
|
||||||
|
$record = ProductCategoryRecommendModel::bypk($id)
|
||||||
|
->withoutField(['language_id', 'created_at', 'updated_at', 'deleted_at'])
|
||||||
|
->find();
|
||||||
|
if (empty($record)) {
|
||||||
|
return error('推荐数据不存在');
|
||||||
|
}
|
||||||
|
|
||||||
|
return success('success', $record);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增数据
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$post = request()->post([
|
||||||
|
'category_id',
|
||||||
|
'title',
|
||||||
|
'image',
|
||||||
|
'desc',
|
||||||
|
'link',
|
||||||
|
'sort',
|
||||||
|
'disabled'
|
||||||
|
]);
|
||||||
|
$data = array_merge($post, ['language_id' => request()->lang_id]);
|
||||||
|
|
||||||
|
// 参数校验
|
||||||
|
$validate = new ProductCategoryRecommendValidate();
|
||||||
|
if (!$validate->scene('create')->check($data)) {
|
||||||
|
return error($validate->getError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存推荐数据
|
||||||
|
$recommend = ProductCategoryRecommendModel::create($data);
|
||||||
|
if ($recommend->isEmpty()) {
|
||||||
|
return error('保存失败');
|
||||||
|
}
|
||||||
|
return success('保存成功');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新数据
|
||||||
|
*/
|
||||||
|
public function update()
|
||||||
|
{
|
||||||
|
$id = request()->param('id/d');
|
||||||
|
$post = request()->post([
|
||||||
|
'category_id',
|
||||||
|
'title',
|
||||||
|
'image',
|
||||||
|
'desc',
|
||||||
|
'link',
|
||||||
|
'sort',
|
||||||
|
'disabled'
|
||||||
|
]);
|
||||||
|
$data = array_merge($post, ['language_id' => request()->lang_id]);
|
||||||
|
|
||||||
|
// 参数校验
|
||||||
|
$validate = new ProductCategoryRecommendValidate();
|
||||||
|
$check_data = array_merge($data, ['id' => $id]);
|
||||||
|
if (!$validate->scene('update')->check($check_data)) {
|
||||||
|
return error($validate->getError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新推荐数据
|
||||||
|
$recommend = ProductCategoryRecommendModel::bypk($id)->find();
|
||||||
|
if (empty($recommend)) {
|
||||||
|
return error('请确认操作对象是否存在');
|
||||||
|
}
|
||||||
|
if (!$recommend->save($data)) {
|
||||||
|
return error('操作失败');
|
||||||
|
}
|
||||||
|
|
||||||
|
return success('操作成功');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
public function delete()
|
||||||
|
{
|
||||||
|
$id = request()->param('id/d');
|
||||||
|
|
||||||
|
// 删除推荐记录数据
|
||||||
|
$record = ProductCategoryRecommendModel::bypk($id)->find();
|
||||||
|
if (empty($record)) {
|
||||||
|
return error('请确认操作对象是否正确');
|
||||||
|
}
|
||||||
|
if (!$record->delete()) {
|
||||||
|
return error('操作失败');
|
||||||
|
}
|
||||||
|
|
||||||
|
return success('操作成功');
|
||||||
|
}
|
||||||
|
}
|
||||||
201
app/admin/controller/v1/SysMallStoreEntrance.php
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace app\admin\controller\v1;
|
||||||
|
|
||||||
|
use app\admin\model\v1\SysMallStoreEntranceModel;
|
||||||
|
use app\admin\validate\v1\SysMallStoreEntranceValidate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统商城店铺入口管理控制器
|
||||||
|
*/
|
||||||
|
class SysMallStoreEntrance
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 分页列表
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$param = request()->get([
|
||||||
|
'name',
|
||||||
|
'page/d' => 1,
|
||||||
|
'size/d' => 10
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
$data = SysMallStoreEntranceModel::withoutField([
|
||||||
|
'language_id',
|
||||||
|
'hover_image',
|
||||||
|
'updated_at',
|
||||||
|
'deleted_at'
|
||||||
|
])
|
||||||
|
->withSearch(['name'], ['name' => $param['name']??null])
|
||||||
|
->language(request()->lang_id)
|
||||||
|
->order(['sort' => 'asc', 'id' => 'desc'])
|
||||||
|
->paginate([
|
||||||
|
'list_rows' => $param['size'],
|
||||||
|
'page' => $param['page'],
|
||||||
|
])
|
||||||
|
?->each(function($item) {
|
||||||
|
// 列表页面图片输出缩略图
|
||||||
|
if (!empty($item['image'])) {
|
||||||
|
$item['image'] = thumb($item['image']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return success('获取成功', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情
|
||||||
|
*/
|
||||||
|
public function read()
|
||||||
|
{
|
||||||
|
$id = request()->param('id/d');
|
||||||
|
$record = SysMallStoreEntranceModel::bypk($id)
|
||||||
|
->withoutField(['language_id', 'created_at', 'updated_at', 'deleted_at'])
|
||||||
|
->find();
|
||||||
|
if (empty($record)) {
|
||||||
|
return error('商城店铺入口数据不存在');
|
||||||
|
}
|
||||||
|
|
||||||
|
return success('success', $record);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增数据
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$post = request()->post([
|
||||||
|
'name',
|
||||||
|
'image',
|
||||||
|
'hover_image',
|
||||||
|
'link',
|
||||||
|
'sort',
|
||||||
|
'disabled'
|
||||||
|
]);
|
||||||
|
$data = array_merge($post, ['language_id' => request()->lang_id]);
|
||||||
|
|
||||||
|
// 参数校验
|
||||||
|
$validate = new SysMallStoreEntranceValidate();
|
||||||
|
if (!$validate->scene('create')->check($data)) {
|
||||||
|
return error($validate->getError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
$entrance = SysMallStoreEntranceModel::create($data);
|
||||||
|
if ($entrance->isEmpty()) {
|
||||||
|
return error('保存失败');
|
||||||
|
}
|
||||||
|
return success('保存成功');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新数据
|
||||||
|
*/
|
||||||
|
public function update()
|
||||||
|
{
|
||||||
|
$id = request()->param('id/d');
|
||||||
|
$post = request()->post([
|
||||||
|
'name',
|
||||||
|
'image',
|
||||||
|
'hover_image',
|
||||||
|
'link',
|
||||||
|
'sort',
|
||||||
|
'disabled'
|
||||||
|
]);
|
||||||
|
$data = array_merge($post, ['language_id' => request()->lang_id]);
|
||||||
|
|
||||||
|
// 参数校验
|
||||||
|
$validate = new SysMallStoreEntranceValidate();
|
||||||
|
$check_data = array_merge($data, ['id' => $id]);
|
||||||
|
if (!$validate->scene('update')->check($check_data)) {
|
||||||
|
return error($validate->getError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新数据
|
||||||
|
$entrance = SysMallStoreEntranceModel::bypk($id)->find();
|
||||||
|
if (empty($entrance)) {
|
||||||
|
return error('请确认操作对象是否存在');
|
||||||
|
}
|
||||||
|
if (!$entrance->save($data)) {
|
||||||
|
return error('操作失败');
|
||||||
|
}
|
||||||
|
|
||||||
|
return success('操作成功');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
public function delete()
|
||||||
|
{
|
||||||
|
$id = request()->param('id/d');
|
||||||
|
|
||||||
|
// 删除数据
|
||||||
|
$record = SysMallStoreEntranceModel::bypk($id)->find();
|
||||||
|
if (empty($record)) {
|
||||||
|
return error('请确认操作对象是否正确');
|
||||||
|
}
|
||||||
|
if (!$record->delete()) {
|
||||||
|
return error('操作失败');
|
||||||
|
}
|
||||||
|
|
||||||
|
return success('操作成功');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出Excel
|
||||||
|
*/
|
||||||
|
public function export()
|
||||||
|
{
|
||||||
|
$schema = [
|
||||||
|
'id' => 'ID',
|
||||||
|
'image' => '图片',
|
||||||
|
'hover_image' => '悬浮图',
|
||||||
|
'name' => '名称',
|
||||||
|
'link' => '链接地址',
|
||||||
|
'sort' => '排序',
|
||||||
|
'disabled' => '状态',
|
||||||
|
'created_at' => '添加时间'
|
||||||
|
];
|
||||||
|
|
||||||
|
// 获取导出数据
|
||||||
|
$data = $this->getExportData();
|
||||||
|
|
||||||
|
// 导出
|
||||||
|
return xlsx_writer($data, $schema, '系统商城店铺入口列表' . date('YmdHis'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取要导出的数据
|
||||||
|
private function getExportData()
|
||||||
|
{
|
||||||
|
$server = request()->server();
|
||||||
|
$image_host = $server['REQUEST_SCHEME'] . "://" . $server['SERVER_NAME'] . '/';
|
||||||
|
$param = request()->get(['name']);
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
return SysMallStoreEntranceModel::withoutField([
|
||||||
|
'language_id',
|
||||||
|
'updated_at',
|
||||||
|
'deleted_at'
|
||||||
|
])
|
||||||
|
->withSearch(['name'], ['name' => $param['name']??null])
|
||||||
|
->language(request()->lang_id)
|
||||||
|
->order(['sort' => 'asc', 'id' => 'desc'])
|
||||||
|
->select()
|
||||||
|
?->each(function($item) use($image_host) {
|
||||||
|
// 拼接完整图片URL
|
||||||
|
if (!empty($item['image'])) {
|
||||||
|
$item['image'] = url_join($image_host, $item['image']);
|
||||||
|
}
|
||||||
|
if (!empty($item['hover_image'])) {
|
||||||
|
$item['hover_image'] = url_join($image_host, $item['hover_image']);
|
||||||
|
}
|
||||||
|
// 状态转换
|
||||||
|
$item['disabled'] = $item['disabled'] == 1 ? '禁用' : '启用';
|
||||||
|
})
|
||||||
|
->toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
47
app/admin/model/v1/ProductCategoryRecommendModel.php
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
declare (strict_types = 1);
|
||||||
|
|
||||||
|
namespace app\admin\model\v1;
|
||||||
|
|
||||||
|
use app\common\model\ProductCategoryRecommendBaseModel;
|
||||||
|
use think\model\concern\SoftDelete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品分类推荐模型
|
||||||
|
* @mixin \think\Model
|
||||||
|
*/
|
||||||
|
class ProductCategoryRecommendModel extends ProductCategoryRecommendBaseModel
|
||||||
|
{
|
||||||
|
// 启用软件删除
|
||||||
|
use SoftDelete;
|
||||||
|
// 软件删除时间字段
|
||||||
|
protected $deleteTime = 'deleted_at';
|
||||||
|
|
||||||
|
// 关联语言
|
||||||
|
public function language()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(\app\index\model\LanguageModel::class, 'language_id', 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关联产品分类
|
||||||
|
public function category()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(\app\index\model\ProductCategoryModel::class, 'category_id', 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 所属语言范围查询
|
||||||
|
public function scopeLanguage($query, $language)
|
||||||
|
{
|
||||||
|
$query->where($this->getTable() . '.language_id', '=', $language);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关键词搜索
|
||||||
|
public function searchKeywordsAttr($query, string|null $keywords)
|
||||||
|
{
|
||||||
|
if (is_null($keywords)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$query->where($this->getTable() . '.title', 'like', "%{$keywords}%")
|
||||||
|
->whereOr($this->getTable() . '.desc', 'like', "%{$keywords}%");
|
||||||
|
}
|
||||||
|
}
|
||||||
61
app/admin/model/v1/SysMallStoreEntranceModel.php
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
declare (strict_types = 1);
|
||||||
|
|
||||||
|
namespace app\admin\model\v1;
|
||||||
|
|
||||||
|
use app\common\model\SysMallStoreEntranceBaseModel;
|
||||||
|
use think\model\concern\SoftDelete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统商城店铺入口模型
|
||||||
|
* @mixin \think\Model
|
||||||
|
*/
|
||||||
|
class SysMallStoreEntranceModel extends SysMallStoreEntranceBaseModel
|
||||||
|
{
|
||||||
|
// 启用软删除
|
||||||
|
use SoftDelete;
|
||||||
|
// 软删除字段
|
||||||
|
protected $deleteTime = 'deleted_at';
|
||||||
|
|
||||||
|
// 关联语言
|
||||||
|
public function language()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(\app\index\model\LanguageModel::class, 'language_id', 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 所属语言范围查询
|
||||||
|
public function scopeLanguage($query, $language)
|
||||||
|
{
|
||||||
|
$query->where($this->getTable() . '.language_id', '=', $language);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询启用状态
|
||||||
|
public function scopeEnabled($query)
|
||||||
|
{
|
||||||
|
$query->where('disabled', '=', 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询禁用状态
|
||||||
|
public function scopeDisabled($query)
|
||||||
|
{
|
||||||
|
$query->where('disabled', '=', 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按名称搜索
|
||||||
|
public function searchNameAttr($query, $value, $data)
|
||||||
|
{
|
||||||
|
if (is_null($value)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$query->where('name', 'like', "%{$value}%");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按链接地址搜索
|
||||||
|
public function searchLinkAttr($query, $value, $data)
|
||||||
|
{
|
||||||
|
if (is_null($value)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$query->where('link_url', 'like', "%{$value}%");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -311,6 +311,27 @@ Route::group('v1', function () {
|
|||||||
|
|
||||||
// 分类删除
|
// 分类删除
|
||||||
Route::delete('delete/:id', 'ProductCategory/delete');
|
Route::delete('delete/:id', 'ProductCategory/delete');
|
||||||
|
|
||||||
|
// 产品分类推荐数据
|
||||||
|
Route::group('recommend', function () {
|
||||||
|
// 推荐数据分页列表
|
||||||
|
Route::get('index', 'ProductCategoryRecommend/index');
|
||||||
|
|
||||||
|
// 推荐数据导出
|
||||||
|
Route::get('export', 'ProductCategoryRecommend/export');
|
||||||
|
|
||||||
|
// 推荐数据详情
|
||||||
|
Route::get('read/:id', 'ProductCategoryRecommend/read');
|
||||||
|
|
||||||
|
// 推荐数据新增
|
||||||
|
Route::post('save', 'ProductCategoryRecommend/save');
|
||||||
|
|
||||||
|
// 推荐数据更新
|
||||||
|
Route::put('update/:id', 'ProductCategoryRecommend/update');
|
||||||
|
|
||||||
|
// 推荐数据删除
|
||||||
|
Route::delete('delete/:id', 'ProductCategoryRecommend/delete');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// 产品购买链接
|
// 产品购买链接
|
||||||
@@ -574,6 +595,29 @@ Route::group('v1', function () {
|
|||||||
// 反馈管理 - 产品询盘列表
|
// 反馈管理 - 产品询盘列表
|
||||||
Route::get('product/inquiry/index', 'ProductInquiry/index');
|
Route::get('product/inquiry/index', 'ProductInquiry/index');
|
||||||
|
|
||||||
|
// 系统商城店铺入口
|
||||||
|
Route::group('mall', function() {
|
||||||
|
Route::group('store', function() {
|
||||||
|
// 店铺入口列表分页
|
||||||
|
Route::get('index', 'SysMallStoreEntrance/index');
|
||||||
|
|
||||||
|
// 店铺入口导出
|
||||||
|
Route::get('export', 'SysMallStoreEntrance/export');
|
||||||
|
|
||||||
|
// 店铺入口详情
|
||||||
|
Route::get('read/:id', 'SysMallStoreEntrance/read');
|
||||||
|
|
||||||
|
// 店铺入口新增
|
||||||
|
Route::post('save', 'SysMallStoreEntrance/save');
|
||||||
|
|
||||||
|
// 店铺入口更新
|
||||||
|
Route::put('update/:id', 'SysMallStoreEntrance/update');
|
||||||
|
|
||||||
|
// 店铺入口删除
|
||||||
|
Route::delete('delete/:id', 'SysMallStoreEntrance/delete');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// 配置项列表
|
// 配置项列表
|
||||||
Route::group('config', function() {
|
Route::group('config', function() {
|
||||||
// 配置分组
|
// 配置分组
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ class NavigationItemValidate extends Validate
|
|||||||
'nav_id' => 'require|integer',
|
'nav_id' => 'require|integer',
|
||||||
'pid' => 'integer|different:id|checkPidNotBeChildren',
|
'pid' => 'integer|different:id|checkPidNotBeChildren',
|
||||||
'name' => 'require|max:64',
|
'name' => 'require|max:64',
|
||||||
|
'desc' => 'max:255',
|
||||||
'icon' => 'max:64',
|
'icon' => 'max:64',
|
||||||
|
'image' => 'max:255',
|
||||||
'link_to' => 'require|max:64|in:article,article_category,product,product_category,system_page,custom',
|
'link_to' => 'require|max:64|in:article,article_category,product,product_category,system_page,custom',
|
||||||
'link' => 'max:255',
|
'link' => 'max:255',
|
||||||
'sort' => 'integer',
|
'sort' => 'integer',
|
||||||
@@ -44,7 +46,9 @@ class NavigationItemValidate extends Validate
|
|||||||
'pid.checkPidNotBeChildren' => '父级ID不能为自身的子导航',
|
'pid.checkPidNotBeChildren' => '父级ID不能为自身的子导航',
|
||||||
'name.require' => '导航名称不能为空',
|
'name.require' => '导航名称不能为空',
|
||||||
'name.max' => '导航名称最多不能超过64个字符',
|
'name.max' => '导航名称最多不能超过64个字符',
|
||||||
|
'desc.max' => '导航名称最多不能超过:rule个字符',
|
||||||
'icon.max' => '图标最多不能超过64个字符',
|
'icon.max' => '图标最多不能超过64个字符',
|
||||||
|
'image.max' => '图标最多不能超过:rule个字符',
|
||||||
'link_to.require' => '链接类型不能为空',
|
'link_to.require' => '链接类型不能为空',
|
||||||
'link_to.max' => '链接类型最多不能超过64个字符',
|
'link_to.max' => '链接类型最多不能超过64个字符',
|
||||||
'link_to.in' => '链接类型必须是article,article_category,product_category,product,system_page,custom中之一',
|
'link_to.in' => '链接类型必须是article,article_category,product_category,product,system_page,custom中之一',
|
||||||
|
|||||||
63
app/admin/validate/v1/ProductCategoryRecommendValidate.php
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
declare (strict_types = 1);
|
||||||
|
|
||||||
|
namespace app\admin\validate\v1;
|
||||||
|
|
||||||
|
use think\Validate;
|
||||||
|
|
||||||
|
class ProductCategoryRecommendValidate extends Validate
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 定义验证规则
|
||||||
|
* 格式:'字段名' => ['规则1','规则2'...]
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $rule = [
|
||||||
|
'language_id' => 'require|integer',
|
||||||
|
'category_id' => 'require|integer',
|
||||||
|
'title' => 'require|max:255',
|
||||||
|
'image' => 'require|max:255',
|
||||||
|
'desc' => 'require|max:255',
|
||||||
|
'link' => 'max:500',
|
||||||
|
'sort' => 'require|integer',
|
||||||
|
'disabled' => 'in:0,1'
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定义错误信息
|
||||||
|
* 格式:'字段名.规则名' => '错误信息'
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $message = [
|
||||||
|
'id.require' => 'ID不能为空',
|
||||||
|
'id.integer' => 'ID必须是整数',
|
||||||
|
'language_id.require' => '语言ID不能为空',
|
||||||
|
'language_id.integer' => '语言ID必须是整数',
|
||||||
|
'category_id.require' => '分类ID不能为空',
|
||||||
|
'category_id.integer' => '分类ID必须是整数',
|
||||||
|
'title.require' => '标题不能为空',
|
||||||
|
'title.max' => '标题长度不能超过:rule个字符',
|
||||||
|
'image.require' => '图片不能为空',
|
||||||
|
'image.max' => '图片长度不能超过:rule个字符',
|
||||||
|
'desc.require' => '描述不能为空',
|
||||||
|
'desc.max' => '描述长度不能超过:rule个字符',
|
||||||
|
'link.max' => '链接长度不能超过:rule个字符',
|
||||||
|
'sort.require' => '排序不能为空',
|
||||||
|
'sort.integer' => '排序必须是整数',
|
||||||
|
'disabled.in' => '禁用状态只能是0或1',
|
||||||
|
];
|
||||||
|
|
||||||
|
// 新增场景
|
||||||
|
protected function sceneCreate()
|
||||||
|
{
|
||||||
|
return $this->remove('id', 'require|integer');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新场景
|
||||||
|
protected function sceneUpdate()
|
||||||
|
{
|
||||||
|
return $this->append('id', 'require|integer');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,8 +5,6 @@ namespace app\admin\validate\v1;
|
|||||||
|
|
||||||
use think\Validate;
|
use think\Validate;
|
||||||
|
|
||||||
use function PHPSTORM_META\type;
|
|
||||||
|
|
||||||
class ProductValidate extends Validate
|
class ProductValidate extends Validate
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ class SysBannerValidate extends BaseValidate
|
|||||||
'at_platform.in' => '显示端口只能是pc或mobile',
|
'at_platform.in' => '显示端口只能是pc或mobile',
|
||||||
'at_page.max' => '页面位置最多255个字符',
|
'at_page.max' => '页面位置最多255个字符',
|
||||||
'unique_label.max' => '唯一标识最多64个字符',
|
'unique_label.max' => '唯一标识最多64个字符',
|
||||||
'unique_label.mustOmit' => '更新时不能有unique_label字段',
|
|
||||||
'name.require' => '名称不能为空',
|
'name.require' => '名称不能为空',
|
||||||
'name.max' => '名称最多64个字符',
|
'name.max' => '名称最多64个字符',
|
||||||
'desc.max' => '描述最多255个字符',
|
'desc.max' => '描述最多255个字符',
|
||||||
@@ -61,6 +60,6 @@ class SysBannerValidate extends BaseValidate
|
|||||||
// 编辑场景
|
// 编辑场景
|
||||||
public function sceneEdit()
|
public function sceneEdit()
|
||||||
{
|
{
|
||||||
return $this->remove('language_id', 'require|integer')->append('unique_label', 'mustOmit');
|
return $this->remove('language_id', 'require|integer');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
61
app/admin/validate/v1/SysMallStoreEntranceValidate.php
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
declare (strict_types = 1);
|
||||||
|
|
||||||
|
namespace app\admin\validate\v1;
|
||||||
|
|
||||||
|
use think\Validate;
|
||||||
|
|
||||||
|
class SysMallStoreEntranceValidate extends Validate
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 定义验证规则
|
||||||
|
* 格式:'字段名' => ['规则1','规则2'...]
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $rule = [
|
||||||
|
'id' => 'require|integer',
|
||||||
|
'language_id' => 'require|integer',
|
||||||
|
'name' => 'require|max:255',
|
||||||
|
'image' => 'require|max:255',
|
||||||
|
'hover_image' => 'max:255',
|
||||||
|
'link' => 'url|max:500',
|
||||||
|
'sort' => 'require|integer',
|
||||||
|
'disabled' => 'in:0,1',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定义错误信息
|
||||||
|
* 格式:'字段名.规则名' => '错误信息'
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $message = [
|
||||||
|
'id.require' => 'ID不能为空',
|
||||||
|
'id.integer' => 'ID必须是整数',
|
||||||
|
'language_id.require' => '语言ID不能为空',
|
||||||
|
'language_id.integer' => '语言ID必须是整数',
|
||||||
|
'name.require' => '商城名称不能为空',
|
||||||
|
'name.max' => '商城名称长度不能超过:rule个字符',
|
||||||
|
'image.require' => '图片不能为空',
|
||||||
|
'image.max' => '图片长度不能超过:rule个字符',
|
||||||
|
'hover_image.max' => '悬浮图长度不能超过:rule个字符',
|
||||||
|
'link.url' => '链接地址必须是有效的URL',
|
||||||
|
'link.max' => '链接地址长度不能超过:rule个字符',
|
||||||
|
'sort.require' => '排序不能为空',
|
||||||
|
'sort.integer' => '排序必须是整数',
|
||||||
|
'disabled.in' => '禁用状态只能是0或1',
|
||||||
|
];
|
||||||
|
|
||||||
|
// 新增场景
|
||||||
|
protected function sceneCreate()
|
||||||
|
{
|
||||||
|
return $this->remove('id', 'require|integer');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新场景
|
||||||
|
protected function sceneUpdate()
|
||||||
|
{
|
||||||
|
return $this->append('id', 'require|integer');
|
||||||
|
}
|
||||||
|
}
|
||||||
33
app/common/model/ProductCategoryRecommendBaseModel.php
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
declare (strict_types = 1);
|
||||||
|
|
||||||
|
namespace app\common\model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品分类推荐模型
|
||||||
|
* @mixin \think\Model
|
||||||
|
*/
|
||||||
|
class ProductCategoryRecommendBaseModel extends BaseModel
|
||||||
|
{
|
||||||
|
// 表名
|
||||||
|
protected $name = 'product_category_recommend';
|
||||||
|
|
||||||
|
// 主键
|
||||||
|
protected $pk = 'id';
|
||||||
|
|
||||||
|
// 字段信息
|
||||||
|
protected $schema = [
|
||||||
|
'id' => 'int',
|
||||||
|
'language_id' => 'int',
|
||||||
|
'category_id' => 'int',
|
||||||
|
'title' => 'string',
|
||||||
|
'image' => 'string',
|
||||||
|
'desc' => 'string',
|
||||||
|
'link' => 'string',
|
||||||
|
'sort' => 'int',
|
||||||
|
'disabled' => 'int',
|
||||||
|
'created_at' => 'datetime',
|
||||||
|
'updated_at' => 'datetime',
|
||||||
|
'deleted_at' => 'datetime'
|
||||||
|
];
|
||||||
|
}
|
||||||
32
app/common/model/SysMallStoreEntranceBaseModel.php
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
declare (strict_types = 1);
|
||||||
|
|
||||||
|
namespace app\common\model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统商城店铺入口模型
|
||||||
|
* @mixin \think\Model
|
||||||
|
*/
|
||||||
|
class SysMallStoreEntranceBaseModel extends BaseModel
|
||||||
|
{
|
||||||
|
// 表名
|
||||||
|
protected $name = 'sys_mall_store_entrance';
|
||||||
|
|
||||||
|
// 主键
|
||||||
|
protected $pk = 'id';
|
||||||
|
|
||||||
|
// 字段信息
|
||||||
|
protected $schema = [
|
||||||
|
'id' => 'int',
|
||||||
|
'language_id' => 'int',
|
||||||
|
'name' => 'string',
|
||||||
|
'image' => 'string',
|
||||||
|
'hover_image' => 'string',
|
||||||
|
'link' => 'string',
|
||||||
|
'sort' => 'int',
|
||||||
|
'disabled' => 'int',
|
||||||
|
'created_at' => 'datetime',
|
||||||
|
'updated_at' => 'datetime',
|
||||||
|
'deleted_at' => 'datetime',
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -21,7 +21,9 @@ class SysNavigationItemBaseModel extends BaseModel
|
|||||||
'nav_id' => 'int',
|
'nav_id' => 'int',
|
||||||
'pid' => 'int',
|
'pid' => 'int',
|
||||||
'name' => 'string',
|
'name' => 'string',
|
||||||
|
'desc' => 'string',
|
||||||
'icon' => 'string',
|
'icon' => 'string',
|
||||||
|
'image' => 'string',
|
||||||
'link_to' => 'string',
|
'link_to' => 'string',
|
||||||
'link' => 'string',
|
'link' => 'string',
|
||||||
'sort' => 'int',
|
'sort' => 'int',
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use app\index\model\LanguageModel;
|
|||||||
use app\index\model\ProductCategoryModel;
|
use app\index\model\ProductCategoryModel;
|
||||||
use app\index\model\ProductModel;
|
use app\index\model\ProductModel;
|
||||||
use app\index\model\SysConfigModel;
|
use app\index\model\SysConfigModel;
|
||||||
|
use app\index\model\SysMallStoreEntranceModel;
|
||||||
use app\index\model\SysNavigationItemModel;
|
use app\index\model\SysNavigationItemModel;
|
||||||
use think\facade\Lang;
|
use think\facade\Lang;
|
||||||
use think\facade\View;
|
use think\facade\View;
|
||||||
@@ -38,7 +39,7 @@ abstract class Common extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取产品分类
|
// 获取产品分类
|
||||||
$categorys = $this->getProductCategory($this->lang_id);
|
$categorys = $this->getProductCategory($this->lang_id, true);
|
||||||
// 输出产品分类
|
// 输出产品分类
|
||||||
View::assign('header_categorys', $categorys);
|
View::assign('header_categorys', $categorys);
|
||||||
|
|
||||||
@@ -47,6 +48,9 @@ abstract class Common extends BaseController
|
|||||||
// 输出热销产品
|
// 输出热销产品
|
||||||
View::assign('header_hot_products', $hot_products);
|
View::assign('header_hot_products', $hot_products);
|
||||||
|
|
||||||
|
// 获取商品购买入口
|
||||||
|
View::assign("header_mall_entrance", $this->getMallStoreEntrance($this->lang_id));
|
||||||
|
|
||||||
// 输出顶部导航
|
// 输出顶部导航
|
||||||
View::assign('header_navigation', $this->getNavigation('NAV_67f3701f3e831', $this->lang_id));
|
View::assign('header_navigation', $this->getNavigation('NAV_67f3701f3e831', $this->lang_id));
|
||||||
|
|
||||||
@@ -78,7 +82,7 @@ abstract class Common extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取产品分类
|
// 获取产品分类
|
||||||
protected function getProductCategory($language = 1)
|
protected function getProductCategory($language = 1, $with_recommends = false)
|
||||||
{
|
{
|
||||||
$categorys = ProductCategoryModel::field([
|
$categorys = ProductCategoryModel::field([
|
||||||
'id',
|
'id',
|
||||||
@@ -87,15 +91,48 @@ abstract class Common extends BaseController
|
|||||||
'icon',
|
'icon',
|
||||||
'level'
|
'level'
|
||||||
])
|
])
|
||||||
|
->when($with_recommends, function($query) {
|
||||||
|
$query->with(['recommends' => function($query) {
|
||||||
|
$query->field(['id', 'category_id', 'title', 'image', 'desc', 'link'])->disabled(false)
|
||||||
|
->order(['sort' => 'asc', 'id' => 'desc']);
|
||||||
|
}]);
|
||||||
|
})
|
||||||
->language($language)
|
->language($language)
|
||||||
->displayed()
|
->displayed()
|
||||||
->order(['sort' => 'asc', 'id' => 'desc'])
|
->order(['sort' => 'asc', 'id' => 'desc'])
|
||||||
->select();
|
->select()
|
||||||
|
->hidden(["recommends.category_id"]);
|
||||||
if ($categorys->isEmpty()) {
|
if ($categorys->isEmpty()) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_to_tree($categorys->toArray(), 0, 'pid', 1, false);
|
return $this->toTreeAndChunk($categorys->toArray(), 0, 1);
|
||||||
|
}
|
||||||
|
private function toTreeAndChunk(array $categorys, int $pid, int|bool $level): array
|
||||||
|
{
|
||||||
|
$ret = [];
|
||||||
|
foreach ($categorys as $item) {
|
||||||
|
if ($item['pid'] == $pid) {
|
||||||
|
$lv = $level;
|
||||||
|
if ($level !== false) {
|
||||||
|
$item['level'] = $level;
|
||||||
|
$lv = $level + 1;
|
||||||
|
}
|
||||||
|
$children = $this->toTreeAndChunk($categorys, $item['id'], $lv);
|
||||||
|
if (!empty($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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取顶部导航
|
// 获取顶部导航
|
||||||
@@ -107,13 +144,6 @@ abstract class Common extends BaseController
|
|||||||
'status' => 1
|
'status' => 1
|
||||||
])
|
])
|
||||||
->where('status', '=', 1)
|
->where('status', '=', 1)
|
||||||
->where(function($query) {
|
|
||||||
// 临时代码,移动端暂时不显示 "AI PC"
|
|
||||||
if (request()->from == 'mobile') {
|
|
||||||
$table_name = SysNavigationItemModel::getTable();
|
|
||||||
$query->whereNotIn($table_name . ".id", [78]);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
->order(['sort' => 'asc', 'id' => 'asc'])
|
->order(['sort' => 'asc', 'id' => 'asc'])
|
||||||
->select();
|
->select();
|
||||||
if ($nav->isEmpty()) {
|
if ($nav->isEmpty()) {
|
||||||
@@ -171,6 +201,26 @@ abstract class Common extends BaseController
|
|||||||
return $languages;
|
return $languages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取商品购买入口
|
||||||
|
private function getMallStoreEntrance($language = 1)
|
||||||
|
{
|
||||||
|
return SysMallStoreEntranceModel::field([
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'image',
|
||||||
|
'hover_image',
|
||||||
|
'link'
|
||||||
|
])
|
||||||
|
->language($language)
|
||||||
|
->enabled()
|
||||||
|
->order(['sort' => 'asc', 'id' => 'desc'])
|
||||||
|
->select()
|
||||||
|
?->each(function($item) {
|
||||||
|
$item->image = thumb($item->image);
|
||||||
|
return $item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 获取系统联系方式配置
|
// 获取系统联系方式配置
|
||||||
protected function getSysConfig($language, $group = [])
|
protected function getSysConfig($language, $group = [])
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -267,6 +267,59 @@ class Product extends Common
|
|||||||
return View::fetch('subcategory');
|
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');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 产品搜索
|
* 产品搜索
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ return [
|
|||||||
'产品列表' => 'Products',
|
'产品列表' => 'Products',
|
||||||
'搜索' => 'Search',
|
'搜索' => 'Search',
|
||||||
'搜索历史' => 'Search History',
|
'搜索历史' => 'Search History',
|
||||||
|
'请输入搜索关键词' => 'Please enter a search keyword',
|
||||||
|
'搜索记录' => 'Search History',
|
||||||
|
'清空' => 'Clear',
|
||||||
'请择地区' => 'SELECT A REGION',
|
'请择地区' => 'SELECT A REGION',
|
||||||
'产品' => 'Product',
|
'产品' => 'Product',
|
||||||
'联系方式' => 'Contact',
|
'联系方式' => 'Contact',
|
||||||
@@ -234,6 +237,6 @@ return [
|
|||||||
"接口大满贯" => "Full-Featured Ports",
|
"接口大满贯" => "Full-Featured Ports",
|
||||||
"酷睿i5-12450H" => "Core i5-12450H",
|
"酷睿i5-12450H" => "Core i5-12450H",
|
||||||
"锐龙9 6900HX" => "Ryzen9 6900HX",
|
"锐龙9 6900HX" => "Ryzen9 6900HX",
|
||||||
"标配多种接口,会议室连接电脑、U盘传输文件、TF卡读取等,全都轻松搞定" => "Versatile Ports for Easy Connectivity. Effortlessly link to pro",
|
"标配多种接口,会议室连接电脑、</br>U盘传输文件、TF卡读取等,全都轻松搞定" => "Versatile Ports for Easy Connectivity. Effortlessly</br> link to projectors, U disks, TF cards, and more.",
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -5,10 +5,17 @@ return [
|
|||||||
'产品列表' => 'Products',
|
'产品列表' => 'Products',
|
||||||
'店铺' => 'Store',
|
'店铺' => 'Store',
|
||||||
'搜索记录' => 'Search History',
|
'搜索记录' => 'Search History',
|
||||||
'热销产品' => 'Popular Products',
|
|
||||||
'产品' => 'Product',
|
'产品' => 'Product',
|
||||||
'联系我们' => 'Contact',
|
'联系我们' => 'Contact',
|
||||||
|
|
||||||
|
// 新导航栏 - 2023-03-31
|
||||||
|
'搜索' => 'Search',
|
||||||
|
'搜索产品、分类...' => 'Search products and categories...',
|
||||||
|
'最近搜索' => 'Recent Searches',
|
||||||
|
'清空' => 'Clear',
|
||||||
|
'热销产品' => 'Popular Products',
|
||||||
|
'购买' => 'Buy',
|
||||||
|
|
||||||
// 返回文本
|
// 返回文本
|
||||||
'提交成功' => 'success',
|
'提交成功' => 'success',
|
||||||
'提交失败' => 'fail',
|
'提交失败' => 'fail',
|
||||||
|
|||||||
@@ -17,6 +17,12 @@ class ProductCategoryModel extends ProductCategoryBaseModel
|
|||||||
// 软件删除时间字段
|
// 软件删除时间字段
|
||||||
protected $deleteTime = 'deleted_at';
|
protected $deleteTime = 'deleted_at';
|
||||||
|
|
||||||
|
// 关联产品推荐
|
||||||
|
public function recommends()
|
||||||
|
{
|
||||||
|
return $this->hasMany(ProductCategoryRecommendModel::class, 'category_id', 'id');
|
||||||
|
}
|
||||||
|
|
||||||
// 所属语言范围查询
|
// 所属语言范围查询
|
||||||
public function scopeLanguage($query, $language)
|
public function scopeLanguage($query, $language)
|
||||||
{
|
{
|
||||||
|
|||||||
30
app/index/model/ProductCategoryRecommendModel.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
declare (strict_types = 1);
|
||||||
|
|
||||||
|
namespace app\index\model;
|
||||||
|
|
||||||
|
use app\common\model\ProductCategoryRecommendBaseModel;
|
||||||
|
use think\model\concern\SoftDelete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品分类推荐模型
|
||||||
|
* @mixin \think\Model
|
||||||
|
*/
|
||||||
|
class ProductCategoryRecommendModel extends ProductCategoryRecommendBaseModel
|
||||||
|
{
|
||||||
|
// 启用软件删除
|
||||||
|
use SoftDelete;
|
||||||
|
// 软件删除时间字段
|
||||||
|
protected $deleteTime = 'deleted_at';
|
||||||
|
|
||||||
|
// 所属语言范围查询
|
||||||
|
public function scopeLanguage($query, $language)
|
||||||
|
{
|
||||||
|
$query->where($this->getTable() . '.language_id', '=', $language);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeDisabled($query, $disabled = true)
|
||||||
|
{
|
||||||
|
$query->where($this->getTable() . '.disabled', '=', (int)$disabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
43
app/index/model/SysMallStoreEntranceModel.php
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
declare (strict_types = 1);
|
||||||
|
|
||||||
|
namespace app\index\model;
|
||||||
|
|
||||||
|
use app\common\model\SysMallStoreEntranceBaseModel;
|
||||||
|
use think\model\concern\SoftDelete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统商城店铺入口模型
|
||||||
|
* @mixin \think\Model
|
||||||
|
*/
|
||||||
|
class SysMallStoreEntranceModel extends SysMallStoreEntranceBaseModel
|
||||||
|
{
|
||||||
|
// 启用软删除
|
||||||
|
use SoftDelete;
|
||||||
|
// 软删除字段
|
||||||
|
protected $deleteTime = 'deleted_at';
|
||||||
|
|
||||||
|
// 关联语言
|
||||||
|
public function language()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(\app\index\model\LanguageModel::class, 'language_id', 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 所属语言范围查询
|
||||||
|
public function scopeLanguage($query, $language)
|
||||||
|
{
|
||||||
|
$query->where($this->getTable() . '.language_id', '=', $language);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询启用状态
|
||||||
|
public function scopeEnabled($query)
|
||||||
|
{
|
||||||
|
$query->where('disabled', '=', 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询禁用状态
|
||||||
|
public function scopeDisabled($query)
|
||||||
|
{
|
||||||
|
$query->where('disabled', '=', 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,6 +18,8 @@ Route::group('product', function () {
|
|||||||
Route::get('category/:id', 'Product/category');
|
Route::get('category/:id', 'Product/category');
|
||||||
// 产品分类 - 查看子类
|
// 产品分类 - 查看子类
|
||||||
Route::get('subcategory/:id', 'Product/subcategory');
|
Route::get('subcategory/:id', 'Product/subcategory');
|
||||||
|
// 单纯分类页
|
||||||
|
Route::get('classify/:id', 'Product/classify');
|
||||||
// 产品详情页
|
// 产品详情页
|
||||||
Route::get('detail/:id', 'Product/detail');
|
Route::get('detail/:id', 'Product/detail');
|
||||||
// 产品询盘
|
// 产品询盘
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<!-- banner-->
|
<!-- banner-->
|
||||||
<div class="oidx-banner">
|
<div class="oidx-banner">
|
||||||
{notempty name="focus_images"}
|
{notempty name="focus_images"}
|
||||||
<div class="swiper-container bannerswiper">
|
<div class="swiper-container bannerswiper" style="background: #fff;">
|
||||||
<div class="swiper-wrapper">
|
<div class="swiper-wrapper">
|
||||||
{volist name="focus_images" id="fi"}
|
{volist name="focus_images" id="fi"}
|
||||||
<div class="swiper-slide">
|
<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,161 +1,662 @@
|
|||||||
<header class="oircoEgapp-head">
|
<link rel="stylesheet" href="__CSS__/new_header.css">
|
||||||
<div class="headtop">
|
<header>
|
||||||
<a href="/"><img src="__IMAGES__/logo.png" class="headerlogimg" /></a>
|
<div class="mobile-header-box">
|
||||||
<div class="action-r">
|
<div class="mobile-header-left">
|
||||||
<div class="right img-responsive cursor_p">
|
<img src="__IMAGES__/header/nav.png" class="nav-img">
|
||||||
<span class="icon-category cursor_p top-menu-toggle"><i class="icon-menu-svg"></i></span>
|
<img src="__IMAGES__/header/x.png" class="nav-img1">
|
||||||
<span class="icon-keyword cursor_p top-search-toggle"><i class="icon-search-svg"></i></span>
|
<a href="/" target="_self" style="display: flex; justify-content: center;">
|
||||||
<span class="mask-up cursor_p top-country-toggle"><i class="icon-lag-svg"></i></span>
|
<img src="__IMAGES__/logo.png" class="nav-log">
|
||||||
</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>
|
</a>
|
||||||
</li>
|
</div>
|
||||||
|
<div class="mobile-header-right">
|
||||||
|
<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" 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>{:lang_i18n('产品列表')}</span>
|
||||||
|
<img src="__IMAGES__/header/b.png" class="menu-item-img">
|
||||||
|
</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}
|
{/volist}
|
||||||
</ul>
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{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>{$nav.name}</span>
|
||||||
|
<img src="__IMAGES__/header/b.png" class="menu-item-img">
|
||||||
|
</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>
|
||||||
|
{/volist}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/volist}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ====================== 购物车弹窗 ====================== -->
|
||||||
|
<div class="modal-overlay" id="cartModal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<img src="__IMAGES__/header/x.png" class="modal-close">
|
||||||
|
{if condition="!empty($header_mall_entrance)"}
|
||||||
|
<div class="modal-items-list">
|
||||||
|
{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="__IMAGES__/header/x.png" class="modal-close">
|
||||||
|
<div class="lang-items-list">
|
||||||
|
{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>
|
||||||
|
|
||||||
|
<!-- ====================== 搜索弹窗 ====================== -->
|
||||||
|
<div class="modal-overlay" id="searchModal">
|
||||||
|
<div class="search-modal-content">
|
||||||
|
<img src="__IMAGES__/header/x.png" class="modal-close">
|
||||||
|
<div class="search-input-box">
|
||||||
|
<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">{:lang_i18n('搜索记录')}</div>
|
||||||
|
<div class="search-history-clear" id="clearAllHistory">{:lang_i18n('清空')}</div>
|
||||||
|
</div>
|
||||||
|
<div class="search-history-list" id="searchHistoryList">
|
||||||
|
<!-- 搜索记录会动态显示在这里 -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<script type="text/javascript">
|
<script>
|
||||||
$(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();
|
|
||||||
})
|
|
||||||
|
|
||||||
// 移动端顶部宽度设置和主体内容宽度一致
|
document.addEventListener('DOMContentLoaded', function ()
|
||||||
var pageWidth = $('.oricoEGapp').outerWidth();
|
{
|
||||||
// 设置.header-PC元素的宽度
|
const navBtn = document.querySelector('.nav-img');
|
||||||
$('.oircoEgapp-head').css('width', pageWidth + 'px');
|
const navBtn1 = document.querySelector('.nav-img1');
|
||||||
// 可选:监听窗口大小变化,实时更新宽度
|
const dropdownMenu = document.querySelector('.nav-dropdown-menu');
|
||||||
$(window).resize(function() {
|
|
||||||
var newWidth = $('.oricoEGapp').outerWidth();
|
// 禁止body滚动
|
||||||
$('.oircoEgapp-head').css('width', newWidth + 'px');
|
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滚动
|
||||||
history();
|
if (!hasOpenMenu) {
|
||||||
})
|
enableBodyScroll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function history() {
|
// 关闭单个子菜单并重置滚动位置
|
||||||
var keywords = new URL(window.location.href).searchParams.get('keywords')
|
function closeSubMenu(subMenu, menuItem) {
|
||||||
var history_keywords = localStorage.getItem('header_search_keywords');
|
if (subMenu) {
|
||||||
if (!history_keywords) {
|
subMenu.classList.remove('show');
|
||||||
history_keywords = [];
|
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');
|
||||||
|
navBtn.style.display = 'none';
|
||||||
|
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');
|
||||||
|
const subMenu = item.querySelector('.sub-menu');
|
||||||
|
const box = item.querySelector('.menu-item-box');
|
||||||
|
|
||||||
|
if (isHasChild && subMenu) {
|
||||||
|
// 移除原有事件,重新绑定(确保只有一个展开)
|
||||||
|
const newBox = box.cloneNode(true);
|
||||||
|
box.parentNode.replaceChild(newBox, box);
|
||||||
|
|
||||||
|
newBox.addEventListener('click', function (e)
|
||||||
|
{
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
// 检查当前是否已展开
|
||||||
|
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 {
|
} else {
|
||||||
history_keywords = JSON.parse(history_keywords);
|
closeSubMenu(subMenu, item);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
// 记录搜索关键词
|
} else {
|
||||||
if (keywords) {
|
const link = item.getAttribute('data-link');
|
||||||
if (history_keywords.includes(keywords)) {
|
if (link) {
|
||||||
history_keywords.splice(history_keywords.indexOf(keywords), 1);
|
item.addEventListener('click', function (e)
|
||||||
|
{
|
||||||
|
e.stopPropagation();
|
||||||
|
window.location.href = link;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
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;
|
// 阻止子菜单链接冒泡
|
||||||
|
document.querySelectorAll('.sub-item').forEach(function (sub)
|
||||||
|
{
|
||||||
|
sub.addEventListener('click', function (e)
|
||||||
|
{
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
dropdownMenu.addEventListener('click', function (e)
|
||||||
|
{
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
|
||||||
|
navBtn1.style.display = 'none';
|
||||||
|
navBtn.style.display = 'block';
|
||||||
|
|
||||||
|
// 关闭所有弹窗的公共函数
|
||||||
|
function closeAllModals ()
|
||||||
|
{
|
||||||
|
cartModal.classList.remove('show');
|
||||||
|
langModal.classList.remove('show');
|
||||||
|
searchModal.classList.remove('show');
|
||||||
|
if (searchInput) {
|
||||||
|
searchInput.value = '';
|
||||||
|
if (searchClearBtn) searchClearBtn.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================== 购物车弹窗交互 ======================
|
||||||
|
const cardBtn = document.querySelector('.nav-card');
|
||||||
|
const cartModal = document.getElementById('cartModal');
|
||||||
|
const cartModalClose = cartModal.querySelector('.modal-close');
|
||||||
|
|
||||||
|
cardBtn.addEventListener('click', function (e)
|
||||||
|
{
|
||||||
|
e.stopPropagation();
|
||||||
|
// 关闭下拉菜单和其他弹窗
|
||||||
|
dropdownMenu.classList.remove('show');
|
||||||
|
navBtn.style.display = 'block';
|
||||||
|
navBtn1.style.display = 'none';
|
||||||
|
closeAllModals();
|
||||||
|
// 复位所有子菜单
|
||||||
|
resetAllSubMenus();
|
||||||
|
cartModal.classList.add('show');
|
||||||
|
});
|
||||||
|
|
||||||
|
cartModalClose.addEventListener('click', function ()
|
||||||
|
{
|
||||||
|
cartModal.classList.remove('show');
|
||||||
|
});
|
||||||
|
|
||||||
|
cartModal.addEventListener('click', function (e)
|
||||||
|
{
|
||||||
|
if (e.target === cartModal) {
|
||||||
|
cartModal.classList.remove('show');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ====================== 语言弹窗交互 ======================
|
||||||
|
const langBtn = document.querySelector('.nav-lang');
|
||||||
|
const langModal = document.getElementById('langModal');
|
||||||
|
const langModalClose = langModal.querySelector('.modal-close');
|
||||||
|
|
||||||
|
langBtn.addEventListener('click', function (e)
|
||||||
|
{
|
||||||
|
e.stopPropagation();
|
||||||
|
// 关闭下拉菜单和其他弹窗
|
||||||
|
dropdownMenu.classList.remove('show');
|
||||||
|
navBtn.style.display = 'block';
|
||||||
|
navBtn1.style.display = 'none';
|
||||||
|
closeAllModals();
|
||||||
|
// 复位所有子菜单
|
||||||
|
resetAllSubMenus();
|
||||||
|
langModal.classList.add('show');
|
||||||
|
});
|
||||||
|
|
||||||
|
langModalClose.addEventListener('click', function ()
|
||||||
|
{
|
||||||
|
langModal.classList.remove('show');
|
||||||
|
});
|
||||||
|
|
||||||
|
langModal.addEventListener('click', function (e)
|
||||||
|
{
|
||||||
|
if (e.target === langModal) {
|
||||||
|
langModal.classList.remove('show');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelectorAll('.lang-item').forEach(function (item)
|
||||||
|
{
|
||||||
|
item.addEventListener('click', function (e)
|
||||||
|
{
|
||||||
|
e.stopPropagation();
|
||||||
|
console.log('选择了语言:', this.innerText);
|
||||||
|
langModal.classList.remove('show');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ====================== 搜索记录功能 ======================
|
||||||
|
// 获取搜索记录
|
||||||
|
function getSearchHistory ()
|
||||||
|
{
|
||||||
|
const history = localStorage.getItem('searchHistory');
|
||||||
|
return history ? JSON.parse(history) : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存搜索记录
|
||||||
|
function saveSearchHistory (history)
|
||||||
|
{
|
||||||
|
localStorage.setItem('searchHistory', JSON.stringify(history));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加搜索记录
|
||||||
|
function addSearchHistory (keyword)
|
||||||
|
{
|
||||||
|
if (!keyword || !keyword.trim()) return;
|
||||||
|
keyword = keyword.trim();
|
||||||
|
let history = getSearchHistory();
|
||||||
|
history = history.filter(item => item !== keyword);
|
||||||
|
history.unshift(keyword);
|
||||||
|
if (history.length > 10) {
|
||||||
|
history = history.slice(0, 10);
|
||||||
|
}
|
||||||
|
saveSearchHistory(history);
|
||||||
|
renderSearchHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除单条搜索记录
|
||||||
|
function deleteSearchHistoryItem (keyword)
|
||||||
|
{
|
||||||
|
let history = getSearchHistory();
|
||||||
|
history = history.filter(item => item !== keyword);
|
||||||
|
saveSearchHistory(history);
|
||||||
|
renderSearchHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空所有搜索记录
|
||||||
|
function clearAllSearchHistory ()
|
||||||
|
{
|
||||||
|
saveSearchHistory([]);
|
||||||
|
renderSearchHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 渲染搜索记录列表
|
||||||
|
function renderSearchHistory ()
|
||||||
|
{
|
||||||
|
const historyList = document.getElementById('searchHistoryList');
|
||||||
|
const history = getSearchHistory();
|
||||||
|
|
||||||
|
if (!historyList) return;
|
||||||
|
|
||||||
|
if (history.length === 0) {
|
||||||
|
historyList.innerHTML = '<div class="empty-history">暂无搜索记录</div>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
historyList.innerHTML = '';
|
||||||
|
history.forEach(function (keyword)
|
||||||
|
{
|
||||||
|
const itemDiv = document.createElement('div');
|
||||||
|
itemDiv.className = 'search-history-item';
|
||||||
|
itemDiv.innerHTML = `
|
||||||
|
<span>${escapeHtml(keyword)}</span>
|
||||||
|
<img src="__IMAGES__/header/x.png" class="delete-icon" data-keyword="${escapeHtml(keyword)}">
|
||||||
|
`;
|
||||||
|
itemDiv.addEventListener('click', function (e)
|
||||||
|
{
|
||||||
|
if (e.target.classList && e.target.classList.contains('delete-icon')) {
|
||||||
|
e.stopPropagation();
|
||||||
|
deleteSearchHistoryItem(keyword);
|
||||||
|
} else {
|
||||||
|
e.stopPropagation();
|
||||||
|
searchInput.value = keyword;
|
||||||
|
doSearch(keyword);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
historyList.appendChild(itemDiv);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 简单的防XSS
|
||||||
|
function escapeHtml (str)
|
||||||
|
{
|
||||||
|
return str.replace(/[&<>]/g, function (m)
|
||||||
|
{
|
||||||
|
if (m === '&') return '&';
|
||||||
|
if (m === '<') return '<';
|
||||||
|
if (m === '>') return '>';
|
||||||
|
return m;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================== 搜索弹窗交互 ======================
|
||||||
|
const searchBtn = document.querySelector('.nav-search');
|
||||||
|
const searchModal = document.getElementById('searchModal');
|
||||||
|
const searchModalClose = searchModal.querySelector('.modal-close');
|
||||||
|
const searchInput = document.getElementById('searchInput');
|
||||||
|
const searchSubmit = document.getElementById('searchSubmit');
|
||||||
|
const searchClearBtn = document.getElementById('searchClearBtn');
|
||||||
|
const clearAllHistoryBtn = document.getElementById('clearAllHistory');
|
||||||
|
|
||||||
|
searchInput.addEventListener('input', function (e)
|
||||||
|
{
|
||||||
|
if (searchInput.value.length > 0) {
|
||||||
|
searchClearBtn.style.display = 'block';
|
||||||
|
} else {
|
||||||
|
searchClearBtn.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
searchClearBtn.addEventListener('click', function (e)
|
||||||
|
{
|
||||||
|
e.stopPropagation();
|
||||||
|
searchInput.value = '';
|
||||||
|
searchClearBtn.style.display = 'none';
|
||||||
|
searchInput.focus();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (clearAllHistoryBtn) {
|
||||||
|
clearAllHistoryBtn.addEventListener('click', function (e)
|
||||||
|
{
|
||||||
|
e.stopPropagation();
|
||||||
|
clearAllSearchHistory();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
searchBtn.addEventListener('click', function (e)
|
||||||
|
{
|
||||||
|
e.stopPropagation();
|
||||||
|
// 关闭下拉菜单和其他弹窗
|
||||||
|
dropdownMenu.classList.remove('show');
|
||||||
|
navBtn.style.display = 'block';
|
||||||
|
navBtn1.style.display = 'none';
|
||||||
|
closeAllModals();
|
||||||
|
// 复位所有子菜单
|
||||||
|
resetAllSubMenus();
|
||||||
|
renderSearchHistory();
|
||||||
|
searchModal.classList.add('show');
|
||||||
|
setTimeout(() =>
|
||||||
|
{
|
||||||
|
searchInput.focus();
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
searchModalClose.addEventListener('click', function ()
|
||||||
|
{
|
||||||
|
searchModal.classList.remove('show');
|
||||||
|
searchInput.value = '';
|
||||||
|
searchClearBtn.style.display = 'none';
|
||||||
|
});
|
||||||
|
|
||||||
|
searchModal.addEventListener('click', function (e)
|
||||||
|
{
|
||||||
|
if (e.target === searchModal) {
|
||||||
|
searchModal.classList.remove('show');
|
||||||
|
searchInput.value = '';
|
||||||
|
searchClearBtn.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 执行搜索
|
||||||
|
function doSearch (keyword)
|
||||||
|
{
|
||||||
|
if (keyword && keyword.trim()) {
|
||||||
|
const searchKeyword = keyword.trim();
|
||||||
|
console.log('搜索关键词:', searchKeyword);
|
||||||
|
if (searchKeyword) {
|
||||||
|
addSearchHistory(searchKeyword);
|
||||||
|
window.location.href = "{:url('product/search')}?keywords=" + encodeURIComponent(searchKeyword);
|
||||||
|
searchModal.classList.remove('show');
|
||||||
|
searchInput.value = '';
|
||||||
|
searchClearBtn.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
searchSubmit.addEventListener('click', function (e)
|
||||||
|
{
|
||||||
|
e.stopPropagation();
|
||||||
|
doSearch(searchInput.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
searchInput.addEventListener('keypress', function (e)
|
||||||
|
{
|
||||||
|
console.log(e,'========e=============')
|
||||||
|
if (e.key === 'Enter' || e.key === 'enter' || e.keyCode === 13) {
|
||||||
|
e.preventDefault();
|
||||||
|
doSearch(searchInput.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ====================== 添加:点击空白区域关闭所有子菜单 ======================
|
||||||
|
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>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -30,10 +30,12 @@
|
|||||||
function setRootFontSize ()
|
function setRootFontSize ()
|
||||||
{
|
{
|
||||||
var clientWidth = docEl.clientWidth;
|
var clientWidth = docEl.clientWidth;
|
||||||
|
console.log(clientWidth,'=clientWidth=')
|
||||||
if (!clientWidth) return;
|
if (!clientWidth) return;
|
||||||
var fontSize = clientWidth / 7.5; // 750px/7.5=100px,375px/7.5=50px
|
var fontSize = clientWidth / 7.5; // 750px/7.5=100px,375px/7.5=50px
|
||||||
// 直接修改内联样式,优先级最高
|
// 直接修改内联样式,优先级最高
|
||||||
docEl.setAttribute('style', 'font-size: ' + fontSize + 'px !important;');
|
docEl.setAttribute('style', 'font-size: ' + fontSize + 'px !important;');
|
||||||
|
console.log(fontSize,'=fontSize=')
|
||||||
}
|
}
|
||||||
|
|
||||||
setRootFontSize();
|
setRootFontSize();
|
||||||
@@ -46,7 +48,7 @@
|
|||||||
{block name="main"}
|
{block name="main"}
|
||||||
{notempty name="data.top_focus_images"}
|
{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">
|
<div class="swiper-wrapper">
|
||||||
{volist name="data.top_focus_images" id="tfi"}
|
{volist name="data.top_focus_images" id="tfi"}
|
||||||
<div class="swiper-slide auto-swiper-slide">
|
<div class="swiper-slide auto-swiper-slide">
|
||||||
@@ -116,8 +118,13 @@
|
|||||||
{assign name="cpu_first_section" value=":array_shift($data.cpu)"/}
|
{assign name="cpu_first_section" value=":array_shift($data.cpu)"/}
|
||||||
<div class="cpu-main" style="background: url('{$cpu_first_section.image|default=\'\'}');background-size:100% auto">
|
<div class="cpu-main" style="background: url('{$cpu_first_section.image|default=\'\'}');background-size:100% auto">
|
||||||
<div class="cpu-texts">
|
<div class="cpu-texts">
|
||||||
<div class="cpu-texts-t">{$cpu_first_section.title|default=''}</div>
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
<p class="cpu-texts-p">{$cpu_first_section.short_title|default=''}</p>
|
<div class="cpu-texts-t f36 lh1">{$cpu_first_section.title|default=''|raw}</div>
|
||||||
|
<p class="cpu-texts-p f18">{$cpu_first_section.short_title|default=''|raw}</p>
|
||||||
|
{else/}
|
||||||
|
<div class="cpu-texts-t">{$cpu_first_section.title|default=''|raw}</div>
|
||||||
|
<p class="cpu-texts-p">{$cpu_first_section.short_title|default=''|raw}</p>
|
||||||
|
{/eq}
|
||||||
</div>
|
</div>
|
||||||
<div class="cpu-footer">
|
<div class="cpu-footer">
|
||||||
<div class="cpu-footer-img">
|
<div class="cpu-footer-img">
|
||||||
@@ -197,8 +204,13 @@
|
|||||||
<div class="gpu">
|
<div class="gpu">
|
||||||
{assign name="gpu_first_section" value=":array_shift($data.gpu)"/}
|
{assign name="gpu_first_section" value=":array_shift($data.gpu)"/}
|
||||||
<div class="gpu-texts">
|
<div class="gpu-texts">
|
||||||
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
|
<div class="gpu-texts-t f36">{$gpu_first_section.title|default=''|raw}</div>
|
||||||
|
<div class="gpu-texts-p f18">{$gpu_first_section.short_title|default=''|raw}</div>
|
||||||
|
{else/}
|
||||||
<div class="gpu-texts-t">{$gpu_first_section.title|default=''|raw}</div>
|
<div class="gpu-texts-t">{$gpu_first_section.title|default=''|raw}</div>
|
||||||
<div class="gpu-texts-p">{$gpu_first_section.short_title|default=''|raw}</div>
|
<div class="gpu-texts-p">{$gpu_first_section.short_title|default=''|raw}</div>
|
||||||
|
{/eq}
|
||||||
</div>
|
</div>
|
||||||
<div class="gpu-main-img" style="background: url('{$gpu_first_section.image|default=\'\'}');background-size:100% auto">
|
<div class="gpu-main-img" style="background: url('{$gpu_first_section.image|default=\'\'}');background-size:100% auto">
|
||||||
<div class="gpu-amd-img">
|
<div class="gpu-amd-img">
|
||||||
@@ -266,9 +278,17 @@
|
|||||||
{notempty name="data.ram"}
|
{notempty name="data.ram"}
|
||||||
<!-- 内存 memory-->
|
<!-- 内存 memory-->
|
||||||
<div class="memory">
|
<div class="memory">
|
||||||
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
|
<div class="memory-t f36 lh1">{$data.ram.title|raw}</div>
|
||||||
|
{else/}
|
||||||
<div class="memory-t">{$data.ram.title|raw}</div>
|
<div class="memory-t">{$data.ram.title|raw}</div>
|
||||||
|
{/eq}
|
||||||
<div class="memory-img" style="background: url('{$data.ram.image|default=\'\'}'); background-size:100% auto">
|
<div class="memory-img" style="background: url('{$data.ram.image|default=\'\'}'); background-size:100% auto">
|
||||||
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
|
<div class="memory-p f18">{$data.ram.short_title|raw}</div>
|
||||||
|
{else/}
|
||||||
<div class="memory-p ">{$data.ram.short_title|raw}</div>
|
<div class="memory-p ">{$data.ram.short_title|raw}</div>
|
||||||
|
{/eq}
|
||||||
<div class="memory-footer-img">{$data.ram.desc|raw}</div>
|
<div class="memory-footer-img">{$data.ram.desc|raw}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -278,7 +298,12 @@
|
|||||||
<div class="m2">
|
<div class="m2">
|
||||||
{assign name="ssd_first_section" value=":array_shift($data.hard_drive)"/}
|
{assign name="ssd_first_section" value=":array_shift($data.hard_drive)"/}
|
||||||
<div class="m2-bg" style="background: url('{$ssd_first_section.image|default=\'\'}');background-size:100% auto">
|
<div class="m2-bg" style="background: url('{$ssd_first_section.image|default=\'\'}');background-size:100% auto">
|
||||||
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
|
<div class="m2-bg-t1 f36 lh1">{$ssd_first_section.title|default=''|raw}</div>
|
||||||
|
{else/}
|
||||||
<div class="m2-bg-t1">{$ssd_first_section.title|default=''|raw}</div>
|
<div class="m2-bg-t1">{$ssd_first_section.title|default=''|raw}</div>
|
||||||
|
{/eq}
|
||||||
|
<div class="m2-bg-p">{$ssd_first_section.short_title|default=''|raw}</div>
|
||||||
<div class="m2-img-box">
|
<div class="m2-img-box">
|
||||||
{volist name="data.hard_drive" id="ho"}
|
{volist name="data.hard_drive" id="ho"}
|
||||||
<img src="{$ho.image}" alt="{$ho.title}" loading="lazy">
|
<img src="{$ho.image}" alt="{$ho.title}" loading="lazy">
|
||||||
@@ -292,8 +317,13 @@
|
|||||||
<div class="fs">
|
<div class="fs">
|
||||||
{notempty name="data.cooling_system.0"}
|
{notempty name="data.cooling_system.0"}
|
||||||
<div class="dl">
|
<div class="dl">
|
||||||
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
|
<div class="dl-t f36">{$data.cooling_system.0.title|raw}</div>
|
||||||
|
<p class="dl-p f18">{$data.cooling_system.0.short_title|raw}</p>
|
||||||
|
{else/}
|
||||||
<div class="dl-t">{$data.cooling_system.0.title|raw}</div>
|
<div class="dl-t">{$data.cooling_system.0.title|raw}</div>
|
||||||
<p class="dl-p">{$data.cooling_system.0.short_title|raw}</p>
|
<p class="dl-p">{$data.cooling_system.0.short_title|raw}</p>
|
||||||
|
{/eq}
|
||||||
</div>
|
</div>
|
||||||
{/notempty}
|
{/notempty}
|
||||||
<div class="fs-box">
|
<div class="fs-box">
|
||||||
@@ -322,7 +352,11 @@
|
|||||||
{notempty name="data.apps"}
|
{notempty name="data.apps"}
|
||||||
<!-- 性能大拿 -->
|
<!-- 性能大拿 -->
|
||||||
<div class="xn">
|
<div class="xn">
|
||||||
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
|
<div class="xn-t f28 ">{$data.apps.title|default=''}</div>
|
||||||
|
{else/}
|
||||||
<div class="xn-t">{$data.apps.title|default=''}</div>
|
<div class="xn-t">{$data.apps.title|default=''}</div>
|
||||||
|
{/eq}
|
||||||
<div class="xn-container">
|
<div class="xn-container">
|
||||||
<div class="xn-image-section">
|
<div class="xn-image-section">
|
||||||
<img src="{$data.apps.image|default=''}" alt="" class="zoom-image first-image">
|
<img src="{$data.apps.image|default=''}" alt="" class="zoom-image first-image">
|
||||||
@@ -335,9 +369,17 @@
|
|||||||
<!-- IPS -->
|
<!-- IPS -->
|
||||||
<div class="ips">
|
<div class="ips">
|
||||||
{assign name="ips_fisrt_section" value=":array_shift($data.screen_soft_light)"/}
|
{assign name="ips_fisrt_section" value=":array_shift($data.screen_soft_light)"/}
|
||||||
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
|
<div class="ips-t f48">{$ips_fisrt_section.title|default=''|raw}</div>
|
||||||
|
{else/}
|
||||||
<div class="ips-t">{$ips_fisrt_section.title|default=''|raw}</div>
|
<div class="ips-t">{$ips_fisrt_section.title|default=''|raw}</div>
|
||||||
|
{/eq}
|
||||||
<div class="ips-bg" style="background: url('{$ips_fisrt_section.image|default=\'\'}');background-size:100% auto">
|
<div class="ips-bg" style="background: url('{$ips_fisrt_section.image|default=\'\'}');background-size:100% auto">
|
||||||
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
|
<p class="f18">{$ips_fisrt_section.short_title|default=''|raw}</p>
|
||||||
|
{else/}
|
||||||
<p>{$ips_fisrt_section.short_title|default=''|raw}</p>
|
<p>{$ips_fisrt_section.short_title|default=''|raw}</p>
|
||||||
|
{/eq}
|
||||||
</div>
|
</div>
|
||||||
<div class="ips-imgs">
|
<div class="ips-imgs">
|
||||||
{volist name="data.screen_soft_light" id="lo"}
|
{volist name="data.screen_soft_light" id="lo"}
|
||||||
@@ -350,9 +392,17 @@
|
|||||||
<!-- 色彩RGB -->
|
<!-- 色彩RGB -->
|
||||||
<div class="rgb">
|
<div class="rgb">
|
||||||
{assign name="gamut_first_section" value=":array_shift($data.screen_color_gamut)"/}
|
{assign name="gamut_first_section" value=":array_shift($data.screen_color_gamut)"/}
|
||||||
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
|
<div class="rgb-t f36 lh1">{$gamut_first_section.title|default=''|raw}</div>
|
||||||
|
{else/}
|
||||||
<div class="rgb-t">{$gamut_first_section.title|default=''|raw}</div>
|
<div class="rgb-t">{$gamut_first_section.title|default=''|raw}</div>
|
||||||
|
{/eq}
|
||||||
<div class="rgb-bg" style="background: url('{$gamut_first_section.image|default=\'\'}');background-size:100% auto">
|
<div class="rgb-bg" style="background: url('{$gamut_first_section.image|default=\'\'}');background-size:100% auto">
|
||||||
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
|
<p class="rgb-p f18">{$gamut_first_section.short_title|default=''|raw}</p>
|
||||||
|
{else/}
|
||||||
<p class="rgb-p">{$gamut_first_section.short_title|default=''|raw}</p>
|
<p class="rgb-p">{$gamut_first_section.short_title|default=''|raw}</p>
|
||||||
|
{/eq}
|
||||||
</div>
|
</div>
|
||||||
<div class="rgb-imgs">
|
<div class="rgb-imgs">
|
||||||
{volist name="data.screen_color_gamut" id="go"}
|
{volist name="data.screen_color_gamut" id="go"}
|
||||||
@@ -366,8 +416,13 @@
|
|||||||
<div class="bly">
|
<div class="bly">
|
||||||
{assign name="glare_first_section" value=":array_shift($data.screen_anti_glare)"/}
|
{assign name="glare_first_section" value=":array_shift($data.screen_anti_glare)"/}
|
||||||
<div class="bly-texts">
|
<div class="bly-texts">
|
||||||
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
|
<div class="bly-t f36 lh1">{$glare_first_section.title|default=''|raw}</div>
|
||||||
|
<div class="bly-p f18">{$glare_first_section.short_title|default=''|raw}</div>
|
||||||
|
{else/}
|
||||||
<div class="bly-t">{$glare_first_section.title|default=''|raw}</div>
|
<div class="bly-t">{$glare_first_section.title|default=''|raw}</div>
|
||||||
<div class="bly-p">{$glare_first_section.short_title|default=''|raw}</div>
|
<div class="bly-p">{$glare_first_section.short_title|default=''|raw}</div>
|
||||||
|
{/eq}
|
||||||
</div>
|
</div>
|
||||||
<div class="beforeafter ba-slider" style="border-radius: 0.14rem;height: 3.4rem;">
|
<div class="beforeafter ba-slider" style="border-radius: 0.14rem;height: 3.4rem;">
|
||||||
{assign name="glare_left" value=":array_shift($data.screen_anti_glare)"/}
|
{assign name="glare_left" value=":array_shift($data.screen_anti_glare)"/}
|
||||||
@@ -385,8 +440,13 @@
|
|||||||
<div class="qb">
|
<div class="qb">
|
||||||
<div class="qb-text">
|
<div class="qb-text">
|
||||||
{assign name="texture_first_section" value=":array_shift($data.exterior_texture)"/}
|
{assign name="texture_first_section" value=":array_shift($data.exterior_texture)"/}
|
||||||
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
|
<div class="qb-t f36 lh1">{$texture_first_section.title|default=''|raw}</div>
|
||||||
|
<div class="qb-p f18">{$texture_first_section.short_title|default=''|raw}</div>
|
||||||
|
{else/}
|
||||||
<div class="qb-t">{$texture_first_section.title|default=''|raw}</div>
|
<div class="qb-t">{$texture_first_section.title|default=''|raw}</div>
|
||||||
<div class="qb-p">{$texture_first_section.short_title|default=''|raw}</div>
|
<div class="qb-p">{$texture_first_section.short_title|default=''|raw}</div>
|
||||||
|
{/eq}
|
||||||
<div class="swiper-container auto-swiper-container">
|
<div class="swiper-container auto-swiper-container">
|
||||||
<div class="swiper-wrapper">
|
<div class="swiper-wrapper">
|
||||||
{volist name="data.exterior_texture" id="to"}
|
{volist name="data.exterior_texture" id="to"}
|
||||||
@@ -404,8 +464,13 @@
|
|||||||
{assign name="wifi_first_section" value=":array_shift($data.network_card)"/}
|
{assign name="wifi_first_section" value=":array_shift($data.network_card)"/}
|
||||||
<div class="wifi" style="background: url('{$wifi_first_section.image|default=\'\'}');background-size:100% auto">
|
<div class="wifi" style="background: url('{$wifi_first_section.image|default=\'\'}');background-size:100% auto">
|
||||||
<div class="wifi-texts">
|
<div class="wifi-texts">
|
||||||
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
|
<div class="wifi-t f36 ">{$wifi_first_section.title|default=''|raw}</div>
|
||||||
|
<div class="wifi-p f18">{$wifi_first_section.short_title|default=''|raw}</div>
|
||||||
|
{else/}
|
||||||
<div class="wifi-t">{$wifi_first_section.title|default=''|raw}</div>
|
<div class="wifi-t">{$wifi_first_section.title|default=''|raw}</div>
|
||||||
<div class="wifi-p">{$wifi_first_section.short_title|default=''|raw}</div>
|
<div class="wifi-p">{$wifi_first_section.short_title|default=''|raw}</div>
|
||||||
|
{/eq}
|
||||||
</div>
|
</div>
|
||||||
<div class="wifi-img">
|
<div class="wifi-img">
|
||||||
{volist name="data.network_card" id="co"}
|
{volist name="data.network_card" id="co"}
|
||||||
@@ -419,8 +484,13 @@
|
|||||||
{assign name="battery_first_section" value=":array_shift($data.battery_life)"/}
|
{assign name="battery_first_section" value=":array_shift($data.battery_life)"/}
|
||||||
<div class="endurance" style="background: url('{$battery_first_section.image|default=\'\'|raw}');background-size:100% auto">
|
<div class="endurance" style="background: url('{$battery_first_section.image|default=\'\'|raw}');background-size:100% auto">
|
||||||
<div class="endurance-texts">
|
<div class="endurance-texts">
|
||||||
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
|
<div class="endurance-t f36">{$battery_first_section.title|default=''|raw}</div>
|
||||||
|
<div class="endurance-p f18">{$battery_first_section.short_title|default=''|raw}</div>
|
||||||
|
{else/}
|
||||||
<div class="endurance-t">{$battery_first_section.title|default=''|raw}</div>
|
<div class="endurance-t">{$battery_first_section.title|default=''|raw}</div>
|
||||||
<div class="endurance-p">{$battery_first_section.short_title|default=''|raw}</div>
|
<div class="endurance-p">{$battery_first_section.short_title|default=''|raw}</div>
|
||||||
|
{/eq}
|
||||||
</div>
|
</div>
|
||||||
<div class="endurance-img">
|
<div class="endurance-img">
|
||||||
{volist name="data.battery_life" id="lo"}
|
{volist name="data.battery_life" id="lo"}
|
||||||
@@ -431,43 +501,78 @@
|
|||||||
</div>
|
</div>
|
||||||
{/notempty}
|
{/notempty}
|
||||||
<!-- 接口大满贯 -->
|
<!-- 接口大满贯 -->
|
||||||
|
|
||||||
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
|
<div class="zoom-t f36 lh1">{:lang_i18n('接口大满贯')}</div>
|
||||||
|
{else/}
|
||||||
<div class="zoom-t">{:lang_i18n('接口大满贯')}</div>
|
<div class="zoom-t">{:lang_i18n('接口大满贯')}</div>
|
||||||
|
{/eq}
|
||||||
<div class="zoom-container" id="zoomContainer">
|
<div class="zoom-container" id="zoomContainer">
|
||||||
<div class="img-wrapper">
|
<div class="img-wrapper">
|
||||||
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
|
<p class="zoom-p f18">{:lang_i18n('标配多种接口,会议室连接电脑、</br>U盘传输文件、TF卡读取等,全都轻松搞定')}</p>
|
||||||
|
{else/}
|
||||||
<p class="zoom-p">{:lang_i18n('标配多种接口,会议室连接电脑、</br>U盘传输文件、TF卡读取等,全都轻松搞定')}</p>
|
<p class="zoom-p">{:lang_i18n('标配多种接口,会议室连接电脑、</br>U盘传输文件、TF卡读取等,全都轻松搞定')}</p>
|
||||||
|
{/eq}
|
||||||
<img src="__IMAGES__/topic_laptop/zoom-img-1.png" alt="接口图" class="bg-img" id="bgImg" loading="lazy">
|
<img src="__IMAGES__/topic_laptop/zoom-img-1.png" alt="接口图" class="bg-img" id="bgImg" loading="lazy">
|
||||||
</div>
|
</div>
|
||||||
<!-- 左边 -->
|
<!-- 左边 -->
|
||||||
<div class="annotation anno-delay-1" style="top:60%; left: 37.5%;">
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
<span style="text-align: center; font-size: 0.18rem;">{:lang_i18n('肯辛通锁孔')}</span>
|
<div class="annotation anno-delay-1 anno-up1" style="top: 29%; left: 33%;">
|
||||||
|
<span style="text-align: center; font-size: 0.16rem;">Gigabit <br/> Ethernet</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="annotation anno-delay-1 anno-up" style="top: 31.5%; left: 32%;">
|
{else/}
|
||||||
<span style="text-align: center; font-size: 0.18rem;">{:lang_i18n('千兆网口')}</span>
|
<div class="annotation anno-delay-1 anno-up" style="top: 32.5%; left: 32%;">
|
||||||
|
<span style="text-align: center; font-size: 0.16rem;">千兆网口</span>
|
||||||
|
</div>
|
||||||
|
{/eq}
|
||||||
|
<div class="annotation anno-delay-1" style="top:60%; left: 39%;">
|
||||||
|
<span style="text-align: center; font-size: 0.16rem;">{:lang_i18n('肯辛通锁孔')}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="annotation anno-delay-1" style="top: 68%; left: 26%;">
|
<div class="annotation anno-delay-1" style="top: 68%; left: 26%;">
|
||||||
<span style="text-align: center; font-size: 0.16rem;">{:lang_i18n('USB-A<br/>(5Gbps)')}</span>
|
<span style="text-align: center; font-size: 0.16rem;">{:lang_i18n('USB-A<br/>(5Gbps)')}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="annotation anno-delay-1 anno-up1" style="top:35.5%; left:18%;">
|
<div class="annotation anno-delay-1 anno-up1" style="top:35.5%; left:18%;">
|
||||||
<span style="text-align: center; font-size: 0.18rem;">{:lang_i18n('USB-A<br />(480Mbps)')}</span>
|
<span style="text-align: center; font-size: 0.16rem;">{:lang_i18n('USB-A<br/>(480Mbps)')}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="annotation anno-delay-1" style="top: 73%; left: 14.5%;">
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
<span style="text-align: center; font-size: 0.18rem;">{:lang_i18n('3.5mm<br />耳麦合一')}</span>
|
<div class="annotation anno-delay-1" style="top: 73%; left: 13.5%;">
|
||||||
|
<span style="text-align: center; font-size: 0.16rem;">3.5mm <br/> Combo Audio</span>
|
||||||
</div>
|
</div>
|
||||||
|
{else/}
|
||||||
|
<div class="annotation anno-delay-1" style="top: 73%; left: 15.5%;">
|
||||||
|
<span style="text-align: center; font-size: 0.16rem;">3.5mm<br/>耳麦合一</span>
|
||||||
|
</div>
|
||||||
|
{/eq}
|
||||||
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
|
<div class="annotation anno-delay-1 anno-up1" style="top: 40%; left: 9.5%;">
|
||||||
|
<span style="text-align: center; font-size: 0.16rem;">TF 3.0 <br/> Card Slot</span>
|
||||||
|
</div>
|
||||||
|
{else/}
|
||||||
<div class="annotation anno-delay-1 anno-up" style="top: 43%; left: 9%;">
|
<div class="annotation anno-delay-1 anno-up" style="top: 43%; left: 9%;">
|
||||||
<span style="text-align: center; font-size: 0.18rem;">{:lang_i18n('TF口3.0')}</span>
|
<span style="text-align: center; font-size: 0.16rem;">TF口3.0</span>
|
||||||
</div>
|
</div>
|
||||||
|
{/eq}
|
||||||
|
|
||||||
<!-- 右边 -->
|
<!-- 右边 -->
|
||||||
<div class="annotation anno-delay-1" style="top: 64%; left: 58%;">
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
<span style="text-align: center; font-size: 0.18rem;">{:lang_i18n('全功能<br />USB-C')}</span>
|
<div class="annotation anno-delay-1" style="top: 64%; left: 56.5%;">
|
||||||
|
<span style="text-align: center; font-size: 0.16rem;">All-in-One <br/> USB-C</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="annotation anno-up anno-delay-1" style="top: 34%; left: 65%;">
|
{else/}
|
||||||
<span style="text-align: center; font-size: 0.18rem;">{:lang_i18n('HDMI')}</span>
|
<div class="annotation anno-delay-1" style="top: 64%; left: 58.5%;">
|
||||||
|
<span style="text-align: center; font-size: 0.16rem;">全功能<br/>USB-C</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="annotation anno-delay-1" style="top: 70.5%; left: 70.5%;">
|
{/eq}
|
||||||
<span style="text-align: center; font-size: 0.18rem;">{:lang_i18n('USB-A<br />(5Gbps)')}</span>
|
|
||||||
|
<div class="annotation anno-up anno-delay-1" style="top: 34%; left: 66.5%;">
|
||||||
|
<span style="text-align: center; font-size: 0.16rem;">{:lang_i18n('HDMI')}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="annotation anno-up1 anno-delay-1" style="top:38.5%; left: 77%;">
|
<div class="annotation anno-delay-1" style="top: 70.5%; left: 71.5%;">
|
||||||
<span style="text-align: center; font-size: 0.18rem;">{:lang_i18n('USB-C<br />(5Gbps)')}</span>
|
<span style="text-align: center; font-size: 0.16rem;">{:lang_i18n('USB-A<br/>(5Gbps)')}</span>
|
||||||
|
</div>
|
||||||
|
<div class="annotation anno-up1 anno-delay-1" style="top:38.5%; left: 78%;">
|
||||||
|
<span style="text-align: center; font-size: 0.16rem;">{:lang_i18n('USB-C<br/>(5Gbps)')}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{notempty name="data.scene_focus_images"}
|
{notempty name="data.scene_focus_images"}
|
||||||
@@ -491,8 +596,21 @@
|
|||||||
{assign name="camare_microphone" value=":array_shift($data.camare_microphone_security)"/}
|
{assign name="camare_microphone" value=":array_shift($data.camare_microphone_security)"/}
|
||||||
{assign name="security" value=":array_shift($data.camare_microphone_security)"/}
|
{assign name="security" value=":array_shift($data.camare_microphone_security)"/}
|
||||||
<div class="tabs-container">
|
<div class="tabs-container">
|
||||||
{notempty name="camare_microphone"}<div class="tab-t active" data-index="0">{$camare_microphone.title|default=''}</div>{/notempty}
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
{notempty name="security"}<div class="tab-t" data-index="1">{$security.title|default=''}</div>{/notempty}
|
{notempty name="camare_microphone"}
|
||||||
|
<div class="tab-t active f36 lh1" data-index="0">{$camare_microphone.title|default=''}</div>
|
||||||
|
{/notempty}
|
||||||
|
{notempty name="security"}
|
||||||
|
<div class="tab-t f36 lh1" data-index="1">{$security.title|default=''}</div>
|
||||||
|
{/notempty}
|
||||||
|
{else/}
|
||||||
|
{notempty name="camare_microphone"}
|
||||||
|
<div class="tab-t active" data-index="0">{$camare_microphone.title|default=''}</div>
|
||||||
|
{/notempty}
|
||||||
|
{notempty name="security"}
|
||||||
|
<div class="tab-t" data-index="1">{$security.title|default=''}</div>
|
||||||
|
{/notempty}
|
||||||
|
{/eq}
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
{notempty name="camare_microphone"}
|
{notempty name="camare_microphone"}
|
||||||
<div class="tab-panel active">
|
<div class="tab-panel active">
|
||||||
@@ -547,9 +665,16 @@
|
|||||||
{/notempty}
|
{/notempty}
|
||||||
{notempty name="data.webpage_footnotes"}
|
{notempty name="data.webpage_footnotes"}
|
||||||
<!-- 底部文字 -->
|
<!-- 底部文字 -->
|
||||||
|
{eq name=":cookie('think_lang')" value="en-us"}
|
||||||
|
<div class="footer-texts-en">
|
||||||
|
{$data.webpage_footnotes.desc|raw|htmlspecialchars_decode}
|
||||||
|
</div>
|
||||||
|
{else/}
|
||||||
<div class="footer-texts">
|
<div class="footer-texts">
|
||||||
{$data.webpage_footnotes.desc|raw|htmlspecialchars_decode}
|
{$data.webpage_footnotes.desc|raw|htmlspecialchars_decode}
|
||||||
</div>
|
</div>
|
||||||
|
{/eq}
|
||||||
|
|
||||||
{/notempty}
|
{/notempty}
|
||||||
{/block}
|
{/block}
|
||||||
{block name="script"}
|
{block name="script"}
|
||||||
@@ -957,18 +1082,18 @@
|
|||||||
const allVideos = document.querySelectorAll('.fs-video');
|
const allVideos = document.querySelectorAll('.fs-video');
|
||||||
const fsBox = document.querySelector('.fs-box');
|
const fsBox = document.querySelector('.fs-box');
|
||||||
let isVideoPlaying = false;
|
let isVideoPlaying = false;
|
||||||
let videoTip = null;
|
// let videoTip = null;
|
||||||
|
|
||||||
// 初始化视频提示
|
// 初始化视频提示
|
||||||
const initVideoTip = () =>
|
// const initVideoTip = () =>
|
||||||
{
|
// {
|
||||||
if (!fsBox || videoTip) return;
|
// if (!fsBox || videoTip) return;
|
||||||
videoTip = document.createElement('div');
|
// videoTip = document.createElement('div');
|
||||||
videoTip.className = 'video-tip';
|
// videoTip.className = 'video-tip';
|
||||||
videoTip.innerText = '点击播放视频';
|
// videoTip.innerText = '点击播放视频';
|
||||||
fsBox.appendChild(videoTip);
|
// fsBox.appendChild(videoTip);
|
||||||
videoTip.style.display = 'none';
|
// videoTip.style.display = 'none';
|
||||||
};
|
// };
|
||||||
|
|
||||||
// 停止所有视频(仅暂停,无显隐)
|
// 停止所有视频(仅暂停,无显隐)
|
||||||
function stopAllVideos ()
|
function stopAllVideos ()
|
||||||
@@ -978,7 +1103,7 @@
|
|||||||
video.pause(); // 仅暂停,删除display修改
|
video.pause(); // 仅暂停,删除display修改
|
||||||
});
|
});
|
||||||
isVideoPlaying = false;
|
isVideoPlaying = false;
|
||||||
if (videoTip) videoTip.style.display = 'none';
|
// if (videoTip) videoTip.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 播放指定视频(仅播放,无显隐)
|
// 播放指定视频(仅播放,无显隐)
|
||||||
@@ -992,17 +1117,17 @@
|
|||||||
video.play().then(() =>
|
video.play().then(() =>
|
||||||
{
|
{
|
||||||
isVideoPlaying = true;
|
isVideoPlaying = true;
|
||||||
if (videoTip) videoTip.style.display = 'none';
|
// if (videoTip) videoTip.style.display = 'none';
|
||||||
}).catch((err) =>
|
}).catch((err) =>
|
||||||
{
|
{
|
||||||
console.log('视频自动播放失败:', err);
|
console.log('视频自动播放失败:', err);
|
||||||
if (videoTip) videoTip.style.display = 'block';
|
// if (videoTip) videoTip.style.display = 'block';
|
||||||
// 点击视频手动播放(仅执行一次)
|
// 点击视频手动播放(仅执行一次)
|
||||||
video.addEventListener('click', () =>
|
video.addEventListener('click', () =>
|
||||||
{
|
{
|
||||||
video.play();
|
video.play();
|
||||||
isVideoPlaying = true;
|
isVideoPlaying = true;
|
||||||
if (videoTip) videoTip.style.display = 'none';
|
// if (videoTip) videoTip.style.display = 'none';
|
||||||
}, { once: true });
|
}, { once: true });
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -1055,7 +1180,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 初始化执行
|
// 初始化执行
|
||||||
initVideoTip();
|
// initVideoTip();
|
||||||
window.addEventListener('scroll', handleVideoScroll, { passive: true });
|
window.addEventListener('scroll', handleVideoScroll, { passive: true });
|
||||||
window.addEventListener('resize', handleVideoResize);
|
window.addEventListener('resize', handleVideoResize);
|
||||||
// 页面加载完成后尝试播放视频
|
// 页面加载完成后尝试播放视频
|
||||||
|
|||||||
@@ -31,15 +31,13 @@
|
|||||||
<link rel="stylesheet" href="__CSS__/topic_power_prodline/footer.css">
|
<link rel="stylesheet" href="__CSS__/topic_power_prodline/footer.css">
|
||||||
|
|
||||||
{/block}
|
{/block}
|
||||||
{block name="header"}
|
|
||||||
<!-- 重置header头为空 -->
|
|
||||||
{/block}
|
|
||||||
{block name="main"}
|
{block name="main"}
|
||||||
<a class="header" href="/">
|
<!-- <a class="header" href="/">
|
||||||
<div class="header-img">
|
<div class="header-img">
|
||||||
<img src="__IMAGES__/logo.png" alt="">
|
<img src="__IMAGES__/logo.png" alt="">
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a> -->
|
||||||
<!-- 轮播核心容器 -->
|
<!-- 轮播核心容器 -->
|
||||||
<div class="swiper-container auto-swiper-container" >
|
<div class="swiper-container auto-swiper-container" >
|
||||||
{notempty name="data.focus_image"}
|
{notempty name="data.focus_image"}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<div class="pageMain">
|
<div class="pageMain">
|
||||||
<!-- banner -->
|
<!-- banner -->
|
||||||
{notempty name="focus_images"}
|
{notempty name="focus_images"}
|
||||||
<div class="swiper-container bannerswiper">
|
<div class="swiper-container bannerswiper" style="background: #fff;">
|
||||||
<div class="swiper-wrapper">
|
<div class="swiper-wrapper">
|
||||||
{volist name="focus_images" id="focus"}
|
{volist name="focus_images" id="focus"}
|
||||||
<div class="swiper-slide">
|
<div class="swiper-slide">
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
{/block}
|
{/block}
|
||||||
{block name="main"}
|
{block name="main"}
|
||||||
{notempty name="data.top_focus_images"}
|
{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">
|
<div class="swiper-wrapper">
|
||||||
{volist name="data.top_focus_images" id="tfi"}
|
{volist name="data.top_focus_images" id="tfi"}
|
||||||
<div class="swiper-slide auto-swiper-slide">
|
<div class="swiper-slide auto-swiper-slide">
|
||||||
@@ -1037,17 +1037,17 @@
|
|||||||
const allVideos = document.querySelectorAll('.fs-video');
|
const allVideos = document.querySelectorAll('.fs-video');
|
||||||
const fsBox = document.querySelector('.fs-box');
|
const fsBox = document.querySelector('.fs-box');
|
||||||
let isVideoPlaying = false;
|
let isVideoPlaying = false;
|
||||||
let videoTip = null;
|
// let videoTip = null;
|
||||||
|
|
||||||
// 初始化视频提示
|
// 初始化视频提示
|
||||||
const initVideoTip = () => {
|
// const initVideoTip = () => {
|
||||||
if (!fsBox || videoTip) return;
|
// if (!fsBox || videoTip) return;
|
||||||
videoTip = document.createElement('div');
|
// videoTip = document.createElement('div');
|
||||||
videoTip.className = 'video-tip';
|
// videoTip.className = 'video-tip';
|
||||||
videoTip.innerText = '点击播放视频';
|
// videoTip.innerText = '点击播放视频';
|
||||||
fsBox.appendChild(videoTip);
|
// fsBox.appendChild(videoTip);
|
||||||
videoTip.style.display = 'none';
|
// videoTip.style.display = 'none';
|
||||||
};
|
// };
|
||||||
|
|
||||||
// 停止所有视频
|
// 停止所有视频
|
||||||
function stopAllVideos ()
|
function stopAllVideos ()
|
||||||
@@ -1060,7 +1060,7 @@
|
|||||||
if (img) img.style.display = 'block';
|
if (img) img.style.display = 'block';
|
||||||
});
|
});
|
||||||
isVideoPlaying = false;
|
isVideoPlaying = false;
|
||||||
if (videoTip) videoTip.style.display = 'none';
|
// if (videoTip) videoTip.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 播放指定视频
|
// 播放指定视频
|
||||||
@@ -1075,7 +1075,7 @@
|
|||||||
video.muted = true;
|
video.muted = true;
|
||||||
video.play().then(() => {
|
video.play().then(() => {
|
||||||
isVideoPlaying = true;
|
isVideoPlaying = true;
|
||||||
if (videoTip) videoTip.style.display = 'none';
|
// if (videoTip) videoTip.style.display = 'none';
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.log('视频自动播放失败:', err);
|
console.log('视频自动播放失败:', err);
|
||||||
video.style.display = 'block';
|
video.style.display = 'block';
|
||||||
@@ -1085,7 +1085,7 @@
|
|||||||
video.addEventListener('click', () => {
|
video.addEventListener('click', () => {
|
||||||
video.play();
|
video.play();
|
||||||
isVideoPlaying = true;
|
isVideoPlaying = true;
|
||||||
if (videoTip) videoTip.style.display = 'none';
|
// if (videoTip) videoTip.style.display = 'none';
|
||||||
}, { once: true });
|
}, { once: true });
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -1140,7 +1140,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 初始化
|
// 初始化
|
||||||
initVideoTip();
|
// initVideoTip();
|
||||||
window.addEventListener('scroll', handleVideoScroll, { passive: true });
|
window.addEventListener('scroll', handleVideoScroll, { passive: true });
|
||||||
window.addEventListener('resize', handleVideoResize);
|
window.addEventListener('resize', handleVideoResize);
|
||||||
// 页面加载完成后尝试播放
|
// 页面加载完成后尝试播放
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ class CreateSysNavigationItem extends Migrator
|
|||||||
$table->addColumn('nav_id', 'string', ['limit' => 64, 'null' => false, 'comment' => '所属导航ID'])
|
$table->addColumn('nav_id', 'string', ['limit' => 64, 'null' => false, 'comment' => '所属导航ID'])
|
||||||
->addColumn('pid', 'integer', ['null' => false, 'default' => 0, 'comment' => '父级ID'])
|
->addColumn('pid', 'integer', ['null' => false, 'default' => 0, 'comment' => '父级ID'])
|
||||||
->addColumn('name', 'string', ['limit' => 64, 'null' => false, 'comment' => '名称'])
|
->addColumn('name', 'string', ['limit' => 64, 'null' => false, 'comment' => '名称'])
|
||||||
|
->addColumn('desc', 'string', ['limit' => 255, 'null' => true, 'default' => null, 'comment' => '描述'])
|
||||||
->addColumn('icon', 'string', ['limit' => 64, 'null' => true, 'default' => null, 'comment' => '图标'])
|
->addColumn('icon', 'string', ['limit' => 64, 'null' => true, 'default' => null, 'comment' => '图标'])
|
||||||
|
->addColumn('image', 'string', ['limit' => 255, 'null' => true, 'default' => null, 'comment' => '图片'])
|
||||||
->addColumn('link_to', 'string', ['limit' => 64, 'null' => true, 'default' => null, 'comment' => '链接到(类型): article:文章, article_category:文章分类, product:产品, product_category:产品分类, custom:自定义链接'])
|
->addColumn('link_to', 'string', ['limit' => 64, 'null' => true, 'default' => null, 'comment' => '链接到(类型): article:文章, article_category:文章分类, product:产品, product_category:产品分类, custom:自定义链接'])
|
||||||
->addColumn('link', 'string', ['limit' => 255, 'null' => true, 'default' => null, 'comment' => '链接'])
|
->addColumn('link', 'string', ['limit' => 255, 'null' => true, 'default' => null, 'comment' => '链接'])
|
||||||
->addColumn('sort', 'integer', ['limit' => 11, 'null' => false, 'default' => 0, 'comment' => '排序'])
|
->addColumn('sort', 'integer', ['limit' => 11, 'null' => false, 'default' => 0, 'comment' => '排序'])
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use think\migration\Migrator;
|
||||||
|
use think\migration\db\Column;
|
||||||
|
|
||||||
|
class CreateProductCategoryRecommend extends Migrator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Change Method.
|
||||||
|
*
|
||||||
|
* Write your reversible migrations using this method.
|
||||||
|
*
|
||||||
|
* More information on writing migrations is available here:
|
||||||
|
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
|
||||||
|
*
|
||||||
|
* The following commands can be used in this method and Phinx will
|
||||||
|
* automatically reverse them when rolling back:
|
||||||
|
*
|
||||||
|
* createTable
|
||||||
|
* renameTable
|
||||||
|
* addColumn
|
||||||
|
* renameColumn
|
||||||
|
* addIndex
|
||||||
|
* addForeignKey
|
||||||
|
*
|
||||||
|
* Remember to call "create()" or "update()" and NOT "save()" when working
|
||||||
|
* with the Table class.
|
||||||
|
*/
|
||||||
|
public function change()
|
||||||
|
{
|
||||||
|
$table = $this->table('product_category_recommend', [
|
||||||
|
'engine' => 'MyISAM',
|
||||||
|
'collation' => 'utf8mb4_general_ci',
|
||||||
|
'comment' => '产品分类推荐表'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$table->addColumn('language_id', 'integer', ['signed' => false, 'null' => false, 'comment' => '语言ID'])
|
||||||
|
->addColumn('category_id', 'integer', ['signed' => false, 'null' => false, 'comment' => '分类ID'])
|
||||||
|
->addColumn('title', 'string', ['limit' => 255, 'comment' => '标题'])
|
||||||
|
->addColumn('image', 'string', ['limit' => 255, 'default' => '', 'comment' => '图片'])
|
||||||
|
->addColumn('desc', 'string', ['limit' => 255, 'comment' => '描述'])
|
||||||
|
->addColumn('link', 'string', ['limit' => 500, 'default' => '', 'comment' => '外链地址'])
|
||||||
|
->addColumn('sort', 'integer', ['default' => 0, 'comment' => '排序'])
|
||||||
|
->addColumn('disabled', 'boolean', ['default' => 0, 'comment' => '是否禁用 0:启用 1:禁用'])
|
||||||
|
->addColumn('created_at', 'timestamp', ["null" => false,'default' => 'CURRENT_TIMESTAMP', 'comment' => '创建时间'])
|
||||||
|
->addColumn('updated_at', 'timestamp', ["null" => false,'default' => 'CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP', 'comment' => '更新时间'])
|
||||||
|
->addColumn('deleted_at', 'timestamp', ['null' => true, 'comment' => '删除时间'])
|
||||||
|
->create();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use think\migration\Migrator;
|
||||||
|
use think\migration\db\Column;
|
||||||
|
|
||||||
|
class SysMallStoreEntrance extends Migrator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Change Method.
|
||||||
|
*
|
||||||
|
* Write your reversible migrations using this method.
|
||||||
|
*
|
||||||
|
* More information on writing migrations is available here:
|
||||||
|
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
|
||||||
|
*
|
||||||
|
* The following commands can be used in this method and Phinx will
|
||||||
|
* automatically reverse them when rolling back:
|
||||||
|
*
|
||||||
|
* createTable
|
||||||
|
* renameTable
|
||||||
|
* addColumn
|
||||||
|
* renameColumn
|
||||||
|
* addIndex
|
||||||
|
* addForeignKey
|
||||||
|
*
|
||||||
|
* Remember to call "create()" or "update()" and NOT "save()" when working
|
||||||
|
* with the Table class.
|
||||||
|
*/
|
||||||
|
public function change()
|
||||||
|
{
|
||||||
|
$table = $this->table('sys_mall_store_entrance', [
|
||||||
|
'engine' => 'MyISAM',
|
||||||
|
'collation' => 'utf8mb4_general_ci',
|
||||||
|
'comment' => '系统商城店铺入口表'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$table->addColumn('language_id', 'integer', ['signed' => false, 'null' => false, 'comment' => '语言ID'])
|
||||||
|
->addColumn('name', 'string', ['limit' => 255, 'null' => false, 'comment' => '商城名称'])
|
||||||
|
->addColumn('image', 'string', ['limit' => 255, 'default' => '', 'comment' => '图片'])
|
||||||
|
->addColumn('hover_image', 'string', ['limit' => 255, 'default' => '', 'comment' => '悬浮图'])
|
||||||
|
->addColumn('link', 'string', ['limit' => 500, 'default' => '', 'comment' => '链接地址'])
|
||||||
|
->addColumn('sort', 'integer', ['default' => 0, 'comment' => '排序'])
|
||||||
|
->addColumn('disabled', 'boolean', ['default' => 0, 'comment' => '是否禁用 0:启用 1:禁用'])
|
||||||
|
->addColumn('created_at', 'timestamp', ['null' => false, 'default' => 'CURRENT_TIMESTAMP', 'comment' => '创建时间'])
|
||||||
|
->addColumn('updated_at', 'timestamp', ['null' => false, 'default' => 'CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP', 'comment' => '更新时间'])
|
||||||
|
->addColumn('deleted_at', 'timestamp', ['null' => true, 'comment' => '删除时间'])
|
||||||
|
->addIndex(['language_id'], ['name' => 'idx_language_id'])
|
||||||
|
->create();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding-top: 50px;
|
padding-top: 46px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.iotb_bgw {
|
.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;
|
align-items: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding-top: 50px;
|
padding-top: 46px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.iotb_bgw {
|
.iotb_bgw {
|
||||||
|
|||||||
@@ -156,7 +156,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding-top: 50px;
|
padding-top: 46px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.iotb_bgw {
|
.iotb_bgw {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
.oricoEGapp .oricoEGapp-index .oidx-banner {
|
.oricoEGapp .oricoEGapp-index .oidx-banner {
|
||||||
margin-top: 3.5rem;
|
margin-top: 46px;
|
||||||
z-index: 9;
|
z-index: 9;
|
||||||
}
|
}
|
||||||
.oricoEGapp .oricoEGapp-index .oidx-banner .swiper-container {
|
.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;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin-top: 3.4rem;
|
margin-top:46px;
|
||||||
}
|
}
|
||||||
.oricoEGapp-newarrival .ona-topimg {
|
.oricoEGapp-newarrival .ona-topimg {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
|||||||
@@ -33,13 +33,13 @@
|
|||||||
transform: scale(0.8);
|
transform: scale(0.8);
|
||||||
}
|
}
|
||||||
.bly-t {
|
.bly-t {
|
||||||
font-size: 0.36rem;
|
font-size: 0.48rem;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.bly-p {
|
.bly-p {
|
||||||
font-size: 0.18rem;
|
font-size: 0.20rem;
|
||||||
color: #cbcfd8;
|
color: #cbcfd8;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -10,18 +10,19 @@
|
|||||||
}
|
}
|
||||||
.cpu-texts-t {
|
.cpu-texts-t {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 0.36rem;
|
font-size: 0.48rem;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding-top: 0.19rem;
|
padding-top: 0.19rem;
|
||||||
}
|
}
|
||||||
.cpu-texts-p {
|
.cpu-texts-p {
|
||||||
color: #cbcfd8;
|
color: #cbcfd8;
|
||||||
font-size: 0.18rem;
|
font-size: 0.20rem;
|
||||||
margin-top: 0.37rem;
|
margin-top: 0.37rem;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cpu-footer {
|
.cpu-footer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
|||||||
@@ -23,12 +23,12 @@
|
|||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
.endurance-t span:nth-child(2) {
|
.endurance-t span:nth-child(2) {
|
||||||
font-size: 0.36rem;
|
font-size: 0.48rem;
|
||||||
margin-left: 0.11rem;
|
margin-left: 0.11rem;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
.endurance-p {
|
.endurance-p {
|
||||||
font-size: 0.18rem;
|
font-size: 0.20rem;
|
||||||
color: #cbcfd8;
|
color: #cbcfd8;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding-top: 0.37rem;
|
padding-top: 0.37rem;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
width: 6.8rem;
|
width: 6.8rem;
|
||||||
margin: 1.5rem 0.35rem;
|
margin: 1.5rem 0.35rem;
|
||||||
/* font-size: 0.16rem; */
|
/* font-size: 0.16rem; */
|
||||||
color: #cbcfd8;
|
color: #909399;
|
||||||
/* white-space: normal; */
|
/* white-space: normal; */
|
||||||
/* margin-top: 1.5rem;
|
/* margin-top: 1.5rem;
|
||||||
margin-bottom: 1.5rem; */
|
margin-bottom: 1.5rem; */
|
||||||
@@ -28,23 +28,34 @@
|
|||||||
.footer-texts p {
|
.footer-texts p {
|
||||||
width: 6.8rem;
|
width: 6.8rem;
|
||||||
font-size: 0.16rem;
|
font-size: 0.16rem;
|
||||||
padding-left: 0.05rem;
|
padding-left: 0.1rem;
|
||||||
text-indent: -0.1rem;
|
text-indent: -0.2rem;
|
||||||
line-height: 1.5;
|
/* line-height: 1.5;
|
||||||
margin-bottom: 0.1rem;
|
margin-bottom: 0.1rem; */
|
||||||
font-family: 'HarmonyOS-Light';
|
font-family: 'HarmonyOS-Light';
|
||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.footer-texts-en {
|
.footer-texts-en {
|
||||||
width: 6.8rem;
|
width: 6.8rem;
|
||||||
margin: 0 auto;
|
margin: 1.5rem 0.35rem;
|
||||||
font-size: 0.16rem;
|
/* font-size: 0.16rem; */
|
||||||
color: #cbcfd8;
|
color: #909399;
|
||||||
white-space: normal;
|
/* white-space: normal; */
|
||||||
|
/* margin-top: 1.5rem;
|
||||||
|
margin-bottom: 1.5rem; */
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
.footer-texts-en p {
|
.footer-texts-en p {
|
||||||
text-indent: clamp(-16px, -1vw, -0.22rem);
|
width: 6.8rem;
|
||||||
|
font-size: 0.16rem;
|
||||||
|
padding-left: 0.1rem;
|
||||||
|
text-indent: -0.1rem;
|
||||||
|
/* line-height: 1.5;
|
||||||
|
margin-bottom: 0.1rem; */
|
||||||
font-family: 'HarmonyOS-Light';
|
font-family: 'HarmonyOS-Light';
|
||||||
|
/* letter-spacing: 1px; */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -53,23 +64,33 @@
|
|||||||
}
|
}
|
||||||
.oircoEgapp-foot .m_footer {
|
.oircoEgapp-foot .m_footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
/* flex-direction: row; */
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
margin:0 4%;
|
||||||
|
padding-top: 0 !important;
|
||||||
}
|
}
|
||||||
.oircoEgapp-foot .m_footer .left,
|
/* .oircoEgapp-foot .m_footer .left,
|
||||||
.oircoEgapp-foot .foot-con {
|
.oircoEgapp-foot .foot-con {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
} */
|
||||||
.oircoEgapp-foot .m_footer .right {
|
.oircoEgapp-foot .m_footer .right {
|
||||||
max-width: 55%;
|
flex:1;
|
||||||
|
width: 50% !important;
|
||||||
|
display: flex !important;
|
||||||
|
justify-content: end !important;
|
||||||
|
/* max-width: 55%; */
|
||||||
}
|
}
|
||||||
.oircoEgapp-foot .m_footer .left {
|
.oircoEgapp-foot .m_footer .left {
|
||||||
max-width: 40%;
|
flex:1 !important;
|
||||||
|
/* max-width: 40%;
|
||||||
justify-content: end;
|
justify-content: end;
|
||||||
margin-right: 4%;
|
margin-right: 4%; */
|
||||||
|
width: 50% !important;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
.oircoEgapp-foot .foot-con span {
|
.oircoEgapp-foot .foot-con span {
|
||||||
width: auto;
|
width: auto;
|
||||||
@@ -89,17 +110,18 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
.foot-cate {
|
.foot-cate {
|
||||||
padding: 0 0.16rem;
|
padding: 0.16rem;
|
||||||
}
|
}
|
||||||
.foot-cate h3 {
|
.foot-cate h3 {
|
||||||
font-size: 0.28rem;
|
font-size: 0.28rem;
|
||||||
}
|
}
|
||||||
.foot-cate li {
|
.foot-cate li {
|
||||||
padding: 0.7rem 0;
|
padding: 0.16rem 0;
|
||||||
min-height: 1.8rem;
|
min-height: 276px;
|
||||||
|
|
||||||
}
|
}
|
||||||
.foot-cate li p {
|
.foot-cate li p {
|
||||||
line-height: 0.8rem;
|
line-height: 40px;
|
||||||
}
|
}
|
||||||
.m_footer .right {
|
.m_footer .right {
|
||||||
float: right;
|
float: right;
|
||||||
@@ -107,7 +129,7 @@
|
|||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
.foot-con span {
|
.foot-con span {
|
||||||
font-size:0.28rem;
|
font-size:14px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
@@ -127,10 +149,13 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
.m_footer .left img {
|
.m_footer .left img {
|
||||||
width: 0.55rem;
|
width: 30px;
|
||||||
padding-right: 0.2rem;
|
padding-right:0 !important;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
.oircoEgapp-foot .m_footer .right {
|
/* .oircoEgapp-foot .m_footer .right {
|
||||||
max-width: 50%;
|
max-width: 50%;
|
||||||
|
} */
|
||||||
|
.m_footer .right {
|
||||||
|
padding: 0 !important;
|
||||||
}
|
}
|
||||||
@@ -3,10 +3,7 @@
|
|||||||
}
|
}
|
||||||
.fs-box {
|
.fs-box {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
aspect-ratio: 16/9; /* 2560/1440=16/9,核心比例约束 */
|
aspect-ratio: 16/9;
|
||||||
position: relative;
|
|
||||||
will-change: contents; /* 告诉浏览器该元素即将变化,提前优化 */
|
|
||||||
contain: layout paint; /* 限制重排重绘范围 */
|
|
||||||
}
|
}
|
||||||
.fs-img,
|
.fs-img,
|
||||||
.fs-video {
|
.fs-video {
|
||||||
@@ -17,7 +14,6 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.fs-box-img {
|
.fs-box-img {
|
||||||
display: flex;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
@@ -27,15 +23,19 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 0.11rem;
|
gap: 0.11rem;
|
||||||
|
|
||||||
}
|
}
|
||||||
.fs-h-img img {
|
.fs-h-img img {
|
||||||
width: 3.35rem;
|
width: 3.35rem;
|
||||||
|
aspect-ratio: 335/95;
|
||||||
|
|
||||||
}
|
}
|
||||||
.fs-b-img {
|
.fs-b-img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-top: 0.1rem;
|
margin-top: 0.1rem;
|
||||||
|
aspect-ratio: 681/122;
|
||||||
}
|
}
|
||||||
.fs-b-img img {
|
.fs-b-img img {
|
||||||
width: 6.81rem;
|
width: 6.81rem;
|
||||||
@@ -52,14 +52,14 @@
|
|||||||
}
|
}
|
||||||
.dl-t {
|
.dl-t {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 0.36rem;
|
font-size: 0.48rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
.dl-p {
|
.dl-p {
|
||||||
color: #cbcfd8;
|
color: #cbcfd8;
|
||||||
font-size: 0.18rem;
|
font-size: 0.20rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding-top: 0.37rem;
|
padding-top: 0.37rem;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
}
|
}
|
||||||
.gpu-texts {
|
.gpu-texts {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 0.36rem;
|
font-size: 0.48rem;
|
||||||
margin: 0 0.34rem;
|
margin: 0 0.34rem;
|
||||||
}
|
}
|
||||||
.gpu-texts-t {
|
.gpu-texts-t {
|
||||||
@@ -13,10 +13,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.gpu-texts-p {
|
.gpu-texts-p {
|
||||||
font-size: 0.16rem;
|
font-size: 0.20rem;
|
||||||
color: #cbcfd8;
|
color: #cbcfd8;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
margin-top: 0.32rem;
|
margin-top: 0.37rem;
|
||||||
}
|
}
|
||||||
.gpu-main-img {
|
.gpu-main-img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -18,7 +18,9 @@
|
|||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
.oircoEgapp-head .headtop .headerlogimg {
|
.oircoEgapp-head .headtop .headerlogimg {
|
||||||
width: 2.25rem !important;
|
|
||||||
|
max-width: 140px;
|
||||||
|
min-width: 123px;
|
||||||
height: auto !important;
|
height: auto !important;
|
||||||
display: block;
|
display: block;
|
||||||
/* height: 2.25rem; */
|
/* height: 2.25rem; */
|
||||||
@@ -61,7 +63,7 @@
|
|||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
.cursor_p span {
|
.cursor_p span {
|
||||||
font-size: 0.38rem;
|
font-size: 22px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
@@ -71,7 +73,7 @@
|
|||||||
padding-left: 0.2rem;
|
padding-left: 0.2rem;
|
||||||
}
|
}
|
||||||
.cursor_p span:hover {
|
.cursor_p span:hover {
|
||||||
font-size: 0.38rem;
|
font-size:22px;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: inherit;
|
overflow: inherit;
|
||||||
|
|||||||
@@ -5,9 +5,38 @@
|
|||||||
html {
|
html {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
max-width: 100vw !important;
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #000;
|
background: #000;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
max-width: 100vw !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.f36{
|
||||||
|
font-size: 0.36rem !important;
|
||||||
|
font-family: "HarmonyOS-Medium" !important;
|
||||||
|
/* line-height: 1 !important; */
|
||||||
|
}
|
||||||
|
.f18{
|
||||||
|
font-size: 0.18rem !important;
|
||||||
|
line-height: 1.5 !important;
|
||||||
|
}
|
||||||
|
.lh1 {
|
||||||
|
line-height: 1 !important;
|
||||||
|
}
|
||||||
|
.f28 {
|
||||||
|
font-size: 0.28rem !important;
|
||||||
|
font-family: "HarmonyOS-Medium" !important;
|
||||||
|
}
|
||||||
|
.f48 {
|
||||||
|
font-size: 0.48rem !important;
|
||||||
|
line-height: 1 !important;
|
||||||
|
margin-bottom: 0.6rem !important;
|
||||||
|
font-family: "HarmonyOS-Medium" !important;
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.ips-t {
|
.ips-t {
|
||||||
font-size: 0.36rem;
|
font-size: 0.48rem;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
margin-top: 1.5rem;
|
margin-top: 1.5rem;
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.ips-bg p {
|
.ips-bg p {
|
||||||
font-size: 0.18rem;
|
font-size: 0.20rem;
|
||||||
color: #cbcfd8;
|
color: #cbcfd8;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
margin-left: 0.38rem;
|
margin-left: 0.38rem;
|
||||||
|
|||||||
@@ -9,13 +9,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.m2-bg-t1 {
|
.m2-bg-t1 {
|
||||||
font-size: 0.36rem;
|
font-size: 0.48rem;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
padding-top: 1.3rem;
|
padding-top: 1.3rem;
|
||||||
}
|
}
|
||||||
|
.m2-bg-p {
|
||||||
|
color: #CBCFD8ff;
|
||||||
|
font-size: 0.18rem;
|
||||||
|
padding-top:0.37rem;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
}
|
||||||
.m2-img-box {
|
.m2-img-box {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0.66rem;
|
bottom: 0.66rem;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.memory-t {
|
.memory-t {
|
||||||
font-size: 0.36rem;
|
font-size: 0.48rem;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
}
|
}
|
||||||
.memory-p {
|
.memory-p {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: 0.18rem;
|
font-size: 0.20rem;
|
||||||
color: #cbcfd8;
|
color: #cbcfd8;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
@@ -26,9 +26,14 @@
|
|||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
bottom: -0.74rem;
|
bottom: -0.74rem;
|
||||||
|
width: 6.83rem;
|
||||||
|
}
|
||||||
|
.memory-footer-img p {
|
||||||
|
height:0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.memory-footer-img img {
|
.memory-footer-img img {
|
||||||
width: 6.83rem;
|
width: 6.83rem;
|
||||||
|
|
||||||
display: block;
|
display: block;
|
||||||
|
aspect-ratio: 683/148;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,13 @@
|
|||||||
} */
|
} */
|
||||||
.qb-t {
|
.qb-t {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: 0.36rem;
|
font-size: 0.48rem;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding-top: 1.5rem;
|
padding-top: 1.5rem;
|
||||||
}
|
}
|
||||||
.qb-p {
|
.qb-p {
|
||||||
font-size: 0.18rem;
|
font-size: 0.20rem;
|
||||||
color: #cbcfd8;
|
color: #cbcfd8;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding-top: 0.37rem;
|
padding-top: 0.37rem;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
.rgb-t {
|
.rgb-t {
|
||||||
font-size: 0.36rem;
|
font-size: 0.48rem;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
aspect-ratio: 750/582;
|
aspect-ratio: 750/582;
|
||||||
}
|
}
|
||||||
.rgb-p {
|
.rgb-p {
|
||||||
font-size: 0.18rem;
|
font-size: 0.20rem;
|
||||||
color: #cbcfd8;
|
color: #cbcfd8;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
.swiper-container-texts {
|
.swiper-container-texts {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: 0.91rem;
|
top: 1.2rem;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -39,13 +39,13 @@
|
|||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
.swiper-container-texts-p {
|
.swiper-container-texts-p {
|
||||||
padding-top: 0.68rem;
|
padding-top: 0.54rem;
|
||||||
font-size: 0.16rem;
|
font-size: 0.16rem;
|
||||||
/* text-align: center; */
|
/* text-align: center; */
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
letter-spacing: 1.3px;
|
/* letter-spacing: px; */
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
.swiper-container-texts-p div {
|
.swiper-container-texts-p div {
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding-top: 0.63rem;
|
padding-top: 0.54rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.swiper-container-texts-img a {
|
.swiper-container-texts-img a {
|
||||||
@@ -73,6 +73,7 @@
|
|||||||
max-width: 1.18rem;
|
max-width: 1.18rem;
|
||||||
}
|
}
|
||||||
.swiper-slide-t {
|
.swiper-slide-t {
|
||||||
|
padding-top: 0.3rem;
|
||||||
font-size: 0.2rem;
|
font-size: 0.2rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
/* 改为inline-flex,宽度由子元素决定 */
|
/* 改为inline-flex,宽度由子元素决定 */
|
||||||
position: relative;
|
position: relative;
|
||||||
border-bottom: 1px solid #cbcfd8;
|
border-bottom: 1px solid #909399;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
width: 1.75rem;
|
width: 1.75rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -36,10 +36,10 @@
|
|||||||
.tab-indicator {
|
.tab-indicator {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
height: 2px;
|
height:1px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
transform: translateX(0);
|
transform: translateX(0);
|
||||||
width: 0.87rem;
|
width: auto;
|
||||||
transition: transform 0.3s cubic-bezier(0.25, 0.1, 0.25, 1),
|
transition: transform 0.3s cubic-bezier(0.25, 0.1, 0.25, 1),
|
||||||
width 0.3s cubic-bezier(0.25, 0.1, 0.25, 1);
|
width 0.3s cubic-bezier(0.25, 0.1, 0.25, 1);
|
||||||
will-change: transform, width;
|
will-change: transform, width;
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
.tab-t {
|
.tab-t {
|
||||||
font-size: 0.36rem;
|
font-size: 0.48rem;
|
||||||
color: #cbcfd8;
|
color: #cbcfd8;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|||||||
@@ -12,12 +12,12 @@
|
|||||||
}
|
}
|
||||||
.wifi-t {
|
.wifi-t {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: 0.36rem;
|
font-size: 0.48rem;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
.wifi-p {
|
.wifi-p {
|
||||||
font-size: 0.18rem;
|
font-size: 0.20rem;
|
||||||
color: #cbcfd8;
|
color: #cbcfd8;
|
||||||
padding-top: 0.37rem;
|
padding-top: 0.37rem;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.xn-t {
|
.xn-t {
|
||||||
font-size: 0.36rem;
|
font-size: 0.48rem;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: 1.5rem;
|
margin-top: 1.5rem;
|
||||||
@@ -55,4 +55,10 @@
|
|||||||
/* 确保p标签是块级,且换行正常 */
|
/* 确保p标签是块级,且换行正常 */
|
||||||
display: block;
|
display: block;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
white-space: nowrap;
|
||||||
|
/* 2. 超出元素宽度的内容隐藏 */
|
||||||
|
overflow: hidden;
|
||||||
|
/* 3. 将超出的文本替换为省略号... */
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
/* 可选:给元素设置一个固定宽度(确保省略效果生效) */
|
||||||
}
|
}
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
/* 标注样式:关键修正 - 基于容器绝对定位,百分比参考图片原始比例 */
|
/* 标注样式:关键修正 - 基于容器绝对定位,百分比参考图片原始比例 */
|
||||||
.annotation {
|
.annotation {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
color: #48494d;
|
color: #fff;
|
||||||
font-size: calc(12px + 0.3vw);
|
font-size: calc(12px + 0.3vw);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(calc(10px + 0.5vw));
|
transform: translateY(calc(10px + 0.5vw));
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
width: 0.01rem;
|
width: 0.01rem;
|
||||||
height: 0;
|
height: 0;
|
||||||
bottom: calc(100% + 6px);
|
bottom: calc(100% + 6px);
|
||||||
background-color: #48494d;
|
background-color: #fff;
|
||||||
transition: height 0.8s ease;
|
transition: height 0.8s ease;
|
||||||
transform-origin: bottom center;
|
transform-origin: bottom center;
|
||||||
}
|
}
|
||||||
@@ -92,20 +92,19 @@
|
|||||||
/* 标注显示时,设置线条最终高度 */
|
/* 标注显示时,设置线条最终高度 */
|
||||||
.annotation.anno-show span::before {
|
.annotation.anno-show span::before {
|
||||||
height: 0.57rem;
|
height: 0.57rem;
|
||||||
/* 最终高度(vw单位) */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.zoom-t {
|
.zoom-t {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 0.36rem;
|
font-size: 0.48rem;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
padding-top: 1.5rem;
|
padding-top: 1.5rem;
|
||||||
}
|
}
|
||||||
.zoom-p {
|
.zoom-p {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 0.18rem;
|
font-size: 0.20rem;
|
||||||
color: #cbcfd8;
|
color: #cbcfd8;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0.37rem;
|
top: 0.37rem;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
/* max-height: 900px; */
|
/* max-height: 900px; */
|
||||||
min-height: 300px;
|
min-height: 300px;
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-top:60px;
|
margin-top:46px;
|
||||||
|
|
||||||
}
|
}
|
||||||
/* 轮播项 - 填充容器高度 */
|
/* 轮播项 - 填充容器高度 */
|
||||||
|
|||||||
BIN
public/static/index/mobile/images/header/b.png
Normal file
|
After Width: | Height: | Size: 356 B |
BIN
public/static/index/mobile/images/header/card.png
Normal file
|
After Width: | Height: | Size: 991 B |
BIN
public/static/index/mobile/images/header/lang.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
public/static/index/mobile/images/header/left.png
Normal file
|
After Width: | Height: | Size: 271 B |
BIN
public/static/index/mobile/images/header/nav.png
Normal file
|
After Width: | Height: | Size: 211 B |
BIN
public/static/index/mobile/images/header/s.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
public/static/index/mobile/images/header/search.png
Normal file
|
After Width: | Height: | Size: 1021 B |
BIN
public/static/index/mobile/images/header/u.png
Normal file
|
After Width: | Height: | Size: 490 B |
BIN
public/static/index/mobile/images/header/x.png
Normal file
|
After Width: | Height: | Size: 521 B |
BIN
public/static/index/mobile/images/header/z.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
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 |
1033
public/static/index/pc/css/header.css
Normal file
@@ -17,7 +17,6 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-top: 3.75rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.orico_Page_index .pageMain .bannerswiper .swiper-slide img {
|
.orico_Page_index .pageMain .bannerswiper .swiper-slide img {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 2.5rem 0 1.375rem 0;
|
padding: 2.5rem 0 1.375rem 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-top: 3%;
|
/* margin-top: 3%; */
|
||||||
}
|
}
|
||||||
.orico_Page_prdetail .oriprdetail .product_address {
|
.orico_Page_prdetail .oriprdetail .product_address {
|
||||||
width: 70%;
|
width: 70%;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
}
|
}
|
||||||
.orico_Page_subcategory .pageMain {
|
.orico_Page_subcategory .pageMain {
|
||||||
width: 85%;
|
width: 85%;
|
||||||
padding: 7.5rem 0 10px;
|
padding: 54px 0 10px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -1,406 +1,13 @@
|
|||||||
@charset "UTF-8";
|
.header {
|
||||||
/* 全局文字最小尺寸兜底 */
|
max-width: 100% !important;
|
||||||
.header-PC {
|
width: 100% !important;
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
height: 60px;
|
|
||||||
background: #fff;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
z-index: 100;
|
|
||||||
}
|
}
|
||||||
.header-PC * {
|
.header-nav-outer {
|
||||||
min-font-size: 16px !important; /* 强制最小16px */
|
max-width: 1920px;
|
||||||
box-sizing: border-box;
|
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;
|
overflow-x: hidden;
|
||||||
scroll-behavior: smooth !important;
|
scroll-behavior: smooth !important;
|
||||||
-webkit-overflow-scrolling: touch !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时生效 */
|
/* 当视口宽度大于1920px时生效 */
|
||||||
@media screen and (min-width: 1920px) {
|
@media screen and (min-width: 1920px) {
|
||||||
@@ -39,7 +32,3 @@ body {
|
|||||||
transform 1.2s ease-in-out,
|
transform 1.2s ease-in-out,
|
||||||
visibility 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%;
|
width: 100%;
|
||||||
height: clamp(2.5rem, 5vw, 15rem);
|
height: clamp(2.5rem, 5vw, 15rem);
|
||||||
}
|
}
|
||||||
.header {
|
/* .header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
}
|
} */
|
||||||
.header-img {
|
/* .header-img {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -76,4 +76,4 @@ a {
|
|||||||
padding-top: 0.5rem;
|
padding-top: 0.5rem;
|
||||||
padding-bottom: 0.5rem;
|
padding-bottom: 0.5rem;
|
||||||
|
|
||||||
}
|
} */
|
||||||
|
|||||||
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 |
@@ -244,6 +244,25 @@ class ImageMigrator:
|
|||||||
if self.verbose:
|
if self.verbose:
|
||||||
print("连接已关闭")
|
print("连接已关闭")
|
||||||
|
|
||||||
|
def chown_target(self, owner: str, target_path: str) -> bool:
|
||||||
|
command = f"sudo chown {owner} {target_path}"
|
||||||
|
stdin, stdout, stderr = self.target_client.exec_command(command)
|
||||||
|
# 如果需要输入sudo密码
|
||||||
|
if "sudo" in command and self.target_config.password:
|
||||||
|
stdin.write(self.target_config.password + "\n")
|
||||||
|
stdin.flush()
|
||||||
|
|
||||||
|
if self.verbose:
|
||||||
|
# 获取输出和错误
|
||||||
|
# output = stdout.read().decode()
|
||||||
|
error = stderr.read().decode()
|
||||||
|
exit_code = stdout.channel.recv_exit_status()
|
||||||
|
if exit_code == 0:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print(f"DEBUG chown_target: 修改 {target_path} 的所有者失败: {error}")
|
||||||
|
return False
|
||||||
|
|
||||||
def ensure_target_directory(self, remote_dir: str) -> bool:
|
def ensure_target_directory(self, remote_dir: str) -> bool:
|
||||||
"""确保目标目录存在(递归创建)"""
|
"""确保目标目录存在(递归创建)"""
|
||||||
try:
|
try:
|
||||||
@@ -298,11 +317,17 @@ class ImageMigrator:
|
|||||||
f"DEBUG ensure_target_directory: 创建目录: {current_path}"
|
f"DEBUG ensure_target_directory: 创建目录: {current_path}"
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
|
# 创建目录
|
||||||
self.target_sftp.mkdir(current_path)
|
self.target_sftp.mkdir(current_path)
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
print(
|
print(
|
||||||
f"DEBUG ensure_target_directory: 目录创建成功: {current_path}"
|
f"DEBUG ensure_target_directory: 目录创建成功: {current_path}"
|
||||||
)
|
)
|
||||||
|
# 修改目录所有者
|
||||||
|
if self.chown_target("www", current_path) and self.verbose:
|
||||||
|
print(
|
||||||
|
f"DEBUG ensure_target_directory: {current_path} 所有者修改为 www 成功"
|
||||||
|
)
|
||||||
except Exception as mkdir_e:
|
except Exception as mkdir_e:
|
||||||
# 如果创建失败,可能是权限问题或目录已存在
|
# 如果创建失败,可能是权限问题或目录已存在
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
@@ -519,6 +544,8 @@ class ImageMigrator:
|
|||||||
print(f"DEBUG: 目录stat也失败: {stat_e}")
|
print(f"DEBUG: 目录stat也失败: {stat_e}")
|
||||||
|
|
||||||
self.target_sftp.put(temp_path, target_path)
|
self.target_sftp.put(temp_path, target_path)
|
||||||
|
if self.chown_target("www", target_path) and self.verbose:
|
||||||
|
print(f"DEBUG transfer_file: {target_path} 所有者修改为 www 成功")
|
||||||
|
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
print("DEBUG: 上传完成")
|
print("DEBUG: 上传完成")
|
||||||
@@ -672,13 +699,18 @@ def create_example_config(config_file: str):
|
|||||||
def read_image_paths(image_list_file: str) -> List[str]:
|
def read_image_paths(image_list_file: str) -> List[str]:
|
||||||
"""从文件读取图片路径列表"""
|
"""从文件读取图片路径列表"""
|
||||||
paths = []
|
paths = []
|
||||||
|
not_images = []
|
||||||
try:
|
try:
|
||||||
with open(image_list_file, "r", encoding="utf-8") as f:
|
with open(image_list_file, "r", encoding="utf-8") as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if line and not line.startswith("#"):
|
if line and not line.startswith("#"):
|
||||||
|
if not line.endswith((".png", ".jpeg", ".jpg", ".gif", ".webp")):
|
||||||
|
not_images.append(line)
|
||||||
|
else:
|
||||||
paths.append(line)
|
paths.append(line)
|
||||||
print(f"从文件读取 {len(paths)} 个图片路径")
|
print(f"从文件中读取到 {len(paths)} 个图片路径数据行")
|
||||||
|
print(f"从文件中读取到 {len(not_images)} 个非图片路径数据行")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"读取图片路径文件失败 {image_list_file}: {e}")
|
print(f"读取图片路径文件失败 {image_list_file}: {e}")
|
||||||
return paths
|
return paths
|
||||||
@@ -889,9 +921,14 @@ def main():
|
|||||||
print("请使用 --input 指定文件或直接在命令行提供路径")
|
print("请使用 --input 指定文件或直接在命令行提供路径")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
origin_paths = image_paths
|
||||||
# 去重
|
# 去重
|
||||||
image_paths = list(set(image_paths))
|
image_paths = list(set(image_paths))
|
||||||
|
|
||||||
|
repeats = len(origin_paths) - len(image_paths)
|
||||||
|
if repeats > 0:
|
||||||
|
print(f"从文件中读取到 {repeats} 个重复图片路径数据行")
|
||||||
|
|
||||||
# 创建并运行迁移器
|
# 创建并运行迁移器
|
||||||
migrator = ImageMigrator(
|
migrator = ImageMigrator(
|
||||||
source_config=source_config,
|
source_config=source_config,
|
||||||
|
|||||||