335 Commits

Author SHA1 Message Date
ouzhiqiang
9d8e22d270 修改分类 2025-09-19 15:14:55 +08:00
ouzhiqiang
f154f3ddf6 修改分类 2025-09-19 14:59:45 +08:00
ouzhiqiang
2073a27ef7 修改分类 2025-09-19 14:48:10 +08:00
ouzhiqiang
e301fc7e94 修改分类 2025-09-19 14:47:05 +08:00
ouzhiqiang
f9251d944e 修改分类 2025-09-19 14:36:08 +08:00
ouzhiqiang
1e6187801d Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-09-19 14:32:27 +08:00
ouzhiqiang
346dcebba3 修改分类 2025-09-19 14:31:56 +08:00
ab7b23e5d1 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-09-19 14:13:56 +08:00
325221bd67 1 2025-09-19 14:13:53 +08:00
ouzhiqiang
721e91dc31 修改分类 2025-09-19 11:37:41 +08:00
ouzhiqiang
12e51c6f46 修改分类 2025-09-19 11:22:25 +08:00
ouzhiqiang
8ba9006173 修改分类 2025-09-19 11:17:49 +08:00
ouzhiqiang
a7d413871b 修改分类 2025-09-19 11:09:29 +08:00
ouzhiqiang
ce6a882c17 修改分类 2025-09-19 10:41:41 +08:00
ouzhiqiang
7e7cfeacbc 修改分类 2025-09-19 10:36:26 +08:00
ouzhiqiang
e1961d2a83 修改分类 2025-09-19 10:29:25 +08:00
ouzhiqiang
d313617e2b 修改分类 2025-09-19 10:23:02 +08:00
ouzhiqiang
f0c82c848f 修改分类 2025-09-19 10:04:47 +08:00
ouzhiqiang
f606dc64a5 修改分类 2025-09-19 09:53:40 +08:00
ouzhiqiang
39dc3c4e1a 修改分类 2025-09-19 09:51:29 +08:00
ouzhiqiang
52b265f36e Merge branch 'ozq-dev' into dev 2025-09-18 17:50:21 +08:00
ouzhiqiang
5f9fb74696 修改分类 2025-09-18 17:50:05 +08:00
ouzhiqiang
b251c78b2f Merge branch 'ozq-dev' into dev 2025-09-18 17:47:43 +08:00
ouzhiqiang
2e1c83d46d 修改分类 2025-09-18 17:47:22 +08:00
ouzhiqiang
0265cb0629 Merge branch 'ozq-dev' into dev 2025-09-18 17:23:25 +08:00
ouzhiqiang
68d66b2925 修改分类 2025-09-18 17:23:07 +08:00
ouzhiqiang
601403bf3e Merge branch 'ozq-dev' into dev 2025-09-18 17:16:43 +08:00
ouzhiqiang
bbe2197b38 修改分类 2025-09-18 17:16:24 +08:00
ouzhiqiang
ee955a3674 Merge branch 'ozq-dev' into dev 2025-09-18 17:13:22 +08:00
ouzhiqiang
e45df84312 修改分类 2025-09-18 17:13:04 +08:00
ouzhiqiang
4e0891da97 Merge branch 'ozq-dev' into dev 2025-09-18 17:04:44 +08:00
ouzhiqiang
f9b895732e 修改分类 2025-09-18 17:04:29 +08:00
ouzhiqiang
e72ecd55f4 Merge branch 'ozq-dev' into dev 2025-09-18 17:01:25 +08:00
ouzhiqiang
558b418d18 修改分类 2025-09-18 17:01:08 +08:00
ouzhiqiang
78cbc5de6e Merge branch 'ozq-dev' into dev 2025-09-18 16:56:01 +08:00
ouzhiqiang
f7b610df72 修改分类 2025-09-18 16:55:47 +08:00
ouzhiqiang
b1522a365b Merge branch 'ozq-dev' into dev 2025-09-18 16:53:26 +08:00
ouzhiqiang
48906ec9cd 修改分类 2025-09-18 16:53:06 +08:00
ouzhiqiang
b57cb8dfd6 Merge branch 'ozq-dev' into dev 2025-09-18 16:49:16 +08:00
ouzhiqiang
7d70c55557 修改分类 2025-09-18 16:48:45 +08:00
ouzhiqiang
4fdda8435d Merge branch 'ozq-dev' into dev 2025-09-18 16:11:52 +08:00
ouzhiqiang
7a96809bfe 修改分类 2025-09-18 16:11:36 +08:00
ouzhiqiang
62b3e2798f Merge branch 'ozq-dev' into dev 2025-09-18 16:08:29 +08:00
ouzhiqiang
bfeac736ea 修改分类 2025-09-18 16:08:05 +08:00
ouzhiqiang
74ea50b7e4 Merge branch 'ozq-dev' into dev 2025-09-18 16:01:20 +08:00
ouzhiqiang
8a617c06e9 修改分类 2025-09-18 16:00:49 +08:00
ouzhiqiang
efa8acaf12 Merge branch 'ozq-dev' into dev 2025-09-18 15:39:28 +08:00
ouzhiqiang
d3ff726e90 修改分类 2025-09-18 15:38:59 +08:00
ouzhiqiang
7880c18e85 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-09-18 15:26:19 +08:00
ouzhiqiang
e80ba5ac7d 修改分类 2025-09-18 15:25:29 +08:00
20b5fd901b 1 2025-09-18 11:59:32 +08:00
e38c00f59c 1 2025-09-18 11:57:52 +08:00
a18706f7d4 分类补充 2025-09-18 11:56:48 +08:00
4ff2ee4a76 移动端帮助中心三级菜单 2025-09-18 11:52:52 +08:00
2ca708fd4a 帮助中心文档三级菜单 2025-09-18 11:21:50 +08:00
29761f551d Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-09-18 11:15:12 +08:00
fdb75e4888 feat: 添加open api client管理命令 2025-09-17 17:48:27 +08:00
5fde7159e0 Merge branch 'dev' 2025-08-26 14:53:55 +08:00
6068efa03f refactor: 去掉多余目录 2025-08-26 14:53:38 +08:00
738b293ea2 fix: 修复“检测文件地址并根据情况转换为文件系统地址”url为null情况报错问题 2025-08-26 14:53:17 +08:00
a1be105c31 Merge branch 'dev' 2025-08-08 09:18:33 +08:00
03374856e4 fix: 修复产品目录分类树数据问题 2025-08-08 09:18:13 +08:00
f07741ff19 Merge branch 'dev' 2025-08-07 17:08:12 +08:00
c64450d74c fix: admapi - 产品目录同步分类更新时bug修复 2025-08-07 17:07:52 +08:00
e462b38ff9 Merge branch 'dev' 2025-08-07 11:38:17 +08:00
b96021d21d Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-08-07 11:37:49 +08:00
12d6fdc3a6 style:底部样式修改 2025-08-07 11:36:56 +08:00
cd3f651a2a Merge branch 'dev' 2025-08-07 10:20:10 +08:00
1e4b416cac fix: mobile - 底部“联系我们”取值问题 2025-08-07 10:19:45 +08:00
e38446f3fd Merge branch 'dev' 2025-08-07 10:18:06 +08:00
06b9d42ae4 fix: mobile - 底部“联系我们”取值问题 2025-08-07 10:17:24 +08:00
99d78069d5 Merge branch 'dev' 2025-08-07 10:12:04 +08:00
342a3754aa fix: mobile - 底部“联系我们”取值问题 2025-08-07 10:03:50 +08:00
51e9c8ced1 Merge branch 'dev' 2025-08-06 15:35:50 +08:00
b13d481e1e perf openapi 图片地址拼接 2025-08-06 15:35:35 +08:00
da8f204167 Merge branch 'dev' 2025-08-06 12:45:49 +08:00
c1979da1af fix: 后台 - 修改各导出图片等文件地址拼接问题 2025-08-06 11:56:53 +08:00
1802f57906 fix: 后台 产品导出数据问题 2025-08-06 11:40:44 +08:00
3fa3b8fb63 fix: 后台 产品导出数据问题 2025-08-06 11:40:09 +08:00
fb2b1455bc fix: mobile下视频分类地址错误 2025-07-31 10:55:26 +08:00
cc497b2ebc fix: 获取文件系统磁盘未判断“//”情况 2025-07-31 09:03:49 +08:00
2b450a2e9c fix: 首页“场景介绍”无法点击 2025-07-31 09:03:48 +08:00
e266e89a97 1 2025-07-30 17:08:22 +08:00
2a94a7ecec 1 2025-07-30 17:07:37 +08:00
9137335ce3 1 2025-07-30 16:48:54 +08:00
b8946f223a 1 2025-07-30 16:47:15 +08:00
3a8440c2b9 1 2025-07-30 16:44:32 +08:00
c2bba7fb56 1 2025-07-30 16:40:36 +08:00
052570fefa Merge branch 'dev' 2025-07-30 16:33:15 +08:00
09b1f9f14c style:产品详情 2025-07-30 16:13:37 +08:00
37825f88ba .ql-editor 2025-07-30 15:43:42 +08:00
1c7434b591 .ql-editor 2025-07-30 15:42:52 +08:00
585da730ea style:产品详情样式 2025-07-30 15:35:16 +08:00
2ecc51d8a9 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-30 15:25:01 +08:00
ad7148ccfc style:详情样式 2025-07-30 15:24:58 +08:00
1e00db6c97 fix: 字段长度限制 2025-07-30 11:13:17 +08:00
5ed692a672 fix: 字段长度限制 2025-07-30 11:12:13 +08:00
5f7156470e Merge branch 'dev' 2025-07-29 17:52:13 +08:00
3aafcd3f3b refactor: 修改后台banner的“链接地址”长度限制为510 2025-07-29 17:51:56 +08:00
9b339d6364 Merge branch 'dev' 2025-07-29 16:48:16 +08:00
09f9bfd301 Merge branch 'dev' 2025-07-29 16:47:31 +08:00
910a07ea47 1 2025-07-29 14:16:51 +08:00
c27d529b82 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-29 14:14:29 +08:00
b6724c0361 视频宽度限制 2025-07-29 14:14:27 +08:00
d4fa15f671 文章视频限制 2025-07-29 14:13:34 +08:00
60229ae058 fix: migrations/seeds 2025-07-29 14:08:30 +08:00
6cf27d8b9c fix: 产品详情-分类路径bug 2025-07-29 12:00:22 +08:00
6ba7181e3f 文章详情样式调整 2025-07-28 14:50:26 +08:00
4334c2db66 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-28 14:34:41 +08:00
d7e93567d9 style:宽度调整 2025-07-28 14:25:01 +08:00
e19ba6a315 chore: composer.json 2025-07-28 11:13:56 +08:00
a8e7ad2430 perf: migrations/seeds 2025-07-28 10:33:44 +08:00
55c8762255 perf: 七牛云存储 2025-07-28 10:16:03 +08:00
43a4f5f706 refactor: .gitignore 2025-07-25 18:00:14 +08:00
c6cff2e97d refactor: 七牛云上传 2025-07-25 17:57:31 +08:00
5d53c26c5c 文章详情样式调整 2025-07-25 13:47:37 +08:00
857bb4ad21 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-24 10:00:18 +08:00
b3dfb8655b 1 2025-07-24 10:00:14 +08:00
10c1f86708 feat: 七牛云上传开发 2025-07-23 17:55:34 +08:00
62a67bf7a0 perf: 自定义语言检测中间件 2025-07-23 17:55:34 +08:00
4dc4932ac7 补充 2025-07-23 17:25:57 +08:00
b99c07ef4a .ql-editor 关于tab切换的样式同步 2025-07-23 17:20:11 +08:00
f8dc645048 样式修改 2025-07-22 16:48:22 +08:00
051b4ed7e7 Merge branch 'dev' 2025-07-21 17:32:36 +08:00
142e29f131 fix: pc 产品,附件,视频搜索去除首尾空格 2025-07-21 17:31:17 +08:00
7f58f1ff83 fix: pc 视频搜索 2025-07-21 16:55:06 +08:00
5650ccfb87 fix: pc 视频搜索 2025-07-21 16:54:43 +08:00
439c9073b8 Merge branch 'dev' 2025-07-19 10:48:27 +08:00
f78f164326 fix: 图片上传命名问题 2025-07-19 10:48:07 +08:00
5fb2abe818 Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-18 15:19:02 +08:00
1f3b646495 1 2025-07-18 15:16:09 +08:00
a1ea5c6752 标题提取空过滤 样式修改 2025-07-18 15:15:13 +08:00
beb86140a6 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-18 14:42:10 +08:00
0d442fb63a Merge branch 'dev' 2025-07-18 14:40:20 +08:00
af139f6bf4 fix: nas 文章详情页分类排序问题 2025-07-18 14:40:02 +08:00
1d79ea5186 Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-18 14:39:33 +08:00
de02e59b0e 1 2025-07-18 14:39:30 +08:00
f4fa5afcfa Merge branch 'dev' 2025-07-18 13:36:33 +08:00
2c40c95794 fix: 横幅分类不可小于0 2025-07-18 13:33:58 +08:00
70534f2a97 fix: nas帮助中心文件分类未排序 2025-07-18 12:36:20 +08:00
4515939fcf Achievement 2025-07-18 10:29:26 +08:00
b16971e6f1 nas_help_banner 格式修改 2025-07-18 10:16:58 +08:00
3840206e7c indeximg1 ,indeximg2压缩webp 2025-07-18 09:44:41 +08:00
ef1f786417 编辑器样式修改 2025-07-17 17:45:34 +08:00
745671bd33 1 2025-07-17 17:04:16 +08:00
a13ea053e3 1 2025-07-17 17:02:29 +08:00
0725cd779f 1 2025-07-17 17:01:17 +08:00
47caddad60 Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-17 16:49:08 +08:00
5db4263f67 1 2025-07-17 16:49:03 +08:00
9887bd1045 Merge branch 'dev' 2025-07-17 16:43:24 +08:00
768e1ed786 perf: 优化openapi接口频率限制 2025-07-17 16:43:02 +08:00
f211f58068 1 2025-07-17 16:40:23 +08:00
e7e7386054 1 2025-07-17 16:35:38 +08:00
9c7f2d394b 1 2025-07-17 16:31:42 +08:00
a1f1716f5c 1还原 2025-07-17 16:27:14 +08:00
250f78593a 还原 2025-07-17 16:25:01 +08:00
2c0b8161a5 1 2025-07-17 16:22:28 +08:00
83fa83e00d 1 2025-07-17 16:18:57 +08:00
176b25b631 1 2025-07-17 16:11:01 +08:00
4b2566b762 ·1 2025-07-17 16:02:31 +08:00
a25f87de9f 1 2025-07-17 15:40:29 +08:00
ec6fa7fe77 1 2025-07-17 15:39:17 +08:00
0ba299ee05 1 2025-07-17 15:32:22 +08:00
d06002d95c 1 2025-07-17 15:30:43 +08:00
1758fb8995 格式化 2025-07-17 15:22:56 +08:00
52259d573c Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-17 15:20:55 +08:00
a680391d86 1 2025-07-17 15:19:56 +08:00
0e0ed64b38 1 2025-07-17 15:18:38 +08:00
5221b43c01 1 2025-07-17 15:13:01 +08:00
a373ee7163 1 2025-07-17 15:08:52 +08:00
07692a2a29 1 2025-07-17 12:00:46 +08:00
3c7bdd8ac9 Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-17 11:49:33 +08:00
db3b704d89 1 2025-07-17 11:49:31 +08:00
6e3e0d59db fix: database/seeds 2025-07-17 11:44:00 +08:00
f8884aa736 1 2025-07-17 11:42:38 +08:00
8e62d95864 1 2025-07-17 11:30:52 +08:00
7bf88fd578 英文单词不换行 2025-07-17 10:48:37 +08:00
a4330c1216 1 2025-07-17 10:36:36 +08:00
6c80dbabeb 图片拉伸 2025-07-17 10:24:00 +08:00
e0009fb8fa .header-PC #header .nav3 .choesCountry 2025-07-17 10:19:09 +08:00
66da36a907 fix: database/seeds 2025-07-17 09:58:09 +08:00
702e874e08 1 2025-07-17 09:49:05 +08:00
7e486e463c Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-17 09:45:12 +08:00
df482bbcdd .ql-editor>* 2025-07-17 09:45:07 +08:00
7651b056b6 feat: 后台管理 产品列表添加按添加时间倒序 2025-07-16 18:12:11 +08:00
877c8835d9 img {display: block;}注释 2025-07-16 17:44:55 +08:00
67865d64cd .narshelpCenterdetail-app .nhlpapp-search 2025-07-16 16:55:44 +08:00
699e55ffa1 Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-16 16:53:03 +08:00
4ca9a84d14 移动端nas文章底部操作 2025-07-16 16:53:01 +08:00
ac5d0143ac fix: pc nas专题logo中文下要点击,英文下不要 2025-07-16 15:39:35 +08:00
6434d031ca fix: 产品分类排序 2025-07-16 15:32:38 +08:00
8f2dbf8798 fix: pc 产品详情添加型号 2025-07-16 15:24:22 +08:00
7a0c3af1e9 .ql-container 2025-07-16 14:51:07 +08:00
7879f7914b 文章样式 2025-07-16 14:45:33 +08:00
99a69bad5f Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-16 14:14:05 +08:00
38783d80a0 1 2025-07-16 14:13:13 +08:00
b37ed217cd 1 2025-07-16 14:11:52 +08:00
dd687120cc 还原footer 2025-07-16 14:07:43 +08:00
004a007148 1 2025-07-16 14:02:32 +08:00
5018a59045 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-16 13:39:34 +08:00
8fa1399902 Merge branch 'dev' 2025-07-16 13:39:07 +08:00
e781887d16 fix: 产品目录同步产品默认在售 2025-07-16 13:38:54 +08:00
55d72124a0 Merge branch 'dev' 2025-07-16 11:52:05 +08:00
3eda90f2d1 fix: 后台管理 产品参数问题 2025-07-16 11:51:48 +08:00
6b815ea414 Merge branch 'dev' 2025-07-16 10:31:39 +08:00
df8001d43e fix: 产品搜索无数据语言问题 2025-07-16 10:31:14 +08:00
7f8ad55c97 pc编辑文本样式 2025-07-16 10:19:42 +08:00
14f0f1609e 添加编辑器样式 2025-07-16 10:17:58 +08:00
6c176a1039 1 2025-07-16 10:12:28 +08:00
bffe804a7b 1 2025-07-16 10:10:36 +08:00
a9beb0dda6 1 2025-07-16 10:04:54 +08:00
3c72fa125f 1 2025-07-16 10:02:47 +08:00
81df05e0f9 1 2025-07-16 09:56:05 +08:00
e0fd77837d 1 2025-07-16 09:54:28 +08:00
7344691613 Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-16 09:51:31 +08:00
fe697df167 1 2025-07-16 09:51:26 +08:00
b743688d99 Merge branch 'dev' 2025-07-15 15:00:51 +08:00
51b6841a3a fix: openapi token有效期配置 2025-07-15 15:00:38 +08:00
768ed5b0fb fix: openapi token有效期配置 2025-07-15 14:59:25 +08:00
0c2f96fd49 Merge branch 'dev' 2025-07-15 14:49:47 +08:00
40c8385776 perf: openapi token有效期配置 2025-07-15 14:49:03 +08:00
80c6647a0c Merge branch 'dev' 2025-07-15 14:45:54 +08:00
187a0affcc perf: openapi token有效期配置 2025-07-15 14:45:16 +08:00
a35288dd0b Merge branch 'dev' 2025-07-15 14:21:30 +08:00
b36627ec25 perf: openapi client授权过期 2025-07-15 14:21:16 +08:00
eb2a98e7fe fix: admapi 角色菜单权力model 2025-07-15 14:21:04 +08:00
5c79e33ce1 perf: openapi client授权过期 2025-07-15 14:20:36 +08:00
341e1f54fb fix: admapi 角色菜单权力model 2025-07-15 13:50:50 +08:00
78925fbbab Merge branch 'dev' 2025-07-15 10:48:30 +08:00
d9e056972c perf: .gitignore 2025-07-15 10:46:17 +08:00
b09f7d1e6f fix: mobile subcategory.html 2025-07-15 09:54:58 +08:00
ad0f7f4b87 fix: mobile subcategory.html 2025-07-15 09:54:38 +08:00
61e4ac1fb3 smallImgDown相对位置修改 2025-07-15 09:36:55 +08:00
728730433b bsImg 高度自适应 2025-07-15 09:32:07 +08:00
3a50a23cfa Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-15 09:30:05 +08:00
1dc03040f1 .bttj 修改 2025-07-15 09:30:02 +08:00
900d73d389 fix: mobile subcategory.html 2025-07-15 09:25:25 +08:00
5b69987d6e perf: mobile 产品分类与搜索页改为缩略图 2025-07-15 09:22:21 +08:00
512c07b5a8 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-15 09:19:14 +08:00
885b86ded9 顶部底部自适应 2025-07-15 09:18:11 +08:00
c04b7cae38 fix: mobile view问题 2025-07-15 09:16:01 +08:00
3ff0137e4b Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-14 17:18:35 +08:00
15c18d5fc1 1 2025-07-14 17:06:45 +08:00
91b083f0e5 去掉新品的标题和更多 2025-07-14 17:05:44 +08:00
a3dccb8b19 sceneitem1 2025-07-14 16:41:58 +08:00
974f561c5a 1 2025-07-14 16:39:59 +08:00
8fd52854cc 1 2025-07-14 16:34:11 +08:00
b9b865ece0 1 2025-07-14 16:26:35 +08:00
acc39f4580 1 2025-07-14 16:25:49 +08:00
e82c201a2b 1 2025-07-14 16:24:22 +08:00
6927bdbc42 1 2025-07-14 16:23:25 +08:00
3db7e42e71 1 2025-07-14 16:09:53 +08:00
12bd511d0b 1 2025-07-14 16:09:02 +08:00
4a52be183c 1 2025-07-14 16:08:13 +08:00
58324ebb33 1 2025-07-14 16:07:06 +08:00
8ccca36e44 Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-14 16:02:37 +08:00
d6c7a0f11e 样式修改6 2025-07-14 16:02:35 +08:00
858468b72b fix: 底部备案信息 2025-07-14 15:52:13 +08:00
3eadc5c3eb fix: 底部备案信息 2025-07-14 15:51:22 +08:00
fe324bc62f fix: 底部备案信息 2025-07-14 15:50:13 +08:00
2329b1bbe6 pref: 数据同步 2025-07-14 15:50:13 +08:00
134c75cc4b fix: 底部备案信息 2025-07-14 15:49:50 +08:00
3b737b0bd0 1 2025-07-14 15:46:47 +08:00
2da153e935 样式修改4 2025-07-14 15:46:18 +08:00
271f22ea18 样式修改2 2025-07-14 15:35:57 +08:00
4a56e7e980 Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-14 15:13:12 +08:00
b3475a7d06 样式修改 2025-07-14 15:13:09 +08:00
988bdde6f1 pref: 数据同步 2025-07-14 14:30:59 +08:00
456209121e Merge branch 'dev' 2025-07-14 14:06:16 +08:00
8186a424de fix: 顶部搜索产品图片显示缩略图 2025-07-14 14:06:04 +08:00
ebc8c6431a Merge branch 'dev' 2025-07-14 13:44:06 +08:00
7cbb6adb5d fix: 视频描述字段长度校验 2025-07-14 13:43:52 +08:00
4b8963161f perf: 数据同步 2025-07-14 13:42:50 +08:00
eeb79e8c56 Merge branch 'dev' 2025-07-14 11:47:51 +08:00
2a503cbf68 fix: 产品详情购买链接排序 2025-07-14 11:47:41 +08:00
aed2ce4655 fix: pc 顶部“店铺”新标签打开 2025-07-14 11:27:59 +08:00
70b524ce04 Merge branch 'master' of https://gitea.f2b211.com/jsasg/orico-official-website 2025-07-14 11:27:38 +08:00
db82564148 style 2025-07-14 11:27:34 +08:00
386cd613ee fix: pc 顶部“店铺”新标签打开 2025-07-14 11:25:02 +08:00
dc8a3dc5da fix: pc 底部导航新标签页打开无效 2025-07-14 11:04:34 +08:00
4ec2985468 perf: 数据同步 2025-07-14 11:04:34 +08:00
796231a50e fix: pc 底部导航新标签页打开无效 2025-07-14 11:01:14 +08:00
6b082f2de9 perf: 数据同步 2025-07-14 11:00:43 +08:00
jsasg
83287098ee Merge branch 'dev' 2025-07-11 22:39:16 +08:00
jsasg
b67959163b fix: 图片上传 2025-07-11 22:34:32 +08:00
ba04d6d220 fix: 底部 2025-07-11 20:15:38 +08:00
457c06948c fix: 文章验证 2025-07-11 20:15:20 +08:00
c0b6ddf11b Merge branch 'dev' 2025-07-11 18:07:42 +08:00
a8960c3c81 fix: 底部 2025-07-11 18:07:25 +08:00
d4be3ff937 fix: 文章验证 2025-07-11 18:07:25 +08:00
751d4ce12d style:样式修改3 2025-07-11 17:15:44 +08:00
9c6e26ce05 style:样式调整 2025-07-11 16:52:09 +08:00
25a55ba9f5 style:样式修改 2025-07-11 16:32:58 +08:00
b8b8d8d58f fix:如果底部没有内容就不要显示li这个标签 2025-07-11 16:22:34 +08:00
31d747a0b0 style:样式修改 2025-07-11 16:13:49 +08:00
0025b0a5bb ljm master分支 2025-07-11 15:57:27 +08:00
002c4055eb Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-11 15:44:59 +08:00
738986d715 fix:pc导航修改 2025-07-11 15:44:56 +08:00
673f4d101a fix: mobile下没有jquery 2025-07-11 15:22:01 +08:00
553c010dc2 fix: 上传 2025-07-11 11:47:05 +08:00
c18ba2dbc2 fix: 导航未过滤已禁用 2025-07-11 10:32:05 +08:00
13eec27ea9 add:本地添加jQuery和swiper文件,防止cdn失效 2025-07-10 17:38:17 +08:00
84e41958c9 perf: mysql递归查询兼容处理 2025-07-10 17:30:01 +08:00
7045bd7b7d perf: 修改analytics 2025-07-09 17:30:02 +08:00
cbb0699fae pref: think文件 2025-07-09 16:34:27 +08:00
e1b4266513 perf: redis env配置 2025-07-09 16:15:58 +08:00
c109748c79 perf: env 2025-07-09 13:58:59 +08:00
87b4917120 fix: 同步产品目录产品分类及产品 2025-07-09 11:32:59 +08:00
48e3ec7c2c · 2025-07-09 10:25:02 +08:00
92679d3ebc 样式修改 2025-07-09 10:21:48 +08:00
dc94ec5f5f Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-08 10:54:46 +08:00
c67ae635d8 style:样式修改 2025-07-08 10:54:43 +08:00
4233efe422 fix: 后台图片上传路径bug 2025-07-07 18:01:12 +08:00
28e3e08f86 fix: 后台图片上传路径bug 2025-07-07 17:50:52 +08:00
be7f4edff5 pref: 图片大小调整 2025-07-07 16:39:02 +08:00
3d777043e8 pref: 图片大小调整 2025-07-07 16:22:51 +08:00
9aafb6321b 1 2025-07-07 15:27:22 +08:00
942a5706ca 1 2025-07-07 15:23:30 +08:00
73b8562d71 style:单词换行 2025-07-07 15:21:44 +08:00
c3733e24a7 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-07 15:15:32 +08:00
eeaa27d0b4 style:品类换行 2025-07-07 15:15:30 +08:00
a5e20a3840 feat: migration/seed 2025-07-05 18:01:22 +08:00
d809690724 Merge branch 'dev' of https://gitea.f2b211.com/jsasg/orico-official-website into dev 2025-07-05 17:35:30 +08:00
447885529e style:样式调整 2025-07-05 17:35:27 +08:00
89e46189bd feat: 后台 图片上传新增webp格式转换处理 2025-07-05 15:19:46 +08:00
29ea63199c fix: openapi 文章详情取消author,source字段输出 2025-07-05 14:41:32 +08:00
3ef1fc634a fix: openapi 文章分类取消short_name, desc字段输出 2025-07-05 14:02:17 +08:00
4d988c316b fix: openapi 取消产品分类icon,desc字段输出 2025-07-05 14:01:51 +08:00
9182ed29d9 fix: openapi取消产品详情sku->sort字段输出 2025-07-05 13:47:57 +08:00
e1388c63b7 fix: openapi 产品接口取消desc输出 2025-07-05 11:49:55 +08:00
a0d53c6e0e 返回顶部 只要页面过长就显示 2025-07-05 11:12:52 +08:00
6603af60ef id修改为类,间距调整 2025-07-05 10:20:59 +08:00
336f27bc23 Merge branch 'cssupdate' into dev 2025-07-05 09:53:30 +08:00
256975b592 doc: 注释 2025-07-05 09:18:24 +08:00
90508c8c37 fix: openapi 产品详情不输出links->platform问题 2025-07-04 17:42:29 +08:00
120 changed files with 5060 additions and 945 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

@@ -0,0 +1,42 @@
<?php
declare (strict_types = 1);
namespace app\command\OpenApiMgr;
use oauth\OAuthStorage;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
class AddClient extends Command
{
protected function configure()
{
// 指令配置
$this->setName('OpenApiMgr:AddClient')
->addArgument('salt', Argument::OPTIONAL, "开放API的client_secret密钥的盐值")
->setDescription('开放API的client管理');
}
protected function execute(Input $input, Output $output)
{
$salt = $input->getArgument('salt');
$salt = empty($salt) ? null : trim($salt);
// 指令输出
$oauth = new OAuthStorage($salt);
$client_id = random_str(13, 'all', 0);
$client_secret = random_str(32, 'all', 0);
$ok = $oauth->addClient($client_id, $client_secret, null);
if (!$ok) {
$output->writeln("添加失败");
return;
}
$output->writeln("添加成功:\nClientID: {$client_id}\nClientSecret: {$client_secret}\n");
}
}

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,91 @@ 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|null $url, string $disk): string
{
if (is_null($url)) {
return '';
}
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|null $url): string
{
if (is_null($url)) {
return '';
}
$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') {

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([
@@ -396,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

@@ -192,6 +192,8 @@ class TopicNas extends Common
{
// 获取文章分类及文章数据
$parent = ArticleCategoryModel::uniqueLabel('CATEGORY_681182e0a4529')->language($this->lang_id)->value('id');
$parent_two = ArticleCategoryModel::parent($parent)->language($this->lang_id)->column('id');//二级分类id
array_push($parent_two,$parent);
$article_categorys = ArticleCategoryModel::with(['article' => function($query) {
$query->field(['id', 'title', 'category_id'])
->order(['sort' => 'asc', 'id' => 'desc'])
@@ -199,14 +201,48 @@ class TopicNas extends Common
}])
->field([
'id',
'pid',
'name',
'icon'
])
->language($this->lang_id)
->parent($parent)
// ->parent($parent)
->parentChild($parent_two)
->isShow(true)
->order(['sort' => 'asc', 'id' => 'desc'])
->select();
View::assign('article_categorys', $article_categorys);
//查询三级分类
$article_categorys_new = [];
$article_categorys_two = [];
// dump($article_categorys->toArray());exit;
if (!$article_categorys->isEmpty()) {
foreach ($article_categorys->toArray() as $kk=>$vv) {
if ( $parent == $vv['pid'] ) {
array_push($article_categorys_new,$vv);
} else {
$article_categorys_two[$vv['pid']][] = $vv;
}
}
if ( !empty($article_categorys_two) ) {
foreach ($article_categorys_new as &$vvv) {
$articles = $vvv['article'];
if ( isset($article_categorys_two[$vvv['id']]) ) {
foreach ($article_categorys_two[$vvv['id']] as $v) {
foreach ($v['article'] as $av) {
if ( count($articles) < 3 ) {
array_push($articles,$av);
}
}
}
}
$vvv['article'] = $articles;
}
}
}
View::assign('article_categorys', $article_categorys_new);
// View::assign('article_categorys', $article_categorys);
$contacts = [];
// 获取banner数据
@@ -245,19 +281,46 @@ class TopicNas extends Common
// 获取文章分类及文章数据
$parent = ArticleCategoryModel::uniqueLabel('CATEGORY_681182e0a4529')->language($this->lang_id)->value('id');
$parent_two = ArticleCategoryModel::parent($parent)->language($this->lang_id)->column('id');//二级分类id
array_push($parent_two,$parent);
$article_categorys = ArticleCategoryModel::with(['article' => function ($query) {
$query->field(['id', 'title', 'category_id'])->order(['sort' => 'asc', 'id' => 'desc']);
}])
->field([
'id',
'pid',
'name',
'icon'
])
->language($this->lang_id)
->parent($parent)
// ->parent($parent)
->parentChild($parent_two)
->isShow(true)
->order(['sort' => 'asc', 'id' => 'desc'])
->select();
View::assign('article_categorys', $article_categorys);
// dump($article_categorys->toArray());exit;
//查询三级分类
$article_categorys_new = [];
$article_categorys_two = [];
if (!$article_categorys->isEmpty()) {
foreach ($article_categorys->toArray() as $kk=>$vv) {
if ( $parent == $vv['pid'] ) {
$vv['child'] = '';
array_push($article_categorys_new,$vv);
} else {
$article_categorys_two[$vv['pid']][] = $vv;
}
}
if ( !empty($article_categorys_two) ) {
foreach ($article_categorys_new as &$vvv) {
$vvv['child'] = isset($article_categorys_two[$vvv['id']])?$article_categorys_two[$vvv['id']]:'';
}
}
}
// dump($article_categorys_new);exit;
// dump($article_categorys_two);exit;
View::assign('article_categorys', $article_categorys_new);
return View::fetch('help_detail');
}
@@ -274,17 +337,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', []);
// 获取文章数据
@@ -299,8 +378,18 @@ class TopicNas extends Common
->language($this->lang_id)
->where('category_id', 'IN', array_column($categorys, 'id'))
->select();
//查询上级id
$parent_two = ArticleCategoryModel::parentColumn(array_column($categorys, 'id'))->language($this->lang_id)->column('pid','id');//二级分类id
$articles_data = $articles->toArray();
foreach ($articles_data as &$v) {
$v['pid'] = 0;
if ( $parent_two[$v['category_id']] !== $parent ) {
$v['pid'] = $v['category_id'];
$v['category_id'] = $parent_two[$v['category_id']];
}
}
return success('success', $articles->toArray());
return success('success', $articles_data);
}
/**

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

@@ -46,6 +46,27 @@ class ArticleCategoryModel extends ArticleCategoryBaseModel
$query->where('pid', '=', $parent);
}
// 所属上级分类范围查询
public function scopeParentChild($query, $parent)
{
if (is_array($parent)) {
$query->where('pid', 'IN', $parent);
return;
}
$query->where('pid', '=', $parent);
}
// 所属上级分类查询
public function scopeParentColumn($query, $parent)
{
if (is_array($parent)) {
$query->where('id', 'IN', $parent);
return;
}
$query->where('id', '=', $parent);
}
// 所属子分类范围查询
public function scopeChild($query, $id, $merge_self = false)
{

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>

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,6 +12,27 @@
<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">
@@ -46,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,22 +53,44 @@
<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">
{volist name="article_categorys" id="ac" key="idx"}
<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.child" id="ad"}
<li class="two-mues">
<a href="#" class="two-a">
<div><img src="__IMAGES__/nars-jt.png"
class="arrow {if condition='$ad.id == $Request.get.pid'}rotate{/if}">
</div>
<span>{$ad.name}</span>
</a>
<ul class="thress-mues" {if condition='$ad.id == $Request.get.pid' }style="display: block;" {/if}>
{volist name="ad.article" id="ae"}
<li>
<a href="{:url('/index/topic/nas/help_detail', ['cid' => $ac.id ,'pid' => $ad.id, 'id' => $ae.id])}"
style="margin-left:18%;padding: 0.4rem;">{$ae.title}</a>
</li>
{/volist}
</ul>
</li>
{/volist}
{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>
@@ -73,10 +98,34 @@
</ul>
</div>
{/volist}
</div>
{/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}
@@ -102,6 +151,17 @@
$(this).next('.sub-list').slideToggle();
$(this).find('.arrow').toggleClass('rotate');
});
//分类二三级交互
$('.two-a').click(function(e) {
e.preventDefault();
e.stopPropagation(); // 阻止事件冒泡
// 切换当前二级菜单的箭头方向
$(this).find('.arrow').toggleClass('rotate');
// 切换对应的三级菜单显示/隐藏
$(this).siblings('.thress-mues').slideToggle();
});
// 点击顶部搜索图标-点击取消关闭
$('#ssico').click(function () {
$('.nhlpapp-pagescate').hide();
@@ -110,6 +170,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 +209,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>
<!-- 产品主图切换和参数详情-->
@@ -38,11 +42,11 @@
<div id="imageMenu_{$sku.id}" class="imageMenu">
<ul class="image_list">
{volist name="sku.photo_album" id="photo"}
<li id="onlickImg"><img src="{:thumb($photo)}" data-url="{$photo}" /></li>
<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}
</ul>
</div>
@@ -50,7 +54,7 @@
<div class="scrollbutton smallImgDown"></div>
</div>
<!-- 产品大图 -->
<div class="bigImg" id="vertical">
<div class="bigImg" id="vertical" style="width: 75%;">
<!-- 主图 -->
{notempty name="sku.photo_album[0]"}
<img src="{$sku.photo_album[0]}" id="midimg" />
@@ -66,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>
@@ -107,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}
@@ -123,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>
<!-- 关联产品 -->

View File

@@ -35,7 +35,7 @@
</ul>
<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

@@ -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,7 @@
<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() {
@@ -24,13 +24,13 @@
// 直接输出对应的 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>
@@ -55,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);
})();
@@ -65,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"}

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,13 +26,13 @@
<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>
<div class="nhlp-tx-list">
{volist name="vo.article" id="va" key="index"}
<a class="txrow" href="{:url('/index/topic/nas/help_detail', ['cid' => $vo.id, 'id' => $va.id])}">
<a class="txrow" href="{:url('/index/topic/nas/help_detail', ['pid' => $va.category_id,'cid' => $vo.id, 'id' => $va.id])}">
<div class="nhlp-point"></div>
<span class="nhlpsp">{$va.title}</span>
<span class="narhelpgoimg">
@@ -41,7 +41,7 @@
</a>
{/volist}
{if condition="count($vo.article) >= 3"}
<a class="ckgdbt" href="{:url('/index/topic/nas/help_detail', ['cid' => $vo.id, 'id' => isset($vo.article[0])?$vo.article[0]['id']:0])}">
<a class="ckgdbt" href="{:url('/index/topic/nas/help_detail', ['cid' => $vo.id, 'id' => isset($vo.article[0])?$vo.article[0]['id']:0,'pid' => isset($vo.article[0])?$vo.article[0]['category_id']:0])}">
{:lang_i18n('查看更多')} >
</a>
{/if}

View File

@@ -1,17 +1,17 @@
{extend name="public/nas_base" /}
{block name="title"}
{notempty name="article.seo_title"}<title>{$article.seo_title}</title>{else /}{__BLOCK__}{/notempty}
{notempty name="article.seo_title"}<title>{$article.seo_title}</title>{else /}{__BLOCK__}{/notempty}
{/block}
{block name="seo"}
{notempty name="article.seo_keywords"}
<meta name="keywords" content="{$article.seo_keywords}" />
<meta name="description" content="{$article.seo_desc}" />
{else /}
{__BLOCK__}
{/notempty}
{notempty name="article.seo_keywords"}
<meta name="keywords" content="{$article.seo_keywords}" />
<meta name="description" content="{$article.seo_desc}" />
{else /}
{__BLOCK__}
{/notempty}
{/block}
{block name="style"}
<link rel="stylesheet" href="__CSS__/topic_nas_help-detail.css"/>
<link rel="stylesheet" href="__CSS__/topic_nas_help-detail.css" />
{/block}
{block name="main"}
<div class="orico_Page_index">
@@ -32,33 +32,49 @@
<div class="nars-hlpdt-ml">
{notempty name="article_categorys"}
<div class="nav-tree">
<!-- start 三级菜单 -->
{volist name="article_categorys" id="ac"}
<div class="category">
<!-- 一级 -->
<div class="category-title">
<div class="arrow {if condition='$ac.id == $Request.get.cid'}rotate{/if}">
<img src="__IMAGES__/nas-jt.png" class="arrow {if condition='$ac.id == $Request.get.cid'}rotate{/if}" />
</div>
<div class="arrow {if condition='$ac.id == $Request.get.cid'}rotate{/if}"><img src="__IMAGES__/nas-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}>
{volist name="ac.article" id="ar"}
<li>
<a
href="{:url('/index/topic/nas/help_detail', ['cid' => $ac.id, 'id' => $ar.id])}"
{eq name="ar.id" value="$Request.get.id"}class="active"{/eq}
>
{$ar.title}
<!-- 二级-->
<ul class="sub-list" {if condition='$ac.id == $Request.get.cid' }style="display: block;" {/if}>
{volist name="ac.child" id="ad"}
<li class="two-mues">
<a href="#" class="two-a">
<div class="arrow {if condition='$ad.id == $Request.get.pid'}rotate{/if}"><img src="__IMAGES__/nas-jt.png" class="arrow {if condition='$ad.id == $Request.get.pid'}rotate{/if}" /></div>
<span>{$ad.name}</span>
</a>
<ul class="thress-mues" {if condition='$ad.id == $Request.get.pid' }style="display: block;" {/if}>
{volist name="ad.article" id="ae"}
<li><a href="{:url('/index/topic/nas/help_detail', ['cid' => $ac.id,'pid' => $ad.id, 'id' => $ae.id])}" style="padding-top: 6px;padding-left: 30px;" {eq
name="ae.id" value="$Request.get.id" }class="active" {/eq}>{$ae.title}</a></li>
{/volist}
</ul>
<!-- 三级-->
</li>
{/volist}
{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;" {eq
name="ar.id" value="$Request.get.id" }class="active" {/eq}>{$ar.title}</a></li>
{/volist}
</ul>
</div>
{/volist}
<!-- end 三级菜单 -->
</div>
{/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">
@@ -73,10 +89,22 @@
{block name="script"}
<script type="text/javascript">
$(document).ready(function () {
// 一级菜单点击事件
$('.category-title').click(function () {
$(this).next('.sub-list').slideToggle();
$(this).find('.arrow').toggleClass('rotate');
});
// 二级菜单点击事件
$('.two-a').click(function(e) {
e.preventDefault();
e.stopPropagation(); // 阻止事件冒泡
// 切换当前二级菜单的箭头方向
$(this).find('.arrow').toggleClass('rotate');
// 切换对应的三级菜单显示/隐藏
$(this).siblings('.thress-mues').slideToggle();
});
// 搜索
$(document).on('click', function (e) {
var target = $(e.target);
@@ -107,7 +135,7 @@
html = '<ul>'
$.each(r.data, function (k, v) {
html +=
'<li><a href="{:url(\'/index/topic/nas/help_detail\')}?cid=' + v.category_id + '&id=' + v.id + '">' + v.title + '</a></li>'
'<li><a href="{:url(\'/index/topic/nas/help_detail\')}?cid=' + v.category_id + '&id=' + v.id + '&pid=' + v.pid + '">' + v.title + '</a></li>'
})
html += '</ul>'
}
@@ -119,21 +147,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

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

@@ -35,7 +35,6 @@ class Product
'name',
'short_name',
'cover_image',
'desc',
'deleted_at'
])
->where(function($query) use($params) {
@@ -76,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'])
@@ -99,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

@@ -2,9 +2,12 @@
// +----------------------------------------------------------------------
// | 控制台配置
// +----------------------------------------------------------------------
return [
// 指令定义
'commands' => [
'data:migrate' => \app\command\DataMigration::class,
'openapi:addclient' => \app\command\OpenApiMgr\AddClient::class,
],
];

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

@@ -1,2 +0,0 @@
*
!.gitignore

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

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

@@ -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;
@@ -215,4 +219,32 @@
.narshelpCenterdetail-app .nhlpapp-pagescate .nars-hlpdt-ml .sub-list li a:hover {
color: #1f2635;
border-bottom: 1px solid #1f2635;
}
/*9.18 添加三级样式*/
.narshelpCenterdetail-app .nhlpapp-pagescate .nars-hlpdt-ml .sub-list .two-mues {
position: relative;
}
.narshelpCenterdetail-app .nhlpapp-pagescate .nars-hlpdt-ml .sub-list .two-mues .two-a {
position: relative;
padding-top: 6px;
display: flex;
font-size: 0.95rem !important;
flex-direction: row;
}
.narshelpCenterdetail-app .nhlpapp-pagescate .nars-hlpdt-ml .sub-list .two-mues .two-a:hover {
border-bottom: none;
}
.narshelpCenterdetail-app .nhlpapp-pagescate .nars-hlpdt-ml .sub-list .thress-mues {
display: none;
}
.narshelpCenterdetail-app .nhlpapp-pagescate .nars-hlpdt-ml .sub-list .thress-mues a {
padding-top: 0.375rem;
padding-left: 1.875rem;
}

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;

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