293 Commits

Author SHA1 Message Date
7f765f40ee Merge branch 'dev' 2025-08-08 09:18:33 +08:00
2a9c3332f7 fix: 修复产品目录分类树数据问题 2025-08-08 09:18:13 +08:00
12822ccb6b Merge branch 'dev' 2025-08-07 17:08:12 +08:00
4872574eb0 fix: admapi - 产品目录同步分类更新时bug修复 2025-08-07 17:07:52 +08:00
fa893d6b53 Merge branch 'dev' 2025-08-07 11:38:17 +08:00
f9445b6f49 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-08-07 11:37:49 +08:00
fea5f233a9 style:底部样式修改 2025-08-07 11:36:56 +08:00
e2b65856d2 Merge branch 'dev' 2025-08-07 10:20:10 +08:00
3733ce720d fix: mobile - 底部“联系我们”取值问题 2025-08-07 10:19:45 +08:00
0b82dbbf5f Merge branch 'dev' 2025-08-07 10:18:06 +08:00
74d70fe815 fix: mobile - 底部“联系我们”取值问题 2025-08-07 10:17:24 +08:00
0f2dc12752 Merge branch 'dev' 2025-08-07 10:12:04 +08:00
499e86f52b fix: mobile - 底部“联系我们”取值问题 2025-08-07 10:03:50 +08:00
b24987fbd2 Merge branch 'dev' 2025-08-06 15:35:50 +08:00
19aecea497 perf openapi 图片地址拼接 2025-08-06 15:35:35 +08:00
9060ed8274 Merge branch 'dev' 2025-08-06 12:45:49 +08:00
54d15595ce fix: 后台 - 修改各导出图片等文件地址拼接问题 2025-08-06 11:56:53 +08:00
101c1ae807 fix: 后台 产品导出数据问题 2025-08-06 11:40:44 +08:00
ed7f274c6e fix: 后台 产品导出数据问题 2025-08-06 11:40:09 +08:00
1288ffd51b fix: mobile下视频分类地址错误 2025-07-31 10:55:26 +08:00
62e43375ab fix: 获取文件系统磁盘未判断“//”情况 2025-07-31 09:03:49 +08:00
9f01db7d54 fix: 首页“场景介绍”无法点击 2025-07-31 09:03:48 +08:00
ac06090792 1 2025-07-30 17:08:22 +08:00
6e6e4ac47c 1 2025-07-30 17:07:37 +08:00
8ccc4b0cd5 1 2025-07-30 16:48:54 +08:00
55cd7f2b62 1 2025-07-30 16:47:15 +08:00
43e1ae0422 1 2025-07-30 16:44:32 +08:00
7fcb78dde0 1 2025-07-30 16:40:36 +08:00
6872a13141 Merge branch 'dev' 2025-07-30 16:33:15 +08:00
234658f443 style:产品详情 2025-07-30 16:13:37 +08:00
9f9a384075 .ql-editor 2025-07-30 15:43:42 +08:00
047d7979ff .ql-editor 2025-07-30 15:42:52 +08:00
3544c08005 style:产品详情样式 2025-07-30 15:35:16 +08:00
2ff6d274d9 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-30 15:25:01 +08:00
d31d2359c6 style:详情样式 2025-07-30 15:24:58 +08:00
6f9c89da7b fix: 字段长度限制 2025-07-30 11:13:17 +08:00
9c6659830c fix: 字段长度限制 2025-07-30 11:12:13 +08:00
4c906723df Merge branch 'dev' 2025-07-29 17:52:13 +08:00
d93aa62fbf refactor: 修改后台banner的“链接地址”长度限制为510 2025-07-29 17:51:56 +08:00
f216ba82b4 Merge branch 'dev' 2025-07-29 16:48:16 +08:00
bcd537ef25 Merge branch 'dev' 2025-07-29 16:47:31 +08:00
589a099cdd 1 2025-07-29 14:16:51 +08:00
e13b30bbb2 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-29 14:14:29 +08:00
eb924d42d4 视频宽度限制 2025-07-29 14:14:27 +08:00
9378efe401 文章视频限制 2025-07-29 14:13:34 +08:00
84dd8ea84b fix: migrations/seeds 2025-07-29 14:08:30 +08:00
4c2441b1b6 fix: 产品详情-分类路径bug 2025-07-29 12:00:22 +08:00
db8e0803c1 文章详情样式调整 2025-07-28 14:50:26 +08:00
72b8230d5a Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-28 14:34:41 +08:00
5a8f32e0f8 style:宽度调整 2025-07-28 14:25:01 +08:00
517c2e954b chore: composer.json 2025-07-28 11:13:56 +08:00
eee40e6010 perf: migrations/seeds 2025-07-28 10:33:44 +08:00
a7882da734 perf: 七牛云存储 2025-07-28 10:16:03 +08:00
64ea309b30 refactor: .gitignore 2025-07-25 18:00:14 +08:00
708fee0490 refactor: 七牛云上传 2025-07-25 17:57:31 +08:00
5623c4160e 文章详情样式调整 2025-07-25 13:47:37 +08:00
b660d82c94 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-24 10:00:18 +08:00
8f5d3ed60f 1 2025-07-24 10:00:14 +08:00
0f7e768bc4 feat: 七牛云上传开发 2025-07-23 17:55:34 +08:00
1d84ba373b perf: 自定义语言检测中间件 2025-07-23 17:55:34 +08:00
76e8372059 补充 2025-07-23 17:25:57 +08:00
fdb91466ca .ql-editor 关于tab切换的样式同步 2025-07-23 17:20:11 +08:00
133c58c268 样式修改 2025-07-22 16:48:22 +08:00
c2ad978614 Merge branch 'dev' 2025-07-21 17:32:36 +08:00
865fe2fc44 fix: pc 产品,附件,视频搜索去除首尾空格 2025-07-21 17:31:17 +08:00
0f4c7fec5d fix: pc 视频搜索 2025-07-21 16:55:06 +08:00
1cfae69a27 fix: pc 视频搜索 2025-07-21 16:54:43 +08:00
aa00a24b89 Merge branch 'dev' 2025-07-19 10:48:27 +08:00
0b2c408525 fix: 图片上传命名问题 2025-07-19 10:48:07 +08:00
e6b255b824 Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-18 15:19:02 +08:00
d7e8fe1d6e 1 2025-07-18 15:16:09 +08:00
2a31e22ad8 标题提取空过滤 样式修改 2025-07-18 15:15:13 +08:00
99765a6112 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-18 14:42:10 +08:00
5ae6d5681d Merge branch 'dev' 2025-07-18 14:40:20 +08:00
d2b274b559 fix: nas 文章详情页分类排序问题 2025-07-18 14:40:02 +08:00
3cb4eacff4 Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-18 14:39:33 +08:00
2a4349daab 1 2025-07-18 14:39:30 +08:00
4e8320e871 Merge branch 'dev' 2025-07-18 13:36:33 +08:00
3c8f9773be fix: 横幅分类不可小于0 2025-07-18 13:33:58 +08:00
d04343e9c8 fix: nas帮助中心文件分类未排序 2025-07-18 12:36:20 +08:00
ed24f4fcd0 Achievement 2025-07-18 10:29:26 +08:00
c340155bca nas_help_banner 格式修改 2025-07-18 10:16:58 +08:00
78616faa73 indeximg1 ,indeximg2压缩webp 2025-07-18 09:44:41 +08:00
abd3072ada 编辑器样式修改 2025-07-17 17:45:34 +08:00
17f11559d8 1 2025-07-17 17:04:16 +08:00
7b28b2ef20 1 2025-07-17 17:02:29 +08:00
3790816964 1 2025-07-17 17:01:17 +08:00
03fe4ee0ed Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-17 16:49:08 +08:00
21f600270f 1 2025-07-17 16:49:03 +08:00
43d153c004 Merge branch 'dev' 2025-07-17 16:43:24 +08:00
83468671f1 perf: 优化openapi接口频率限制 2025-07-17 16:43:02 +08:00
f6e52294f0 1 2025-07-17 16:40:23 +08:00
fd64633761 1 2025-07-17 16:35:38 +08:00
19d6944c06 1 2025-07-17 16:31:42 +08:00
7e66a9ecfb 1还原 2025-07-17 16:27:14 +08:00
6925061380 还原 2025-07-17 16:25:01 +08:00
77b988c6b7 1 2025-07-17 16:22:28 +08:00
35723f59a4 1 2025-07-17 16:18:57 +08:00
567798643c 1 2025-07-17 16:11:01 +08:00
912d770c33 ·1 2025-07-17 16:02:31 +08:00
856ce0e7cc 1 2025-07-17 15:40:29 +08:00
7c3c75b22e 1 2025-07-17 15:39:17 +08:00
17ea1ea832 1 2025-07-17 15:32:22 +08:00
693c442060 1 2025-07-17 15:30:43 +08:00
4079574575 格式化 2025-07-17 15:22:56 +08:00
314fb66112 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-17 15:20:55 +08:00
d0b4d74b46 1 2025-07-17 15:19:56 +08:00
44e759564f 1 2025-07-17 15:18:38 +08:00
84bf7662e9 1 2025-07-17 15:13:01 +08:00
0b71bb0254 1 2025-07-17 15:08:52 +08:00
5f5c7d7cf4 1 2025-07-17 12:00:46 +08:00
5e9ace5832 Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-17 11:49:33 +08:00
e00fb9eadb 1 2025-07-17 11:49:31 +08:00
99734ab92a fix: database/seeds 2025-07-17 11:44:00 +08:00
b1fb932aae 1 2025-07-17 11:42:38 +08:00
97b851e8a6 1 2025-07-17 11:30:52 +08:00
e736271536 英文单词不换行 2025-07-17 10:48:37 +08:00
74d1524d8d 1 2025-07-17 10:36:36 +08:00
3bb1909ecd 图片拉伸 2025-07-17 10:24:00 +08:00
2870cbb544 .header-PC #header .nav3 .choesCountry 2025-07-17 10:19:09 +08:00
710d6244d4 fix: database/seeds 2025-07-17 09:58:09 +08:00
b5b27f0555 1 2025-07-17 09:49:05 +08:00
3a2631b99a Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-17 09:45:12 +08:00
6ddb7df8aa .ql-editor>* 2025-07-17 09:45:07 +08:00
09b28a1159 feat: 后台管理 产品列表添加按添加时间倒序 2025-07-16 18:12:11 +08:00
5949e576ed img {display: block;}注释 2025-07-16 17:44:55 +08:00
e04b66295f .narshelpCenterdetail-app .nhlpapp-search 2025-07-16 16:55:44 +08:00
7802c80009 Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-16 16:53:03 +08:00
ce347c514b 移动端nas文章底部操作 2025-07-16 16:53:01 +08:00
3d991abcd5 fix: pc nas专题logo中文下要点击,英文下不要 2025-07-16 15:39:35 +08:00
fa1f6a70db fix: 产品分类排序 2025-07-16 15:32:38 +08:00
fb0a3f9371 fix: pc 产品详情添加型号 2025-07-16 15:24:22 +08:00
fc6079ef32 .ql-container 2025-07-16 14:51:07 +08:00
82a6b171b9 文章样式 2025-07-16 14:45:33 +08:00
4891b07ba2 Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-16 14:14:05 +08:00
9789cec2bf 1 2025-07-16 14:13:13 +08:00
a59bb22c65 1 2025-07-16 14:11:52 +08:00
5b1a281e0f 还原footer 2025-07-16 14:07:43 +08:00
d168e5bb93 1 2025-07-16 14:02:32 +08:00
76685ce103 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-16 13:39:34 +08:00
db38224b14 Merge branch 'dev' 2025-07-16 13:39:07 +08:00
a52fb091a8 fix: 产品目录同步产品默认在售 2025-07-16 13:38:54 +08:00
13b4464473 Merge branch 'dev' 2025-07-16 11:52:05 +08:00
2b8f8c8294 fix: 后台管理 产品参数问题 2025-07-16 11:51:48 +08:00
f18afbe6ca Merge branch 'dev' 2025-07-16 10:31:39 +08:00
12422f06b4 fix: 产品搜索无数据语言问题 2025-07-16 10:31:14 +08:00
6b4612cd09 pc编辑文本样式 2025-07-16 10:19:42 +08:00
70ed7d917f 添加编辑器样式 2025-07-16 10:17:58 +08:00
3c994973c1 1 2025-07-16 10:12:28 +08:00
4672f76264 1 2025-07-16 10:10:36 +08:00
98ec9cdc49 1 2025-07-16 10:04:54 +08:00
0ad2a41ab3 1 2025-07-16 10:02:47 +08:00
1553a1f2ed 1 2025-07-16 09:56:05 +08:00
9bdb290760 1 2025-07-16 09:54:28 +08:00
b2014b104f Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-16 09:51:31 +08:00
791380e53c 1 2025-07-16 09:51:26 +08:00
1c3aa90c3a Merge branch 'dev' 2025-07-15 15:00:51 +08:00
425140d4ac fix: openapi token有效期配置 2025-07-15 15:00:38 +08:00
e32f75234a fix: openapi token有效期配置 2025-07-15 14:59:25 +08:00
103fc4dd24 Merge branch 'dev' 2025-07-15 14:49:47 +08:00
6eac1e5d7b perf: openapi token有效期配置 2025-07-15 14:49:03 +08:00
c171073174 Merge branch 'dev' 2025-07-15 14:45:54 +08:00
5c0e96df27 perf: openapi token有效期配置 2025-07-15 14:45:16 +08:00
4a91a4f673 Merge branch 'dev' 2025-07-15 14:21:30 +08:00
9e22cde6ba perf: openapi client授权过期 2025-07-15 14:21:16 +08:00
7ee92398cf fix: admapi 角色菜单权力model 2025-07-15 14:21:04 +08:00
f2c09736de perf: openapi client授权过期 2025-07-15 14:20:36 +08:00
7957b56f29 fix: admapi 角色菜单权力model 2025-07-15 13:50:50 +08:00
dcfa73bdc1 Merge branch 'dev' 2025-07-15 10:48:30 +08:00
3b4f747cb1 perf: .gitignore 2025-07-15 10:46:17 +08:00
401683be6b fix: mobile subcategory.html 2025-07-15 09:54:58 +08:00
a8e80dfa26 fix: mobile subcategory.html 2025-07-15 09:54:38 +08:00
ca38a3a7b6 smallImgDown相对位置修改 2025-07-15 09:36:55 +08:00
6b1ec81bd0 bsImg 高度自适应 2025-07-15 09:32:07 +08:00
01952774b1 Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-15 09:30:05 +08:00
ee35e2ce4b .bttj 修改 2025-07-15 09:30:02 +08:00
d20e703bfe fix: mobile subcategory.html 2025-07-15 09:25:25 +08:00
2ac0708ac1 perf: mobile 产品分类与搜索页改为缩略图 2025-07-15 09:22:21 +08:00
f292e68b5b Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-15 09:19:14 +08:00
fe1a07f56a 顶部底部自适应 2025-07-15 09:18:11 +08:00
be7d256007 fix: mobile view问题 2025-07-15 09:16:01 +08:00
d3c8ffaeb1 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-14 17:18:35 +08:00
14f0cc0607 1 2025-07-14 17:06:45 +08:00
ae52ae7de5 去掉新品的标题和更多 2025-07-14 17:05:44 +08:00
510f89b84c sceneitem1 2025-07-14 16:41:58 +08:00
0aa4e82095 1 2025-07-14 16:39:59 +08:00
14e611d02e 1 2025-07-14 16:34:11 +08:00
8c1ff8da6e 1 2025-07-14 16:26:35 +08:00
bb37146be8 1 2025-07-14 16:25:49 +08:00
5fbdbda62d 1 2025-07-14 16:24:22 +08:00
3688c0efd4 1 2025-07-14 16:23:25 +08:00
1de9769edb 1 2025-07-14 16:09:53 +08:00
e0dd787bf3 1 2025-07-14 16:09:02 +08:00
a9681677a9 1 2025-07-14 16:08:13 +08:00
761a033b46 1 2025-07-14 16:07:06 +08:00
554a87d0cf Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-14 16:02:37 +08:00
26c60ae751 样式修改6 2025-07-14 16:02:35 +08:00
902f40e28c fix: 底部备案信息 2025-07-14 15:52:13 +08:00
d8744d2070 fix: 底部备案信息 2025-07-14 15:51:22 +08:00
f23ab69761 fix: 底部备案信息 2025-07-14 15:50:13 +08:00
470a3e1687 pref: 数据同步 2025-07-14 15:50:13 +08:00
932f2b8705 fix: 底部备案信息 2025-07-14 15:49:50 +08:00
b14a75c3a2 1 2025-07-14 15:46:47 +08:00
f0b02ba83b 样式修改4 2025-07-14 15:46:18 +08:00
a36633a559 样式修改2 2025-07-14 15:35:57 +08:00
7daaf12908 Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-14 15:13:12 +08:00
4111e05957 样式修改 2025-07-14 15:13:09 +08:00
ce665b9ea4 pref: 数据同步 2025-07-14 14:30:59 +08:00
082ed00d74 Merge branch 'dev' 2025-07-14 14:06:16 +08:00
6c3f6247f8 fix: 顶部搜索产品图片显示缩略图 2025-07-14 14:06:04 +08:00
881ce98a72 Merge branch 'dev' 2025-07-14 13:44:06 +08:00
51ceeff0d7 fix: 视频描述字段长度校验 2025-07-14 13:43:52 +08:00
c0bd15cbd9 perf: 数据同步 2025-07-14 13:42:50 +08:00
e26b0094ee Merge branch 'dev' 2025-07-14 11:47:51 +08:00
afc70e1b68 fix: 产品详情购买链接排序 2025-07-14 11:47:41 +08:00
a96e3780fb fix: pc 顶部“店铺”新标签打开 2025-07-14 11:27:59 +08:00
7c781f4eaa Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-14 11:27:38 +08:00
c938438838 style 2025-07-14 11:27:34 +08:00
10024e40c2 fix: pc 顶部“店铺”新标签打开 2025-07-14 11:25:02 +08:00
612fb44215 fix: pc 底部导航新标签页打开无效 2025-07-14 11:04:34 +08:00
b9ed1a7328 perf: 数据同步 2025-07-14 11:04:34 +08:00
9c71a45f8b fix: pc 底部导航新标签页打开无效 2025-07-14 11:01:14 +08:00
a751f3aa97 perf: 数据同步 2025-07-14 11:00:43 +08:00
jsasg
bb8f42774f Merge branch 'dev' 2025-07-11 22:39:16 +08:00
jsasg
d902abe57d fix: 图片上传 2025-07-11 22:34:32 +08:00
873d873b4e fix: 底部 2025-07-11 20:15:38 +08:00
3dd4aa231e fix: 文章验证 2025-07-11 20:15:20 +08:00
87d943fc63 Merge branch 'dev' 2025-07-11 18:07:42 +08:00
d6f5c19616 fix: 底部 2025-07-11 18:07:25 +08:00
2fc9e7650a fix: 文章验证 2025-07-11 18:07:25 +08:00
0cc4ea2936 style:样式修改3 2025-07-11 17:15:44 +08:00
1ce367999e style:样式调整 2025-07-11 16:52:09 +08:00
f15f27e17a style:样式修改 2025-07-11 16:32:58 +08:00
31d4e641f8 fix:如果底部没有内容就不要显示li这个标签 2025-07-11 16:22:34 +08:00
9b211f804f style:样式修改 2025-07-11 16:13:49 +08:00
c3e1f08908 ljm master分支 2025-07-11 15:57:27 +08:00
76bd01e458 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-11 15:44:59 +08:00
7dbe56da33 fix:pc导航修改 2025-07-11 15:44:56 +08:00
f5bc3980dd fix: mobile下没有jquery 2025-07-11 15:22:01 +08:00
b37d795818 fix: 上传 2025-07-11 11:47:05 +08:00
4b64eb35aa fix: 导航未过滤已禁用 2025-07-11 10:32:05 +08:00
ee161ee7f6 add:本地添加jQuery和swiper文件,防止cdn失效 2025-07-10 17:38:17 +08:00
b0d241c22e perf: mysql递归查询兼容处理 2025-07-10 17:30:01 +08:00
9ac90d3fef perf: 修改analytics 2025-07-09 17:30:02 +08:00
17ce193e43 pref: think文件 2025-07-09 16:34:27 +08:00
8c64c35afd perf: redis env配置 2025-07-09 16:15:58 +08:00
8d4163ed88 perf: env 2025-07-09 13:58:59 +08:00
91a38dee28 fix: 同步产品目录产品分类及产品 2025-07-09 11:32:59 +08:00
ca6296a276 · 2025-07-09 10:25:02 +08:00
b1fd726226 样式修改 2025-07-09 10:21:48 +08:00
d924716d6a Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-08 10:54:46 +08:00
a383d56291 style:样式修改 2025-07-08 10:54:43 +08:00
c1a443efba fix: 后台图片上传路径bug 2025-07-07 18:01:12 +08:00
e77b72381b fix: 后台图片上传路径bug 2025-07-07 17:50:52 +08:00
91883e132f pref: 图片大小调整 2025-07-07 16:39:02 +08:00
91b2474981 pref: 图片大小调整 2025-07-07 16:22:51 +08:00
a19e8f6e34 1 2025-07-07 15:27:22 +08:00
895f2040aa 1 2025-07-07 15:23:30 +08:00
b6174e1055 style:单词换行 2025-07-07 15:21:44 +08:00
040237447a Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-07 15:15:32 +08:00
7df2727fed style:品类换行 2025-07-07 15:15:30 +08:00
0fb0c35d1d feat: migration/seed 2025-07-05 18:01:22 +08:00
db05632769 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-05 17:35:30 +08:00
f1af59b09a style:样式调整 2025-07-05 17:35:27 +08:00
861ecabcac feat: 后台 图片上传新增webp格式转换处理 2025-07-05 15:19:46 +08:00
3117a5b047 fix: openapi 文章详情取消author,source字段输出 2025-07-05 14:41:32 +08:00
d90acae078 fix: openapi 文章分类取消short_name, desc字段输出 2025-07-05 14:02:17 +08:00
26b1f21e86 fix: openapi 取消产品分类icon,desc字段输出 2025-07-05 14:01:51 +08:00
555996d72e fix: openapi取消产品详情sku->sort字段输出 2025-07-05 13:47:57 +08:00
9f9941f45d fix: openapi 产品接口取消desc输出 2025-07-05 11:49:55 +08:00
fd1db5134a 返回顶部 只要页面过长就显示 2025-07-05 11:12:52 +08:00
ff83880144 id修改为类,间距调整 2025-07-05 10:20:59 +08:00
21c295b26a Merge branch 'cssupdate' into dev 2025-07-05 09:53:30 +08:00
673f208792 产品详情切换问题修改 2025-07-05 09:51:50 +08:00
7a82081af2 doc: 注释 2025-07-05 09:18:24 +08:00
68e56eead0 fix: openapi 产品详情不输出links->platform问题 2025-07-04 17:42:29 +08:00
d8ac9530d8 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-04 17:17:41 +08:00
63c3d47f3d style:样式修改 2025-07-04 17:17:38 +08:00
8116315a6d fix: pc nas专题页 导航选中状态 2025-07-04 16:40:03 +08:00
b892a1346d fix: openapi 产品列表 2025-07-04 10:34:23 +08:00
4942af1fae fix: mobile 产品详情页图册中视频放第一个sku下最后一个 2025-07-03 14:01:34 +08:00
b0935db1b8 fix: pc 产品详情页图册中视频放第一个sku下最后一个 2025-07-03 13:56:57 +08:00
3d83c95a72 fix: mobile nas专题顶部导航 2025-07-02 15:30:25 +08:00
96bd1fc4c2 fix: pc 文章提交提示语言未区分语言 2025-07-02 15:06:28 +08:00
45218f85af pref: pc 产品详情表单提交 2025-07-02 14:44:35 +08:00
27f23cd321 fix: pc 产品搜索结果分布 2025-07-02 14:19:53 +08:00
aba102d63c perf: 关键词高亮 2025-07-02 10:59:01 +08:00
326ea8ae7e Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-02 10:57:38 +08:00
bc87c88b25 swiper uc兼容 2025-07-02 10:57:35 +08:00
c08900c694 feat: 从产品目录同步产品相关数据 2025-07-02 10:44:55 +08:00
401658981c fix: pc nas专题页 联系我们第一项无js效果 2025-07-02 10:44:55 +08:00
b6115b7a16 style:样式问题修改8 2025-07-02 10:44:29 +08:00
e9d40dcd82 style:样式问题修改7 2025-07-02 10:44:29 +08:00
121 changed files with 5167 additions and 1140 deletions

5
.env
View File

@@ -1,5 +0,0 @@
[JWT]
TTL=3600
REFRESH_TTL=20160
SECRET=b43e6276644ed60e65c50d1b324ba10b

View File

@@ -1,32 +0,0 @@
APP_DEBUG = true
DB_TYPE = mysql
DB_HOST = localhost
DB_NAME = orico-official-website
DB_USER = orico-ow
DB_PASS = 14Xi17NIK8V2qAXE8oMataHEsaR8lE
DB_PORT = 3306
DB_CHARSET = utf8mb4
DB_PREFIX = ow_
DEFAULT_LANG = zh-cn
# 前端代理服务器ip影响使用代理访问情况下的客户端ip获取
PROXY_SERVER_IP[] = 120.79.27.160
[JWT]
TTL=3600
REFRESH_TTL=20160
SECRET=b43e6276644ed60e65c50d1b324ba10b
# 后台不需要登录的接口
[ADMIN_AUTH]
WHITE_LIST[] = v1/user/login
WHITE_LIST[] = v1/user/captcha
# 不需记录日志的接口
[ADMIN_API]
IGNORE_LOGGING_LIST[] = v1/OperateLog/index
MAX_IMAGE_SIZE = 5mb # 图片上传最大限制
MAX_VIDEO_SIZE = 150mb # 视频上传最大限制
MAX_ATTACHMENT_SIZE = 100mb # 附件上传最大限制

View File

@@ -1,55 +0,0 @@
APP_DEBUG = true
DB_TYPE = mysql
DB_HOST = 127.0.0.1
DB_NAME = orico-official-website
DB_USER = orico-official-website
DB_PASS = 14Xi17NIK8V2qAXE8oMataHEsaR8lE
DB_PORT = 3306
DB_CHARSET = utf8mb4
DB_PREFIX = ow_
DEFAULT_LANG = zh-cn
# 前端代理服务器ip影响使用代理访问情况下的客户端ip获取
PROXY_SERVER_IP[] = 120.79.27.160
[JWT]
TTL=3600
REFRESH_TTL=20160
SECRET=b43e6276644ed60e65c50d1b324ba10b
# 后台不需要登录的接口
[ADMIN_AUTH]
WHITE_LIST[] = v1/user/login
WHITE_LIST[] = v1/user/captcha
# 不需记录日志的接口
[ADMIN_API]
IGNORE_LOGGING_LIST[] = v1/OperateLog/index
MAX_IMAGE_SIZE = 5mb; # 图片上传最大限制
MAX_VIDEO_SIZE = 150mb; # 视频上传最大限制
MAX_ATTACHMENT_SIZE = 100mb; # 附件上传最大限制
# 开放API
[OPENAPI]
RESOURCE_IMAGES_DOMAIN = http://local.orico.com; # 图片资源服务器地址
RESOURCE_VIDEOS_DOMAIN = http://local.orico.com; # 视频资源服务器地址
# 视图模板规则配置
[VIEW_TPL]
# 视图目录
# query 规则URL参数 mtpl=1 表示移动端访问
# 例如http://xxxx.com?mtpl=1
# domain 规则:根据特定域名,判断是否移动端访问
# 例如http://mobile.orico.cn
RULE = query
# query 规则参数名
RULE_QUERY_NAME = mtpl
# query 规则参数值
RULE_QUERY_VALUE = 1
# domain 规则协议
RULE_DOMAIN_SCHEME[] = http
RULE_DOMAIN_SCHEME[] = https
# domain 规则域名
RULE_DOMAIN_HOST = mobile.orico.cn

View File

@@ -1,11 +1,96 @@
APP_DEBUG = true
DB_TYPE = mysql
DB_HOST = 127.0.0.1
DB_NAME = test
DB_USER = username
DB_PASS = password
DB_HOST = localhost
DB_NAME = orico-official-website
DB_USER = orico-ow
DB_PASS = 14Xi17NIK8V2qAXE8oMataHEsaR8lE
DB_PORT = 3306
DB_CHARSET = utf8
DB_CHARSET = utf8mb4
DB_PREFIX = ow_
DB_VERSION = 8
DEFAULT_LANG = zh-cn
# 前端代理服务器ip影响使用代理访问情况下的客户端ip获取
PROXY_SERVER_IP[] = 120.79.27.160
# redis 配置
REDIS_HOST = 127.0.0.1
REDIS_PORT = 6379
REDIS_PASSWORD = ''
REDIS_PREFIX = ow:
[JWT]
TTL=3600
REFRESH_TTL=20160
SECRET=b43e6276644ed60e65c50d1b324ba10b
# 七牛云存储配置
[QINIU_CLOUD]
BUCKET = orico-official-website
BASE_URL = //ow.static.f2b211.com
ACCESS_KEY = dOsTum4a5qvhPTBbZRPX0pIOU7PZWRX7htKjztms
SECRET_KEY = KFxsGbnErkALFfeGdMa8QWTdodJbamMX0iznLe-q
# 后台不需要登录的接口
[ADMIN_AUTH]
WHITE_LIST[] = v1/user/login
WHITE_LIST[] = v1/user/captcha
WHITE_LIST[] = receive_sync/category
WHITE_LIST[] = receive_sync/product
# 不需记录日志的接口
[ADMIN_API]
IGNORE_LOGGING_LIST[] = v1/OperateLog/index
MAX_IMAGE_SIZE = 5mb; # 图片上传最大限制
MAX_VIDEO_SIZE = 150mb; # 视频上传最大限制
MAX_ATTACHMENT_SIZE = 100mb; # 附件上传最大限制
# 开放API
[OPENAPI]
ACCESS_TOKEN_LIFETIME = 3600; # 访问令牌有效期
REFRESH_TOKEN_LIFETIME = 1209600; # 刷新令牌有效期
RESOURCE_IMAGES_DOMAIN = http://local.orico.com; # 图片资源服务器地址
RESOURCE_VIDEOS_DOMAIN = http://local.orico.com; # 视频资源服务器地址
# 七牛云存储配置
[QINUI]
BUCKET = orico
BASE_URL = http://local.orico.com
ACCESS_KEY = 1234567890
SECRET_KEY = 1234567890
# 前台视图模板规则配置
[INDEX_VIEW_TPL]
# 视图目录
# query 规则URL参数 mtpl=1 表示移动端访问
# 例如http://xxxx.com?mtpl=1
# domain 规则:根据特定域名,判断是否移动端访问
# 例如http://mobile.orico.cn
RULE = query
# query 规则参数名
RULE_QUERY_NAME = mtpl
# query 规则参数值
RULE_QUERY_VALUE = 1
# domain 规则协议
RULE_DOMAIN_SCHEME[] = http
RULE_DOMAIN_SCHEME[] = https
# domain 规则域名
RULE_DOMAIN_HOST = mobile.orico.cn
# 前台语言检测配置
[INDEX_LANG_DETECT]
# 是否启用域名检测方式来检测语言
DOMAIN_DETECT = true
# 域名规则
# 格式:域名=语言
# 例如mobile.orico.cn=zh-cn
DOMAIN_RULE[] = orico.cn=zh-cn
DOMAIN_RULE[] = orico.com.cn=zh-cn
DOMAIN_RULE[] = www.orico.cn=zh-cn
DOMAIN_RULE[] = www.orico.com.cn=zh-cn
DOMAIN_RULE[] = ow.f2b211.com=zh-cn
DOMAIN_RULE[] = orico.cc=en-us
DOMAIN_RULE[] = www.orico.cc=en-us
DOMAIN_RULE[] = ow.us.f2b211.com=en-us

6
.gitignore vendored
View File

@@ -3,7 +3,13 @@ composer.phar
composer.lock
.DS_Store
Thumbs.db
.env
.env.dev
.env.local
.env.prod
public/dist
public/opendoc
/.idea
/.vscode
/vendor

View File

@@ -99,18 +99,20 @@ class ReceiveProductSync
}
$category = ProductCategoryModel::language($lang_id)->tcoId($tco_category['id'])->find();
$tco_parent = ProductTcoCategoryModel::language($lang_id)->tcoId($tco_category['tco_pid'])->find();
if (!empty($tco_parent)) {
$parent = ProductCategoryModel::language($lang_id)->tcoId($tco_parent['id'])->find();
if ($parent->isEmpty()) {
throw new \Exception('产品分类父级不存在');
if (!empty($category)) {
$tco_parent = ProductTcoCategoryModel::language($lang_id)->tcoId($tco_category['tco_pid'])->find();
if (!empty($tco_parent)) {
$parent = ProductCategoryModel::language($lang_id)->tcoId($tco_parent['id'])->find();
if ($parent->isEmpty()) {
throw new \Exception('产品分类父级不存在');
}
$category['pid'] = $parent['id'];
$category['path'] = $parent['path'] . $parent['pid'];
$category['level'] = $parent['level'] + 1;
}
if (!$category->save()) {
throw new \Exception('产品分类更新失败');
}
$category['pid'] = $parent['id'];
$category['path'] = $parent['path'] . $parent['pid'];
$category['level'] = $parent['level'] + 1;
}
if (!$category->save($category)) {
throw new \Exception('产品分类更新失败');
}
}
@@ -162,7 +164,7 @@ class ReceiveProductSync
}
try {
$product_tco_category = ProductTcoCategoryModel::language($lang_id)->erpCade($data['category_erp_code'])->find();
$product_tco_category = ProductTcoCategoryModel::language($lang_id)->erpCode($data['category_erp_code'])->find();
if (empty($product_tco_category)) {
throw new \Exception('官网未找到产品目录同步分类');
}
@@ -183,13 +185,13 @@ class ReceiveProductSync
'desc' => '',
'video_img' => '',
'video_url' => '',
'is_sale' => 0,
'is_sale' => 1,
'is_new' => 0,
'is_hot' => 0,
'is_show' => Operate_Of_ReceiveSync::Disable == $data['operate'] ? 0 : 1,
'is_show' => 0,
'sort' => 0,
'detail' => '',
'status' => 1,
'status' => Operate_Of_ReceiveSync::Disable == $data['operate'] ? -1 : 1,
'seo_title' => '',
'seo_keywords' => '',
'seo_desc' => '',
@@ -203,7 +205,7 @@ class ReceiveProductSync
$product->spu = $data['spu'];
$product->name = $data['name'];
$product->category_id = $product_category['id'];
$product->is_show = Operate_Of_ReceiveSync::Disable == $data['operate'] ? 0 : 1;
$product->status = Operate_Of_ReceiveSync::Disable == $data['operate'] ? -1 : 1;
if (!$product->save()) {
throw new \Exception('产品更新失败');
}

View File

@@ -228,7 +228,7 @@ class Article
private function getExportArticleData()
{
$server = request()->server();
$image_host = $server['REQUEST_SCHEME'] . "://" . $server['SERVER_NAME'] . config('filesystem.disks.public.url') . '/';
$image_host = $server['REQUEST_SCHEME'] . "://" . $server['SERVER_NAME'] . '/';
$param = request()->param(['title', 'category_id', 'release_time']);
$data = ArticleModel::field([
'*',
@@ -253,7 +253,7 @@ class Article
])
->bindAttr('category', ['category_name' => 'name'])
->each(function ($item) use($image_host) {
$item->image = !empty($item->image) ? $image_host . $item->image : '';
$item->image = !empty($item->image) ? url_join($image_host, $item->image) : '';
return $item;
});

View File

@@ -262,11 +262,9 @@ class BannerItem
// 获取导出数据
private function getBannerExportData()
{
$param = request()->param([
'title',
'banner_id',
'created_at'
]);
$server = request()->server();
$image_host = $server['REQUEST_SCHEME'] . "://" . $server['SERVER_NAME'] . '/';
$param = request()->param(['title', 'banner_id', 'created_at']);
return SysBannerItemModel::alias('item')
->field([
'item.id',
@@ -311,7 +309,13 @@ class BannerItem
}
})
->order(['item.sort' => 'asc', 'item.id' => 'desc'])
->select();
->select()
->each(function($item) use($image_host) {
$item->image = !empty($item->image) ? url_join($image_host, $item->image) : '';
$item->extra_image = !empty($item->extra_image) ? url_join($image_host, $item->extra_image) : '';
$item->video = !empty($item->video) ? url_join($image_host, $item->video) : '';
return $item;
});
}
// 删除

View File

@@ -57,7 +57,7 @@ class Product
])
->categoryNullable($param['category_id']??null)
->isShowNullable(isset($param['is_show']) ? (bool)$param['is_show'] : null)
->order(['sort' => 'asc', 'id' => 'desc'])
->order(['sort' => 'asc', 'created_at' => 'desc', 'id' => 'desc'])
->paginate([
'list_rows' => $param['size'],
'page' => $param['page'],
@@ -171,7 +171,7 @@ class Product
// 更新产品参数
if ($put['params'] != "") {
ProductParamsModel::productId($id)->delete();
if (preg_match_all('/(\S+):(.[^\s]+)/', $put['params'], $match_result)) {
if (preg_match_all('/(.+):(.+)/', $put['params'], $match_result)) {
$params = [];
for ($i = 0; $i < count($match_result[0]); $i++) {
$params[] = [
@@ -346,7 +346,7 @@ class Product
private function getExportProductData()
{
$server = request()->server();
$image_host = $server['REQUEST_SCHEME'] . "://" . $server['SERVER_NAME'] . config('filesystem.disks.public.url') . '/';
$image_host = $server['REQUEST_SCHEME'] . "://" . $server['SERVER_NAME'] . '/';
$param = request()->param([
'name',
'spu',
@@ -360,10 +360,10 @@ class Product
'spu',
'name',
'short_name',
'CONCAT("' . $image_host . '", `cover_image`)' => 'cover_image',
'cover_image',
'desc',
'CONCAT("' . $image_host . '", `video_img`)' => 'video_img',
'CONCAT("' . $image_host . '", `video_url`)' => 'video_url',
'video_img',
'video_url',
'CASE WHEN is_new = 1 THEN "是" ELSE "否" END' => 'is_new',
'CASE WHEN is_hot = 1 THEN "是" ELSE "否" END' => 'is_hot',
'CASE WHEN is_sale = 1 THEN "是" ELSE "否" END' => 'is_sale',
@@ -390,7 +390,18 @@ class Product
->order(['id' => 'asc'])
->select()
->bindAttr('category', ['category_name' => 'name'])
->hidden(['category_id', 'category']);
->hidden(['category_id', 'category'])
->each(function($item) use($image_host) {
if (!empty($item["cover_image"])) {
$item["cover_image"] = url_join($image_host, $item["cover_image"]);
}
if (!empty($item["video_img"])) {
$item["video_img"] = url_join($image_host, $item["video_img"]);
}
if (!empty($item["video_url"])) {
$item["video_url"] = url_join($image_host, $item["video_url"]);
}
});
if (!$products->isEmpty()) {
// 产品参数

View File

@@ -16,8 +16,9 @@ class ProductTcoCategory
$param = request()->param(['name']);
$categorys = ProductTcoCategoryModel::field([
'tco_id' => 'id',
'tco_pid' => 'pid',
'id',
'tco_id',
'tco_pid',
'name',
])
->withSearch(['name'], [
@@ -25,10 +26,10 @@ class ProductTcoCategory
])
->language(request()->lang_id)
->enabled()
->order(['id' => 'asc'])
->order(['tco_id' => 'asc'])
->select()
->toArray();
return success('获取成功', array_to_tree($categorys, 0, 'pid', false));
return success('获取成功', array_to_tree($categorys, 0, 'tco_pid', false, true, 'tco_id'));
}
}

View File

@@ -9,6 +9,7 @@ use app\admin\model\v1\SysAttachmentUploadRecordModel;
use Intervention\Image\ImageManager;
use Intervention\Image\Typography\FontFactory;
use think\facade\Filesystem;
use filesystem\Qiniu;
/**
* 文件上传控制器
@@ -45,17 +46,39 @@ class Upload
// 获取图片上传配置
list(
'filename_keep' => $filename_keep,
'filemd5_unique' => $filemd5_unique
'filemd5_unique' => $filemd5_unique,
'filetype_to' => $filetype_to,
) = $this->getUploadOptions('upload_image');
// 获取文件大小
$file_size = $file->getSize();
// 获取文件mime类型
$mime_type = $file->getOriginalMime();
// 是否需要根据文件MD5值检查文件是否已存在
$image_model = $filemd5_unique ? SysImageUploadRecordModel::md5($filemd5)->find() : null;
if (is_null($image_model)) {
// 检查是否需要保留原文件名生成器
$name_rule = fn() => $filename_keep ? $this->filenameGenerator($file) : null;
$filename = Filesystem::disk('image')->putFile($param['module'], $file, $name_rule());
// 处理图片
$image_manager = ImageManager::imagick();
$image = $image_manager->read('.' . $storage . '/' . $filename);
$image_manager = ImageManager::gd();
if ($filetype_to == 'original') {
$filename = Filesystem::disk('image')->putFile($param['module'], $file, $name_rule());
$image = $image_manager->read('.' . $storage . '/' . $filename);
}
else if ($filetype_to == 'webp') {
$image = $image_manager->read($file->getRealPath());
// 转换为webp格式
$webp = $image->toWebp(75);
$root = config('filesystem.disks.image.root');
$filename = $param['module'] . '/' . ($name_rule() ? $name_rule()() : date('Ymd') . '/' . md5((string)time() . random_str(8))) . '.webp';
$webp->save($this->checkPath($root . '/' . $filename));
// 获取webp文件大小
$file_size = $webp->size();
// 获取webp文件mime类型
$mime_type = $webp->mimetype();
}
// 水印
list(
@@ -126,15 +149,15 @@ class Upload
$idx = strrpos($filename, '.');
$thumb_filename = mb_substr($filename, 0, $idx) . '_thumb.' . mb_substr($filename, $idx + 1);
$image->save('.' . $storage . '/' . $thumb_filename);
// 保存图片
$image_model = new SysImageUploadRecordModel();
$image_model->language_id = request()->lang_id;
$image_model->module = $param['module'];
$image_model->image_path = $filename;
$image_model->image_thumb = $thumb_filename;
$image_model->file_size = $file->getSize();
$image_model->file_type = $file->getOriginalMime();
$image_model->image_path = $storage . '/' . $filename;
$image_model->image_thumb = $storage . '/' . $thumb_filename;
$image_model->file_size = $file_size;
$image_model->file_type = $mime_type;
$image_model->file_md5 = $filemd5;
$image_model->file_sha1 = $filesha1;
if (!$image_model->save()) {
@@ -143,8 +166,8 @@ class Upload
}
return success('操作成功', [
'path' => $storage . '/' . $image_model->image_path,
'thumb_path' => $storage . '/' . $image_model->image_thumb,
'path' => $image_model->image_path,
'thumb_path' => $image_model->image_thumb,
'filemd5' => $image_model->file_md5,
'filesha1' => $image_model->file_sha1
]);
@@ -154,6 +177,30 @@ class Upload
return error('上传失败');
}
/**
* 检查路径
*
* @param string $path
* @return string
*/
private function checkPath($path): string
{
$ok = true;
$filename = basename($path);
$dirname = dirname($path);
if (!is_dir($dirname)) {
$ok = @mkdir($dirname, 0755, true);
}
else if (!is_writable($dirname)) {
$ok = @chmod($dirname,0755);
}
if ($ok) {
return $dirname . '/' . $filename;
}
throw new \Exception("上传目标目录不可用");
}
/**
* 文件名生成回调
*
@@ -175,10 +222,12 @@ class Upload
$config_model = new \app\admin\controller\v1\SiteConfig;
$config = $config_model->getByGroupUniqueLabel('upload');
$options = data_get($config, $module, []);
throw_if(empty($options), '上传配置错误');
return [
'filename_keep' => (int)data_get($options, 'filename_keep.value', 0) == 1,
'filemd5_unique' => (int)data_get($options, 'filemd5_unique.value', 0) == 1,
'filetype_to' => data_get($options, 'filetype_to.value', 'original'),
'save_to' => data_get($options, 'save_to.value', 'local'),
];
}
/**
@@ -220,7 +269,7 @@ class Upload
];
}
/**
* 计算文水印偏移量
* 计算文水印偏移量
*
* @param string $position
* @param integer $offset_x
@@ -298,20 +347,35 @@ class Upload
// 获取视频上传配置
list(
'filename_keep' => $filename_keep,
'filemd5_unique' => $filemd5_unique
'filemd5_unique' => $filemd5_unique,
'save_to' => $save_to,
) = $this->getUploadOptions('upload_video');
// 是否需要根据文件MD5值检查文件是否已存在
$video = $filemd5_unique ? SysVideoUploadRecordModel::md5($filemd5)->find() : null;
if (is_null($video)) {
// 保存位置配置 key
$disk = 'video';
// 检查是否需要保留原文件名
$name_rule = fn() => $filename_keep ? $this->filenameGenerator($file) : null;
$filename = Filesystem::disk('video')->putFile($param['module'], $file, $name_rule());
// 保存到七牛云
if ($save_to == 'qiniu_cloud') {
$disk = 'video_qiniu';
$storage = config('filesystem.disks.video_qiniu.path_prefix');
}
$filename = Filesystem::disk($disk)->putFile($param['module'], $file, $name_rule());
// 组装视频路径
$video_path = $storage . '/' . $filename;
if ($save_to == 'qiniu_cloud') {
$video_path = Filesystem::disk($disk)->url($filename);
}
// 保存视频
$video = new SysVideoUploadRecordModel();
$video->language_id = request()->lang_id;
$video->module = $param['module'];
$video->video_path = $filename;
$video->video_path = $video_path;
$video->file_size = $file->getSize();
$video->file_type = $file->getOriginalMime();
$video->file_md5 = $filemd5;
@@ -322,7 +386,7 @@ class Upload
}
return success('上传成功', [
'path' => $storage . '/' . $video->video_path,
'path' => $video->video_path,
'file_md5' => $video->file_md5,
'file_sha1' => $video->file_sha1
]);
@@ -352,25 +416,42 @@ class Upload
return error($validate->getError());
}
$storage = config('filesystem.disks.public.url');
$filemd5 = $file->md5();
$filesha1 = $file->sha1();
// 获取附件上传配置
list(
'filename_keep' => $filename_keep,
'filemd5_unique' => $filemd5_unique
'filemd5_unique' => $filemd5_unique,
'save_to' => $save_to
) = $this->getUploadOptions('upload_attachment');
// 是否需要根据文件MD5值检查文件是否已存在
$attachment = $filemd5_unique ? SysAttachmentUploadRecordModel::md5($filemd5)->find() : null;
if (is_null($attachment)) {
// 保存位置配置 key
$disk = 'public';
// 检查是否需要保留原文件名
$name_rule = fn() => $filename_keep ? $this->filenameGenerator($file) : null;
$filename = Filesystem::disk('public')->putFile('attachments', $file, $name_rule());
// 保存视频
// 保存到七牛云
if ($save_to == 'qiniu_cloud') {
$disk = 'public_qiniu';
$storage = config('filesystem.disks.public_qiniu.path_prefix');
}
$filename = Filesystem::disk($disk)->putFile('attachments', $file, $name_rule());
// 组装附件路径
$attachment_path = $storage . '/' . $filename;
if ($save_to == 'qiniu_cloud') {
$attachment_path = Filesystem::disk($disk)->url($filename);
}
// 保存附件
$attachment = new SysAttachmentUploadRecordModel();
$attachment->language_id = request()->lang_id;
$attachment->attachment_path = $filename;
$attachment->attachment_path = $attachment_path;
$attachment->file_size = $file->getSize();
$attachment->file_type = $file->getOriginalMime();
$attachment->file_md5 = $filemd5;
@@ -380,9 +461,8 @@ class Upload
}
}
$storage = config('filesystem.disks.public.url');
return success('上传成功', [
'path' => $storage . '/' . $attachment->attachment_path,
'path' => $attachment->attachment_path,
'file_md5' => $attachment->file_md5,
'file_sha1' => $attachment->file_sha1
]);

View File

@@ -209,9 +209,6 @@ class Video
]);
$domain = request()->domain();
$image_path = Config::get('filesystem.disks.image.url');
$video_path = Config::get('filesystem.disks.video.url');
return VideoModel::withoutField([
'language_id',
'updated_at',
@@ -230,13 +227,9 @@ class Video
->select()
->bindAttr('category', ['category_name' => 'name'])
->hidden(['category_id', 'category'])
->each(function ($item) use($domain, $image_path, $video_path) {
if (!empty($item->image)) {
$item->image = $domain . $image_path . '/' . $item->image;
}
if (!empty($item->video)) {
$item->video = $domain . $video_path . '/' . $item->video;
}
->each(function ($item) use($domain) {
$item->image = !empty($item->image) ? url_join($domain, $item->image) : '';
$item->video = !empty($item->video) ? url_join($domain, $item->video) : '';
$item->recommend = $item->recommend == 1 ? '是' : '否';
$item->status = $item->status == 1 ? '启用' : '禁用';
return $item;

View File

@@ -616,6 +616,12 @@ Route::group('v1', function () {
});
})->prefix('v1.');
// 接收产品目录同步数据
Route::group('receive_sync', function () {
Route::post('category', 'ReceiveProductSync/category');
Route::post('product', 'ReceiveProductSync/product');
});
Route::miss(function() {
return '404 Not Found!';
});

View File

@@ -64,19 +64,36 @@ class ArticleCategoryValidate extends Validate
if ($value == 0) {
return true;
}
$children = [];
$table_name = (new ArticleCategoryModel)->getTable();
$children = Db::query(
preg_replace(
'/\s+/u',
' ',
"WITH RECURSIVE article_tree_by AS (
SELECT a.id, a.pid FROM $table_name a WHERE a.id = {$data['id']}
UNION ALL
SELECT k.id, k.pid FROM $table_name k INNER JOIN article_tree_by t ON t.id = k.pid
if (env('DB_VERSION', '5') == '8') {
$children = Db::query(
preg_replace(
'/\s+/u',
' ',
"WITH RECURSIVE article_tree_by AS (
SELECT a.id, a.pid FROM $table_name a WHERE a.id = {$data['id']}
UNION ALL
SELECT k.id, k.pid FROM $table_name k INNER JOIN article_tree_by t ON t.id = k.pid
)
SELECT id FROM article_tree_by WHERE id <> {$data['id']};"
)
SELECT id FROM article_tree_by WHERE id <> {$data['id']};"
)
);
);
} else {
$children = \think\facade\Db::query("
SELECT t2.id
FROM (
SELECT
@r AS _id, (SELECT @r := GROUP_CONCAT(id) FROM $table_name WHERE FIND_IN_SET(pid, _id)) AS parent_id
FROM
(SELECT @r := {$data['id']}) vars, $table_name h
WHERE @r <> 0) t1
JOIN $table_name t2
ON FIND_IN_SET(t2.pid, t1._id)
ORDER BY t2.id;
");
}
if (!empty($children) && in_array($data['pid'], array_column($children, 'id'))) {
return false;
}

View File

@@ -23,9 +23,9 @@ class ArticleValidate extends Validate
'sort' => 'integer',
'recommend' => 'require|in:0,1',
'release_time' => 'dateFormat:Y-m-d H:i:s',
'seo_title' => 'max:255',
'seo_keywords' => 'max:255',
'seo_desc' => 'max:255'
'seo_title' => 'max:512',
'seo_keywords' => 'max:512',
'seo_desc' => 'max:1024'
];
/**
@@ -48,8 +48,8 @@ class ArticleValidate extends Validate
'recommend.require' => '推荐状态不能为空',
'recommend.in' => '推荐状态的值必须是0或1',
'release_time.dateFormat' => '发布时间格式不正确',
'seo_title.max' => 'SEO标题长度不能超过255个字符',
'seo_keywords.max' => 'SEO关键字长度不能超过255个字符',
'seo_desc.max' => 'SEO描述长度不能超过255个字符'
'seo_title.max' => 'SEO标题长度不能超过512个字符',
'seo_keywords.max' => 'SEO关键字长度不能超过512个字符',
'seo_desc.max' => 'SEO描述长度不能超过1024个字符'
];
}

View File

@@ -49,19 +49,36 @@ class AttachmentCategoryValidate extends Validate
if ($value == 0) {
return true;
}
$children = [];
$table_name = (new AttachmentCategoryModel)->getTable();
$children = Db::query(
preg_replace(
'/\s+/u',
' ',
"WITH RECURSIVE attachment_tree_by AS (
SELECT a.id, a.pid FROM $table_name a WHERE a.id = {$data['id']}
UNION ALL
SELECT k.id, k.pid FROM $table_name k INNER JOIN attachment_tree_by t ON t.id = k.pid
if (env('DB_VERSION', '5') == '8') {
$children = Db::query(
preg_replace(
'/\s+/u',
' ',
"WITH RECURSIVE attachment_tree_by AS (
SELECT a.id, a.pid FROM $table_name a WHERE a.id = {$data['id']}
UNION ALL
SELECT k.id, k.pid FROM $table_name k INNER JOIN attachment_tree_by t ON t.id = k.pid
)
SELECT id FROM attachment_tree_by WHERE id <> {$data['id']};"
)
SELECT id FROM attachment_tree_by WHERE id <> {$data['id']};"
)
);
);
} else {
$children = \think\facade\Db::query("
SELECT t2.id
FROM (
SELECT
@r AS _id, (SELECT @r := GROUP_CONCAT(id) FROM $table_name WHERE FIND_IN_SET(pid, _id)) AS parent_id
FROM
(SELECT @r := {$data['id']}) vars, $table_name h
WHERE @r <> 0) t1
JOIN $table_name t2
ON FIND_IN_SET(t2.pid, t1._id)
ORDER BY t2.id;
");
}
if (!empty($children) && in_array($data['pid'], array_column($children, 'id'))) {
return false;
}

View File

@@ -61,19 +61,36 @@ class NavigationItemValidate extends Validate
if ($value == 0) {
return true;
}
$children = [];
$table_name = (new SysNavigationItemModel)->getTable();
$children = Db::query(
preg_replace(
'/\s+/u',
' ',
"WITH RECURSIVE tree_by AS (
SELECT a.id, a.pid FROM $table_name a WHERE a.id = {$data['id']}
UNION ALL
SELECT k.id, k.pid FROM $table_name k INNER JOIN tree_by t ON t.id = k.pid
if (env('DB_VERSION', '5') == '8') {
$children = Db::query(
preg_replace(
'/\s+/u',
' ',
"WITH RECURSIVE tree_by AS (
SELECT a.id, a.pid FROM $table_name a WHERE a.id = {$data['id']}
UNION ALL
SELECT k.id, k.pid FROM $table_name k INNER JOIN tree_by t ON t.id = k.pid
)
SELECT id FROM tree_by WHERE id <> {$data['id']};"
)
SELECT id FROM tree_by WHERE id <> {$data['id']};"
)
);
);
} else {
$children = \think\facade\Db::query("
SELECT t2.id
FROM (
SELECT
@r AS _id, (SELECT @r := GROUP_CONCAT(id) FROM $table_name WHERE FIND_IN_SET(pid, _id)) AS parent_id
FROM
(SELECT @r := {$data['id']}) vars, $table_name h
WHERE @r <> 0) t1
JOIN $table_name t2
ON FIND_IN_SET(t2.pid, t1._id)
ORDER BY t2.id;
");
}
if (!empty($children) && in_array($data['pid'], array_column($children, 'id'))) {
return false;
}

View File

@@ -15,7 +15,7 @@ class SysBannerItemValidate extends Validate
*/
protected $rule = [
'id' => 'require|integer',
'banner_id' => 'require|integer',
'banner_id' => 'require|integer|gt:0',
'title' => 'require|max:256',
'title_txt_color' => 'max:7',
'desc' => 'max:1024',
@@ -25,7 +25,7 @@ class SysBannerItemValidate extends Validate
'extra_image' => 'max:255',
'video' => 'max:255',
'link_to' => 'requireIf:type,image|max:64|in:article,article_category,product,product_category,system_page,custom',
'link' => 'max:255',
'link' => 'max:510',
'sort' => 'integer',
'status' => 'in:-1,1'
];
@@ -41,6 +41,7 @@ class SysBannerItemValidate extends Validate
'id.integer' => 'ID必须是整数',
'banner_id.require' => '横幅项分类不能为空',
'banner_id.integer' => '横幅项分类必须是整数',
'banner_id.gt' => '该横幅分类不可选',
'title.require' => '名称不能为空',
'title.max' => '名称最多不能超过256个字符',
'title_txt_color.max' => '名称字体颜色最多不能超过7个字符',
@@ -53,7 +54,7 @@ class SysBannerItemValidate extends Validate
'link_to.requireIf' => '链接类型不能为空',
'link_to.max' => '链接类型最多不能超过64个字符',
'link_to.in' => '链接类型必须是article,article_category,product,product_category,system_page,custom中之一',
'link.max' => '链接最多不能超过255个字符',
'link.max' => '链接最多不能超过512个字符',
'sort.integer' => '排序值必须是整数',
'status.in' => '状态必须是-1或1'
];

View File

@@ -74,19 +74,36 @@ class SysMenuValidate extends Validate
if ($value == 0) {
return true;
}
$children = [];
$table_name = (new SysMenuModel)->getTable();
$children = Db::query(
preg_replace(
'/\s+/u',
' ',
"WITH RECURSIVE menu_tree_by AS (
SELECT a.id, a.pid FROM $table_name a WHERE a.id = {$data['id']}
UNION ALL
SELECT k.id, k.pid FROM $table_name k INNER JOIN menu_tree_by t ON t.id = k.pid
if (env('DB_VERSION', '5') == '8') {
$children = Db::query(
preg_replace(
'/\s+/u',
' ',
"WITH RECURSIVE menu_tree_by AS (
SELECT a.id, a.pid FROM $table_name a WHERE a.id = {$data['id']}
UNION ALL
SELECT k.id, k.pid FROM $table_name k INNER JOIN menu_tree_by t ON t.id = k.pid
)
SELECT id FROM menu_tree_by WHERE id <> {$data['id']};"
)
SELECT id FROM menu_tree_by WHERE id <> {$data['id']};"
)
);
);
} else {
$children = \think\facade\Db::query("
SELECT t2.id
FROM (
SELECT
@r AS _id, (SELECT @r := GROUP_CONCAT(id) FROM $table_name WHERE FIND_IN_SET(pid, _id)) AS parent_id
FROM
(SELECT @r := {$data['id']}) vars, $table_name h
WHERE @r <> 0) t1
JOIN $table_name t2
ON FIND_IN_SET(t2.pid, t1._id)
ORDER BY t2.id;
");
}
if (!empty($children) && in_array($data['pid'], array_column($children, 'id'))) {
return false;
}

View File

@@ -17,8 +17,8 @@ class VideoValidate extends Validate
'id' => 'require|integer',
'language_id' => 'require|integer',
'category_id' => 'require|integer',
'name' => 'require|max:64',
'desc' => 'max:255',
'name' => 'require|max:128',
'desc' => 'max:512',
'image' => 'max:125',
'video' => 'max:125',
'link' => 'url|max:125',
@@ -43,8 +43,8 @@ class VideoValidate extends Validate
'category_id.require' => '分类不能为空',
'category_id.integer' => '分类参数类型错误',
'name.require' => '名称不能为空',
'name.max' => '名称不能超过64个字符',
'desc.max' => '描述不能超过255个字符',
'name.max' => '名称不能超过128个字符',
'desc.max' => '描述不能超过512个字符',
'image.max' => '图片不能超过125个字符',
'video.max' => '视频不能超过125个字符',
'link.url' => '链接格式错误',

View File

@@ -61,6 +61,9 @@ class DataMigration extends Command
// 迁移文章
// $this->migrateArticle([
// 16 => 7,
// 31 => 9,
// 32 => 8,
// 68 => 10,
// 69 => 11,
// 70 => 12,
@@ -290,14 +293,15 @@ class DataMigration extends Command
$old_db = Db::connect('old');
$success_map = [];
$success_arr = include_once(runtime_path() . 'product_success.php');
$success_arr = []; // include_once(runtime_path() . 'product_success.php');
foreach ($success_arr as $so) {
$success_map['p_' . $so['cod_product_id']] = $so;
}
$arr = include_once(runtime_path() . 'product_ids.php');
$products = $old_db->name('product')
->where('country_code', 'in', ['ZH', 'US'])
->where('id', '>', 15789)
->where('id', 'in', array_unique(array_column($arr, 'cod_product_id')))
->order(['id' => 'asc'])
->cursor();
@@ -374,7 +378,16 @@ class DataMigration extends Command
'deleted_at' => $v['stat'] == -1 ? date('Y-m-d H:i:s') : null,
];
// 保存产品数据
$id = Db::name('product')->insertGetId($item);
$prod = Db::name('product')
->where('language_id', '=', $item['language_id'])
->where('spu', '=', $item['spu'])
->find();
if (!empty($prod)) {
$id = $prod['id'];
Db::name('product')->where('id', '=', $prod['id'])->update($item);
} else {
$id = Db::name('product')->insertGetId($item);
}
// 保存产品参数数据
if (!empty($v['product_view'])) {
@@ -387,7 +400,21 @@ class DataMigration extends Command
'value' => $p['desc_desc']
];
}
Db::name('product_params')->insertAll($prarms);
$old_params = Db::name('product_params')
->where('product_id', '=', $id)
->select();
if ($old_params->isEmpty()) {
Db::name('product_params')->insertAll($prarms);
} else {
foreach ($old_params as $op) {
Db::name('product_params')
->where('product_id', '=', $id)
->where('name', '=', $op['name'])
->update([
'value' => $op['value']
]);
}
}
}
// 保存sku数据
@@ -444,7 +471,7 @@ class DataMigration extends Command
if ($k != 'sort') {
$attr_value = $at;
if (in_array($k, ['颜色', 'Color'])) {
if ($k == 'Color') $k = '颜色';
// if ($k == 'Color') $k = '颜色';
$attr_value = '/static/common/images/colors/' . $at . '.png';
}
$images[$pkey]['color'] = $at;
@@ -468,7 +495,7 @@ class DataMigration extends Command
}
}
$attr_arr = [
'attr_id' => $attrs_map[$v['country_code']]['颜色'],
'attr_id' => $attrs_map[$v['country_code']][$v['country_code'] == 'ZH' ? '颜色' : 'Color'],
'attr_value' => $attr_value,
];
if (
@@ -514,7 +541,7 @@ class DataMigration extends Command
$skus[] = [
'main_image' => $ti['image_url'],
'attrs' => [[
'attr_id' => $attrs_map[$v['country_code']]['颜色'],
'attr_id' => $attrs_map[$v['country_code']][$v['country_code'] == 'ZH' ? '颜色' : 'Color'],
'attr_value' => $ti['image_color'],
]],
'pkey' => $tpkey
@@ -575,6 +602,7 @@ class DataMigration extends Command
}
foreach ($skus as $sku) {
Db::name('product_sku')->where('product_id', '=', $sku['product_id'])->delete();
$sku_id = Db::name('product_sku')->insertGetId([
'product_id' => $sku['product_id'],
'sku' => $sku['sku']??'',
@@ -584,6 +612,7 @@ class DataMigration extends Command
if (!empty($sku['attrs'])) {
foreach ($sku['attrs'] as $attr) {
if (!empty($sku_id)) {
Db::name('product_sku_attr')->where('sku_id', '=', $sku_id)->delete();
Db::name('product_sku_attr')->insert([
'sku_id' => $sku_id,
'attr_id' => $attr['attr_id'],
@@ -601,7 +630,7 @@ class DataMigration extends Command
sprintf('["ow_product_id" => %d, "cod_product_id" => %d]'.PHP_EOL, $id, $v['id']),
FILE_APPEND
);
$this->println(sprintf('迁移产品ID%s => %s 【耗时:%s】', $v['id'], 0, round(microtime(true) - $start, 2) . 's'));
$this->println(sprintf('迁移产品ID%s => %s 【耗时:%s】', $v['id'], $id, round(microtime(true) - $start, 2) . 's'));
} catch (\Throwable $th) {
Db::rollback();
file_put_contents(
@@ -694,9 +723,12 @@ class DataMigration extends Command
throw new \Exception('请确认分类ID');
}
// 1634
$article = Db::connect('old')
->name('article')
->where('country_code', 'in', ['ZH', 'US'])
->where('cid', 'in', array_keys($category_map))
->where('id', '=', 351)
->order(['id' => 'asc'])
->cursor();
@@ -745,7 +777,16 @@ class DataMigration extends Command
'release_time' => date('Y-m-d H:i:s', $v['createtime']),
'deleted_at' => $v['stat'] == -1 ? date('Y-m-d H:i:s') : null
];
$id = Db::name('article')->insertGetId($item);
$ret = Db::name('article')
->where('language_id', '=', $item['language_id'])
->where('title', '=', $item['title'])
->find();
if (empty($ret)) {
$id = Db::name('article')->insertGetId($item);
} else {
$id = $ret['id'];
Db::name('article')->where('id', '=', $ret['id'])->update($item);
}
$this->println(sprintf('迁移文章ID%s => %s', $v['id'], $id));
}
@@ -779,7 +820,15 @@ class DataMigration extends Command
'recommend' => $val['is_home'],
'sort' => $val['sort'] == 9999 ? 0 : $val['sort']
];
Db::name('faq')->insert($item);
$ret = Db::name('faq')
->where('language_id', '=', $item['language_id'])
->where('question', '=', $item['question'])
->find();
if (empty($ret)) {
Db::name('faq')->insert($item);
} else {
Db::name('faq')->where('id', '=', $ret['id'])->update($item);
}
}
}
@@ -881,7 +930,8 @@ class DataMigration extends Command
{
$videos = Db::connect('old')
->name('video')
->where('id', '>', 844)
// ->where('id', '>', 844)
->where('cid', 'in', array_keys($category_map))
->where('country_code', 'in', ['ZH', 'US'])
->order(['id' => 'asc'])
->cursor();
@@ -921,7 +971,16 @@ class DataMigration extends Command
'seo_desc' => $val['seo_description'],
'deleted_at' => $val['stat'] == -1 ? date('Y-m-d H:i:s') : null
];
Db::name('video')->insert($item);
$ret = Db::name('video')
->where('language_id', '=', $item['language_id'])
->where('name', '=', $item['name'])
->find();
if (empty($ret)) {
Db::name('video')->insert($item);
} else {
Db::name('video')->where('id', '=', $ret['id'])->update($item);
}
$this->println('迁移视频ID' . $val['id']);
}
}
@@ -929,7 +988,7 @@ class DataMigration extends Command
class UploadMannager
{
const UPLOAD_BASE_API = 'http://dev.ow.f2b211.com';
const UPLOAD_BASE_API = 'http://ow.f2b211.com';
const DOWNLOAD_BASE_API = 'http://www.orico.com.cn';
const DOWNLOAD_TEMP_PATH = '/var/www/html/orico-official-website/public/migrate_temp_images';
private $username = 'admin';
@@ -942,7 +1001,7 @@ class UploadMannager
{
// 登录获取token
$this->token = $this->getAuthorization();
$this->maps = include_once(runtime_path() . 'fiber_product_image_mapping.php');
$this->maps = []; // include_once(runtime_path() . 'fiber_product_image_mapping.php');
}
// 下载图片
@@ -1062,6 +1121,7 @@ class UploadMannager
print($http_code . PHP_EOL);
}
file_put_contents(runtime_path() . 'upload.txt', $response . PHP_EOL, FILE_APPEND);
$ret = json_decode($response, true);
if (empty($ret)) {
throw new \Exception($response);

View File

@@ -80,7 +80,7 @@ if (!function_exists('array_to_tree')) {
* @param bool $keep_pid 是否保留pid
* @return array
*/
function array_to_tree(array $data, int $pid, string $with = 'pid', int|bool $level = 1, bool $keep_pid = true)
function array_to_tree(array $data, int $pid, string $with = 'pid', int|bool $level = 1, bool $keep_pid = true, $with_ref = 'id')
{
$ret = [];
foreach ($data as $item) {
@@ -93,7 +93,7 @@ if (!function_exists('array_to_tree')) {
if ($keep_pid === false) {
unset($item[$with]);
}
$children = array_to_tree($data, $item['id'], $with, $lv, $keep_pid);
$children = array_to_tree($data, $item[$with_ref], $with, $lv, $keep_pid, $with_ref);
if ($children) {
$item['children'] = $children;
}
@@ -144,4 +144,83 @@ if (!function_exists('thumb')) {
return mb_substr($url, 0, $idx, 'utf-8') . '_thumb' . mb_substr($url, $idx, $len - $idx, 'utf-8');
}
}
if (!function_exists('get_filesystem_url')) {
/**
* 获取文件系统的访问 URL
* @param string $url 文件地址
* @param string $disk 磁盘配置 key
* @return string
*/
function get_filesystem_url(string $url, string $disk): string
{
if (\think\helper\Str::startsWith($url, ['http://', 'https://', '//'])) {
return $url;
}
if (empty($disk)) {
return '';
}
return \think\facade\Filesystem::disk($disk)->url($url);
}
}
if (!function_exists('url_filesystem_detect')) {
/**
* 检测文件地址并根据情况转换为文件系统地址
* @param string $url 文件地址
* @return string
*/
function url_filesystem_detect(string $url): string
{
$idx = strrpos($url, '.');
if ($idx === false) {
return $url;
}
$disks = [
'public_qiniu' => '_' . base64_encode('public_qiniu'),
'video_qiniu' => '_' . base64_encode('video_qiniu')
];
foreach ($disks as $disk => $marker) {
if (str_ends_with(mb_substr($url, 0, $idx), $marker)) {
return get_filesystem_url($url, $disk);
}
}
return $url;
}
}
if (!function_exists('url_join')) {
/**
* 合并URL
* @param string $url 基础URL
* @param string $path 路径
* @param bool $remove_slash 是否移除首尾的斜杠
* @return string
*/
function url_join(string $url, string $path, bool $remove_slash = true): string
{
if (empty($url)) {
return $path;
}
if (empty($path)) {
return $url;
}
if (\think\helper\Str::startsWith($path, ['http://', 'https://', '//'])) {
return $path;
}
if ($remove_slash) {
if (str_ends_with($url, '/') && str_starts_with($path, '/')) {
return $url . substr($path, 1);
}
if (!str_ends_with($url, '/') && !str_starts_with($path, '/')) {
return $url . '/' . $path;
}
}
return $url . $path;
}
}

View File

@@ -18,6 +18,6 @@ class SysRoleAuthorityBaseModel extends Model
protected $schema = [
'role_id' => 'int',
'menu_id' => 'int',
'permission' => 'int',
'permission' => 'string',
];
}

View File

@@ -194,14 +194,14 @@ if (!function_exists('get_platform')) {
} else {
// 在非移动端环境,根据配置规则判断是否要显示移动端
$view_cfg = $view_cfg = [
'rule' => env('VIEW_TPL.RULE', 'query'),
'rule' => env('INDEX_VIEW_TPL.RULE', 'query'),
'query' => [
'name' => env('VIEW_TPL.RULE_QUERY_NAME', 'mtpl'),
'value' => env('VIEW_TPL.RULE_QUERY_VALUE', '1'),
'name' => env('INDEX_VIEW_TPL.RULE_QUERY_NAME', 'mtpl'),
'value' => env('INDEX_VIEW_TPL.RULE_QUERY_VALUE', '1'),
],
'domain' => [
'scheme' => env('VIEW_TPL.RULE_DOMAIN_SCHEME', ['http']),
'host' => env('VIEW_TPL.RULE_DOMAIN_HOST'),
'scheme' => env('INDEX_VIEW_TPL.RULE_DOMAIN_SCHEME', ['http']),
'host' => env('INDEX_VIEW_TPL.RULE_DOMAIN_HOST'),
],
];
if ($view_cfg['rule'] == 'query') {
@@ -226,18 +226,18 @@ if (!function_exists('get_platform')) {
if (!function_exists('highlight_keywords')) {
/**
* 高亮关键词
* @param string $item
* @param string $keywords
* @param array $class
* @param string $text // 要处理的文本
* @param string $keyword // 关键词
* @param string|callable $repalce // 替换函数或字符串
* @return string
*/
function highlight_keywords(string $text, string $keywords, array $class=[]): string
function highlight_keywords(string $text, string $keyword, string|callable $replace): string
{
return preg_replace_callback('/' . preg_quote($keywords, '/') . '+/i', function($match) use($text, $class) {
if (empty($match)) {
return $text;
}
return '<strong class="' . implode(' ', $class) . '">' . $match[0] . '</strong>';
return preg_replace_callback('/' . preg_quote($keyword, '/') . '+/i', function($match) use($text, $replace) {
if (empty($match)) return $text;
if (is_string($replace)) return '<strong>' . $match[0] . '</strong>';
if (is_callable($replace)) return $replace($match[0]);
return $match[0];
}, $text);
}
}

View File

@@ -170,9 +170,9 @@ class Article extends Common
]);
$ret = ArticleLeaveMessageModel::create($data);
if ($ret->isEmpty()) {
return error(lang('留言提交失败'));
return error(lang('信息提交失败'));
}
return success(lang('留言提交成功'));
return success(lang('信息已成功提交!'));
}
}

View File

@@ -21,9 +21,9 @@ class Attachment extends Common
{
$param = request()->param([
'id',
'keyword',
'page/d' => 1,
'size/d' => 12,
'keyword' => '',
'page/d' => 1,
'size/d' => 12,
]);
// 获取附件分类
@@ -48,9 +48,9 @@ class Attachment extends Common
'support_platform',
'attach',
])
->withSearch(['name'], ['name' => $param['keyword']??null])
->withSearch(['name'], ['name' => !empty($param['keyword']) ? trim($param['keyword']) : null])
->language($this->lang_id)
->category($param['id']??null)
->category(!empty($param['id']) ? $param['id'] : $categorys[0]['id']??null)
->order(['sort' => 'asc', 'id' => 'desc'])
->paginate([
'list_rows' => $param['size'],
@@ -59,6 +59,16 @@ class Attachment extends Common
'id' => $param['id']??null
]
]);
if (!$attachements->isEmpty()) {
$attachements->each(function($item) {
if (is_array($item->attach)) {
$item->attach = array_map(function($v) {
$v['file_path'] = url_filesystem_detect($v['file_path']);
return $v;
}, $item->attach);
}
});
}
View::assign('attachements', $attachements);
View::assign('page', $attachements->render());
@@ -109,9 +119,9 @@ class Attachment extends Common
'video',
'link'
])
->withSearch(['name'], ['name' => $param['keyword']??null])
->withSearch(['name'], ['name' => !empty($param['keyword']) ? trim($param['keyword']) : null])
->language($this->lang_id)
->category($param['id']??$video_categorys[0]['id']??null)
->category(!empty($param['id']) ? $param['id'] : $video_categorys[0]['id']??null)
->order(['sort' => 'asc', 'id' => 'desc'])
->paginate([
'list_rows' => $param['size'],
@@ -122,6 +132,9 @@ class Attachment extends Common
]);
if (!$videos->isEmpty()) {
$videos->each(function($item) {
$item->video = url_filesystem_detect($item->video);
});
$videos->setCollection($videos->getCollection()->chunk(2));
}
View::assign('videos', $videos);

View File

@@ -106,6 +106,7 @@ abstract class Common extends BaseController
'language_id' => $language,
'status' => 1
])
->where('status', '=', 1)
->order(['sort' => 'asc', 'id' => 'asc'])
->select();
if ($nav->isEmpty()) {

View File

@@ -104,7 +104,7 @@ class Product extends Common
->onSale(true)
->onShelves(true)
->append(['p' => $list[0]['id']])
->order(['sort' => 'asc', 'id' => 'desc'])
->order(['sort' => 'asc', 'created_at' => 'desc', 'id' => 'desc'])
->limit(5)
->buildSql();
$query = \think\facade\Db::table("($sql) as a");
@@ -126,7 +126,7 @@ class Product extends Common
->enabled(true)
->onSale(true)
->onShelves(true)
->order(['sort' => 'asc', 'id' => 'desc'])
->order(['sort' => 'asc', 'created_at' => 'desc', 'id' => 'desc'])
->limit(5);
});
}
@@ -192,7 +192,7 @@ class Product extends Common
->enabled(true)
->onSale(true)
->onShelves(true)
->order(['sort' => 'asc', 'id' => 'desc'])
->order(['sort' => 'asc', 'created_at' => 'desc', 'id' => 'desc'])
->select();
if (!$products->isEmpty()) {
// 获取sku信息
@@ -277,7 +277,7 @@ class Product extends Common
'page/d' => 1,
'size/d' => 10
]);
$keywords = $param['keywords'] ?? '';
$keywords = !empty($param['keywords']) ? trim($param['keywords']) : '';
// 关键词搜索
$products = ProductModel::field([
@@ -299,9 +299,10 @@ class Product extends Common
'query' => request()->param()
])
->each(function ($item) use($keywords) {
$item['spu'] = highlight_keywords($item['spu'], $keywords, ['redpoint']);
$item['name'] = highlight_keywords($item['name'], $keywords, ['redpoint']);
$item['short_name'] = highlight_keywords($item['short_name'], $keywords, ['redpoint']);
$replace = fn($txt) => '<strong class="redpoint">' . $txt . '</strong>';
$item['spu'] = highlight_keywords($item['spu'], $keywords, $replace);
$item['name'] = highlight_keywords($item['name'], $keywords, $replace);
$item['short_name'] = highlight_keywords($item['short_name'], $keywords, $replace);
return $item;
});
View::assign('products', $products);
@@ -395,8 +396,11 @@ class Product extends Common
->order(['sort' => 'asc', 'id' => 'desc'])
->select()
->hidden(['platform'])
->bindAttr('platform', ['platform_name' => 'platform'])
->bindAttr('platform', ['platform_name' => 'platform', 'platform_sort' => 'sort'])
->toArray();
// 根据购买链接平台排序
$sort_by_arr = array_column($product_purchase_links, 'platform_sort');
array_multisort($sort_by_arr, SORT_ASC, $product_purchase_links);
// 获取相关产品信息
$related = ProductRelatedModel::with(['product' => function($query) {

View File

@@ -205,6 +205,7 @@ class TopicNas extends Common
->language($this->lang_id)
->parent($parent)
->isShow(true)
->order(['sort' => 'asc', 'id' => 'desc'])
->select();
View::assign('article_categorys', $article_categorys);
@@ -256,6 +257,7 @@ class TopicNas extends Common
->language($this->lang_id)
->parent($parent)
->isShow(true)
->order(['sort' => 'asc', 'id' => 'desc'])
->select();
View::assign('article_categorys', $article_categorys);
@@ -274,17 +276,33 @@ class TopicNas extends Common
->value('id');
// 获取帮且中心分类子分类
$categorys = [];
$table_name = (new ArticleCategoryModel)->getTable();
$categorys = \think\facade\Db::query(preg_replace(
'/\s+/u',
' ',
"WITH RECURSIVE article_tree_by AS (
SELECT a.id, a.pid FROM $table_name a WHERE a.id = {$parent}
UNION ALL
SELECT k.id, k.pid FROM $table_name k INNER JOIN article_tree_by t ON t.id = k.pid
)
SELECT id FROM article_tree_by WHERE id <> {$parent}"
));
if (env('DB_VERSION', '5') == '8') {
$categorys = \think\facade\Db::query(preg_replace(
'/\s+/u',
' ',
"WITH RECURSIVE article_tree_by AS (
SELECT a.id, a.pid FROM $table_name a WHERE a.id = {$parent}
UNION ALL
SELECT k.id, k.pid FROM $table_name k INNER JOIN article_tree_by t ON t.id = k.pid
)
SELECT id FROM article_tree_by WHERE id <> {$parent}"
));
} else {
$categorys = \think\facade\Db::query("
SELECT t2.id
FROM (
SELECT
@r AS _id, (SELECT @r := GROUP_CONCAT(id) FROM $table_name WHERE FIND_IN_SET(pid, _id)) AS parent_id
FROM
(SELECT @r := $parent) vars, $table_name h
WHERE @r <> 0) t1
JOIN $table_name t2
ON FIND_IN_SET(t2.pid, t1._id)
ORDER BY t2.id;
");
}
if (empty($categorys)) return success('success', []);
// 获取文章数据

View File

@@ -53,6 +53,7 @@ return [
'product/search' => [
'搜索' => 'Search',
'请搜索' => 'Please search...',
'暂无数据' => 'No data',
],
// 产品详情
'product/detail' => [

View File

@@ -161,6 +161,7 @@ return [
// 产品 - 产品详情页
'product/detail' => [
'首页' => 'Home',
'型号' => 'Product Model',
'产品详情' => 'Product Description',
'相关产品' => 'Related Products',
'发送查询' => 'Send Inquiry',
@@ -177,6 +178,11 @@ return [
'提交' => 'SUBMIT',
],
// 产品 - 搜索
'product/search' => [
'暂无数据' => 'No data',
],
// 产品 - 分类
'product/category' => [
'查看全部' => 'View All',

View File

@@ -2,7 +2,8 @@
// 这是系统自动生成的middleware定义文件
return [
// 启用多语言支持
think\middleware\LoadLangPack::class,
// think\middleware\LoadLangPack::class,
app\index\middleware\LoadLangPack::class,
// 确认请求来源
app\index\middleware\ConfirmRequestFrom::class,
];

View File

@@ -0,0 +1,39 @@
<?php
declare (strict_types = 1);
namespace app\index\middleware;
use think\Request;
class LoadLangPack extends \think\middleware\LoadLangPack
{
// 重写检测语言方法
protected function detect(Request $request): string
{
$domain_detect = env('INDEX_LANG_DETECT.DOMAIN_DETECT', false);
if ($domain_detect) {
$lang = $this->getLangSet($request, env('INDEX_LANG_DETECT.DOMAIN_RULE', []));
if ($lang != '') {
return $lang;
}
}
return parent::detect($request);
}
// 根据请求及规则获取语言
private function getLangSet(Request $request, array $rules): string
{
$map = [];
foreach ($rules as $v) {
$val = str_replace('', ',', $v);
$item = explode(',', $v);
foreach ($item as $val) {
$it = explode('=', $val);
$map[$it[0]] = $it[1];
}
}
return $map[$request->host()] ?? '';
}
}

View File

@@ -14,7 +14,7 @@
<div class="tabs">
{notempty name="video_categorys"}
{volist name="video_categorys" id="va"}
<a href="{:url('attachment/index', ['id' => $va.id])}"><div class="tabit active">{$va.name}</div></a>
<a href="{:url('attachment/video', ['id' => $va.id])}"><div class="tabit active">{$va.name}</div></a>
{/volist}
{/notempty}
</div>

View File

@@ -101,7 +101,7 @@
<a href="{$sc.link}"><img src="{$sc.image}" /></a>
<div class="position_a text_center wow animated bounceInLeft">
<p class="f_weight_500 timetitle" {:style(['color'=>$sc['title_txt_color']])}>{$sc.title}</p>
<p class=" margin-top-14 f_weight_400 timedesin" {:style(['color'=>$sc['desc_txt_color']])}>{$sc.desc}</p>
<p class=" margin-top-14 f_weight_400 timedesin" {:style(['color'=>$sc['desc_txt_color']])}>{$sc.desc|raw}</p>
<p class=" margin-top-20 f_weight_400">
<a href="{$sc.link}" class="timeblue"> {:lang_i18n('了解更多')} <img src="__IMAGES__/more-r.png"></a>
</p>
@@ -141,7 +141,7 @@
<img src="{$bs.image}">
<div class="position_a text_center">
<p class=" timetitle" {:style(['color'=>$bs['title_txt_color']])}>{$bs.title} </p>
<p class=" margin-top-14 f_weight_400 timedesin" {:style(['color'=>$bs['desc_txt_color']])}>{$bs.desc}</p>
<p class=" margin-top-14 f_weight_400 timedesin" {:style(['color'=>$bs['desc_txt_color']])}>{$bs.desc|raw}</p>
<p class=" margin-top-20 f_weight_400">
<span class=" timeblue">
<a href="{$bs.link}">{:lang_i18n('了解更多')}<img src="__IMAGES__/more-r.png"></a>

View File

@@ -46,7 +46,7 @@
{volist name="vo.products" id="pro" length="4"}
<li class="img-responsive">
<a href="{:url('product/detail', ['id' => $pro.id])}">
<img src="{$pro.cover_image}">
<img src="{:thumb($pro.cover_image)}">
<span class="title">{$pro.name}</span>
<span class="subtitle">{$pro.spu}</span>
</a>

View File

@@ -22,7 +22,11 @@
<a class="href_01">{:lang_i18n('首页')}</a>
{volist name="product_categorys" id="ca"}
<span class="icon-arrow arrow_address"></span>
{eq name="ca.pid" value="0"}
<a class="href_02" href="{:url('product/category', ['id' => $ca.id])}">{$ca.name}</a>
{else /}
<a class="href_02" href="{:url('product/subcategory', ['id' => $ca.id])}">{$ca.name}</a>
{/eq}
{/volist}
</div>
</div>
@@ -37,6 +41,13 @@
<img src="{$photo}" alt="" />
</div>
{/volist}
{if condition="!empty($product.video_img) && !empty($product.video_url) && $idx == 1"}
<div class="swiper-slide">
<video poster="{$product.video_img}" autoplay="autoplay" muted="muted" loop="loop" id="video" controls>
<source src="{$product.video_url}" type="video/mp4"/>
</video>
</div>
{/if}
</div>
<!-- 如果需要分页器 -->
<div class="swiper-pagination"></div>

View File

@@ -17,7 +17,7 @@
<div class="prlist">
{volist name="products" id="pro"}
<a class="pritem" href="{:url('product/detail',['id'=>$pro.id])}">
<img src="{$pro.cover_image}" class="primg"/>
<img src="{:thumb($pro.cover_image)}" class="primg"/>
<div class="prinfo">
<span class="t1">{$pro.name|raw}</span>
<span class="t2">{$pro.spu|raw}</span>
@@ -28,7 +28,7 @@
<!-- 分页 -->
<div>{$page|raw}</div>
{else/}
<div style="text-align: center; padding: 10%;">暂无数据</div>
<div style="text-align: center; padding: 10%;">{:lang_i18n('暂无数据')}</div>
{/notempty}
</div>
</div>

View File

@@ -19,6 +19,7 @@
<div class="m_Container">
{notempty name="categorys_data"}
<div class="product_list">
{if condition="in_array('products', array_keys($categorys_data[0]))"}
<ul>
{assign name="products" value=":\think\helper\Arr::flatMap(fn($pro) => $pro['products'], $categorys_data)" /}
{volist name="products" id="pr"}
@@ -55,6 +56,7 @@
</li>
{/volist}
</ul>
{/if}
</div>
{/notempty}
</div>

View File

@@ -11,13 +11,12 @@
<link rel="stylesheet" type="text/css" href="__CSS__/public.css" />
<link rel="stylesheet" type="text/css" href="__CSS__/font.css" />
<link rel="stylesheet" type="text/css" href="__CSS__/style.css" />
<!-- <link rel="stylesheet" type="text/css" href="__CSS__/fonts.css" /> -->
<link rel="stylesheet" type="text/css" href="__CSS__/header.css" />
<link rel="stylesheet" type="text/css" href="__CSS__/footer.css" />
{block name="style"}{/block}
<link rel="stylesheet" href="https://unpkg.com/swiper@9/swiper-bundle.min.css">
<script type="text/javascript" src='https://code.jquery.com/jquery-3.6.0.min.js'></script>
<script type="text/javascript" src="https://unpkg.com/swiper@9.4.1/swiper-bundle.min.js"></script>
<link rel="stylesheet" href="__JS__/swiper-bundle9.4.1.min.css" />
<script src="__JS__/jquery-3.6.0.min.js"></script>
<script type="text/javascript" src="__JS__/swiper-bundle9.4.1.min.js"></script>
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
@@ -27,7 +26,7 @@
(function() {
var u="//analytics.f2b211.com/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '1']);
_paq.push(['setSiteId', '2']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
@@ -37,7 +36,7 @@
<body>
<noscript>
<!-- Matomo Image Tracker-->
<img referrerpolicy="no-referrer-when-downgrade" src="https://analytics.f2b211.com/matomo.php?idsite=1&amp;rec=1" style="border:0" alt="" />
<img referrerpolicy="no-referrer-when-downgrade" src="https://analytics.f2b211.com/matomo.php?idsite=2&amp;rec=1" style="border:0" alt="" />
<!-- End Matomo -->
</noscript>
{block name="header"}

View File

@@ -29,12 +29,13 @@
{/notempty}
<li>
<h3>{:lang_i18n('联系方式')}</h3>
{notempty name="contact_config.website_email"}
<p>{$contact_config.website_email.title} {$contact_config.website_email.value}</p>
{/notempty}
{notempty name="contact_config.website_hotline_office_hours"}
<p>{$contact_config.website_hotline_office_hours.title} {$contact_config.website_hotline_office_hours.value}</p>
{/notempty}
{if condition="!empty($contact_config)"}
{volist name="contact_config" id="vo"}
{if condition="$vo.type != 'image'"}
<p>{$vo.value}</p>
{/if}
{/volist}
{/if}
</li>
</ul>
</div>
@@ -64,7 +65,7 @@
<div class="copy-text">
{$basic_config.website_powerby.value}
{notempty name="$basic_config.website_icp"}
<a href="https://beian.miit.gov.cn/" style="color:white;">{$basic_config.website_icp.value}</a>
<a href="https://beian.miit.gov.cn/" style="color:white;">{$basic_config.website_icp.value|raw}</a>
{/notempty}
</div>
{/notempty}

View File

@@ -12,22 +12,30 @@
<span class="icon-category cursor_p top-menu-toggle"><i class="icon-menu-svg"></i></span>
</div>
</div>
</div>
<!-- 顶部国家选择-->
<div class="top-country">
<div class="mask"></div>
<div class="action-sheet">
<div class="menu-title">
<div class="menu-name">{:lang_i18n('请择地区')}</div>
<div class="close-icon">
<img src="__IMAGES__/close.png">
</div>
</div>
<ul>
{volist name="header_languages" id="la"}
<li>
<a href="{$la.lang_url}" target="_blank">
<img src="{$la.lang_icon}">{$la.country_en_name} - {$la.lang_en_name}
</a>
</li>
{/volist}
</ul>
</div>
</div>
<!-- 顶部菜单-->
<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">
@@ -59,7 +67,13 @@
$(this).siblings('.it-1-2').slideToggle(800);
$(this).find('.icon-arrow').addClass('rotate');
});
// 顶部国家选择
$('.top-country-toggle').click(function(){
$(".mask,.action-sheet").show();
})
$('.top-country .close-icon').click(function(){
$(".mask,.action-sheet").hide();
})
// 移动端顶部宽度设置和主体内容宽度一致
var pageWidth = $('.oricoEGapp').outerWidth();
// 设置.header-PC元素的宽度

View File

@@ -22,25 +22,28 @@
<div class="headtop">
{eq name=":cookie('think_lang')" value="zh-cn"}
<a href="{:url('/index/topic/nas/index')}">
{else/}
<a>
{/eq}
<img src="__IMAGES__/logo.png" class="logoicoimg">
</a>
<div style="display: flex;">
<img src="__IMAGES__/fenlei.png" class="ssicoimg" id="flico">
<img src="__IMAGES__/sousuo.png" class="ssicoimg" id="ssico" style="margin-right:32px">
</div>
{else/}
<a>
{/eq}
<img src="__IMAGES__/logo.png" class="logoicoimg">
</a>
<div style="display: flex;">
<img src="__IMAGES__/fenlei.png" class="ssicoimg" id="flico">
<img src="__IMAGES__/sousuo.png" class="ssicoimg" id="ssico" style="margin-right:32px">
</div>
</div>
<!-- 文章内容 -->
<div id="rendered-content" class="nhlp-app-content">
{$article.content|raw|default=''}
<div class="ql-container">
<div id="rendered-content" class="nhlp-app-content ql-editor">
{$article.content|raw|default=''}
</div>
</div>
<!-- 搜索 -->
<div class="nhlpapp-search">
<div class="nhlpappshtop">
<div class="nhlpapp-shdiv">
<input class="nhlp-ipt" id="search-input" placeholder="{:lang_i18n('请输入搜索关键字,如安装赛博云空间,影视库')}" autocomplete="off">
<input class="nhlp-ipt" id="search-input" placeholder="{:lang_i18n('请输入搜索关键字,如安装赛博云空间,影视库')}"
autocomplete="off">
<img src="__IMAGES__/ssapp.png" class="searchimg">
</div>
<span class="closetx">{:lang_i18n('取消')}</span>
@@ -50,7 +53,7 @@
<div class="dropdown" id="dropdown"></div>
</div>
<!-- 分类文章目录 -->
<div class="nhlpapp-pagescate" {:style(['display' => $Request.get.view == 'more' ? 'block' : 'none'])}>
<div class="nhlpapp-pagescate" {:style(['display'=> $Request.get.view == 'more' ? 'block' : 'none'])}>
<div class="nars-hlpdt-ml">
{notempty name="article_categorys"}
<div class="nav-tree">
@@ -58,14 +61,16 @@
<div class="categoryhelp">
<div class="categoryhelp-title">
<div>
<img src="__IMAGES__/nars-jt.png" class="arrow {if condition='$ac.id == $Request.get.cid'}rotate{/if}">
<img src="__IMAGES__/nars-jt.png"
class="arrow {if condition='$ac.id == $Request.get.cid'}rotate{/if}">
</div>
<span>{$ac.name}</span>
</div>
<ul class="sub-list" {if condition='$ac.id == $Request.get.cid'}style="display: block;"{/if}>
<ul class="sub-list" {if condition='$ac.id == $Request.get.cid' }style="display: block;" {/if}>
{volist name="ac.article" id="ar"}
<li>
<a href="{:url('/index/topic/nas/help_detail', ['cid' => $ac.id , 'id' => $ar.id])}" style="padding-top: 6px;">
<a href="{:url('/index/topic/nas/help_detail', ['cid' => $ac.id , 'id' => $ar.id])}"
style="padding-top: 6px;">
{$ar.title}
</a>
</li>
@@ -77,6 +82,27 @@
{/notempty}
</div>
</div>
<!-- 顶部国家选择-->
<div class="top-country">
<div class="mask"></div>
<div class="action-sheet">
<div class="menu-title">
<div class="menu-name">{:lang_i18n('请择地区')}</div>
<div class="close-icon">
<img src="__IMAGES__/close.png">
</div>
</div>
<ul>
{volist name="header_languages" id="la"}
<li>
<a href="{$la.lang_url}" target="_blank">
<img src="{$la.lang_icon}">{$la.country_en_name} - {$la.lang_en_name}
</a>
</li>
{/volist}
</ul>
</div>
</div>
</div>
</div>
{/block}
@@ -110,6 +136,13 @@
$('.closetx').click(function () {
$('.nhlpapp-search').hide();
});
// 顶部国家选择
$('.top-country-toggle').click(function () {
$(".mask,.action-sheet").show();
})
$('.top-country .close-icon').click(function () {
$(".mask,.action-sheet").hide();
})
// 搜索
var timeout = null;
$('#search-input').on('focus input', function () {
@@ -142,6 +175,27 @@
})
}, 300);
});
// 英文截断处理
// 目标容器:富文本内容所在的元素
const contentContainer = $('#rendered-content');
// 遍历所有包含文本内容的标签p、h1-h6、strong等
contentContainer.find('*').each(function () {
const $element = $(this);
const htmlContent = $element.html();
// 条件1排除内容仅为一个&nbsp;的标签(如<p>&nbsp;</p>
if (htmlContent.trim() === '&nbsp;') {
return; // 不处理,继续下一个元素
}
// 条件2检查是否包含&nbsp;且有实际文本内容
if (htmlContent.includes('&nbsp;')) {
// 将所有&nbsp;替换为普通空格(有效占位符,支持单词完整换行)
const newContent = htmlContent.replace(/&nbsp;/g, ' ');
$element.html(newContent);
}
});
});
</script>
{/block}

View File

@@ -5,7 +5,7 @@
{block name="main"}
<div class="orico_Page_achievement">
<div class="achievementMain">
<img src="__IMAGES__/Achievement.png" class="acvImg" />
<img src="__IMAGES__/Achievement.webp" class="acvImg" />
<div class="achInfo">
<div class="title">{:lang_i18n('ORICO荣耀')}</div>
{notempty name="achievement"}

View File

@@ -6,7 +6,7 @@
<div class="orico_Page_brand">
<!--内容 -->
<div class="brandMain">
<img src="__IMAGES__/OurBrand.png" class="img-responsive" />
<img src="__IMAGES__/OurBrand.webp" class="img-responsive" />
{notempty name="banners"}
<div class="our_brand_con">
{volist name="banners" id="ba" offset="0" length="2"}

View File

@@ -24,7 +24,9 @@
<p>{$detail.release_time|date_format_i18n}</p>
</div>
<!-- 文本渲染-->
<div class="blog_content">{$detail.content|raw}</div>
<div class="ql-container">
<div class="blog_content ql-editor">{$detail.content|raw}</div>
</div>
</div>
<!-- 评论只显示前面五条--->
{notempty name="comments"}

View File

@@ -7,14 +7,14 @@
<!-- 内容 -->
<div class="downloadMain">
<div class="topimg">
<img src="__IMAGES__/banner_01.png" />
<img src="__IMAGES__/banner_01.webp" />
<div class="banner_title">{:lang_i18n('软件和驱动程序')}</div>
</div>
<div class="contact_c">
<!-- 搜索 -->
<form action="{:url('attachment/index')}" method="get">
<div class="search_all">
<input type="hidden" name="id" value="{$Request.get.id}" />
<input type="hidden" name="id" value="{$Request.get.id??$categorys[0]['id']??''}" />
<input type="text" name="keyword" placeholder="{:lang_i18n('搜索')}" />
<button class="searchbtn" type="submit"><img src="__IMAGES__/search_blue.png" /></button>
</div>

View File

@@ -7,14 +7,14 @@
<!-- 内容 -->
<div class="downloadMain">
<div class="topimg">
<img src="__IMAGES__/banner_01.png" />
<img src="__IMAGES__/banner_01.webp" />
<div class="banner_title">{:lang_i18n('软件和驱动程序')}</div>
</div>
<div class="contact_c">
<!-- 搜索 -->
<form action="{:url('attachment/video')}" method="get">
<div class="search_all">
<input type="hidden" name="id" value="{$Request.get.id}" />
<input type="hidden" name="id" value="{$Request.get.id??$video_categorys[0]['id']??''}" />
<input type="text" name="keyword" placeholder="{:lang_i18n('搜索')}" />
<button class="searchbtn" type="submit"><img src="__IMAGES__/search_blue.png" /></button>
</div>

View File

@@ -112,13 +112,13 @@
<div class="sceneIntroduction">
{volist name="scenes" id="scene"}
<div class="sceneitem">
<div class="sceneInfo">
<p class="scenetitle" {notempty name="scene.title_txt_color" }style="color:{$scene.title_txt_color};" {/notempty}>{$scene.title}</p>
<a class="sceneInfo" href="{$scene.link}">
<!-- <p class="scenetitle" {notempty name="scene.title_txt_color" }style="color:{$scene.title_txt_color};" {/notempty}>{$scene.title}</p>
<p class="subtitle" {notempty name="scene.desc_txt_color" }style="color:{$scene.desc_txt_color};" {/notempty}>
{$scene.desc|raw}</p>
<a class="sceneMore" href="{$scene.link}">{:lang_i18n('了解更多')} ></a>
</div>
<div style="background-image: url('{$scene.image}');" class="sceneimg"></div>
<a class="sceneMore" href="{$scene.link}">{:lang_i18n('了解更多')} ></a> -->
<div style="background-image: url('{$scene.image}');" class="sceneimg"></div>
</a>
</div>
{/volist}
</div>
@@ -129,10 +129,10 @@
<span class="otsbtitle">{:lang_i18n('强大功能、简单使用')}</span>
<div class="beforeafter ba-slider">
<!-- 对比前的图片 -->
<img src="__IMAGES__/indeximg1.jpg">
<img src="__IMAGES__/indeximg1.webp">
<div class="resize">
<!-- 对比后的图片 -->
<img src="__IMAGES__/indeximg2.jpg">
<img src="__IMAGES__/indeximg2.webp">
</div>
<!-- 可拖动的分隔条 -->
<span class="handle"></span>

View File

@@ -22,7 +22,11 @@
<a class="pathname" href="/">{:lang_i18n('首页')}</a>
{volist name="product_categorys" id="ca"}
<div class="arrow"></div>
{eq name="ca.pid" value="0"}
<a class="pathname" href="{:url('product/category', ['id' => $ca.id])}">{$ca.name}</a>
{else /}
<a class="pathname" href="{:url('product/subcategory', ['id' => $ca.id])}">{$ca.name}</a>
{/eq}
{/volist}
</div>
<!-- 产品主图切换和参数详情-->
@@ -35,33 +39,26 @@
<!-- 左边切换按钮 -->
<div class="scrollbutton smallImgUp disabled"></div>
<!-- 小图片预览 -->
<div id="imageMenu">
<div id="imageMenu_{$sku.id}" class="imageMenu">
<ul class="image_list">
{volist name="sku.photo_album" id="photo"}
<li class="onlickImg"><img src="{:thumb($photo)}" data-url="{$photo}" /></li>
{/volist}
{if condition="!empty($product.video_img) && !empty($product.video_url) && $idx == 1"}
<!-- 产品视频 -->
<li id="onlickImg"><img src="{:thumb($product.video_img)}" data-url="{$product.video_url}" /></li>
<li class="onlickImg"><img src="{:thumb($product.video_img)}" data-url="{$product.video_url}" /></li>
{/if}
{volist name="sku.photo_album" id="photo"}
<li id="onlickImg"><img src="{:thumb($photo)}" data-url="{$photo}" /></li>
{/volist}
</ul>
</div>
<!-- 右边切换按钮 -->
<div class="scrollbutton smallImgDown"></div>
</div>
<!-- 产品大图 -->
<div class="bigImg" id="vertical">
<div class="bigImg" id="vertical" style="width: 75%;">
<!-- 主图 -->
{if condition="!empty($product.video_img) && !empty($product.video_url) && $idx == 1"}
<!-- 如果有视频情况下默认先显示视频 -->
<video poster="{$product.video_img}" autoplay="autoplay" muted="muted" loop="loop" id="video" controls style="width: 510px;height: 510px; position: relative;z-index: 998;">
<source src="{$product.video_url}" type="video/mp4"/>
</video>
{else/}
{notempty name="sku.photo_album[0]"}
<img src="{$sku.photo_album[0]}" id="midimg" />
{/notempty}
{/if}
</div>
</div>
{/volist}
@@ -73,6 +70,11 @@
<p>{$product.short_name|default=''}</p>
<div class="proTfg">
<ul class="swt-Table">
<li class="Table-Row">
<div class="ms3 Table-Cell">{:lang_i18n('型号')}</div>
<div class="ms2 Table-Cell"></div>
<div class="ms4 Table-Cell">{$product.spu}</div>
</li>
{volist name="product_params" id="pp"}
<li class="Table-Row">
<div class="ms3 Table-Cell">{$pp.name}</div>
@@ -114,6 +116,7 @@
{volist name="product_purchase_links" id="ppp" key="k"}
<a class="thebt bttype{$k}" href="{$ppp.link}">{$ppp.platform_name}</a>
{/volist}
<br/>
{eq name=":cookie('think_lang')" value="en-us"}
<a class="thebt bttype3" id="open_form_modal">{:lang_i18n('发送查询')}</a>
{/eq}
@@ -130,8 +133,10 @@
{/notempty}
</div>
<!-- 富文本渲染-->
<div class="products_des" id="detail">
{$product.detail|default=''|raw}
<div class="ql-container">
<div class="products_des ql-editor" id="detail">
{$product.detail|default=''|raw}
</div>
</div>
</div>
<!-- 关联产品 -->
@@ -225,7 +230,7 @@
<textarea name="message" id="message"></textarea>
</div>
</div>
<button type="button" id="send" class="submit-btn">{:lang_i18n('提交')}</button>
<button type="submit" class="submit-btn">{:lang_i18n('提交')}</button>
</form>
</div>
</div>
@@ -273,21 +278,12 @@
// 处理表单提交
modal.find("form").submit(function(e) {
e.preventDefault();
var form = $(this)
var formData = $(this).serialize();
// 这里可以添加代码将formData发送到服务器
// 例如通过AJAX
console.log("提交的数据: " + formData);
// 提交成功后可以选择关闭模态框
modal.hide();
});
// 提交询盘
$('#send').click(function() {
var form = $(this).parents('form');
$.ajax({
url: "{:url('product/inquiry')}",
type: 'POST',
data: form.serialize(),
data: formData,
success: function(r) {
if (r.code == 0) {
form[0].reset(); // 重置表单
@@ -297,6 +293,7 @@
},
error: function(e) {
console.error(e);
modal.hide();
}
})
});

View File

@@ -14,6 +14,7 @@
</div>
</form>
<!-- 搜索结果列表-->
{notempty name="products"}
<ul class="seul">
{volist name="products" id="pro"}
<a href="{:url('product/detail', ['id' => $pro['id']])}">
@@ -32,6 +33,10 @@
</a>
{/volist}
</ul>
<div>{$page|raw}</div>
{else/}
<div style="text-align: center; padding: 10%;">{:lang_i18n('暂无数据')}</div>
{/notempty}
</div>
</div>
{/block}

View File

@@ -24,23 +24,19 @@
// 直接输出对应的 HTML 标签
if (isUCBrowser()) {
document.write(`
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@8.4.7/swiper-bundle.min.css">
<script src="https://cdn.jsdelivr.net/npm/swiper@8.4.7/swiper-bundle.min.js"><\/script>
<link rel="stylesheet" href="__JS__/swiper-bundle8.4.7.min.css">
<script type="text/javascript" src="__JS__/swiper-bundle8.4.7.min.js"><\/script>
`);
} else {
document.write(`
<link rel="stylesheet" href="https://unpkg.com/swiper@9.4.1/swiper-bundle.min.css">
<script src="https://unpkg.com/swiper@9.4.1/swiper-bundle.min.js"><\/script>
<link rel="stylesheet" href="__JS__/swiper-bundle9.4.1.min.css">
<script type="text/javascript" src="__JS__/swiper-bundle9.4.1.min.js"><\/script>
`);
}
</script>
<!-- 你的 jQuery 和其他脚本 -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- <link rel="stylesheet" href="https://unpkg.com/swiper@9/swiper-bundle.min.css">
<script type="text/javascript" src="https://unpkg.com/swiper@9.4.1/swiper-bundle.min.js"></script> -->
<script type="text/javascript" src='https://code.jquery.com/jquery-3.6.0.min.js'></script>
<script src="__JS__/jquery-3.6.0.min.js"></script>
<script type="text/javascript" src="__JS__/before-after.min.js"></script>
<script type="text/javascript" src="__JS__/large.js"></script>
<script type="text/javascript">
@@ -112,7 +108,7 @@
(function() {
var u="//analytics.f2b211.com/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '1']);
_paq.push(['setSiteId', '2']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
@@ -124,7 +120,7 @@
<body>
<noscript>
<!-- Matomo Image Tracker-->
<img referrerpolicy="no-referrer-when-downgrade" src="https://analytics.f2b211.com/matomo.php?idsite=1&amp;rec=1" style="border:0" alt="" />
<img referrerpolicy="no-referrer-when-downgrade" src="https://analytics.f2b211.com/matomo.php?idsite=2&amp;rec=1" style="border:0" alt="" />
<!-- End Matomo -->
</noscript>
{block name="header"}

View File

@@ -27,7 +27,9 @@
<p class="ftitle">{:lang_i18n('产品')}</p>
<ul>
{volist name="header_categorys" id="vo"}
<li><a href="{:url('product/category', ['id' => $vo.id])}" class="fline">{$vo.name}</a></li>
{if condition="!empty($vo.name)"}
<li><a href="{:url('product/category', ['id' => $vo.id])}" class="fline">{$vo.name}</a></li>
{/if}
{/volist}
</ul>
</div>
@@ -38,7 +40,7 @@
{if condition="!empty($vo.children)"}
<ul>
{volist name="vo.children" id="vc"}
<li><a href="{$vc.link}" class="fline">{$vc.name}</a></li>
<li><a href="{$vc.link}" class="fline" target="{$vc.blank==1?'_blank':'_self'}">{$vc.name}</a></li>
{/volist}
</ul>
{/if}
@@ -56,7 +58,7 @@
{else/}
<a href="javascript:void(0);" class="fline">
{$vo.value}
{/if}
{/if}
</a>
</li>
{/volist}
@@ -80,7 +82,7 @@
<div class="ftcopyright">
<span>{$basic_config.website_powerby.value}</span>
{if condition="!empty($basic_config.website_icp)"}
<a href="https://beian.miit.gov.cn/">{$basic_config.website_icp.value}</a>
<a href="https://beian.miit.gov.cn/">{$basic_config.website_icp.value|raw}</a>
{/if}
</div>
{/if}
@@ -89,12 +91,10 @@
</div>
</div>
</footer>
{eq name=":cookie('think_lang')" value="zh-cn"}
<div class="backtop">
<img src="__IMAGES__/ic-backtop.png" class="ictop" />
<span>返回顶部</span>
<span>{eq name=":cookie('think_lang')" value="en-us"}TOP{else /}返回顶部{/eq}</span>
</div>
{/eq}
<script>
$(document).ready(function () {
// 获取窗口高度

View File

@@ -92,7 +92,7 @@
</div>
{eq name=":cookie('think_lang')" value="en-us"}
{notempty name="basic_config['navigation_store_url']['value']"}
<a class="storetopbt" href="{$basic_config['navigation_store_url']['value']}">
<a class="storetopbt" href="{$basic_config['navigation_store_url']['value']}" target="_blank">
<img src="__IMAGES__/shopico.png" class="storeImgico" />{:lang_i18n('店铺')}
</a>
{/notempty}
@@ -115,7 +115,7 @@
<div class="popmain">
{volist name="header_hot_products" id="vo"}
<div class="popitem">
<a href="{:url('product/detail', ['id' => $vo.id])}"><img src="{$vo.cover_image}" class="popimg" /></a>
<a href="{:url('product/detail', ['id' => $vo.id])}"><img src="{:thumb($vo.cover_image)}" class="popimg" /></a>
<div class="productName">{$vo.name}</div>
<div class="produc-dec">{$vo.short_name}</div>
</div>
@@ -155,26 +155,53 @@
return history;
}
// 封装一个函数用于处理鼠标悬停显示和隐藏内容
function handleHover($element, $content) {
$element.mouseenter(function () {
$content.stop(true, true).slideDown(60);
}).mouseleave(function () {
$content.stop(true, true).slideUp(60);
});
// 同时支持鼠标悬停和点击事件
$element
.mouseenter(function () {
$content.stop(true, true).slideDown(60);
})
.mouseleave(function () {
$content.stop(true, true).slideUp(60);
})
.click(function (e) {
// 阻止链接默认跳转(如果有链接的话)
if ($content.is(':visible')) {
$content.stop(true, true).slideUp(60);
} else {
$content.stop(true, true).slideDown(60);
}
// 防止点击事件冒泡到a标签
e.preventDefault();
e.stopPropagation();
});
}
// 处理第一个导航项
handleHover($('.navItem').eq(0), $('.navItem').eq(0).find('.navItemConten'));
// 鼠标移入navItem_cyleft里面的li标签添加类移除其他li的类
// 处理产品列表的下拉菜单
var $firstNav = $('.navItem').eq(0);
if ($firstNav.find('.navItemConten').length) {
handleHover($firstNav, $firstNav.find('.navItemConten'));
}
// 鼠标移入左侧子菜单切换显示
$('.navItem_cyleft li').mouseenter(function () {
$(this).addClass('it_active').siblings().removeClass('it_active');
$('.navItem_cyright').hide();
$('.navItem_cyright').eq($(this).index()).show();
});
// 处理第5 - 8个导航项
for (let i = 4; i < 8; i++) {
handleHover($('.navItem').eq(i), $('.navItem').eq(i).find('.navItemConten1'));
}
// 动态处理所有带有navItemConten1的导航项
$('.navItem').each(function () {
var $this = $(this);
var $dropdown = $this.find('.navItemConten1');
// 只给有下拉菜单的导航项绑定事件
if ($dropdown.length) {
handleHover($this, $dropdown);
}
});
// 点击搜索
$('#openModalBtn').click(function () {
$('#scmodal').toggle();
@@ -182,8 +209,20 @@
$('.close-btn').click(function () {
$('#scmodal').hide();
});
// 点击空白处关闭下拉菜单
$(document).click(function () {
$('.navItemConten, .navItemConten1, #top-country').slideUp(60);
});
// 防止下拉菜单内部点击触发空白处关闭事件
$('.navItemConten, .navItemConten1, #top-country').click(function (e) {
e.stopPropagation();
});
// 搜索历史记录回显
history();
// 执行搜索
$('#serrchinput').keydown(function (event) {
if (event.originalEvent.keyCode == 13) {
@@ -198,9 +237,11 @@
window.location.href = "{:url('product/search')}" + '?keywords=' + keywords;
}
});
// 点击选择国家
$('#countrycheck').click(function () {
$('#countrycheck').click(function (e) {
$('#top-country').toggle();
e.stopPropagation();
});
$('.closecountrybt').click(function () {
$('#top-country').hide();

View File

@@ -13,7 +13,27 @@
<link rel="stylesheet" type="text/css" href="__CSS__/topic_nas_header.css" />
<link rel="stylesheet" type="text/css" href="__CSS__/orico_footer.css" />
{block name="style"}{/block}
<script type="text/javascript" src='https://code.jquery.com/jquery-3.6.0.min.js'></script>
<script src="__JS__/jquery-3.6.0.min.js"></script>
<script>
// 增强型 UC 浏览器检测
function isUCBrowser() {
const ua = navigator.userAgent.toLowerCase();
return ua.includes('ubrowser');
}
// 直接输出对应的 HTML 标签
if (isUCBrowser()) {
document.write(`
<link rel="stylesheet" href="__JS__/swiper-bundle8.4.7.min.css">
<script type="text/javascript" src="__JS__/swiper-bundle8.4.7.min.js"><\/script>
`);
} else {
document.write(`
<link rel="stylesheet" href="__JS__/swiper-bundle9.4.1.min.css">
<script type="text/javascript" src="__JS__/swiper-bundle9.4.1.min.js"><\/script>
`);
}
</script>
<script>
$(window).ready(function () {
if ($(window).width() < 1024) {
@@ -35,7 +55,7 @@
(function() {
var u="//analytics.f2b211.com/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '1']);
_paq.push(['setSiteId', '2']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
@@ -45,7 +65,7 @@
<body>
<noscript>
<!-- Matomo Image Tracker-->
<img referrerpolicy="no-referrer-when-downgrade" src="https://analytics.f2b211.com/matomo.php?idsite=1&amp;rec=1" style="border:0" alt="" />
<img referrerpolicy="no-referrer-when-downgrade" src="https://analytics.f2b211.com/matomo.php?idsite=2&amp;rec=1" style="border:0" alt="" />
<!-- End Matomo -->
</noscript>
{block name="header"}

View File

@@ -63,7 +63,7 @@
<div class="ftcopyright">
<span>{$basic_config.website_powerby.value}</span>
{if condition="!empty($basic_config.website_icp)"}
<a href="https://beian.miit.gov.cn/">{$basic_config.website_icp.value}</a>
<a href="https://beian.miit.gov.cn/">{$basic_config.website_icp.value|raw}</a>
{/if}
</div>
{/if}

View File

@@ -1,6 +1,10 @@
<header class="narsPage-head">
<div class="headcenter">
{eq name=":cookie('think_lang')" value="zh-cn"}
<a href="{:url('/index/topic/nas/index')}">
{else/}
<a>
{/eq}
<img class="logico" style="cursor:pointer;" src="__IMAGES__/logo_nas_{:cookie('think_lang')}.png" />
</a>
{notempty name="header_navigation"}
@@ -17,9 +21,10 @@
<script type="text/javascript">
$(function() {
$('.headnav .navitem').each(function(idx, item) {
$(item).removeClass('hover');
if (compareUrls(location.href, item.href)) {
$(item).addClass('hover').siblings();
var _item = $(item);
_item.removeClass('hover');
if (_item.attr('href') && compareUrls(location.href, _item.get(0).href)) {
_item.addClass('hover').siblings();
}
});

View File

@@ -8,7 +8,7 @@
<div class="narshelpCenterPc">
<!-- banner-搜索 -->
<div class="pagetopbg">
<img src="__IMAGES__/nas_help_banner.jpg" class="hpbgimg" />
<img src="__IMAGES__/nas_help_banner.webp" class="hpbgimg" />
<div class='nhlp-search'>
<input class="nhlp-ipt" id="search-input" placeholder="{:lang_i18n('请输入搜索关键字,如安装赛博云空间,影视库')}" autocomplete="off" />
<img src="__IMAGES__/nas_help_search.png" class="searchimg" />
@@ -26,7 +26,7 @@
<h1 class="helph1">{:lang_i18n('使用教程')}</h1>
<div class="nhlp-row">
{volist name="article_categorys" id="vo" key="idx"}
<div class="nhlpit {gt name='idx' value='6'}nhlpit-w{/gt}">
<div class="nhlpit">
<div class="nhlptl">
<img src="{$vo.icon}" class="bhlpicoimg" />{$vo.name}
</div>

View File

@@ -58,7 +58,9 @@
{/notempty}
</div>
<!--文章详情 -->
<div class="nars-hlpdt-mm" id="rendered-content">{$article.content|raw|default=''}</div>
<div class="ql-container ">
<div class="nars-hlpdt-mm ql-editor" id="rendered-content">{$article.content|raw|default=''}</div>
</div>
<!--锚点定位 -->
<div class="nars-hlpdt-mr">
<div id="title-list">
@@ -119,21 +121,27 @@
// 内容
// 清空标题列表
$("#title-list ul").empty();
// 提取 h1 标题
// 提取 h3 标题
var h1Titles = $("#rendered-content").find("h3");
h1Titles.each(function (index) {
var title = $(this);
var titleText = title.text();
var titleId = "title-" + index;
title.attr("id", titleId);
var listItem = $("<li>");
var link = $("<a>", {
href: "#" + titleId,
text: titleText
// 只有当找到h3标题且内容不为空时才进行处理
if (h1Titles.length > 0) {
h1Titles.each(function (index) {
var title = $(this);
var titleText = title.text().trim(); // 使用trim()去除空白字符
// 只有当标题文本不为空时才添加到列表
if (titleText) {
var titleId = "title-" + index;
title.attr("id", titleId);
var listItem = $("<li>");
var link = $("<a>", {
href: "#" + titleId,
text: titleText
});
listItem.append(link);
$("#title-list ul").append(listItem);
}
});
listItem.append(link);
$("#title-list ul").append(listItem);
});
}
});
</script>
{/block}

View File

@@ -113,7 +113,7 @@
</div>
{/block}
{block name="script"}
<script type="text/javascript" src="https://unpkg.com/swiper@9.4.1/swiper-bundle.min.js"></script>
<!-- <script type="text/javascript" src="https://unpkg.com/swiper@9.4.1/swiper-bundle.min.js"></script> -->
<script type="text/javascript">
$(document).ready(function () {
// banner轮播

View File

@@ -18,7 +18,7 @@ if (!function_exists('image_domain_concat')) {
return $path;
}
return rtrim($domain, '/') . '/' . ltrim($path, '/');
return url_join($domain, $path);
}
}
@@ -39,7 +39,7 @@ if (!function_exists('video_domain_concat')) {
return $path;
}
return rtrim($domain, '/') . '/' . ltrim($path, '/');
return url_join($domain, $path);
}
}

View File

@@ -66,6 +66,8 @@ class Article
])
->withoutField([
'language_id',
'author',
'source',
'seo_title',
'seo_keywords',
'seo_desc',

View File

@@ -27,6 +27,8 @@ class ArticleCategory
$categories = ArticleCategoryModel::withoutField([
'language_id',
'unique_label',
'short_name',
'desc',
'created_at',
'updated_at',
])

View File

@@ -25,7 +25,10 @@ class Authorize
$server = request()->server();
$request = new Request([], $post, [], [], [], $server);
$storage = new OAuthStorage;
$oauth = new OAuth2($storage);
$oauth = new OAuth2($storage, [
'access_token_lifetime' => intval(env('OPENAPI.ACCESS_TOKEN_LIFETIME', 3600)),
'refresh_token_lifetime' => intval(env('OPENAPI.REFRESH_TOKEN_LIFETIME', 1209600)),
]);
$token = $oauth->grantAccessToken($request);
return success('success', json_decode($token->getContent(), true));
} catch (OAuth2ServerException $e) {

View File

@@ -12,6 +12,7 @@ class Product
*/
public function list()
{
$params = request()->get([
'category_id',
'language' => 'zh-cn',
@@ -34,7 +35,6 @@ class Product
'name',
'short_name',
'cover_image',
'desc',
'deleted_at'
])
->where(function($query) use($params) {
@@ -47,8 +47,8 @@ class Product
->order(['sort' => 'asc', 'id' => 'desc'])
->hidden(['category_id'])
->paginate([
'list_row' => $params['size'],
'page' => $params['page']
'list_rows' => $params['size'],
'page' => $params['page']
])
->each(function($item) {
if (!empty($item['cover_image']) && !str_starts_with($item['cover_image'], 'http')) {
@@ -75,14 +75,16 @@ class Product
'params' => fn($query) => $query->field(['product_id', 'name', 'value'])
->hidden(['product_id']),
// 关联sku
'skus' => fn($query) => $query->withoutField(['created_at', 'updated_at'])
'skus' => fn($query) => $query->withoutField(['sort', 'created_at', 'updated_at'])
->with([
'sku_attr' => fn($query) => $query->with('attr')->hidden(['sku_id', 'attr_id'])
])
->hidden(['id', 'product_id']),
// 关联购买链接
'links' => fn($query) => $query->field(['product_id', 'platform_id', 'link'])
->with(['platform' => fn($query) => $query->field(['id', 'platform'])])
->with([
'platforms' => fn($query) => $query->field(['id', 'platform'])
])
->hidden(['product_id', 'platform_id']),
// 关联相关产品
'related' => fn($query) => $query->field(['product_id', 'related_product_id'])
@@ -98,6 +100,7 @@ class Product
])
->withoutField([
'language_id',
'desc',
'stock_qty',
'seo_title',
'seo_keywords',

View File

@@ -27,6 +27,8 @@ class ProductCategory
$categories = ProductCategoryModel::withoutField([
'language_id',
'unique_id',
'icon',
'desc',
'related_tco_category',
'created_at',
'updated_at'

View File

@@ -19,7 +19,10 @@ class Auth
public function handle($request, \Closure $next)
{
try {
$oauth = new OAuth2(new OAuthStorage);
$oauth = new OAuth2(new OAuthStorage, [
'access_token_lifetime' => intval(env('OPENAPI.ACCESS_TOKEN_LIFETIME', 3600)),
'refresh_token_lifetime' => intval(env('OPENAPI.REFRESH_TOKEN_LIFETIME', 1209600)),
]);
$token = $oauth->getBearerToken();
$oauth->verifyAccessToken($token);
} catch (OAuth2ServerException $e) {

View File

@@ -20,6 +20,8 @@ class OAuthClientModel extends Model
'client_secret' => 'string',
'redirect_uri' => 'string',
'enabled' => 'int',
'expired_at' => 'datetime',
'remark' => 'string',
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime'

View File

@@ -12,7 +12,7 @@ use app\common\model\ProductPurchaseLinkBaseModel;
class ProductPurchaseLinkModel extends ProductPurchaseLinkBaseModel
{
// 关联购买平台
public function platform()
public function platforms()
{
return $this->belongsTo(ProductPurchasePlatformModel::class, 'platform_id', 'id')->bind(['platform']);
}

View File

@@ -31,7 +31,11 @@ Route::group('v1', function() {
->middleware(\app\openapi\middleware\Auth::class);
})
->middleware(\think\middleware\Throttle::class, [
'visit_rate' => '5/m',
'prefix' => 'throttle_',
'visit_rate' => '5/m',
'key' => function($throttle, $request) {
return '__CONTROLLER__/__ACTION__/__IP__';
},
'visit_fail_response' => function (\think\middleware\Throttle $throttle, \think\Request $request, int $wait_seconds) {
return \think\Response::create('您的操作过于频繁, 请在 ' . $wait_seconds . ' 秒后再试。')->code(429);
},

View File

@@ -21,9 +21,9 @@
],
"require": {
"php": ">=8.0.0",
"topthink/framework": "^8.0",
"topthink/framework": "8.1.2",
"topthink/think-orm": "v3.0.34",
"topthink/think-filesystem": "^2.0",
"topthink/think-filesystem": "^3.0",
"topthink/think-multi-app": "^1.1",
"topthink/think-migration": "^3.1",
"topthink/think-view": "^2.0",
@@ -34,7 +34,8 @@
"topthink/think-cors": "^1.0",
"phpoffice/phpspreadsheet": "^3.8",
"friendsofsymfony/oauth2-php": "^1.3",
"mobiledetect/mobiledetectlib": "4.8.09"
"mobiledetect/mobiledetectlib": "4.8.09",
"qiniu/php-sdk": "^7.14"
},
"require-dev": {
"symfony/var-dumper": ">=4.2",

View File

@@ -29,15 +29,15 @@ return [
// 驱动方式
'type' => 'redis',
// 服务器地址
'host' => '127.0.0.1',
'host' => env('REDIS_HOST', '127.0.0.1'),
// 端口
'port' => 6379,
'port' => env('REDIS_PORT', 6379),
// 密码
'password' => 'orico@f2b211',
'password' => env('REDIS_PASSWORD', 'orico@f2b211'),
// 缓存有效期 0表示永久缓存
'expire' => 0,
// 缓存前缀
'prefix' => 'ow:',
'prefix' => env('REDIS_PREFIX', 'ow:'),
]
],
];

View File

@@ -39,6 +39,60 @@ return [
// 可见性
'visibility' => 'public',
],
'public_qiniu' => [
// 磁盘类型
'type' => \filesystem\driver\Qiniu::class,
// bucker 名称
'bucket' => env('QINIU_CLOUD.BUCKET', 'orico-official-website'),
// 访问密钥
'access_key' => env('QINIU_CLOUD.ACCESS_KEY', 'dOsTum4a5qvhPTBbZRPX0pIOU7PZWRX7htKjztms'),
// 密钥
'secret_key' => env('QINIU_CLOUD.SECRET_KEY', 'KFxsGbnErkALFfeGdMa8QWTdodJbamMX0iznLe-q'),
// 外部URL
'base_url' => env('QINIU_CLOUD.BASE_URL', '//szw73dlk3.hn-bkt.clouddn.com'),
// 路径
'path_prefix' => '/storage',
// 文件名称回调,可为文件名添加特定标志,以便可以在后续识别
'filename_generator' => function (\think\file\UploadedFile $file, callable $context_generator = null): callable {
return function() use ($file, $context_generator) {
// 为文件名称添加配置名,以为后续可能根据文件名识别文件所属存储配置信息
$marker = '_' . base64_encode('public_qiniu');
$filename = $context_generator ? $context_generator($file) : null;
if ($filename == null) {
return date('Ymd') . '/' . md5(microtime(true) . $file->getPathname()) . $marker;
}
return $filename . $marker;
};
},
],
'video_qiniu' => [
// 磁盘类型
'type' => \filesystem\driver\Qiniu::class,
// bucker 名称
'bucket' => env('QINIU_CLOUD.BUCKET', 'orico-official-website'),
// 访问密钥
'access_key' => env('QINIU_CLOUD.ACCESS_KEY', 'dOsTum4a5qvhPTBbZRPX0pIOU7PZWRX7htKjztms'),
// 密钥
'secret_key' => env('QINIU_CLOUD.SECRET_KEY', 'KFxsGbnErkALFfeGdMa8QWTdodJbamMX0iznLe-q'),
// 外部URL
'base_url' => env('QINIU_CLOUD.BASE_URL', '//szw73dlk3.hn-bkt.clouddn.com'),
// 路径
'path_prefix' => '/storage/videos',
// 文件名称回调,可为文件名添加特定标志,以便可以在后续识别
'filename_generator' => function (\think\file\UploadedFile $file, callable $context_generator = null): callable {
return function() use ($file, $context_generator) {
// 为文件名称添加配置名,以为后续可能根据文件名识别文件所属存储配置信息
$marker = '_' . base64_encode('video_qiniu');
$filename = $context_generator ? $context_generator() : null;
if ($filename == null) {
return date('Ymd') . '/' . md5(microtime(true) . $file->getPathname()) . $marker;
}
return $filename . $marker;
};
},
]
// 更多的磁盘配置信息
],
];

View File

@@ -31,7 +31,7 @@ class CreateVideo extends Migrator
$table = $this->table('video', ['engine' => 'MyISAM', 'comment' => '视频表']);
$table->addColumn('language_id', 'integer', ['signed' => false , 'null' => false, 'comment' => '语言ID'])
->addColumn('category_id', 'integer', ['signed' => false , 'null' => false, 'comment' => '分类ID'])
->addColumn('name', 'string', ['limit' => 64 , 'null' => false, 'comment' => '名称'])
->addColumn('name', 'string', ['limit' => 128 , 'null' => false, 'comment' => '名称'])
->addColumn('desc', 'string', ['limit' => 512, 'null' => true, 'default' => null, 'comment' => '描述信息'])
->addColumn('image', 'string', ['limit' => 125, 'null' => true, 'default' => null, 'comment' => '封面图片'])
->addColumn('video', 'string', ['limit' => 125, 'null' => true, 'default' => null, 'comment' => '视频地址'])

View File

@@ -39,7 +39,7 @@ class CreateSysBannerItem extends Migrator
->addColumn('extra_image', 'string', ['limit' => 255, 'null' => true, 'default' => null, 'comment' => '额外的图片'])
->addColumn('video', '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', 'string', ['limit' => 255, 'null' => true, 'default' => null, 'comment' => '链接'])
->addColumn('link', 'string', ['limit' => 510, 'null' => true, 'default' => null, 'comment' => '链接'])
->addColumn('sort', 'integer', ['limit' => 11, 'null' => false, 'default' => 0, 'comment' => '排序'])
->addColumn('status', 'boolean', ['limit' => 1, 'null' => false, 'default' => 1, 'comment' => '-1为禁用, 1为启用'])
->addColumn('created_at', 'timestamp', ['null' => false, 'default' =>'CURRENT_TIMESTAMP', 'comment' => '创建时间'])

View File

@@ -30,9 +30,9 @@ class SysConfigInit extends Seeder
["id" => 13, "group_id" => 7, "title" => "热线在线时段", "name" => "website_hotline_office_hours", "value" => "周一至周五:东部时间 9:00 - 18:00", "extra" => "", "type" => "textarea", "sort" => 2, "remark" => "售后与技术支持热线在线时段", "created_at" => "2025-04-08 16:11:10", "updated_at" => "2025-06-11 17:09:13", "deleted_at" => null],
["id" => 14, "group_id" => 7, "title" => "售后与技术支持热线", "name" => "website_hotline_number", "value" => "售后与技术支持热线:400-6696-298", "extra" => "", "type" => "textarea", "sort" => 3, "remark" => "售后与技术支持热线号码", "created_at" => "2025-04-08 16:12:05", "updated_at" => "2025-06-11 17:09:13", "deleted_at" => null],
["id" => 15, "group_id" => 7, "title" => "微信公众号二维码", "name" => "website_wx_qrcode", "value" => "/storage/images/webSet/20250408/073545e4b54f4f97c7c790498014d6a0.png", "extra" => "width:126px;height:126px;", "type" => "image", "sort" => 4, "remark" => "微信公众号二维码", "created_at" => "2025-04-08 16:13:58", "updated_at" => "2025-06-11 17:09:13", "deleted_at" => null],
["id" => 16, "group_id" => 8, "title" => "Technical Support", "name" => "website_technical_support_email", "value" => "Technical Support:supports@orico.com.cn1", "extra" => "", "type" => "text", "sort" => 1, "remark" => "", "created_at" => "2025-04-08 16:18:24", "updated_at" => "2025-06-12 09:55:21", "deleted_at" => null],
["id" => 17, "group_id" => 8, "title" => "Business", "name" => "website_business_email", "value" => "Business:oversea-bu@orico.com.cn1", "extra" => "", "type" => "text", "sort" => 2, "remark" => "", "created_at" => "2025-04-08 16:20:12", "updated_at" => "2025-06-12 09:55:21", "deleted_at" => null],
["id" => 18, "group_id" => 8, "title" => "ODM/OEM Service", "name" => "website_ODM/OEM_service_email", "value" => "ODM/OEM Service:odmmarket@orico.com.cn1", "extra" => "", "type" => "text", "sort" => 3, "remark" => "", "created_at" => "2025-04-08 16:27:00", "updated_at" => "2025-06-12 09:55:21", "deleted_at" => null],
["id" => 16, "group_id" => 8, "title" => "Technical Support", "name" => "website_technical_support_email", "value" => "Technical Support:supports@orico.com.cn", "extra" => "", "type" => "text", "sort" => 1, "remark" => "", "created_at" => "2025-04-08 16:18:24", "updated_at" => "2025-06-12 09:55:21", "deleted_at" => null],
["id" => 17, "group_id" => 8, "title" => "Business", "name" => "website_business_email", "value" => "Business:oversea-bu@orico.com.cn", "extra" => "", "type" => "text", "sort" => 2, "remark" => "", "created_at" => "2025-04-08 16:20:12", "updated_at" => "2025-06-12 09:55:21", "deleted_at" => null],
["id" => 18, "group_id" => 8, "title" => "ODM/OEM Service", "name" => "website_ODM/OEM_service_email", "value" => "ODM/OEM Service:odmmarket@orico.com.cn", "extra" => "", "type" => "text", "sort" => 3, "remark" => "", "created_at" => "2025-04-08 16:27:00", "updated_at" => "2025-06-12 09:55:21", "deleted_at" => null],
["id" => 19, "group_id" => 8, "title" => "Monday-Friday", "name" => "website_hotline_office_hours", "value" => "Monday-Friday,9a.m.-6p.m.GMT+81", "extra" => "", "type" => "text", "sort" => 4, "remark" => "", "created_at" => "2025-04-08 16:28:52", "updated_at" => "2025-06-12 09:55:21", "deleted_at" => null],
["id" => 20, "group_id" => 9, "title" => "知呼Icon", "name" => "website_media_zhihu.image", "value" => "/storage/images/webSet/20250408/45ef8e4863d63620ab903cf6557c3469.png", "extra" => "width:30px;height:30px;", "type" => "image", "sort" => 1, "remark" => "", "created_at" => "2025-04-08 16:45:57", "updated_at" => "2025-06-11 17:09:13", "deleted_at" => null],
["id" => 21, "group_id" => 9, "title" => "小红书Icon", "name" => "website_media_xiaohongshu.image", "value" => "/storage/images/webSet/20250408/120f13d01c89864fd20df0e24212c214.png", "extra" => "width:30px;height:30px;", "type" => "image", "sort" => 3, "remark" => "", "created_at" => "2025-04-08 16:46:40", "updated_at" => "2025-06-11 17:09:13", "deleted_at" => null],
@@ -78,7 +78,7 @@ class SysConfigInit extends Seeder
["id" => 61, "group_id" => 1, "title" => "导航位置店铺URL", "name" => "navigation_store_url", "value" => "https://oricotechs.com/", "extra" => null, "type" => "text", "sort" => 6, "remark" => null, "created_at" => "2025-05-13 17:45:46", "updated_at" => "2025-06-11 17:09:13", "deleted_at" => null],
["id" => 62, "group_id" => 4, "title" => "导航位置店铺URL", "name" => "navigation_store_url", "value" => "https://oricotechs.com/", "extra" => null, "type" => "text", "sort" => 6, "remark" => null, "created_at" => "2025-05-13 17:45:46", "updated_at" => "2025-06-12 09:55:21", "deleted_at" => null],
["id" => 63, "group_id" => 7, "title" => "邮箱", "name" => "website_email", "value" => "supports@orico.com.cn", "extra" => null, "type" => "text", "sort" => 1, "remark" => null, "created_at" => "2025-05-23 17:06:53", "updated_at" => "2025-06-11 17:09:13", "deleted_at" => null],
["id" => 64, "group_id" => 8, "title" => "Technical Support", "name" => "website_email", "value" => "supports@orico.com.cn1", "extra" => null, "type" => "text", "sort" => 1, "remark" => null, "created_at" => "2025-05-23 17:06:53", "updated_at" => "2025-06-12 09:55:21", "deleted_at" => null],
["id" => 64, "group_id" => 8, "title" => "Technical Support", "name" => "website_email", "value" => "supports@orico.com.cn", "extra" => null, "type" => "text", "sort" => 1, "remark" => null, "created_at" => "2025-05-23 17:06:53", "updated_at" => "2025-06-12 09:55:21", "deleted_at" => null],
["id" => 65, "group_id" => 3, "title" => "是否开启", "name" => "watermark_enabled", "value" => "0", "extra" => "0:否\n1:是", "type" => "radio", "sort" => 1, "remark" => "", "created_at" => "2025-06-10 15:41:54", "updated_at" => "2025-06-11 17:09:13", "deleted_at" => null],
["id" => 66, "group_id" => 3, "title" => "类型", "name" => "watermark_type", "value" => "TEXT", "extra" => "TEXT:文本['watermark_text_value','watermark_text_font','watermark_text_size','watermark_text_color']\nIMAGE:图片['watermark_image_value','watermark_image_width','watermark_image_height']", "type" => "radio", "sort" => 2, "remark" => "", "created_at" => "2025-06-10 15:44:15", "updated_at" => "2025-06-11 17:09:13", "deleted_at" => null],
["id" => 67, "group_id" => 3, "title" => "水印文本", "name" => "watermark_text_value", "value" => "ORICO", "extra" => "", "type" => "text", "sort" => 3, "remark" => "中文情况下,请确认字体支持中文", "created_at" => "2025-06-10 15:48:38", "updated_at" => "2025-06-11 17:09:13", "deleted_at" => null],
@@ -105,18 +105,24 @@ class SysConfigInit extends Seeder
["id" => 88, "group_id" => 6, "title" => "位置", "name" => "watermark_position", "value" => "top-left", "extra" => "top-left:左上角\ntop-right:右上角\ntop:上 - 水平居中\nleft:左 - 垂直居中\ncenter:水平垂直居中\nright:右 - 垂直居中\nbottom:下 - 水平居中\nbottom-left:左下角\nbottom-right:右下角", "type" => "radio", "sort" => 11, "remark" => null, "created_at" => "2025-06-10 16:02:17", "updated_at" => "2025-06-12 09:55:21", "deleted_at" => null],
["id" => 89, "group_id" => 6, "title" => "外边距 - X轴", "name" => "watermark_offset_x", "value" => "", "extra" => "", "type" => "text", "sort" => 12, "remark" => "在“位置”基础上的x轴偏移量", "created_at" => "2025-06-10 16:06:23", "updated_at" => "2025-06-12 09:55:21", "deleted_at" => null],
["id" => 90, "group_id" => 6, "title" => "外边距 - Y轴", "name" => "watermark_offset_y", "value" => "", "extra" => null, "type" => "text", "sort" => 13, "remark" => "在“位置”基础上的y轴偏移量", "created_at" => "2025-06-10 16:09:23", "updated_at" => "2025-06-12 09:55:21", "deleted_at" => null],
["id" => 91, "group_id" => 14, "title" => "图片 - 保留原文件名", "name" => "upload_image.filename_keep", "value" => NULL, "extra" => "0:否\n1:是", "type" => "radio", "sort" => 1, "remark" => "默认为否", "created_at" => "2025-06-12 11:08:59", "updated_at" => "2025-06-12 11:29:24", "deleted_at" => NULL],
["id" => 92, "group_id" => 14, "title" => "图片 - 唯一性保持", "name" => "upload_image.filemd5_unique", "value" => "1", "extra" => "0:否\n1:是", "type" => "radio", "sort" => 2, "remark" => "如果保持图片文件唯一,重复图片上传时将立即返回已存在的地址;如果不保持,则同模块同一天上传的文件根据原文件名覆盖。", "created_at" => "2025-06-12 11:16:46", "updated_at" => "2025-06-12 11:24:39", "deleted_at" => NULL],
["id" => 93, "group_id" => 14, "title" => "视频 - 保留原文件名", "name" => "upload_video.filename_keep", "value" => NULL, "extra" => "0:否\n1:是", "type" => "radio", "sort" => 3, "remark" => "默认为否", "created_at" => "2025-06-12 11:22:27", "updated_at" => "2025-06-12 11:29:24", "deleted_at" => NULL],
["id" => 94, "group_id" => 14, "title" => "视频 - 唯一性保持", "name" => "upload_video.filemd5_unique", "value" => "1", "extra" => "0:否\n1:是", "type" => "radio", "sort" => 4, "remark" => "如果保持视频文件唯一,重复视频上传时将立即返回已存在的地址;如果不保持,则同模块同一天上传的文件根据原文件名覆盖。", "created_at" => "2025-06-12 11:24:24", "updated_at" => "2025-06-12 11:25:18", "deleted_at" => NULL],
["id" => 95, "group_id" => 14, "title" => "附件 - 保留原文件名", "name" => "upload_attachment.filename_keep", "value" => NULL, "extra" => "0:否\n1:是", "type" => "radio", "sort" => 5, "remark" => "默认为否", "created_at" => "2025-06-12 11:27:08", "updated_at" => "2025-06-12 11:27:08", "deleted_at" => NULL],
["id" => 96, "group_id" => 14, "title" => "附件 - 唯一性保持", "name" => "upload_attachment.filemd5_unique", "value" => "1", "extra" => "0:否\n1:是", "type" => "radio", "sort" => 6, "remark" => "如果保持附件文件唯一,重复附件上传时将立即返回已存在的地址;如果不保持,则同模块同一天上传的文件根据原文件名覆盖。", "created_at" => "2025-06-12 11:28:22", "updated_at" => "2025-06-12 11:28:22", "deleted_at" => NULL],
["id" => 97, "group_id" => 13, "title" => "图片 - 保留原文件名", "name" => "upload_image.filename_keep", "value" => NULL, "extra" => "0:否\n1:是", "type" => "radio", "sort" => 1, "remark" => "默认为否", "created_at" => "2025-06-12 11:08:59", "updated_at" => "2025-06-12 11:29:24", "deleted_at" => NULL],
["id" => 98, "group_id" => 13, "title" => "图片 - 唯一性保持", "name" => "upload_image.filemd5_unique", "value" => "1", "extra" => "0:否\n1:是", "type" => "radio", "sort" => 2, "remark" => "如果保持图片文件唯一,重复图片上传时将立即返回已存在的地址;如果不保持,则同模块同一天上传的文件根据原文件名覆盖", "created_at" => "2025-06-12 11:16:46", "updated_at" => "2025-06-12 11:24:39", "deleted_at" => NULL],
["id" => 99, "group_id" => 13, "title" => "视频 - 保留原文件名", "name" => "upload_video.filename_keep", "value" => NULL, "extra" => "0:否\n1:是", "type" => "radio", "sort" => 3, "remark" => "默认为否", "created_at" => "2025-06-12 11:22:27", "updated_at" => "2025-06-12 11:29:24", "deleted_at" => NULL],
["id" => 100, "group_id" => 13, "title" => "视频 - 唯一性保持", "name" => "upload_video.filemd5_unique", "value" => "1", "extra" => "0:否\n1:是", "type" => "radio", "sort" => 4, "remark" => "如果保持视频文件唯一,重复视频上传时将立即返回已存在的地址;如果不保持,则同模块同一天上传的文件根据原文件名覆盖。", "created_at" => "2025-06-12 11:24:24", "updated_at" => "2025-06-12 11:25:18", "deleted_at" => NULL],
["id" => 101, "group_id" => 13, "title" => "附件 - 保留原文件名", "name" => "upload_attachment.filename_keep", "value" => NULL, "extra" => "0:否\n1:是", "type" => "radio", "sort" => 5, "remark" => "默认为否", "created_at" => "2025-06-12 11:27:08", "updated_at" => "2025-06-12 11:27:08", "deleted_at" => NULL],
["id" => 102, "group_id" => 13, "title" => "附件 - 唯一性保持", "name" => "upload_attachment.filemd5_unique", "value" => "1", "extra" => "0:否\n1:是", "type" => "radio", "sort" => 6, "remark" => "如果保持附件文件唯一,重复附件上传时将立即返回已存在的地址;如果不保持,则同模块同一天上传的文件根据原文件名覆盖。", "created_at" => "2025-06-12 11:28:22", "updated_at" => "2025-06-12 11:28:22", "deleted_at" => NULL],
["id" => 91, "group_id" => 14, "title" => "图片 - 格式转为", "name" => "upload_image.filetype_to", "value" => "original", "extra" => "original:原格式\nwebp:webp格式", "type" => "radio", "sort" => 1, "remark" => "webp格式图片质量为原图75%可大幅压缩图片大小选定webp格式时所有上传图片均保存为webp格式。", "created_at" => "2025-06-12 11:28:22", "updated_at" => "2025-06-12 11:28:22", "deleted_at" => NULL],
["id" => 92, "group_id" => 14, "title" => "图片 - 保留原文件名", "name" => "upload_image.filename_keep", "value" => NULL, "extra" => "0:否\n1:是", "type" => "radio", "sort" => 2, "remark" => "默认为否", "created_at" => "2025-06-12 11:08:59", "updated_at" => "2025-06-12 11:29:24", "deleted_at" => NULL],
["id" => 93, "group_id" => 14, "title" => "图片 - 唯一性保持", "name" => "upload_image.filemd5_unique", "value" => "1", "extra" => "0:否\n1:是", "type" => "radio", "sort" => 3, "remark" => "如果保持图片文件唯一,重复图片上传时将立即返回已存在的地址;如果不保持,则同模块同一天上传的文件根据原文件名覆盖。", "created_at" => "2025-06-12 11:16:46", "updated_at" => "2025-06-12 11:24:39", "deleted_at" => NULL],
["id" => 94, "group_id" => 14, "title" => "视频 - 保留原文件名", "name" => "upload_video.filename_keep", "value" => NULL, "extra" => "0:否\n1:是", "type" => "radio", "sort" => 4, "remark" => "默认为否", "created_at" => "2025-06-12 11:22:27", "updated_at" => "2025-06-12 11:29:24", "deleted_at" => NULL],
["id" => 95, "group_id" => 14, "title" => "视频 - 唯一性保持", "name" => "upload_video.filemd5_unique", "value" => "1", "extra" => "0:否\n1:是", "type" => "radio", "sort" => 5, "remark" => "如果保持视频文件唯一,重复视频上传时将立即返回已存在的地址;如果不保持,则同模块同一天上传的文件根据原文件名覆盖。", "created_at" => "2025-06-12 11:24:24", "updated_at" => "2025-06-12 11:25:18", "deleted_at" => NULL],
["id" => 96, "group_id" => 14, "title" => "附件 - 保留原文件名", "name" => "upload_attachment.filename_keep", "value" => NULL, "extra" => "0:否\n1:是", "type" => "radio", "sort" => 6, "remark" => "默认为否", "created_at" => "2025-06-12 11:27:08", "updated_at" => "2025-06-12 11:27:08", "deleted_at" => NULL],
["id" => 97, "group_id" => 14, "title" => "附件 - 唯一性保持", "name" => "upload_attachment.filemd5_unique", "value" => "1", "extra" => "0:否\n1:是", "type" => "radio", "sort" => 7, "remark" => "如果保持附件文件唯一,重复附件上传时将立即返回已存在的地址;如果不保持,则同模块同一天上传的文件根据原文件名覆盖。", "created_at" => "2025-06-12 11:28:22", "updated_at" => "2025-06-12 11:28:22", "deleted_at" => NULL],
["id" => 98, "group_id" => 13, "title" => "图片 - 格式转为", "name" => "upload_image.filetype_to", "value" => "original", "extra" => "original:原格式\nwebp:webp格式", "type" => "radio", "sort" => 1, "remark" => "webp格式图片质量为原图75%可大幅压缩图片大小选定webp格式时所有上传图片均保存为webp格式", "created_at" => "2025-06-12 11:28:22", "updated_at" => "2025-06-12 11:28:22", "deleted_at" => NULL],
["id" => 99, "group_id" => 13, "title" => "图片 - 保留原文件名", "name" => "upload_image.filename_keep", "value" => NULL, "extra" => "0:否\n1:是", "type" => "radio", "sort" => 2, "remark" => "默认为否", "created_at" => "2025-06-12 11:08:59", "updated_at" => "2025-06-12 11:29:24", "deleted_at" => NULL],
["id" => 100, "group_id" => 13, "title" => "图片 - 唯一性保持", "name" => "upload_image.filemd5_unique", "value" => "1", "extra" => "0:否\n1:是", "type" => "radio", "sort" => 3, "remark" => "如果保持图片文件唯一,重复图片上传时将立即返回已存在的地址;如果不保持,则同模块同一天上传的文件根据原文件名覆盖。", "created_at" => "2025-06-12 11:16:46", "updated_at" => "2025-06-12 11:24:39", "deleted_at" => NULL],
["id" => 101, "group_id" => 13, "title" => "视频 - 保留原文件名", "name" => "upload_video.filename_keep", "value" => NULL, "extra" => "0:否\n1:是", "type" => "radio", "sort" => 4, "remark" => "默认为否", "created_at" => "2025-06-12 11:22:27", "updated_at" => "2025-06-12 11:29:24", "deleted_at" => NULL],
["id" => 102, "group_id" => 13, "title" => "视频 - 唯一性保持", "name" => "upload_video.filemd5_unique", "value" => "1", "extra" => "0:否\n1:是", "type" => "radio", "sort" => 5, "remark" => "如果保持视频文件唯一,重复视频上传时将立即返回已存在的地址;如果不保持,则同模块同一天上传的文件根据原文件名覆盖。", "created_at" => "2025-06-12 11:24:24", "updated_at" => "2025-06-12 11:25:18", "deleted_at" => NULL],
["id" => 103, "group_id" => 13, "title" => "附件 - 保留原文件名", "name" => "upload_attachment.filename_keep", "value" => NULL, "extra" => "0:否\n1:是", "type" => "radio", "sort" => 6, "remark" => "默认为否", "created_at" => "2025-06-12 11:27:08", "updated_at" => "2025-06-12 11:27:08", "deleted_at" => NULL],
["id" => 104, "group_id" => 13, "title" => "附件 - 唯一性保持", "name" => "upload_attachment.filemd5_unique", "value" => "1", "extra" => "0:否\n1:是", "type" => "radio", "sort" => 7, "remark" => "如果保持附件文件唯一,重复附件上传时将立即返回已存在的地址;如果不保持,则同模块同一天上传的文件根据原文件名覆盖。", "created_at" => "2025-06-12 11:28:22", "updated_at" => "2025-06-12 11:28:22", "deleted_at" => NULL],
['id' => 105, 'group_id' => 13, 'title' => '视频 - 保存到', 'name' => 'upload_video.save_to', 'value' => 'qiniu_cloud', 'extra' => 'local:本地\nqiniu_cloud:七牛云', 'type' => 'radio', 'sort' => 6, 'remark' => '视频保存位置,默认为“本地” - [本地为本站点服务器;七牛云为七牛云对象存储,上传经这本站点服务器中转,上传耗时稍慢于“本地”]', 'created_at' => '2025-07-25 10:46:24', 'updated_at' => '2025-07-25 16:41:53', 'deleted_at' => NULL],
['id' => 106, 'group_id' => 13, 'title' => '附件 - 保存到', 'name' => 'upload_attachment.save_to', 'value' => 'local', 'extra' => 'local:本地\nqiniu_cloud:七牛云', 'type' => 'radio', 'sort' => 9, 'remark' => '附件保存位置,默认为“本地” - [本地为本站点服务器;七牛云为七牛云对象存储,上传经这本站点服务器中转,上传耗时稍慢于“本地”]', 'created_at' => '2025-07-25 10:51:34', 'updated_at' => '2025-07-25 16:41:53', 'deleted_at' => NULL],
['id' => 107, 'group_id' => 14, 'title' => '视频 - 保存到', 'name' => 'upload_video.save_to', 'value' => 'qiniu_cloud', 'extra' => 'local:本地\nqiniu_cloud:七牛云', 'type' => 'radio', 'sort' => 6, 'remark' => '视频保存位置,默认为“本地” - [本地为本站点服务器;七牛云为七牛云对象存储,上传经这本站点服务器中转,上传耗时稍慢于“本地”]', 'created_at' => '2025-07-25 10:46:24', 'updated_at' => '2025-07-25 16:41:53', 'deleted_at' => NULL],
['id' => 108, 'group_id' => 14, 'title' => '附件 - 保存到', 'name' => 'upload_attachment.save_to', 'value' => 'local', 'extra' => 'local:本地\nqiniu_cloud:七牛云', 'type' => 'radio', 'sort' => 9, 'remark' => '附件保存位置,默认为“本地” - [本地为本站点服务器;七牛云为七牛云对象存储,上传经这本站点服务器中转,上传耗时稍慢于“本地”]', 'created_at' => '2025-07-25 10:51:34', 'updated_at' => '2025-07-25 16:41:53', 'deleted_at' => NULL],
];
$table = $this->table('sys_config');

View File

@@ -0,0 +1,295 @@
<?php
namespace filesystem\adapter;
use League\Flysystem\Config;
use League\Flysystem\FilesystemAdapter;
use League\Flysystem\FileAttributes;
use League\Flysystem\UnableToCopyFile;
use League\Flysystem\UnableToDeleteFile;
use League\Flysystem\UnableToMoveFile;
use League\Flysystem\UnableToReadFile;
use League\Flysystem\UnableToRetrieveMetadata;
use League\Flysystem\UnableToSetVisibility;
use League\Flysystem\UnableToWriteFile;
use Qiniu\Auth;
use Qiniu\Storage\UploadManager;
use Qiniu\Storage\BucketManager;
class QiniuAdapter implements FilesystemAdapter
{
protected ?Auth $authMgr;
protected ?UploadManager $uploadMgr;
protected ?BucketManager $bucketMgr;
public function __construct(protected string $access_key, protected string $secret_key, protected string $bucket, protected string $base_url, protected string $path)
{
}
private function getAuthMgr(): Auth
{
return $this->authMgr ?? new Auth($this->access_key, $this->secret_key);
}
private function getUploadMgr(): UploadManager
{
return $this->uploadMgr ?? new UploadManager();
}
private function getBucketMgr(): BucketManager
{
return $this->bucketMgr ?? new BucketManager($this->authMgr);
}
private function getPathPrefix(): string
{
$path = ltrim($this->path, '\\/');
if ($path !== '' && !str_ends_with($path, '/')) {
$path = $path . '/';
}
return $path;
}
private function applyPathPrefix(string $path): string
{
$path = ltrim($path, '\\/');
return $this->getPathPrefix() . $path;
}
private static function parseUrl($url): array
{
$result = [];
// Build arrays of values we need to decode before parsing
$entities = [
'%21',
'%2A',
'%27',
'%28',
'%29',
'%3B',
'%3A',
'%40',
'%26',
'%3D',
'%24',
'%2C',
'%2F',
'%3F',
'%23',
'%5B',
'%5D',
'%5C'
];
$replacements = ['!', '*', "'", '(', ')', ';', ':', '@', '&', '=', '$', ',', '/', '?', '#', '[', ']', '/'];
// Create encoded URL with special URL characters decoded so it can be parsed
// All other characters will be encoded
$encodedURL = str_replace($entities, $replacements, urlencode($url));
// Parse the encoded URL
$encodedParts = parse_url($encodedURL);
// Now, decode each value of the resulting array
if ($encodedParts) {
foreach ($encodedParts as $key => $value) {
$result[$key] = urldecode(str_replace($replacements, $entities, $value));
}
}
return $result;
}
private function normalizeHost($domain): string
{
if (0 !== stripos($domain, 'https://') && 0 !== stripos($domain, 'http://')) {
$domain = "http://{$domain}";
}
return rtrim($domain, '/') . '/';
}
private function getUrl(string $path): string
{
$segments = $this->parseUrl($path);
$query = empty($segments['query']) ? '' : '?' . $segments['query'];
return $this->normalizeHost($this->base_url) . ltrim(implode('/', array_map('rawurlencode', explode('/', $segments['path']))), '/') . $query;
}
private function privateDownloadUrl(string $path, int $expires = 3600): string
{
return $this->getAuthMgr()->privateDownloadUrl($this->getUrl($path), $expires);
}
private function getMetadata($path): FileAttributes|array
{
$result = $this->getBucketMgr()->stat($this->bucket, $path);
$result[0]['key'] = $path;
return $this->normalizeFileInfo($result[0]);
}
private function normalizeFileInfo(array $stats): FileAttributes
{
return new FileAttributes(
$stats['key'],
$stats['fsize'] ?? null,
null,
isset($stats['putTime']) ? floor($stats['putTime'] / 10000000) : null,
$stats['mimeType'] ?? null
);
}
public function fileExists(string $path): bool
{
[, $error] = $this->getBucketMgr()->stat($this->bucket, $this->applyPathPrefix($path));
return is_null($error);
}
public function directoryExists(string $path): bool
{
return $this->fileExists($path);
}
public function write(string $path, string $contents, Config $config): void
{
$mime = $config->get('mime', 'application/octet-stream');
/**
* @var Error|null $error
*/
[, $error] = $this->getUploadMgr()->put(
$this->getAuthMgr()->uploadToken($this->bucket),
$this->applyPathPrefix($path),
$contents,
null,
$mime,
$path
);
if ($error) {
throw UnableToWriteFile::atLocation($path, $error->message());
}
}
public function writeStream(string $path, $resource, Config $config): void
{
$data = '';
while (!feof($resource)) {
$data .= fread($resource, 1024);
}
$this->write($path, $data, $config);
}
public function read(string $path): string
{
try {
$result = file_get_contents($this->privateDownloadUrl($path));
} catch (\Exception $th) {
throw UnableToReadFile::fromLocation($path);
}
if (false === $result) {
throw UnableToReadFile::fromLocation($path);
}
return $result;
}
public function readStream(string $path)
{
if (ini_get('allow_url_fopen')) {
if ($result = fopen($this->privateDownloadUrl($path), 'r')) {
return $result;
}
}
throw UnableToReadFile::fromLocation($path);
}
public function delete(string $path): void
{
[, $error] = $this->getBucketMgr()->delete($this->bucket, $this->applyPathPrefix($path));
if (!is_null($error)) {
throw UnableToDeleteFile::atLocation($path);
}
}
public function deleteDirectory(string $path): void
{
$this->delete($path);
}
public function createDirectory(string $path, Config $config): void
{
}
public function setVisibility(string $path, string $visibility): void
{
throw UnableToSetVisibility::atLocation($path);
}
public function visibility(string $path): FileAttributes
{
throw UnableToRetrieveMetadata::visibility($path);
}
public function mimeType(string $path): FileAttributes
{
$meta = $this->getMetadata($path);
if ($meta->mimeType() === null) {
throw UnableToRetrieveMetadata::mimeType($path);
}
return $meta;
}
public function lastModified(string $path): FileAttributes
{
$meta = $this->getMetadata($path);
if ($meta->lastModified() === null) {
throw UnableToRetrieveMetadata::lastModified($path);
}
return $meta;
}
public function fileSize(string $path): FileAttributes
{
$meta = $this->getMetadata($path);
if ($meta->fileSize() === null) {
throw UnableToRetrieveMetadata::fileSize($path);
}
return $meta;
}
public function listContents(string $path, bool $deep): iterable
{
$result = $this->getBucketMgr()->listFiles($this->bucket, $path);
foreach ($result[0]['items'] ?? [] as $files) {
yield $this->normalizeFileInfo($files);
}
}
public function move(string $source, string $destination, Config $config): void
{
[, $error] = $this->getBucketMgr()->rename($this->bucket, $source, $destination);
if (!is_null($error)) {
throw UnableToMoveFile::fromLocationTo($source, $destination);
}
}
public function copy(string $source, string $destination, Config $config): void
{
[, $error] = $this->getBucketMgr()->copy($this->bucket, $source, $this->bucket, $destination);
if (!is_null($error)) {
throw UnableToCopyFile::fromLocationTo($source, $destination);
}
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace filesystem\driver;
use Closure;
use filesystem\adapter\QiniuAdapter;
use League\Flysystem\FilesystemAdapter;
class Qiniu extends \think\filesystem\Driver
{
protected function createAdapter(): FilesystemAdapter
{
return new QiniuAdapter(
$this->config['access_key'],
$this->config['secret_key'],
$this->config['bucket'],
$this->config['base_url'],
$this->config['path_prefix']
);
}
/**
* 保存文件
* @param string $path 路径
* @param \think\File $file 文件
* @param null|string|\Closure $rule 文件名规则
* @param array $options 参数
* @return bool|string
*/
public function putFile(string $path, \think\File $file, $rule = null, array $options = [])
{
if (!empty($this->config['filename_generator']) && $this->config['filename_generator'] instanceof Closure) {
$rule = $this->config['filename_generator']($file, $rule);
}
return $this->putFileAs($path, $file, $file->hashName($rule), $options);
}
public function url(string $path): string
{
if (str_starts_with($path, 'http://') || str_starts_with($path, 'https://')) {
return $path;
}
if (!str_starts_with($path, $this->config['path_prefix'])) {
$path = $this->config['path_prefix'] . '/' . $path;
}
return $this->concatPathToUrl($this->config['base_url'], $path);
}
public function path(string $path): string
{
if (!str_starts_with($path, $this->config['path_prefix'])) {
$path = $this->config['path_prefix'] . '/' . $path;
}
return $path;
}
}

View File

@@ -78,15 +78,18 @@ class OAuthStorage implements IOAuth2GrantCode, IOAuth2RefreshTokens, IOAuth2Gra
public function getClient($client_id): IOAuth2Client
{
// 实现获取客户端的逻辑
$ret = OAuthClientModel::clientId($client_id)->find();
if (is_null($ret)) {
$client = OAuthClientModel::clientId($client_id)->find();
if (is_null($client)) {
throw new \Exception('客户端不存在');
}
if ($ret->enabled != 1) {
if ($client->enabled != 1) {
throw new \Exception('客户端已禁用');
}
if (strtotime($client->expired_at) < time()) {
throw new \Exception('client_id 授权已过期');
}
return new OAuth2Client($ret->client_id, $ret->client_secret, [$ret->redirect_uri]);
return new OAuth2Client($client->client_id, $client->client_secret, [$client->redirect_uri]);
}
public function checkClientCredentials(IOAuth2Client $client, $client_secret = null): bool
@@ -96,6 +99,9 @@ class OAuthStorage implements IOAuth2GrantCode, IOAuth2RefreshTokens, IOAuth2Gra
if (is_null($client)) {
return false;
}
if (strtotime($client->expired_at) < time()) {
throw new \Exception('client_id 授权已过期');
}
return $client->client_secret == hash('sha1', $client->client_id . $client_secret . $this->salt);
}

View File

@@ -137,7 +137,7 @@
font-size: 14px;
font-family: Montserrat-Bold, Montserrat;
font-weight: bold;
width: 212px;
/* width: 212px; */
/* height: 48px; */
padding: 15px 60px;
background: #004bfa;

View File

@@ -130,7 +130,7 @@
padding: 15px;
background: #f2f2f2;
border-radius: 8px;
font-family: Montserrat-Regular, Montserrat;
font-family: Montserrat-Regular, Montserrat;
border: 0;
}
@@ -138,7 +138,7 @@
font-size: 14px;
font-family: Montserrat-Bold, Montserrat;
font-weight: bold;
width: 212px;
/* width: 212px; */
padding: 15px 60px;
background: #004bfa;
border-radius: 28px;

View File

@@ -84,13 +84,15 @@
border: 1px solid transparent;
}
.oricoEGapp-Contact .send {
display: inline-block;
display: block;
background-color: #004bfa;
font-family: "Montserrat-Bold";
font-size: 0.875rem;
padding: 0.75rem 1.5rem;
color: #fff;
border-radius: 1.25rem;
width: fit-content;
margin: 0 auto;
}
.oricoEGapp-Contact .red {
color: #ee2f53;
@@ -198,11 +200,11 @@
padding-top: 1rem;
padding-bottom: 0.5625rem;
font-weight: bold;
width: 70%;
white-space: nowrap;
/* width: 70%; */
/* white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: center;
text-align: center; */
}
.oricoEGapp-Contact .narskfPage .narskf-content .narskf-ct-row .narskfit .narskf-sm {

View File

@@ -87,13 +87,15 @@
border: 1px solid transparent;
}
.oricoEGapp-Contact .send {
display: inline-block;
display: block;
background-color: #004bfa;
font-family: "Montserrat-Bold";
font-size: 0.875rem;
padding: 0.75rem 1.5rem;
color: #fff;
border-radius: 1.25rem;
width: fit-content;
margin: 0 auto;
}
.oricoEGapp-Contact .red {
color: #ee2f53;

View File

@@ -30,7 +30,8 @@
margin: 0 5%;
}
.oricoEGapp .oricoEGapp-index .oidx-cate .cateit {
margin: 0 3.5%;
margin: 0 1%;
width: 50%;
}
.oricoEGapp .oricoEGapp-index .oidx-cate .cateit a{
display: flex;
@@ -45,8 +46,8 @@
}
.oricoEGapp .oricoEGapp-index .oidx-cate .cateit span {
font-size: 0.9rem;
white-space: nowrap;
word-break: keep-all;
word-break: break-word;
overflow-wrap: break-word;
}
.oricoEGapp .oricoEGapp-index .oidx-gg {
width: 100%;

View File

@@ -34,4 +34,5 @@
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 0.5rem;
}

File diff suppressed because it is too large Load Diff

View File

@@ -101,7 +101,7 @@ address {
list-style: none;
padding: 0px;
margin: 0px;
word-break: break-all;
/* word-break: break-all; */
}
a {
text-decoration: none;
@@ -1194,9 +1194,11 @@ video img {
text-align: center;
width: 90%;
margin: 0 auto;
word-break: break-all;
}
.faq-title h3 {
font-size: 1.685rem;
word-break: break-all;
}
.faq-title h5 {
font-size: 1.25rem;
@@ -1209,6 +1211,7 @@ video img {
height: 1.5rem;
font-family: 'Montserrat-Medium';
font-weight: 400;
word-break: break-all;
}
.faq-title p {
font-size: 1.125rem;
@@ -1275,7 +1278,7 @@ video img {
margin-left: 1rem;
}
.foot-cate li {
width: 50%;
min-width: 50%;
display: inline-block;
float: left;
color: #fff;
@@ -1742,7 +1745,7 @@ video img {
padding-left: 1.5rem;
line-height: 0.64rem;
height: 0.54rem;
font-size: 1.2rem;
font-size: 1rem;
}
.goods_details .cpa li:nth-child(2) {
border-left: 1px solid #009fdf;
@@ -2339,6 +2342,59 @@ video img {
margin-bottom: 1.3rem;
}
.products_des {
width: 100%;
margin-bottom: 50px;
}
.products_des img {
width: 100%;
}
.de_t_n {
font-size: 1.5em;
color: #333;
}
.detail_title {
text-align: center;
padding: 2% 0;
}
.detail_title p {
line-height: 2em;
}
.detail_con_a {
margin: auto;
overflow: hidden;
}
.lj_detail_text,
.lj_detail_texts {
font-size: 0.875em;
}
.lj_detail_text p {
line-height: 1.6em;
padding: 0.5% 0;
}
/*seo-pro*/
.seo-pro h3 {
font-size: 1.5em;
text-align: center;
color: #333;
margin: 2% 0 1%;
line-height: 1.2;
font-weight: 400;
}
.seo-pro p {
text-align: center;
margin: 0 0 11px;
}
.seo-pro a {
color: #333;
text-decoration: none;
}
.sa_blue,
.sa_blue a,
.seo-pro a:hover {
color: #009fdf;
}
/*两列*/
.list_two {
width: 100%;

View File

@@ -25,6 +25,7 @@
flex-direction: row;
justify-content: space-between;
background: #fff;
z-index: 10;
}
.narshelpCenterdetail-app .headtop .logoicoimg {
@@ -39,9 +40,12 @@
}
.narshelpCenterdetail-app .nhlp-app-content {
margin: 1.25rem;
/* margin: 1rem; */
height: 100%;
margin-top: 9.2vh;
width: 90%;
margin: 0 auto;
margin-top: 5rem;
}
.narshelpCenterdetail-app #rendered-content img {
@@ -51,7 +55,7 @@
.narshelpCenterdetail-app .nhlpapp-search {
position: fixed;
z-index: 2;
z-index: 12;
top: 0;
height: 100vh;
display: flex;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -152,7 +152,7 @@
}
.orico_Page_achievement .achievementMain .achTimes .timecontent .timelist .timeline-con .con_event_list .event_list div li {
display: inline-block;
width: 100%;
width: 94%;
font-family: Montserrat-Medium, Montserrat;
line-height: 1.5625rem;
font-size: 1rem;
@@ -160,6 +160,11 @@
color: #707070;
padding: 0 0 1.24rem 4.6875rem;
}
.orico_Page_achievement .achievementMain .achTimes .timecontent .timelist .timeline-con .con_event_list .event_list div li p{
white-space: normal;
overflow: hidden;
text-overflow: ellipsis;
}
.orico_Page_achievement .achievementMain .tech {
background: #fff;
width: 100%;

View File

@@ -125,13 +125,13 @@
justify-content: flex-start;
}
.orico_Page_download .downloadMain .contact_c .softlist .softit .left_img {
width: 320px;
height: 320px;
margin-right: 64px;
width: 140px;
height: 140px;
margin-right: 50px;
}
.orico_Page_download .downloadMain .contact_c .softlist .softit .left_img img {
width: 320px;
height: 320px;
width: 140px;
height: 140px;
border-radius: 12px;
overflow: hidden;
}
@@ -162,7 +162,7 @@
color: #004bfa;
background-color: rgba(0, 75, 250, 0.05);
cursor: pointer;
font-size: 0.9rem;
font-size: 1.2rem;
}
.orico_Page_download .downloadMain .page-box {
text-align: center;

View File

@@ -40,11 +40,11 @@
font-size: 1.125rem;
padding-top: 1.6875rem;
padding-bottom: 0.375rem;
width: 70%;
white-space: nowrap;
/* width: 70%; */
/* white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: center;
text-align: center; */
}
.narskfPage .narskf-content .narskf-ct-row .narskfit .narskf-sm {
color: #9a9a9a;

View File

@@ -35,11 +35,13 @@
font-size: 1.125em;
color: #101010;
margin-bottom: 2%;
word-break: break-all;
}
.orico_Page_fq .fqMain .Table-Row .Table-Cell .faq-all-text .faq-des {
font-size: 0.875em;
color: #737373;
line-height: 1.875em;
word-break: break-all;
}
.orico_Page_fq .fqMain .pagination {
zoom: 1;

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
.header-PC #header {
margin: 0 auto;
height: 3.75rem;
width: 100%;
max-width: var(--max-width);
position: fixed;
top: 0;
display: flex;
@@ -14,6 +14,7 @@
z-index: 999;
background: white;
color: black;
width: 100%;
}
.header-PC #header .nav1 {
position: relative;
@@ -211,6 +212,7 @@
.header-PC #header .nav3 .choesCountry {
position: relative;
margin-left: 15%;
display: flex;
}
.header-PC #header .nav3 .choesCountry .topCountry {
display: none;

View File

@@ -29,7 +29,7 @@
margin-right: 10px;
}
.orico_Page_prdetail .charging.on{
border: 2px solid #999;
border: 2px solid #009FDF;
}
.orico_Page_prdetail .oriprdetail {
display: flex;
@@ -90,17 +90,20 @@
overflow: hidden;
height: 31.875rem;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
}
.orico_Page_prdetail .oriprdetail .cp .cpfl .preview .smallImg {
width: 80px;
overflow: hidden;
float: left;
}
.orico_Page_prdetail .oriprdetail .cp .cpfl .preview .smallImg #imageMenu {
.orico_Page_prdetail .oriprdetail .cp .cpfl .preview .smallImg .imageMenu {
width: 100%;
overflow: hidden;
}
.orico_Page_prdetail .oriprdetail .cp .cpfl .preview .smallImg #imageMenu li {
.orico_Page_prdetail .oriprdetail .cp .cpfl .preview .smallImg .imageMenu li {
width: 5rem;
height: 5.4375rem;
overflow: hidden;
@@ -111,12 +114,34 @@
.cpfl
.preview
.smallImg
#imageMenu
.imageMenu
.imageMenu
li
img {
width: 98%;
cursor: pointer;
}
.onlickImg img{
width: 100%;
}
.bigImg {
height: 100%;
overflow: hidden;
}
.bigImg video {
width: 100%;
height: 100%;
object-fit: contain;
background: #fff;
}
@media (max-width: 768px) {
.bigImg video {
height: auto;
max-height: 100%;
}
}
.orico_Page_prdetail .oriprdetail .cp .cpfl .preview .bigImg {
position: relative;
margin: 0 auto;
@@ -204,6 +229,7 @@
}
.orico_Page_prdetail .oriprdetail .cp .cprh .cpcon .proTfg {
margin-top: 0.5rem;
margin-bottom: 0.875rem;
padding: 1rem 0;
font-size: 0.75rem;
border-bottom: 1px solid #ddd;
@@ -384,7 +410,7 @@
flex-direction: column;
}
.orico_Page_prdetail .oriprdetail .oriprInfo img {
max-width: 100%;
width: 100%;
}
.orico_Page_prdetail .oriprdetail .oriprInfo .titleprinfo {
text-align: center;
@@ -582,13 +608,13 @@
.scrollbutton_01.smallImgUp,
.scrollbutton_01.smallImgUp.disabled {
background: url(/static/index/pc/images/fl.png);
left: 0px;
left: 10%;
}
.scrollbutton_01.smallImgDown,
.scrollbutton_01.smallImgDown.disabled {
background: url(/static/index/pc/images/rh.png);
right: 0px;
right: 10%;
}
.scrollbutton.smallImgUp,

Some files were not shown because too many files have changed in this diff Show More