400 Commits

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

4
.gitattributes vendored
View File

@@ -1,12 +1,10 @@
*.eot filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.woff filter=lfs diff=lfs merge=lfs -text
*.woff2 filter=lfs diff=lfs merge=lfs -text
*.svg filter=lfs diff=lfs merge=lfs -text
*.tff filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.rar filter=lfs diff=lfs merge=lfs -text
*.pdf filter=lfs diff=lfs merge=lfs -text
*.gz filter=lfs diff=lfs merge=lfs -text
*.gzip filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.otf filter=lfs diff=lfs merge=lfs -text

View File

@@ -0,0 +1,26 @@
name: Gitea Actions Official-website
run-name: Deploy to ${{ inputs.deploy_target }} by @${{ gitea.actor }}
on:
push:
branches:
- dev
jobs:
deploy-dev:
runs-on: ubuntu-latest
steps:
- name: Setup SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SERVER_SSH_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts
- name: Deploy application
run: |
ssh ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }} << 'EOF'
set -e
cd /www/wwwroot/dev.ow.f2b211.com
# 拉取最新代码
git pull --rebase
EOF

13
.gitignore vendored
View File

@@ -3,9 +3,22 @@ composer.phar
composer.lock
.DS_Store
Thumbs.db
.env
.env.dev
.env.local
.env.prod
.htaccess
.user.ini
404.html
index.html
public/dist*
public/opendoc
public/logo.png
public/.well-known
/.idea
/.vscode
/.zed
/vendor
/.settings
/.buildpath

24
.zed/settings.json Normal file
View File

@@ -0,0 +1,24 @@
// Folder-specific settings
//
// For a full list of overridable settings, and general information on folder-specific settings,
// see the documentation: https://zed.dev/docs/configuring-zed#settings-files
{
"languages": {
"PHP": {
"language_servers": ["intelephense","!phpactor"]
}
},
"lsp": {
"intelephense": {
"initialization_options": {
"stubs": [
"wordpress",
"laravel",
"symfony",
"codeigniter",
"thinkphp"
]
}
}
}
}

View File

@@ -0,0 +1,219 @@
<?php
declare (strict_types = 1);
namespace app\admin\controller;
use app\admin\model\v1\LanguageModel;
use app\admin\model\v1\ProductCategoryModel;
use app\admin\model\v1\ProductModel;
use app\admin\model\v1\ProductTcoCategoryModel;
use think\facade\Db;
class Operate_Of_ReceiveSync
{
const Add = 'add';
const Update = 'update';
const Enable = 'enable';
const Disable = 'disable';
}
/**
* 接收产品相关同步数据
*/
class ReceiveProductSync
{
// 接收产品目录分类同步数据
public function category()
{
$data = request()->post();
if (empty($data)) return error('请确认同步数据');
$validate = validate([
'name|分类名称' => 'require',
'erp_code|分类ERP编码' => 'require',
]);
if (!$validate->check($data)) {
return error((string)$validate->getError());
}
// 获取对应语言ID
$lang_id = LanguageModel::where('code', $data['lang'])->value('id');
if (empty($lang_id)) {
return error('语言不存在');
}
Db::startTrans();
try {
$tco_category_data = [
'language_id' => $lang_id,
'name' => $data['name'],
'tco_id' => $data['tco_id'],
'tco_pid' => $data['tco_pid'],
'tco_path' => $data['tco_path'],
'erp_id' => $data['erp_id'],
'erp_pid' => $data['erp_pid'],
'erp_code' => $data['erp_code'],
'erp_path' => $data['erp_path'],
'disabled' => Operate_Of_ReceiveSync::Disable == $data['operate'] ? 1 : 0,
'sync_time' => strtotime($data['created_at'])
];
$tco_category = ProductTcoCategoryModel::language($lang_id)->erpCode($tco_category_data['erp_code'])->find();
if (empty($tco_category)) {
$tco_category = ProductTcoCategoryModel::create($tco_category_data);
if ($tco_category->isEmpty()) {
throw new \Exception('产品目录分类创建失败');
}
$category_data = [
'language_id' => $lang_id,
'unique_id' => uniqid('PRO_CATE_'),
'pid' => 0,
'path' => '',
'name' => $tco_category_data['name'],
'icon' => '',
'desc' => '',
'related_tco_category' => $tco_category['id'],
'sort' => 0,
'level' => 1,
'is_show' => 1,
];
$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_data['pid'] = $parent['id'];
$category_data['path'] = $parent['path'] . $parent['pid'];
$category_data['level'] = $parent['level'] + 1;
}
$category = ProductCategoryModel::create($category_data);
if ($category->isEmpty()) {
throw new \Exception('产品分类创建失败');
}
}
else if ($tco_category['sync_time'] < $tco_category_data['sync_time']) {
$success = $tco_category->save($tco_category_data);
if (!$success) {
throw new \Exception('产品目录分类更新失败');
}
$category = ProductCategoryModel::language($lang_id)->tcoId($tco_category['id'])->find();
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('产品分类更新失败');
}
}
}
Db::commit();
} catch (\Throwable $th) {
Db::rollback();
return error(sprintf('%s %s:%d', $th->getMessage(), $th->getFile(), $th->getLine()));
}
return success('同步成功');
}
// 接收产品同步数据
public function product()
{
$data = request()->post();
if (empty($data)) {
return error('请确认同步数据');
}
$validate = validate([
'spu' => 'require',
'name' => 'require',
'category_erp_code' => 'require',
'lang' => 'require',
'created_at' => 'require',
]);
if (!$validate->check($data)) {
return error((string)$validate->getError());
}
// 获取对应语言ID
$lang_id = LanguageModel::where('code', $data['lang'])->value('id');
if (empty($lang_id)) {
return error('语言不存在');
}
// 如果 spu_before_modification 存在则根据 spu_before_modification 更新型号
$product = null;
if (!empty($data['spu_before_modification'])) {
$product = ProductModel::language($lang_id)->spu($data['spu_before_modification'])->find();
}
if (
(empty($data['spu_before_modification']) && !empty($data['spu']))
// 避免 spu_before_modification 更新型号时,人为删除了旧型号导致的新增,从而出现重复型号问题,而进行再次验证
|| (!empty($data['spu_before_modification']) && empty($product))
) {
$product = ProductModel::language($lang_id)->spu($data['spu'])->find();
}
try {
$product_tco_category = ProductTcoCategoryModel::language($lang_id)->erpCode($data['category_erp_code'])->find();
if (empty($product_tco_category)) {
throw new \Exception('官网未找到产品目录同步分类');
}
$product_category = ProductCategoryModel::language($lang_id)->tcoId($product_tco_category['id'])->find();
if (empty($product_category)) {
throw new \Exception('官网未找到产品目录同步分类关联的分类');
}
if (empty($product)) {
$product = ProductModel::create([
'language_id' => $lang_id,
'category_id' => $product_category['id'],
'spu' => $data['spu'],
'name' => $data['name'],
'short_name' => '',
'cover_image' => '',
'desc' => '',
'video_img' => '',
'video_url' => '',
'is_sale' => 1,
'is_new' => 0,
'is_hot' => 0,
'is_show' => 0,
'sort' => 0,
'detail' => '',
'status' => Operate_Of_ReceiveSync::Disable == $data['operate'] ? -1 : 1,
'seo_title' => '',
'seo_keywords' => '',
'seo_desc' => '',
'updated_at' => $data['created_at'],
]);
if ($product->isEmpty()) {
throw new \Exception('产品创建失败');
}
}
else if (strtotime($product['updated_at']) < strtotime($data['created_at'])) {
$product->spu = $data['spu'];
$product->name = $data['name'];
$product->category_id = $product_category['id'];
$product->status = Operate_Of_ReceiveSync::Disable == $data['operate'] ? -1 : 1;
if (!$product->save()) {
throw new \Exception('产品更新失败');
}
}
} catch (\Throwable $th) {
return error(sprintf('%s %s:%d', $th->getMessage(), $th->getFile(), $th->getLine()));
}
return success('同步成功');
}
}

View File

@@ -1,71 +0,0 @@
<?php
declare (strict_types = 1);
namespace app\admin\controller;
use app\admin\model\v1\LanguageModel;
use app\admin\model\v1\ProductCategoryModel;
use app\admin\model\v1\ProductTcoCategoryModel;
use think\facade\Db;
class Operate_Of_ReceiveSync
{
const Add = 'add';
const Update = 'update';
const Enable = 'enable';
const Disable = 'disable';
}
/**
* 接收同步数据
*/
class ReceiveSync
{
public function product_category()
{
$data = request()->post();
if (empty($data)) return error('请确认同步数据');
$lang_id = LanguageModel::where('code', $data['lang'])->value('id');
$record = [
'language_id' => $lang_id,
'name' => $data['name'],
'tco_id' => $data['tco_id'],
'tco_pid' => $data['tco_pid'],
'tco_path' => $data['tco_path'],
'erp_id' => $data['erp_id'],
'erp_pid' => $data['erp_pid'],
'erp_code' => $data['erp_code'],
'erp_path' => $data['erp_path'],
'disabled' => 0,
'sync_time' => strtotime($data['created_at'])
];
if (Operate_Of_ReceiveSync::Disable == $data['operate']) {
$record['disabled'] = 1;
}
$validate = validate([
'name|分类名称' => 'require',
'erp_code|分类ERP编码' => 'require',
]);
if (!$validate->check($record)) {
throw new \Exception((string)$validate->getError());
}
$category = ProductTcoCategoryModel::language($lang_id)->erpCode($record['erp_code'])->find();
Db::startTrans();
try {
if (empty($category)) {
ProductTcoCategoryModel::create($record);
ProductCategoryModel::where
} else {
$category->save($record);
}
} catch (\Throwable $th) {
Db::rollback();
throw $th;
}
}
}

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

@@ -101,6 +101,8 @@ class BannerItem
'rel_prod_cate_id',
'title',
'title_txt_color',
'short_title',
'short_title_txt_color',
'desc',
'desc_txt_color',
'type',
@@ -156,6 +158,8 @@ class BannerItem
'rel_prod_cate_id',
'title',
'title_txt_color',
'short_title',
'short_title_txt_color',
'desc',
'desc_txt_color',
'type',
@@ -240,6 +244,7 @@ class BannerItem
'banner_name' => '分类名称',
'title' => '横幅名称',
'title_txt_color' => '横幅名称字体颜色',
'short_title' => '横幅简称',
'desc' => '描述',
'desc_txt_color' => '描述字体颜色',
'type' => '前台显示类型',
@@ -262,17 +267,16 @@ 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',
'banner.name' => 'banner_name',
'item.title',
'item.title_txt_color',
'item.short_title',
'item.desc',
'item.desc_txt_color',
'item.type',
@@ -311,7 +315,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

@@ -342,6 +342,18 @@ class System
'url' => (string)url('/index/topic/nas/download')
]
]
],
[
'id' => 8,
'name' => '电力品线专题',
'url' => '',
'children' => [
[
'id' => 81,
'name' => '首页',
'url' => (string)url('/index/topic/power_prodline/index')
],
]
]
];
}

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_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(
@@ -131,10 +154,10 @@ class Upload
$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

@@ -29,6 +29,12 @@ class ProductCategoryModel extends ProductCategoryBaseModel
$query->where('language_id', '=', $value);
}
// 所属产品目录分类id查询
public function scopeTcoId($query, $value)
{
$query->where('related_tco_category', '=', $value);
}
/**
* 根据是否显示查询
* @param $query

View File

@@ -80,6 +80,12 @@ class ProductModel extends ProductBaseModel
$query->where('category_id', '=', $value);
}
// 规格型号查询
public function scopeSpu($query, $spu)
{
$query->where('spu', '=', $spu);
}
// 启用状态查询
public function scopeEnabled($query)
{

View File

@@ -23,6 +23,12 @@ class ProductTcoCategoryModel extends ProductTcoCategoryBaseModel
$query->where('language_id', '=', $value);
}
// 根据 tco_id 查询
public function scopeTcoId($query, $value)
{
$query->where('tco_id', '=', $value);
}
// 根据ERP Code查询
public function scopeErpCode($query, $value)
{

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,7 +64,10 @@ class ArticleCategoryValidate extends Validate
if ($value == 0) {
return true;
}
$children = [];
$table_name = (new ArticleCategoryModel)->getTable();
if (env('DB_VERSION', '5') == '8') {
$children = Db::query(
preg_replace(
'/\s+/u',
@@ -77,6 +80,20 @@ class ArticleCategoryValidate extends Validate
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,7 +49,10 @@ class AttachmentCategoryValidate extends Validate
if ($value == 0) {
return true;
}
$children = [];
$table_name = (new AttachmentCategoryModel)->getTable();
if (env('DB_VERSION', '5') == '8') {
$children = Db::query(
preg_replace(
'/\s+/u',
@@ -62,6 +65,20 @@ class AttachmentCategoryValidate extends Validate
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,7 +61,10 @@ class NavigationItemValidate extends Validate
if ($value == 0) {
return true;
}
$children = [];
$table_name = (new SysNavigationItemModel)->getTable();
if (env('DB_VERSION', '5') == '8') {
$children = Db::query(
preg_replace(
'/\s+/u',
@@ -74,6 +77,20 @@ class NavigationItemValidate extends Validate
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,7 +74,10 @@ class SysMenuValidate extends Validate
if ($value == 0) {
return true;
}
$children = [];
$table_name = (new SysMenuModel)->getTable();
if (env('DB_VERSION', '5') == '8') {
$children = Db::query(
preg_replace(
'/\s+/u',
@@ -87,6 +90,20 @@ class SysMenuValidate extends Validate
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,
];
// 保存产品数据
$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']
];
}
$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
];
$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']
];
$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
];
$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;
}
@@ -145,3 +145,90 @@ 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

@@ -21,6 +21,8 @@ class SysBannerItemBaseModel extends BaseModel
'banner_id' => 'int',
'title' => 'string',
'title_txt_color' => 'string',
'short_title' => 'string',
'short_title_txt_color' => 'string',
'desc' => 'string',
'desc_txt_color' => 'string',
'type' => 'string',

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,20 @@
<?php
declare (strict_types = 1);
namespace app\index\controller;
use think\facade\View;
use think\Request;
class TopicLaptop extends Common
{
/**
* 专题 - 笔记本电脑首页
*/
public function index()
{
return View::fetch('index');
}
}

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,7 +337,9 @@ class TopicNas extends Common
->value('id');
// 获取帮且中心分类子分类
$categorys = [];
$table_name = (new ArticleCategoryModel)->getTable();
if (env('DB_VERSION', '5') == '8') {
$categorys = \think\facade\Db::query(preg_replace(
'/\s+/u',
' ',
@@ -285,6 +350,20 @@ class TopicNas extends Common
)
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

@@ -0,0 +1,90 @@
<?php
declare(strict_types=1);
namespace app\index\controller;
use app\index\model\SysBannerModel;
use think\facade\View;
use think\Request;
/**
* 专题 - 电力品线控制器
*/
class TopicPowerProdline extends Common
{
/**
* 专题 - 电力品线首页
*/
public function index()
{
$banners = SysBannerModel::with([
'items' => function ($query) {
$query->withoutField(['sort', 'created_at', 'updated_at', 'deleted_at'])
->order(['sort' => 'asc', 'id' => 'desc'])
->enabled(true);
}
])
->atPlatform(request()->from)
->uniqueLabel([
'BANNER_691e729f2428d',
'BANNER_691e732e4ad69',
'BANNER_691e752d2bbe2',
'BANNER_691e75561c4d3',
'BANNER_691e75ec9391c',
'BANNER_691e7616545bf',
'BANNER_691e763fc08f4',
'BANNER_691e765a27eba',
'BANNER_691e76b6af393',
])
->language($this->lang_id)
->enabled(true)
->order(['sort' => 'asc', 'id' => 'desc'])
->select();
$data = [];
if (!$banners->isEmpty()) {
$banners_map = [];
foreach ($banners as $banner) {
$banners_map[$banner->unique_label] = $banner;
}
// 焦点轮播图
$focus_image = data_get($banners_map, 'BANNER_691e729f2428d')?->items->toArray();
if (!empty($focus_image)) $data['focus_image'] = $focus_image;
// 分类
$category = data_get($banners_map, 'BANNER_691e732e4ad69')?->items->toArray();
if (!empty($category)) $data['category'] = $category;
// 为什么选择奥睿科相关数据
$why_choose = data_get($banners_map, 'BANNER_691e752d2bbe2')?->items->toArray();
if (!empty($why_choose)) $data['why_choose'] = $why_choose;
// 差旅充
$travel_charger = data_get($banners_map, 'BANNER_691e75561c4d3')?->items->toArray();
if (!empty($travel_charger)) $data['travel_charger'] = $travel_charger;
// 家居充
$home_charger = data_get($banners_map, 'BANNER_691e75ec9391c')?->items->toArray();
if (!empty($home_charger)) $data['home_charger'] = $home_charger;
// 桌面充
$desktop_charger = data_get($banners_map, 'BANNER_691e7616545bf')?->items->toArray();
if (!empty($desktop_charger)) $data['desktop_charger'] = $desktop_charger;
// 墙充
$wall_charger = data_get($banners_map, 'BANNER_691e763fc08f4')?->items->toArray();
if (!empty($wall_charger)) $data['wall_charger'] = $wall_charger;
// 转换器
$converter = data_get($banners_map, 'BANNER_691e765a27eba')?->items->toArray();
if (!empty($converter)) $data['converter'] = $converter;
// 底部介绍
$footer_info = data_get($banners_map, 'BANNER_691e76b6af393')?->items->toArray();
if (!empty($footer_info)) $data['footer_info'] = $footer_info;
}
View::assign('data', $data);
return View::fetch('index');
}
}

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

@@ -105,6 +105,18 @@ Route::group('topic', function () {
// 专题-Nas软件下载页
Route::get('download', 'TopicNas/download');
});
// 专题 - 电力品线
Route::group('power_prodline', function() {
// 专题 - 电力品线首页
Route::get('index', 'TopicPowerProdline/index');
});
// 专题 - 笔记本电脑
Route::group('laptop', function() {
// 专题 - 笔记本电脑首页
Route::get('index', 'TopicLaptop/index');
});
});
// 数据迁移

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -33,14 +33,17 @@
</div>
</div>
<!-- 文章内容 -->
<div id="rendered-content" class="nhlp-app-content">
<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>
@@ -54,18 +57,40 @@
<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}>
{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

@@ -0,0 +1,765 @@
{extend name="public/base" /}
{block name="style"}
<!-- 将rem适配JS移到这里确保优先执行 -->
<script type="text/javascript">
(function (doc, win) {
var docEl = doc.documentElement;
var resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
function setRootFontSize() {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
var fontSize = clientWidth / 7.5; // 750px/7.5=100px375px/7.5=50px
// 直接修改内联样式,优先级最高
docEl.setAttribute('style', 'font-size: ' + fontSize + 'px !important;');
}
setRootFontSize();
win.addEventListener(resizeEvt, setRootFontSize);
doc.addEventListener('DOMContentLoaded', setRootFontSize);
})(document, window);
</script>
<link rel="stylesheet" href="__CSS__/topic_power_prodline/index.css">
<link rel="stylesheet" href="__CSS__/topic_power_prodline/swiper.css">
<link rel="stylesheet" href="__CSS__/topic_power_prodline/nav.css">
<link rel="stylesheet" href="__CSS__/topic_power_prodline/advantage.css">
<link rel="stylesheet" href="__CSS__/topic_power_prodline/moren.css">
<link rel="stylesheet" href="__CSS__/topic_power_prodline/mask.css">
<link rel="stylesheet" href="__CSS__/topic_power_prodline/product.css">
<link rel="stylesheet" href="__CSS__/topic_power_prodline/product_list.css">
<link rel="stylesheet" href="__CSS__/topic_power_prodline/product_card.css">
<link rel="stylesheet" href="__CSS__/topic_power_prodline/footer.css">
{/block}
{block name="header"}
<!-- 重置header头为空 -->
{/block}
{block name="main"}
<a class="header" href="/">
<div class="header-img">
<img src="__IMAGES__/logo.png" alt="">
</div>
</a>
<!-- 轮播核心容器 -->
<div class="swiper-container auto-swiper-container" >
{notempty name="data.focus_image"}
<div class="swiper-wrapper">
{volist name="data.focus_image" id="fo"}
<a class="swiper-slide auto-swiper-slide" href="{$fo.link}">
<img src="{$fo.image}" alt="{$fo.title}" />
</a>
{/volist}
</div>
<div class="swiper-pagination"></div>
{/notempty}
</div>
<!-- 分类 -->
{notempty name="data.category"}
<div class="nav-box">
{volist name="data.category" id="ca"}
<a class="nav-item" href="{$ca.link}">
<img src="{$ca.image}" alt="{$ca.title}">
<p {:style(['color'=>$ca.title_txt_color])}>{$ca.title}</p>
</a>
{/volist}
</div>
{/notempty}
<!-- 500万 -->
{notempty name="data.why_choose"}
<div class="advantage-section">
{assign name="why_choose_title" value=":array_shift($data.why_choose)" /}
<h2 class="advantage-section__title">{$why_choose_title.title|default=''|raw}</h2>
<div class="advantage-section__list">
{volist name="data.why_choose" id="ch"}
<div class="advantage-card-wrap">
<div class="advantage-card" data-target="design">
<img src="{$ch.image}" alt="{$ch.title}:{$ch.short_title}" class="advantage-card__img">
<div class="advantage-card__content">
<!-- 标题+箭头容器:水平+垂直双居中,内部文字左、箭头右 -->
<div class="advantage-card__heading-wrap">
<div class="advantage-card__heading" {:style(['color'=>$ch.title_txt_color])}>{$ch.title}</div>
<img src="__IMAGES__/jiant.png" alt="" class="card-arrow">
</div>
<div class="advantage-card__description" {:style(['color'=>$ch.short_title_txt_color])}>{$ch.short_title}</div>
<div style="display:none;" class="mack-conten-text">{$ch.desc|raw}</div>
</div>
</div>
</div>
{/volist}
</div>
</div>
{/notempty}
<!-- 产品差旅充 -->
{notempty name="data.travel_charger"}
<div class="product-box">
{assign name="tc_title" value=":array_shift($data.travel_charger)" /}
<div class="product-title">
<h2 class="product-title-h2">{$tc_title.title|default=''}</h2>
<p class="product-title-p">{$tc_title.short_title|default=''}</p>
</div>
<div class="product-container" >
{assign name="tc_first_section_lf" value=":array_shift($data.travel_charger)" /}
{notempty name="tc_first_section_lf"}
<a class="product-left" href="{$tc_first_section_lf.link}">
<img src="{$tc_first_section_lf.image}" alt="{$tc_first_section_lf.title}" class="product-img">
<!-- 公共类+定位类:尺寸统一,定位不同 -->
<div class="product-img-hover top55">
<img src="{$tc_first_section_lf.extra_image}" alt="{$tc_first_section_lf.short_title}" class="img1">
</div>
</a>
{/notempty}
{assign name="tc_first_section_lr" value=":array_shift($data.travel_charger)" /}
{notempty name="tc_first_section_lr"}
<div class="product-right">
<img src="{$tc_first_section_lr.image}" alt="{$tc_first_section_lr.title}" class="right-content right-img">
<video src="{$tc_first_section_lr.video}" class="right-content right-video" muted loop playsinline>
您的浏览器不支持HTML5视频播放请升级浏览器
</video>
<button class="video-play-btn">
<span class="play-icon">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="10" fill="rgba(0,0,0,0.5)" />
<path d="M9 7L16 12L9 17V7Z" fill="white" />
</svg>
</span>
<!-- 暂停图标(默认隐藏) -->
<span class="pause-icon">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="10" fill="rgba(0,0,0,0.5)" />
<rect x="8" y="7" width="3" height="10" fill="white" />
<rect x="13" y="7" width="3" height="10" fill="white" />
</svg>
</span>
</button>
</div>
{/notempty}
</div>
{assign name="tc_second_section" value=":array_splice($data.travel_charger, 0, 4)" /}
{notempty name="tc_second_section"}
<div class="product-card-box">
<div class="product-card-container">
{volist name="tc_second_section" id="tss"}
<a class="product-card-wrap" href="{$tss.link}">
<div class="product-card" >
<div class="product-card-img">
<img src="{$tss.image}" alt="{$tss.title}">
</div>
<div class="product-card-text">
<div class="product-card-title" {:style(['color'=>$tss.title_txt_color])}>{$tss.title}</div>
<div class="product-card-desc" {:style(['color'=>$tss.short_title_txt_color])}>{$tss.short_title}</div>
</div>
<div class="product-card-link">
<img src="__IMAGES__/ljgd.png" alt="查看更多">
</div>
</div>
</a>
{/volist}
</div>
</div>
{assign name="tc_three_section" value=":array_shift($data.travel_charger)" /}
{notempty name="tc_three_section"}
<a href="{$tc_three_section.link}" class="more">
<div class="more-img">
{$tc_three_section.title}
</div>
</a>
{/notempty}
{/notempty}
</div>
{/notempty}
<!-- 产品 家居充-->
{notempty name="data.home_charger"}
<div class="product-box">
{assign name="hc_title" value=":array_shift($data.home_charger)" /}
<div class="product-title">
<h2 class="product-title-h2">{$hc_title.title|default=''}</h2>
<p class="product-title-p">{$hc_title.short_title|default=''}</p>
</div>
<div class="product-container">
{assign name="hc_first_section_lf" value=":array_shift($data.home_charger)" /}
{notempty name="hc_first_section_lf"}
<a class="product-left" href="{$hc_first_section_lf.link}">
<img src="{$hc_first_section_lf.image}" alt="{$hc_first_section_lf.title}" class="product-img">
<!-- 公共类+定位类:尺寸统一,定位不同 -->
<div class="product-img-hover">
<img src="{$hc_first_section_lf.extra_image}" alt="{$hc_first_section_lf.short_title}" class="img2">
</div>
</a>
{/notempty}
{assign name="hc_first_section_lr" value=":array_shift($data.home_charger)" /}
{notempty name="hc_first_section_lr"}
<div class="product-right">
<img src="{$hc_first_section_lr.image}" alt="{$hc_first_section_lr.title}" class="right-content right-img">
<video src="{$hc_first_section_lr.video}" class="right-content right-video" muted loop playsinline >
您的浏览器不支持HTML5视频播放请升级浏览器
</video>
<button class="video-play-btn">
<span class="play-icon">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="10" fill="rgba(0,0,0,0.5)" />
<path d="M9 7L16 12L9 17V7Z" fill="white" />
</svg>
</span>
<!-- 暂停图标(默认隐藏) -->
<span class="pause-icon">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="10" fill="rgba(0,0,0,0.5)" />
<rect x="8" y="7" width="3" height="10" fill="white" />
<rect x="13" y="7" width="3" height="10" fill="white" />
</svg>
</span>
</button>
</div>
{/notempty}
</div>
{assign name="hc_second_section" value=":array_splice($data.home_charger, 0, 4)" /}
{notempty name="hc_second_section"}
<div class="product-card-box">
<div class="product-card-container">
{volist name="hc_second_section" id="hcs"}
<a class="product-card-wrap" href="{$hcs.link}">
<div class="product-card" href="#">
<div class="product-card-img">
<img src="{$hcs.image}" alt="{$hcs.short_title}">
</div>
<div class="product-card-text">
<div class="product-card-title">{$hcs.title}</div>
<div class="product-card-desc">{$hcs.short_title}</div>
</div>
<div class="product-card-link">
<img src="__IMAGES__/ljgd.png" alt="查看更多">
</div>
</div>
</a>
{/volist}
</div>
</div>
{/notempty}
{assign name="hc_three_section" value=":array_shift($data.home_charger)" /}
{notempty name="hc_three_section"}
<a href="{$hc_three_section.link}" class="more">
<div class="more-img">
{$hc_three_section.title}
</div>
</a>
{/notempty}
</div>
{/notempty}
<!-- 产品 桌面充(悬浮图上右超出)底部列表样式不一样(左文右图) -->
<div class="product-box">
{assign name="dc_title" value=":array_shift($data.desktop_charger)" /}
<div class="product-title">
<h2 class="product-title-h2">{$dc_title.title|default=''}</h2>
<p class="product-title-p">{$dc_title.short_title|default=''}</p>
</div>
<div class="product-container">
{assign name="dc_first_section_lf" value=":array_shift($data.desktop_charger)" /}
{notempty name="dc_first_section_lf"}
<a class="product-left" href="{$dc_first_section_lf.link}">
<img src="{$dc_first_section_lf.image}" alt="{$dc_first_section_lf.short_title}" class="product-img">
<!-- 公共类+定位类:尺寸和第一个完全一致,仅定位不同 -->
<div class="product-img-hover right" >
<img src="{$dc_first_section_lf.extra_image}" alt="{$dc_first_section_lf.short_title}" class="img3">
</div>
</a>
{/notempty}
{assign name="dc_first_section_lr" value=":array_shift($data.desktop_charger)" /}
{notempty name="dc_first_section_lr"}
<div class="product-right">
<img src="{$dc_first_section_lr.image}"
alt="使用场景" class="right-content right-img">
<!--muted loop playsinline controls-->
<video
src="{$dc_first_section_lr.video}"
class="right-content right-video" muted loop playsinline >
您的浏览器不支持HTML5视频播放请升级浏览器
</video>
<button class="video-play-btn">
<span class="play-icon">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="10" fill="rgba(0,0,0,0.5)" />
<path d="M9 7L16 12L9 17V7Z" fill="white" />
</svg>
</span>
<!-- 暂停图标(默认隐藏) -->
<span class="pause-icon">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="10" fill="rgba(0,0,0,0.5)" />
<rect x="8" y="7" width="3" height="10" fill="white" />
<rect x="13" y="7" width="3" height="10" fill="white" />
</svg>
</span>
</button>
</div>
{/notempty}
</div>
{assign name="dc_second_section" value=":array_splice($data.desktop_charger, 0, 2)" /}
{notempty name="dc_second_section"}
<div class="product-card-box">
<div class="product-card-container">
{volist name="dc_second_section" id="dcs"}
<a class="product-card-wrap" href="{$dcs.link}">
<div class="product-card" href="#">
<div class="product-card-img">
<img src="{$dcs.image}" alt="{$dcs.short_title}">
</div>
<div class="product-card-text">
<div class="product-card-title">{$dcs.title}</div>
<div class="product-card-desc">{$dcs.short_title}</div>
</div>
<div class="product-card-link">
<img src="__IMAGES__/ljgd.png" alt="查看更多">
</div>
</div>
</a>
{/volist}
</div>
</div>
{/notempty}
{assign name="dc_three_section" value=":array_shift($data.desktop_charger)" /}
{notempty name="dc_three_section"}
<a href="{$dc_three_section.link}" class="more">
<div class="more-img">
{$dc_three_section.title}
</div>
</a>
{/notempty}
</div>
<!-- 墙插 -->
{notempty name="data.wall_charger"}
<div class="product-box">
{assign name="wc_title" value=":array_shift($data.wall_charger)" /}
<div class="product-title">
<h2 class="product-title-h2">{$wc_title.title|default=''}</h2>
<p class="product-title-p">{$wc_title.short_title|default=''}</p>
</div>
<div class="product-container">
{assign name="wc_first_section_lf" value=":array_shift($data.wall_charger)" /}
{notempty name="wc_first_section_lf"}
<a class="product-left" href="{$wc_first_section_lf.link}">
<img src="{$wc_first_section_lf.image}" alt="{$wc_first_section_lf.title}" class="product-img">
<!-- 公共类+定位类:尺寸统一,定位不同 -->
<div class="product-img-hover top70">
<img src="{$wc_first_section_lf.extra_image}" alt="{$wc_first_section_lf.title}" class="img4">
</div>
</a>
{/notempty}
{assign name="wc_first_section_lr" value=":array_shift($data.wall_charger)" /}
{notempty name="wc_first_section_lr"}
<div class="product-right">
<img src="{$wc_first_section_lr.image}" alt="{$wc_first_section_lr.title}" class="right-content right-img">
<video src="{$wc_first_section_lr.video}" class="right-content right-video" muted loop playsinline>
您的浏览器不支持HTML5视频播放请升级浏览器
</video>
<button class="video-play-btn">
<span class="play-icon">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="10" fill="rgba(0,0,0,0.5)" />
<path d="M9 7L16 12L9 17V7Z" fill="white" />
</svg>
</span>
<!-- 暂停图标(默认隐藏) -->
<span class="pause-icon">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="10" fill="rgba(0,0,0,0.5)" />
<rect x="8" y="7" width="3" height="10" fill="white" />
<rect x="13" y="7" width="3" height="10" fill="white" />
</svg>
</span>
</button>
</div>
{/notempty}
</div>
{assign name="wc_more_section" value=":array_shift($data.wall_charger)" /}
{notempty name="wc_more_section"}
<a href="{$wc_more_section.link}" class="more">
<div class="more-img">
{$wc_more_section.title}
</div>
</a>
{/notempty}
</div>
{/notempty}
{notempty name="data.converter"}
<!-- 转换器 -->
<div class="product-box">
{assign name="ct_title" value=":array_shift($data.converter)" /}
<div class="product-title">
<h2 class="product-title-h2">{$ct_title.title|default=''}</h2>
<p class="product-title-p">{$ct_title.short_title|default=''}</p>
</div>
{assign name="ct_more_section" value=":array_pop($data.converter)" /}
{assign name="ct_chunk_section" value=":array_chunk($data.converter, 2)" /}
{assign name="ct_chunk_section_len" value=":count($ct_chunk_section)" /}
{volist name="ct_chunk_section" id="cts" key="k"}
<div class="product-container">
{assign name="cts_lf" value=":array_shift($cts)" /}
{notempty name="cts_lf"}
<a class="product-left" href="{$cts_lf.link}">
<img src="{$cts_lf.image}" alt="{$cts_lf.title}" class="product-img">
<!-- 公共类+定位类:尺寸统一,定位不同 -->
<!--style="display:flex;justify-content: center;"-->
<div class="product-img-hover top40" >
<!-- style="width:70%"-->
<img src="{$cts_lf.extra_image}" alt="{$cts_lf.title}" class="img5">
</div>
</a>
{/notempty}
{assign name="cts_lr" value=":array_shift($cts)" /}
{notempty name="cts_lr"}
<div class="product-right">
<img src="{$cts_lr.image}" alt="{$cts_lr.title}" class="right-content right-img">
<video src="{$cts_lr.video}" class="right-content right-video" muted loop playsinline>
您的浏览器不支持HTML5视频播放请升级浏览器
</video>
<!-- 播放图标 -->
<button class="video-play-btn">
<span class="play-icon">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="10" fill="rgba(0,0,0,0.5)" />
<path d="M9 7L16 12L9 17V7Z" fill="white" />
</svg>
</span>
<!-- 暂停图标(默认隐藏) -->
<span class="pause-icon">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="10" fill="rgba(0,0,0,0.5)" />
<rect x="8" y="7" width="3" height="10" fill="white" />
<rect x="13" y="7" width="3" height="10" fill="white" />
</svg>
</span>
</button>
</div>
{/notempty}
</div>
{neq name="k" value="$ct_chunk_section_len"}
<div class="line"></div>
{/neq}
{/volist}
{notempty name="ct_more_section"}
<a href="{$ct_more_section.link}" class="more">
<div class="more-img">
{$ct_more_section.title}
</div>
</a>
{/notempty}
</div>
{/notempty}
{notempty name="data.footer_info"}
<!-- 底部 -->
<div class="prodline-footer-box">
<div class="prodline-footer-box-img">
<img src="{$data.footer_info.0.image}" alt="">
</div>
</div>
{/notempty}
<!-- 蒙版 -->
<div class="mask" id="mask">
<div class="mask-content" >
<span class="close-btn">&times;</span>
<div class="mask-scroll-content"></div>
</div>
</div>
{/block}
{block name="script"}
<script type="text/javascript">
let swiper=null;
const advantageItems = document.querySelectorAll('.advantage-card');
let scrollTop = 0; // 保存页面滚动位置
let closeBtnHtml = null; // 关闭按钮元素(全局变量,避免重复创建)
const mask = document.getElementById('mask');
const maskContent = document.querySelector('.mask-content');
const maskScrollContent = document.querySelector('.mask-scroll-content'); // 滚动容器(关键!)
const closeBtn = document.querySelector('.close-btn')
// 初始化:确保 maskScrollContent 存在于 maskContent 中(避免被清空)
if (!maskScrollContent) {
// 如果页面没有 mask-scroll-content动态创建确保结构稳定
const scrollContent = document.createElement('div');
scrollContent.className = 'mask-scroll-content';
maskContent.appendChild(scrollContent);
}
function createCloseBtn() {
if (closeBtnHtml) {
closeBtnHtml.remove();
}
closeBtnHtml = document.createElement('span');
closeBtnHtml.className = 'close-btn';
closeBtnHtml.innerHTML = '&times;';
closeBtnHtml.addEventListener('click', hideMask);
// 挂载到 maskContent而非 scrollContent避免被滚动影响位置
maskContent.prepend(closeBtnHtml);
}
function showMask(contentHtml) {
// 保存页面滚动位置
scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
// 关键:将内容填充到 scrollContent 中(而非直接替换 maskContent
maskScrollContent.innerHTML = contentHtml;
createCloseBtn();
// 显示蒙版
mask.style.display = 'flex';
// 禁止滚动(复用你的逻辑)
document.documentElement.classList.add('no-scroll');
document.body.classList.add('no-scroll');
document.body.style.top = `-${scrollTop}px`;
// 额外:打开蒙版时就重置滚动位置(避免残留上次滚动状态)
maskScrollContent.scrollTop = 0;
}
function hideMask() {
// 关键步骤 1先重置 scrollContent 的滚动位置(此时元素还未被销毁)
maskScrollContent.scrollTop = 0;
// 关键步骤 2清空 scrollContent 的内容(而非 maskContent
maskScrollContent.innerHTML = "";
// 隐藏蒙版
mask.style.display = 'none';
// 恢复滚动(复用你的逻辑)
document.documentElement.classList.remove('no-scroll');
document.body.classList.remove('no-scroll');
document.body.style.top = '';
// 还原页面滚动位置
window.scrollTo(0, scrollTop);
// 移除关闭按钮(可选,避免残留)
if (closeBtnHtml) {
closeBtnHtml.remove();
closeBtnHtml = null;
}
}
// 点击卡片显示详情
advantageItems.forEach((item) => {
item.addEventListener('click', (e) => {
// 获取当前点击卡片内的.mack-conten-text元素
const currentMackContent = e.currentTarget.querySelector('.mack-conten-text');
if (currentMackContent) {
// 关键修改获取该元素的子内容innerHTML 本身就是内部HTML不含当前元素标签
// 若想更彻底,可遍历子节点拼接内容(兼容特殊场景)
let contentHtml = '';
Array.from(currentMackContent.childNodes).forEach(child => {
// 只保留元素节点和文本节点(过滤空节点)
if (child.nodeType === 1 || child.nodeType === 3) {
contentHtml += child.outerHTML || child.textContent;
}
});
// 显示蒙版并传入纯净的子内容
showMask(contentHtml);
}
});
});
// 关闭按钮事件
closeBtn.addEventListener('click', hideMask);
// 点击蒙版背景关闭(可选)
mask.addEventListener('click', (e) => {
if (e.target === mask) hideMask();
});
// ESC 键关闭(可选)
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && mask.style.display === 'flex') hideMask();
});
// 关键:拦截蒙版的 touchmove 事件,阻止滚动穿透(移动端核心)
mask.addEventListener(
'touchmove',
(e) => {
// 只有点击蒙版背景(不是内容区域)才阻止滚动
if (e.target === mask) {
e.preventDefault(); // 阻止默认触摸滚动行为
e.stopPropagation(); // 阻止事件冒泡
}
},
{ passive: false }
); // passive: false 必须,否则 preventDefault 无效
document.addEventListener('DOMContentLoaded', () => {
// 初始化所有视频容器
function initVideoContainers() {
const productRights = document.querySelectorAll('.product-right');
// 支持的视频格式
const supportedVideoFormats = ['.mp4', '.webm', '.ogg', '.mov', '.avi', '.mkv', '.flv', '.wmv'];
productRights.forEach((container, index) => {
const video = container.querySelector('.right-video');
const btn = container.querySelector('.video-play-btn');
const img = container.querySelector('.right-img');
if (!video || !btn || !img) return;
const videoSrc = video.src.trim()
console.log(videoSrc,'=videoSrc=')
// 修复:正确检测有效视频地址
// 排除空字符串、null、undefined
const hasValidVideo = !!videoSrc && videoSrc.trim() !== '' && videoSrc !== 'undefined' && videoSrc !== 'null';
// 验证视频格式是否有效
const isValidFormat = supportedVideoFormats.some(format =>
videoSrc.toLowerCase().endsWith(format) ||
(videoSrc.includes('?') && videoSrc.toLowerCase().split('?')[0].endsWith(format))
);
// 初始化状态:无视频或格式无效则保持图片显示,永不切换
if (!hasValidVideo || !isValidFormat) {
img.style.display = 'block';
video.style.display = 'none';
btn.style.display = 'none';
// 绑定空方法,防止调用报错
video.switchMedia = function() {};
console.log(`容器${index}:无有效视频(src="${videoSrc}"),保持图片显示`);
return;
}
// 有有效视频的情况
console.log(`容器${index}:有有效视频(src="${videoSrc}"),初始化播放逻辑`);
// 初始状态
video.style.display = 'none';
video.pause();
img.style.display = 'block';
btn.style.display = 'none';
btn.style.opacity = '0';
// 同步状态函数
function syncMediaState() {
if (img.style.display === 'block') {
btn.style.display = 'none';
btn.style.opacity = '0';
} else {
btn.style.display = 'block';
btn.style.opacity = '1';
btn.classList.toggle('paused', !video.paused && !video.ended);
}
}
// 按钮点击事件
btn.addEventListener('click', () => {
if (video.paused) {
video.play().catch(() => syncMediaState());
} else {
video.pause();
}
syncMediaState();
});
// 视频事件监听
['play', 'pause', 'ended', 'playing', 'waiting'].forEach(event => {
video.addEventListener(event, syncMediaState);
});
// 滚动切换函数
video.switchMedia = function(showVideo) {
// 只处理有有效视频的情况
if (showVideo) {
img.style.display = 'none';
video.style.display = 'block';
video.play().catch(() => {
console.log(`容器${index}:自动播放失败,需要用户交互`);
syncMediaState();
});
} else {
video.pause();
img.style.display = 'block';
video.style.display = 'none';
}
syncMediaState();
};
// 初始同步
syncMediaState();
});
}
// 滚动监听 - 优化版
function setupScrollWatcher() {
let ticking = false;
function updateVideoVisibility() {
const productRights = document.querySelectorAll('.product-right');
productRights.forEach(container => {
const video = container.querySelector('.right-video');
if (!video || !video.switchMedia) return;
// 检查是否在视口中
const rect = container.getBoundingClientRect();
const viewHeight = window.innerHeight || document.documentElement.clientHeight;
const isInView = rect.top < viewHeight * 0.7 && rect.bottom > viewHeight * 0.3;
// 只对有有效视频的元素调用switchMedia
video.switchMedia(isInView);
});
ticking = false;
}
// 使用requestAnimationFrame优化性能
window.addEventListener('scroll', () => {
if (!ticking) {
requestAnimationFrame(updateVideoVisibility);
ticking = true;
}
});
}
// 初始化
initVideoContainers();
setupScrollWatcher();
// 初始检查一次
setTimeout(() => {
const event = new Event('scroll');
window.dispatchEvent(event);
}, 300);
});
window.onload = function () {
if (typeof Swiper === 'undefined') {
console.error('Swiper加载失败请刷新页面重试');
return;
}
swiper = new Swiper('.auto-swiper-container', {
autoplay: {
delay: 3000, // 3秒切换
disableOnInteraction: false,
},
loop: false,
slidesPerView: 1,
spaceBetween: 0,
// 启用分页指示标(核心配置)
pagination: {
el: '.swiper-pagination', // 对应 HTML 中的指示标容器
clickable: true, // 允许点击指示标切换
// dynamicBullets: true, // 动态指示标(当前激活放大)
//dynamicMainBullets: 3, // 动态模式显示3个核心指示标
},
navigation: false,
scrollbar: false,
on: {
resize: function () {
this.update();
},
},
});
window.addEventListener('resize', function () {
swiper.update();
});
// 初始化时触发滚动事件,确保状态正确
window.dispatchEvent(new Event('scroll'));
};
</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>
<a class="sceneMore" href="{$scene.link}">{:lang_i18n('了解更多')} ></a> -->
<div style="background-image: url('{$scene.image}');" class="sceneimg"></div>
</a>
</div>
{/volist}
</div>
@@ -129,10 +129,10 @@
<span class="otsbtitle">{:lang_i18n('强大功能、简单使用')}</span>
<div class="beforeafter ba-slider">
<!-- 对比前的图片 -->
<img src="__IMAGES__/indeximg1.jpg">
<img src="__IMAGES__/indeximg1.webp">
<div class="resize">
<!-- 对比后的图片 -->
<img src="__IMAGES__/indeximg2.jpg">
<img src="__IMAGES__/indeximg2.webp">
</div>
<!-- 可拖动的分隔条 -->
<span class="handle"></span>

View File

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

View File

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

View File

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

View File

@@ -27,7 +27,9 @@
<p class="ftitle">{:lang_i18n('产品')}</p>
<ul>
{volist name="header_categorys" id="vo"}
{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}
@@ -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>
@@ -125,6 +125,43 @@
</div>
</div>
</header>
<script type="text/javascript">
$(function() {
$('.header-PC #header .navItem>a').each(function(idx, item) {
var _item = $(item);
_item.removeClass('active');
if (_item.attr('href') && compareUrls(location.href, _item.get(0).href)) {
_item.addClass('active').siblings();
}
});
// 比较两个URL是否相等支持只有path的情况并处理有无.html后缀的情况
function compareUrls(url1, url2) {
// 如果输入的是相对路径,添加当前域名
if (!url1.startsWith('http')) {
url1 = window.location.origin + (url1.startsWith('/') ? '' : '/') + url1;
}
if (!url2.startsWith('http')) {
url2 = window.location.origin + (url2.startsWith('/') ? '' : '/') + url2;
}
// 将两个URL转换为URL对象
const urlObj1 = new URL(url1);
const urlObj2 = new URL(url2);
// 获取路径名并移除末尾的斜杠
let path1 = urlObj1.pathname.replace(/\/$/, '');
let path2 = urlObj2.pathname.replace(/\/$/, '');
// 移除.html后缀
path1 = path1.replace(/\.html$/, '');
path2 = path2.replace(/\.html$/, '');
// 比较处理后的路径
return path1 === path2;
}
})
</script>
<script>
$(document).ready(function () {
// 搜索历史记录处理
@@ -155,26 +192,53 @@
return history;
}
// 封装一个函数用于处理鼠标悬停显示和隐藏内容
function handleHover($element, $content) {
$element.mouseenter(function () {
// 同时支持鼠标悬停和点击事件
$element
.mouseenter(function () {
$content.stop(true, true).slideDown(60);
}).mouseleave(function () {
})
.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 +246,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 +274,11 @@
window.location.href = "{:url('product/search')}" + '?keywords=' + keywords;
}
});
// 点击选择国家
$('#countrycheck').click(function () {
$('#countrycheck').click(function (e) {
$('#top-country').toggle();
e.stopPropagation();
});
$('.closecountrybt').click(function () {
$('#top-country').hide();

View File

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

View File

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

View File

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

View File

@@ -8,7 +8,7 @@
<div class="narshelpCenterPc">
<!-- banner-搜索 -->
<div class="pagetopbg">
<img src="__IMAGES__/nas_help_banner.jpg" class="hpbgimg" />
<img src="__IMAGES__/nas_help_banner.webp" class="hpbgimg" />
<div class='nhlp-search'>
<input class="nhlp-ipt" id="search-input" placeholder="{:lang_i18n('请输入搜索关键字,如安装赛博云空间,影视库')}" autocomplete="off" />
<img src="__IMAGES__/nas_help_search.png" class="searchimg" />
@@ -26,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}
@@ -136,7 +136,7 @@
$('#dropdown').hide();
}
});
$('.nhlplxwmit:not(:first)').hover(function () {
$('.nhlplxwmit').hover(function () {
// 当鼠标移入时,显示.lxewmimg 并隐藏.lximg
var lxe = $(this).find('.lxewmimg');
var lxi = $(this).find('.lximg');

View File

@@ -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}
{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 style="margin-left: 30px;"><a href="{:url('/index/topic/nas/help_detail', ['cid' => $ac.id,'pid' => $ad.id, 'id' => $ae.id])}" style="padding-top: 6px;" {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,11 +147,15 @@
// 内容
// 清空标题列表
$("#title-list ul").empty();
// 提取 h1 标题
// 提取 h3 标题
var h1Titles = $("#rendered-content").find("h3");
// 只有当找到h3标题且内容不为空时才进行处理
if (h1Titles.length > 0) {
h1Titles.each(function (index) {
var title = $(this);
var titleText = title.text();
var titleText = title.text().trim(); // 使用trim()去除空白字符
// 只有当标题文本不为空时才添加到列表
if (titleText) {
var titleId = "title-" + index;
title.attr("id", titleId);
var listItem = $("<li>");
@@ -133,7 +165,9 @@
});
listItem.append(link);
$("#title-list ul").append(listItem);
}
});
}
});
</script>
{/block}

View File

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

View File

@@ -0,0 +1,573 @@
{extend name="public/base" /}
{block name="style"}
<link rel="stylesheet" href="__CSS__/topic_power_prodline/index.css">
<link rel="stylesheet" href="__CSS__/topic_power_prodline/swiper.css">
<link rel="stylesheet" href="__CSS__/topic_power_prodline/nav.css">
<link rel="stylesheet" href="__CSS__/topic_power_prodline/advantage.css">
<link rel="stylesheet" href="__CSS__/topic_power_prodline/mask.css">
<link rel="stylesheet" href="__CSS__/topic_power_prodline/product.css">
<link rel="stylesheet" href="__CSS__/topic_power_prodline/product_list.css">
<link rel="stylesheet" href="__CSS__/topic_power_prodline/product_card.css">
<link rel="stylesheet" href="__CSS__/topic_power_prodline/footer.css">
{/block}
{block name="main"}
<!-- 轮播核心容器 -->
<div class="swiper-container auto-swiper-container" >
{notempty name="data.focus_image"}
<div class="swiper-wrapper">
{volist name="data.focus_image" id="fo"}
<a class="swiper-slide auto-swiper-slide" href="{$fo.link}">
<img src="{$fo.image}" alt="{$fo.title}" />
</a>
{/volist}
</div>
<div class="swiper-pagination"></div>
{/notempty}
</div>
<!-- 分类 -->
{notempty name="data.category"}
<div class="nav-box">
{volist name="data.category" id="ca"}
<a class="nav-item" href="{$ca.link}">
<img src="{$ca.image}" alt="{$ca.title}">
<p {:style(['color'=>$ca.title_txt_color])}>{$ca.title}</p>
</a>
{/volist}
</div>
{/notempty}
<!-- 500万 -->
{notempty name="data.why_choose"}
<div class="advantage-section">
{assign name="why_choose_title" value=":array_shift($data.why_choose)" /}
<h2 class="advantage-section__title">{$why_choose_title.title|default=''|raw}</h2>
<div class="advantage-section__list">
{volist name="data.why_choose" id="ch"}
<div class="advantage-card-wrap">
<div class="advantage-card" data-target="design">
<img src="{$ch.image}" alt="{$ch.title}:{$ch.short_title}" class="advantage-card__img">
<div class="advantage-card__content">
<!-- 标题+箭头容器:水平+垂直双居中,内部文字左、箭头右 -->
<div class="advantage-card__heading-wrap">
<div class="advantage-card__heading" {:style(['color'=>$ch.title_txt_color])}>{$ch.title}</div>
<img src="__IMAGES__/jiant.png" alt="" class="card-arrow">
</div>
<div class="advantage-card__description" {:style(['color'=>$ch.short_title_txt_color])}>{$ch.short_title}</div>
<div style="display:none;" class="mack-conten-text">{$ch.desc|raw}</div>
</div>
</div>
</div>
{/volist}
</div>
</div>
{/notempty}
<!-- 产品差旅充 -->
{notempty name="data.travel_charger"}
<div class="product-box">
{assign name="tc_title" value=":array_shift($data.travel_charger)" /}
<div class="product-title">
<h2 class="product-title-h2">{$tc_title.title|default=''}</h2>
<p class="product-title-p">{$tc_title.short_title|default=''}</p>
</div>
<div class="product-container" >
{assign name="tc_first_section_lf" value=":array_shift($data.travel_charger)" /}
{notempty name="tc_first_section_lf"}
<a class="product-left" href="{$tc_first_section_lf.link}">
<img src="{$tc_first_section_lf.image}" alt="{$tc_first_section_lf.title}" class="product-img">
<!-- 公共类+定位类:尺寸统一,定位不同 -->
<div class="product-img-hover product-img-1">
<img src="{$tc_first_section_lf.extra_image}" alt="{$tc_first_section_lf.short_title}">
</div>
</a>
{/notempty}
{assign name="tc_first_section_lr" value=":array_shift($data.travel_charger)" /}
{notempty name="tc_first_section_lr"}
<div class="product-right">
<img src="{$tc_first_section_lr.image}" alt="{$tc_first_section_lr.title}" class="right-content right-img">
<video src="{$tc_first_section_lr.video}" class="right-content right-video" muted loop playsinline controls>
您的浏览器不支持HTML5视频播放请升级浏览器
</video>
</div>
{/notempty}
</div>
{assign name="tc_second_section" value=":array_splice($data.travel_charger, 0, 4)" /}
{notempty name="tc_second_section"}
<div class="product-card-box">
<div class="product-card-container">
{volist name="tc_second_section" id="tss"}
<a class="product-card-wrap" href="{$tss.link}">
<div class="product-card" >
<div class="product-card-img">
<img src="{$tss.image}" alt="{$tss.title}">
</div>
<div class="product-card-text">
<div class="product-card-title" {:style(['color'=>$tss.title_txt_color])}>{$tss.title}</div>
<div class="product-card-desc" {:style(['color'=>$tss.short_title_txt_color])}>{$tss.short_title}</div>
</div>
<div class="product-card-link">
<img src="__IMAGES__/ljgd.png" alt="查看更多">
</div>
</div>
</a>
{/volist}
</div>
</div>
{assign name="tc_three_section" value=":array_shift($data.travel_charger)" /}
{notempty name="tc_three_section"}
<a href="{$tc_three_section.link}" class="more">
<div class="more-img">
{$tc_three_section.title}
</div>
</a>
{/notempty}
{/notempty}
</div>
{/notempty}
<!-- 产品 家居充-->
{notempty name="data.home_charger"}
<div class="product-box">
{assign name="hc_title" value=":array_shift($data.home_charger)" /}
<div class="product-title">
<h2 class="product-title-h2">{$hc_title.title|default=''}</h2>
<p class="product-title-p">{$hc_title.short_title|default=''}</p>
</div>
<div class="product-container">
{assign name="hc_first_section_lf" value=":array_shift($data.home_charger)" /}
{notempty name="hc_first_section_lf"}
<a class="product-left" href="{$hc_first_section_lf.link}">
<img src="{$hc_first_section_lf.image}" alt="{$hc_first_section_lf.title}" class="product-img">
<!-- 公共类+定位类:尺寸统一,定位不同 -->
<div class="product-img-hover product-img-1">
<img src="{$hc_first_section_lf.extra_image}" alt="{$hc_first_section_lf.short_title}">
</div>
</a>
{/notempty}
{assign name="hc_first_section_lr" value=":array_shift($data.home_charger)" /}
{notempty name="hc_first_section_lr"}
<div class="product-right">
<img src="{$hc_first_section_lr.image}" alt="{$hc_first_section_lr.title}" class="right-content right-img">
<video src="{$hc_first_section_lr.video}" class="right-content right-video" muted loop playsinline controls>
您的浏览器不支持HTML5视频播放请升级浏览器
</video>
</div>
{/notempty}
</div>
{assign name="hc_second_section" value=":array_splice($data.home_charger, 0, 4)" /}
{notempty name="hc_second_section"}
<div class="product-card-box">
<div class="product-card-container">
{volist name="hc_second_section" id="hcs"}
<a class="product-card-wrap" href="{$hcs.link}">
<div class="product-card" href="#">
<div class="product-card-img">
<img src="{$hcs.image}" alt="{$hcs.short_title}">
</div>
<div class="product-card-text">
<div class="product-card-title">{$hcs.title}</div>
<div class="product-card-desc">{$hcs.short_title}</div>
</div>
<div class="product-card-link">
<img src="__IMAGES__/ljgd.png" alt="查看更多">
</div>
</div>
</a>
{/volist}
</div>
</div>
{/notempty}
{assign name="hc_three_section" value=":array_shift($data.home_charger)" /}
{notempty name="hc_three_section"}
<a href="{$hc_three_section.link}" class="more">
<div class="more-img">
{$hc_three_section.title}
</div>
</a>
{/notempty}
</div>
{/notempty}
<!-- 产品 桌面充(悬浮图上右超出)底部列表样式不一样(左文右图) -->
<div class="product-box">
{assign name="dc_title" value=":array_shift($data.desktop_charger)" /}
<div class="product-title">
<h2 class="product-title-h2">{$dc_title.title|default=''}</h2>
<p class="product-title-p">{$dc_title.short_title|default=''}</p>
</div>
<div class="product-container">
{assign name="dc_first_section_lf" value=":array_shift($data.desktop_charger)" /}
{notempty name="dc_first_section_lf"}
<a class="product-left" href="{$dc_first_section_lf.link}">
<img src="{$dc_first_section_lf.image}" alt="{$dc_first_section_lf.short_title}" class="product-img">
<!-- 公共类+定位类:尺寸和第一个完全一致,仅定位不同 -->
<div class="product-img-hover product-img-2" >
<img src="{$dc_first_section_lf.extra_image}" alt="{$dc_first_section_lf.short_title}">
</div>
</a>
{/notempty}
{assign name="dc_first_section_lr" value=":array_shift($data.desktop_charger)" /}
{notempty name="dc_first_section_lr"}
<div class="product-right">
<img src="{$dc_first_section_lr.image}"
alt="使用场景" class="right-content right-img">
<!--muted loop playsinline controls-->
<video
src="{$dc_first_section_lr.video}"
class="right-content right-video" muted loop playsinline controls>
您的浏览器不支持HTML5视频播放请升级浏览器
</video>
</div>
{/notempty}
</div>
{assign name="dc_second_section" value=":array_splice($data.desktop_charger, 0, 2)" /}
{notempty name="dc_second_section"}
<div class="product-card-box">
<div class="product-card-container2">
{volist name="dc_second_section" id="dcs"}
<a class="product-card2" href="{$dcs.link}">
<div class="product-text2">
<!-- 新增内部容器,确保所有内容左对齐一致性 -->
<div class="product-text-content2">
<div class="product-card-title2">{$dcs.title}</div> <!-- 测试超出一行省略 -->
<div class="product-card-desc2">{$dcs.short_title}</div> <!-- 测试超出2行省略 -->
<div class="product-card-link2">
<img src="__IMAGES__/ljgd.png" alt="了解更多">
</div>
</div>
</div>
<div class="product-card-img2">
<img src="{$dcs.image}" alt="{$dcs.title}">
</div>
</a>
{/volist}
</div>
</div>
{/notempty}
{assign name="dc_three_section" value=":array_shift($data.desktop_charger)" /}
{notempty name="dc_three_section"}
<a href="{$dc_three_section.link}" class="more">
<div class="more-img">
{$dc_three_section.title}
</div>
</a>
{/notempty}
</div>
<!-- 墙插 -->
{notempty name="data.wall_charger"}
<div class="product-box">
{assign name="wc_title" value=":array_shift($data.wall_charger)" /}
<div class="product-title">
<h2 class="product-title-h2">{$wc_title.title|default=''}</h2>
<p class="product-title-p">{$wc_title.short_title|default=''}</p>
</div>
<div class="product-container">
{assign name="wc_first_section_lf" value=":array_shift($data.wall_charger)" /}
{notempty name="wc_first_section_lf"}
<a class="product-left" href="{$wc_first_section_lf.link}">
<img src="{$wc_first_section_lf.image}" alt="{$wc_first_section_lf.title}" class="product-img">
<!-- 公共类+定位类:尺寸统一,定位不同 -->
<div class="product-img-hover product-img-1">
<img src="{$wc_first_section_lf.extra_image}" alt="{$wc_first_section_lf.title}">
</div>
</a>
{/notempty}
{assign name="wc_first_section_lr" value=":array_shift($data.wall_charger)" /}
{notempty name="wc_first_section_lr"}
<div class="product-right">
<img src="{$wc_first_section_lr.image}" alt="{$wc_first_section_lr.title}" class="right-content right-img">
<video src="{$wc_first_section_lr.video}" class="right-content right-video" muted loop playsinline controls>
您的浏览器不支持HTML5视频播放请升级浏览器
</video>
</div>
{/notempty}
</div>
{assign name="wc_more_section" value=":array_shift($data.wall_charger)" /}
{notempty name="wc_more_section"}
<a href="{$wc_more_section.link}" class="more">
<div class="more-img">
{$wc_more_section.title}
</div>
</a>
{/notempty}
</div>
{/notempty}
{notempty name="data.converter"}
<!-- 转换器 -->
<div class="product-box">
{assign name="ct_title" value=":array_shift($data.converter)" /}
<div class="product-title">
<h2 class="product-title-h2">{$ct_title.title|default=''}</h2>
<p class="product-title-p">{$ct_title.short_title|default=''}</p>
</div>
{assign name="ct_more_section" value=":array_pop($data.converter)" /}
{assign name="ct_chunk_section" value=":array_chunk($data.converter, 2)" /}
{assign name="ct_chunk_section_len" value=":count($ct_chunk_section)" /}
{volist name="ct_chunk_section" id="cts" key="k"}
<div class="product-container">
{assign name="cts_lf" value=":array_shift($cts)" /}
{notempty name="cts_lf"}
<a class="product-left" href="{$cts_lf.link}">
<img src="{$cts_lf.image}" alt="{$cts_lf.title}" class="product-img">
<!-- 公共类+定位类:尺寸统一,定位不同 -->
<!--style="display:flex;justify-content: center;"-->
<div class="product-img-hover product-img-1" >
<!-- style="width:70%"-->
<img src="{$cts_lf.extra_image}" alt="{$cts_lf.title}">
</div>
</a>
{/notempty}
{assign name="cts_lr" value=":array_shift($cts)" /}
{notempty name="cts_lr"}
<div class="product-right">
<img src="{$cts_lr.image}" alt="{$cts_lr.title}" class="right-content right-img">
<video src="{$cts_lr.video}" class="right-content right-video" muted loop playsinline controls>
您的浏览器不支持HTML5视频播放请升级浏览器
</video>
</div>
{/notempty}
</div>
{neq name="k" value="$ct_chunk_section_len"}
<div class="line"></div>
{/neq}
{/volist}
{notempty name="ct_more_section"}
<a href="{$ct_more_section.link}" class="more" style="padding: clamp(1.5rem, 3vw, 3rem) 0">
<div class="more-img">
{$ct_more_section.title}
</div>
</a>
{/notempty}
</div>
{/notempty}
{notempty name="data.footer_info"}
<!-- 底部 -->
<div class="prodline-footer-box">
<div class="prodline-footer-box-img">
<img src="{$data.footer_info.0.image}" alt="">
</div>
</div>
{/notempty}
<!-- 蒙版 -->
<div class="mask" id="mask">
<div class="mask-content" >
<span class="close-btn">&times;</span>
<div class="mask-scroll-content"></div>
</div>
</div>
{/block}
{block name="script"}
<script type="text/javascript">
let swiper=null;
const advantageItems = document.querySelectorAll('.advantage-card');
let scrollTop = 0; // 保存页面滚动位置
let closeBtnHtml = null; // 关闭按钮元素(全局变量,避免重复创建)
const mask = document.getElementById('mask');
const maskContent = document.querySelector('.mask-content');
const maskScrollContent = document.querySelector('.mask-scroll-content'); // 滚动容器(关键!)
const closeBtn = document.querySelector('.close-btn')
// 初始化:确保 maskScrollContent 存在于 maskContent 中(避免被清空)
if (!maskScrollContent) {
// 如果页面没有 mask-scroll-content动态创建确保结构稳定
const scrollContent = document.createElement('div');
scrollContent.className = 'mask-scroll-content';
maskContent.appendChild(scrollContent);
}
function createCloseBtn() {
if (closeBtnHtml) {
closeBtnHtml.remove();
}
closeBtnHtml = document.createElement('span');
closeBtnHtml.className = 'close-btn';
closeBtnHtml.innerHTML = '&times;';
closeBtnHtml.addEventListener('click', hideMask);
// 挂载到 maskContent而非 scrollContent避免被滚动影响位置
maskContent.prepend(closeBtnHtml);
}
function showMask(contentHtml) {
// 保存页面滚动位置
scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
// 关键:将内容填充到 scrollContent 中(而非直接替换 maskContent
maskScrollContent.innerHTML = contentHtml;
createCloseBtn();
// 显示蒙版
mask.style.display = 'flex';
// 禁止滚动(复用你的逻辑)
document.documentElement.classList.add('no-scroll');
document.body.classList.add('no-scroll');
document.body.style.top = `-${scrollTop}px`;
// 额外:打开蒙版时就重置滚动位置(避免残留上次滚动状态)
maskScrollContent.scrollTop = 0;
}
function hideMask() {
// 关键步骤 1先重置 scrollContent 的滚动位置(此时元素还未被销毁)
maskScrollContent.scrollTop = 0;
// 关键步骤 2清空 scrollContent 的内容(而非 maskContent
maskScrollContent.innerHTML = "";
// 隐藏蒙版
mask.style.display = 'none';
// 恢复滚动(复用你的逻辑)
document.documentElement.classList.remove('no-scroll');
document.body.classList.remove('no-scroll');
document.body.style.top = '';
// 还原页面滚动位置
window.scrollTo(0, scrollTop);
// 移除关闭按钮(可选,避免残留)
if (closeBtnHtml) {
closeBtnHtml.remove();
closeBtnHtml = null;
}
}
// 点击卡片显示详情
advantageItems.forEach((item) => {
item.addEventListener('click', (e) => {
// 获取当前点击卡片内的.mack-conten-text元素
const currentMackContent = e.currentTarget.querySelector('.mack-conten-text');
if (currentMackContent) {
// 关键修改获取该元素的子内容innerHTML 本身就是内部HTML不含当前元素标签
// 若想更彻底,可遍历子节点拼接内容(兼容特殊场景)
let contentHtml = '';
Array.from(currentMackContent.childNodes).forEach(child => {
// 只保留元素节点和文本节点(过滤空节点)
if (child.nodeType === 1 || child.nodeType === 3) {
contentHtml += child.outerHTML || child.textContent;
}
});
// 显示蒙版并传入纯净的子内容
showMask(contentHtml);
}
});
});
// 关闭按钮事件
closeBtn.addEventListener('click', hideMask);
// 点击蒙版背景关闭(可选)
mask.addEventListener('click', (e) => {
if (e.target === mask) hideMask();
});
// ESC 键关闭(可选)
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && mask.style.display === 'flex') hideMask();
});
// 关键:拦截蒙版的 touchmove 事件,阻止滚动穿透(移动端核心)
mask.addEventListener(
'touchmove',
(e) => {
// 只有点击蒙版背景(不是内容区域)才阻止滚动
if (e.target === mask) {
e.preventDefault(); // 阻止默认触摸滚动行为
e.stopPropagation(); // 阻止事件冒泡
}
},
{ passive: false }
); // passive: false 必须,否则 preventDefault 无效
const allVideos = document.querySelectorAll('.right-video');
// 停止所有视频播放
function stopAllVideos() {
allVideos.forEach((video) => {
video.pause();
video.style.display = 'none';
// 显示对应图片
const img = video.parentElement.querySelector('.right-img');
if (img) img.style.display = 'block';
});
}
// 滚动切换图片/视频(核心逻辑)
window.addEventListener('scroll', function () {
const productRights = document.querySelectorAll('.product-right');
let activeVideo = null;
// 找出当前在视口中的视频容器
productRights.forEach((rightContainer) => {
const img = rightContainer.querySelector('.right-img');
const video = rightContainer.querySelector('.right-video');
const videoSrc = video.src.trim()
if (!img || !video) return;
if(!videoSrc) return;
const rect = rightContainer.getBoundingClientRect();
// 视口判断容器进入视口50%以上视为活跃
const isInView =
rect.top < window.innerHeight * 0.7 &&
rect.bottom > window.innerHeight * 0.3;
if (isInView) {
activeVideo = video;
}
});
// 处理活跃视频
if (activeVideo) {
stopAllVideos(); // 先停止其他视频
const img = activeVideo.parentElement.querySelector('.right-img');
img.style.display = 'none';
activeVideo.style.display = 'block';
// 自动播放(兼容原生控制栏,用户手动暂停后不会强制播放)
if (activeVideo.paused) {
activeVideo.play().catch((err) => {
console.log('视频播放失败(浏览器限制):', err);
// 播放失败时回退到图片
activeVideo.style.display = 'none';
img.style.display = 'block';
});
}
} else {
stopAllVideos(); // 无活跃视频时停止所有播放
}
});
window.onload = function () {
if (typeof Swiper === 'undefined') {
console.error('Swiper加载失败请刷新页面重试');
return;
}
swiper = new Swiper('.auto-swiper-container', {
autoplay: {
delay: 3000, // 3秒切换
disableOnInteraction: false,
},
loop: false,
slidesPerView: 1,
spaceBetween: 0,
// 启用分页指示标(核心配置)
pagination: {
el: '.swiper-pagination', // 对应 HTML 中的指示标容器
clickable: true, // 允许点击指示标切换
// dynamicBullets: true, // 动态指示标(当前激活放大)
//dynamicMainBullets: 3, // 动态模式显示3个核心指示标
},
navigation: false,
scrollbar: false,
on: {
resize: function () {
this.update();
},
},
});
window.addEventListener('resize', function () {
swiper.update();
});
// 初始化时触发滚动事件,确保状态正确
window.dispatchEvent(new Event('scroll'));
};
</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

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -31,7 +31,11 @@ Route::group('v1', function() {
->middleware(\app\openapi\middleware\Auth::class);
})
->middleware(\think\middleware\Throttle::class, [
'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

@@ -32,6 +32,8 @@ class CreateSysBannerItem extends Migrator
$table->addColumn('banner_id', 'integer', ['null' => false, 'comment' => '所属Banner ID'])
->addColumn('title', 'string', ['limit' => 256, 'null' => false, 'comment' => '标题'])
->addColumn('title_txt_color', 'string', ['limit' => 7, 'null' => false, 'default' => '', 'comment' => '标题文本颜色'])
->addColumn('short_title', 'string', ['limit' => 255, 'null' => true, 'comment' => 'banner简称'])
->addColumn('short_title_txt_color', 'string', ['limit' => 7, 'null' => true, 'comment' => 'banner简称文本颜色'])
->addColumn('desc', MysqlAdapter::PHINX_TYPE_TEXT, ['null' => true, 'default' => null, 'comment' => '描述'])
->addColumn('desc_txt_color', 'string', ['limit' => 7, 'null' => false, 'default' => '', 'comment' => '描述文本颜色'])
->addColumn('type', 'string', ['limit' => 16, 'null' => false, 'comment' => '类型: image为图片, video为视频'])
@@ -39,7 +41,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],
@@ -73,12 +73,12 @@ class SysConfigInit extends Seeder
["id" => 56, "group_id" => 12, "title" => "Instagram URL新窗口打开", "name" => "article_share_to_instagram.is_blank", "value" => "1", "extra" => "1:是\n0:否", "type" => "radio", "sort" => 6, "remark" => "", "created_at" => "2025-04-23 17:49:12", "updated_at" => "2025-06-12 09:55:21", "deleted_at" => null],
["id" => 57, "group_id" => 12, "title" => "Twitter URL新窗口打开", "name" => "article_share_to_twitter.is_blank", "value" => "1", "extra" => "1:是\n0:否", "type" => "radio", "sort" => 9, "remark" => "", "created_at" => "2025-04-23 17:49:12", "updated_at" => "2025-06-12 09:55:21", "deleted_at" => null],
["id" => 58, "group_id" => 12, "title" => "Reddit URL新窗口打开", "name" => "article_share_to_reddit.is_blank", "value" => "1", "extra" => "1:是\n0:否", "type" => "radio", "sort" => 12, "remark" => "", "created_at" => "2025-04-23 17:49:12", "updated_at" => "2025-06-12 09:55:21", "deleted_at" => null],
["id" => 59, "group_id" => 1, "title" => "产品询盘可选国家", "name" => "optional_country_for_product_inquiry", "value" => "Afghanistan\nAlbania\nAlgeria\nAmerican Samoa\nAndorra\nAngola\nAnguilla\nAntigua and Barbuda\nArgentina\nArmenia\nAruba\nAustralia\nAustria\nAzerbaijan\nAzores\nBahamas\nBahrain\nBangladesh\nBarbados\nBelarus\nBelgium\nBelize\nBenin\nBermuda\nBhutan\nBolivia\nBosnia and Herzegovina\nBotswana\nBrazil\nBrunei\nBulgaria\nBurkina Faso\nBurundi\nCambodia\nCameroon\nCanada\nCanarias\nCape Verde\nCayman\nCentral African Republic\nChad\nChile\nChina\nColombia\nComoros\nCongo (Congo-Kinshasa)\nCongo\nCook Islands\nCosta Rica\nCote D'Ivoire\nCroatia\nCuba\nCyprus\nCzech\nDenmark\nDjibouti\nDominica\nDominican\nEcuador\nEgypt\nEl Salvador\nEquatorial Guinea\nEritrea\nEstonia\nEthiopia\nFiji\nFinland\nFrance\nFrench Guiana\nFrench Polynesia\nGabon\nGambia\nGeorgia\nGermany\nGhana\nGreece\nGreenland\nGrenada\nGuadeloupe\nGuam\nGuatemala\nGuinea\nGuinea-Bissau\nGuyana\nHaiti\nHonduras\nHungary\nIceland\nIndia\nIndonesia\nIran\nIraq\nIreland\nIsrael\nItaly\nJamaica\nJapan\nJordan\nKazakhstan\nKenya\nKiribati\nKorea (North)\nKorea (South)\nKuwait\nKyrgyzstan\nLaos\nLatvia\nLebanon\nLesotho\nLiberia\nLibya\nLiechtenstein\nLithuania\nLuxembourg\nMacedonia\nMadagascar\nMadeira\nMalawi\nMalaysia\nMaldives\nMali\nMalta\nMarshall Islands\nMartinique\nMauritania\nMauritius\nMexico\nMicronesia\nMoldova\nMonaco\nMongolia\nMontserrat\nMorocco\nMozambique\nMyanmar\nNamibia\nNauru\nNepal\nNetherlands Antilles\nNetherlands\nNew Caledonia\nNew Zealand\nNicaragua\nNiger\nNiue\nNorthern Mariana\nNorway\nOman\nPakistan\nPalau\nPalestine\nPanama\nPapua New Guinea\nParaguay\nPeru\nPhilippines\nPitcairn Islands\nPoland\nPortugal\nPuerto Rico\nQatar\nReunion\nRomania\nRussian Federation\nRwanda\nSaint Helena\nSaint Kitts-Nevis\nSaint Lucia\nSaint Vincent and the Grenadines\nSamoa\nSan Marino\nSao Tome and Principe\nSaudi Arabia\nSenegal\nSerbia\nSeychelles\nSierra Leone\nSingapore\nSlovakia\nSlovenia\nSolomon Islands\nSomalia\nSouth Africa\nSpain\nSri Lanka\nSudan\nSuriname\nSwaziland\nSweden\nSwitzerland\nSyria\nTajikistan\nTanzania\nThailand\nThe British Virgin Islands\nThe United States Virgin Islands\nTimor-Leste\nTogo\nTokelau\nTonga\nTrinidad and Tobago\nTunisia\nTurkey\nTurkmenistan\nTurks and Caicos Islands\nTuvalu\nUganda\nUkraine\nUnited Arab Emirates\nUnited Kingdom\nUnited States\nUruguay\nUzbekistan\nVanuatu\nVatican City\nVenezuela\nVietnam\nWallis and Futuna\nWestern Sahara\nYemen\nZambia\nZimbabwe", "extra" => "", "type" => "textarea", "sort" => 7, "remark" => "", "created_at" => "2025-04-27 11:10:22", "updated_at" => "2025-06-11 17:09:13", "deleted_at" => null],
["id" => 60, "group_id" => 4, "title" => "产品询盘可选国家", "name" => "optional_country_for_product_inquiry", "value" => "Afghanistan\nAlbania\nAlgeria\nAmerican Samoa\nAndorra\nAngola\nAnguilla\nAntigua and Barbuda\nArgentina\nArmenia\nAruba\nAustralia\nAustria\nAzerbaijan\nAzores\nBahamas\nBahrain\nBangladesh\nBarbados\nBelarus\nBelgium\nBelize\nBenin\nBermuda\nBhutan\nBolivia\nBosnia and Herzegovina\nBotswana\nBrazil\nBrunei\nBulgaria\nBurkina Faso\nBurundi\nCambodia\nCameroon\nCanada\nCanarias\nCape Verde\nCayman\nCentral African Republic\nChad\nChile\nChina\nColombia\nComoros\nCongo (Congo-Kinshasa)\nCongo\nCook Islands\nCosta Rica\nCote D'Ivoire\nCroatia\nCuba\nCyprus\nCzech\nDenmark\nDjibouti\nDominica\nDominican\nEcuador\nEgypt\nEl Salvador\nEquatorial Guinea\nEritrea\nEstonia\nEthiopia\nFiji\nFinland\nFrance\nFrench Guiana\nFrench Polynesia\nGabon\nGambia\nGeorgia\nGermany\nGhana\nGreece\nGreenland\nGrenada\nGuadeloupe\nGuam\nGuatemala\nGuinea\nGuinea-Bissau\nGuyana\nHaiti\nHonduras\nHungary\nIceland\nIndia\nIndonesia\nIran\nIraq\nIreland\nIsrael\nItaly\nJamaica\nJapan\nJordan\nKazakhstan\nKenya\nKiribati\nKorea (North)\nKorea (South)\nKuwait\nKyrgyzstan\nLaos\nLatvia\nLebanon\nLesotho\nLiberia\nLibya\nLiechtenstein\nLithuania\nLuxembourg\nMacedonia\nMadagascar\nMadeira\nMalawi\nMalaysia\nMaldives\nMali\nMalta\nMarshall Islands\nMartinique\nMauritania\nMauritius\nMexico\nMicronesia\nMoldova\nMonaco\nMongolia\nMontserrat\nMorocco\nMozambique\nMyanmar\nNamibia\nNauru\nNepal\nNetherlands Antilles\nNetherlands\nNew Caledonia\nNew Zealand\nNicaragua\nNiger\nNiue\nNorthern Mariana\nNorway\nOman\nPakistan\nPalau\nPalestine\nPanama\nPapua New Guinea\nParaguay\nPeru\nPhilippines\nPitcairn Islands\nPoland\nPortugal\nPuerto Rico\nQatar\nReunion\nRomania\nRussian Federation\nRwanda\nSaint Helena\nSaint Kitts-Nevis\nSaint Lucia\nSaint Vincent and the Grenadines\nSamoa\nSan Marino\nSao Tome and Principe\nSaudi Arabia\nSenegal\nSerbia\nSeychelles\nSierra Leone\nSingapore\nSlovakia\nSlovenia\nSolomon Islands\nSomalia\nSouth Africa\nSpain\nSri Lanka\nSudan\nSuriname\nSwaziland\nSweden\nSwitzerland\nSyria\nTajikistan\nTanzania\nThailand\nThe British Virgin Islands\nThe United States Virgin Islands\nTimor-Leste\nTogo\nTokelau\nTonga\nTrinidad and Tobago\nTunisia\nTurkey\nTurkmenistan\nTurks and Caicos Islands\nTuvalu\nUganda\nUkraine\nUnited Arab Emirates\nUnited Kingdom\nUnited States\nUruguay\nUzbekistan\nVanuatu\nVatican City\nVenezuela\nVietnam\nWallis and Futuna\nWestern Sahara\nYemen\nZambia\nZimbabwe", "extra" => null, "type" => "textarea", "sort" => 7, "remark" => null, "created_at" => "2025-04-27 11:23:25", "updated_at" => "2025-06-12 09:55:21", "deleted_at" => null],
["id" => 59, "group_id" => 1, "title" => "产品询盘可选国家", "name" => "optional_country_for_product_inquiry", "value" => "Afghanistan\nAlbania\nAlgeria\nAmerican Samoa\nAndorra\nAngola\nAnguilla\nAntigua and Barbuda\nArgentina\nArmenia\nAruba\nAustralia\nAustria\nAzerbaijan\nAzores\nBahamas\nBahrain\nBangladesh\nBarbados\nBelarus\nBelgium\nBelize\nBenin\nBermuda\nBhutan\nBolivia\nBosnia and Herzegovina\nBotswana\nBrazil\nBrunei\nBulgaria\nBurkina Faso\nBurundi\nCambodia\nCameroon\nCanada\nCanarias\nCape Verde\nCayman\nCentral African Republic\nChad\nChile\nChina\nColombia\nComoros\nCongo (Congo-Kinshasa)\nCongo\nCook Islands\nCosta Rica\nCote D'Ivoire\nCroatia\nCuba\nCyprus\nCzech\nDenmark\nDjibouti\nDominica\nDominican\nEcuador\nEgypt\nEl Salvador\nEquatorial Guinea\nEritrea\nEstonia\nEthiopia\nFiji\nFinland\nFrance\nFrench Guiana\nFrench Polynesia\nGabon\nGambia\nGeorgia\nGermany\nGhana\nGreece\nGreenland\nGrenada\nGuadeloupe\nGuam\nGuatemala\nGuinea\nGuinea-Bissau\nGuyana\nHaiti\nHonduras\nHungary\nIceland\nIndia\nIndonesia\nIran\nIraq\nIreland\nIsrael\nItaly\nJamaica\nJapan\nJordan\nKazakhstan\nKenya\nKiribati\nKorea (North)\nKorea (South)\nKuwait\nKyrgyzstan\nLaos\nLatvia\nLebanon\nLesotho\nLiberia\nLibya\nLiechtenstein\nLithuania\nLuxembourg\nMacedonia\nMadagascar\nMadeira\nMalawi\nMalaysia\nMaldives\nMali\nMalta\nMarshall Islands\nMartinique\nMauritania\nMauritius\nMexico\nMicronesia\nMoldova\nMonaco\nMongolia\nMetropolis\nMorocco\nMozambique\nMyanmar\nNamibia\nNauru\nNepal\nNetherlands Antilles\nNetherlands\nNew Caledonia\nNew Zealand\nNicaragua\nNiger\nNiue\nNorthern Mariana\nNorway\nOman\nPakistan\nPalau\nPalestine\nPanama\nPapua New Guinea\nParaguay\nPeru\nPhilippines\nPitcairn Islands\nPoland\nPortugal\nPuerto Rico\nQatar\nReunion\nRomania\nRussian Federation\nRwanda\nSaint Helena\nSaint Kitts-Nevis\nSaint Lucia\nSaint Vincent and the Grenadines\nSamoa\nSan Marino\nSao Tome and Principe\nSaudi Arabia\nSenegal\nSerbia\nSeychelles\nSierra Leone\nSingapore\nSlovakia\nSlovenia\nSolomon Islands\nSomalia\nSouth Africa\nSpain\nSri Lanka\nSudan\nSuriname\nSwaziland\nSweden\nSwitzerland\nSyria\nTajikistan\nTanzania\nThailand\nThe British Virgin Islands\nThe United States Virgin Islands\nTimor-Leste\nTogo\nTokelau\nTonga\nTrinidad and Tobago\nTunisia\nTurkey\nTurkmenistan\nTurks and Caicos Islands\nTuvalu\nUganda\nUkraine\nUnited Arab Emirates\nUnited Kingdom\nUnited States\nUruguay\nUzbekistan\nVanuatu\nVatican City\nVenezuela\nVietnam\nWallis and Futuna\nWestern Sahara\nYemen\nZambia\nZimbabwe", "extra" => "", "type" => "textarea", "sort" => 7, "remark" => "", "created_at" => "2025-04-27 11:10:22", "updated_at" => "2025-06-11 17:09:13", "deleted_at" => null],
["id" => 60, "group_id" => 4, "title" => "产品询盘可选国家", "name" => "optional_country_for_product_inquiry", "value" => "Afghanistan\nAlbania\nAlgeria\nAmerican Samoa\nAndorra\nAngola\nAnguilla\nAntigua and Barbuda\nArgentina\nArmenia\nAruba\nAustralia\nAustria\nAzerbaijan\nAzores\nBahamas\nBahrain\nBangladesh\nBarbados\nBelarus\nBelgium\nBelize\nBenin\nBermuda\nBhutan\nBolivia\nBosnia and Herzegovina\nBotswana\nBrazil\nBrunei\nBulgaria\nBurkina Faso\nBurundi\nCambodia\nCameroon\nCanada\nCanarias\nCape Verde\nCayman\nCentral African Republic\nChad\nChile\nChina\nColombia\nComoros\nCongo (Congo-Kinshasa)\nCongo\nCook Islands\nCosta Rica\nCote D'Ivoire\nCroatia\nCuba\nCyprus\nCzech\nDenmark\nDjibouti\nDominica\nDominican\nEcuador\nEgypt\nEl Salvador\nEquatorial Guinea\nEritrea\nEstonia\nEthiopia\nFiji\nFinland\nFrance\nFrench Guiana\nFrench Polynesia\nGabon\nGambia\nGeorgia\nGermany\nGhana\nGreece\nGreenland\nGrenada\nGuadeloupe\nGuam\nGuatemala\nGuinea\nGuinea-Bissau\nGuyana\nHaiti\nHonduras\nHungary\nIceland\nIndia\nIndonesia\nIran\nIraq\nIreland\nIsrael\nItaly\nJamaica\nJapan\nJordan\nKazakhstan\nKenya\nKiribati\nKorea (North)\nKorea (South)\nKuwait\nKyrgyzstan\nLaos\nLatvia\nLebanon\nLesotho\nLiberia\nLibya\nLiechtenstein\nLithuania\nLuxembourg\nMacedonia\nMadagascar\nMadeira\nMalawi\nMalaysia\nMaldives\nMali\nMalta\nMarshall Islands\nMartinique\nMauritania\nMauritius\nMexico\nMicronesia\nMoldova\nMonaco\nMongolia\nMetropolis\nMorocco\nMozambique\nMyanmar\nNamibia\nNauru\nNepal\nNetherlands Antilles\nNetherlands\nNew Caledonia\nNew Zealand\nNicaragua\nNiger\nNiue\nNorthern Mariana\nNorway\nOman\nPakistan\nPalau\nPalestine\nPanama\nPapua New Guinea\nParaguay\nPeru\nPhilippines\nPitcairn Islands\nPoland\nPortugal\nPuerto Rico\nQatar\nReunion\nRomania\nRussian Federation\nRwanda\nSaint Helena\nSaint Kitts-Nevis\nSaint Lucia\nSaint Vincent and the Grenadines\nSamoa\nSan Marino\nSao Tome and Principe\nSaudi Arabia\nSenegal\nSerbia\nSeychelles\nSierra Leone\nSingapore\nSlovakia\nSlovenia\nSolomon Islands\nSomalia\nSouth Africa\nSpain\nSri Lanka\nSudan\nSuriname\nSwaziland\nSweden\nSwitzerland\nSyria\nTajikistan\nTanzania\nThailand\nThe British Virgin Islands\nThe United States Virgin Islands\nTimor-Leste\nTogo\nTokelau\nTonga\nTrinidad and Tobago\nTunisia\nTurkey\nTurkmenistan\nTurks and Caicos Islands\nTuvalu\nUganda\nUkraine\nUnited Arab Emirates\nUnited Kingdom\nUnited States\nUruguay\nUzbekistan\nVanuatu\nVatican City\nVenezuela\nVietnam\nWallis and Futuna\nWestern Sahara\nYemen\nZambia\nZimbabwe", "extra" => null, "type" => "textarea", "sort" => 7, "remark" => null, "created_at" => "2025-04-27 11:23:25", "updated_at" => "2025-06-12 09:55:21", "deleted_at" => null],
["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,54 +0,0 @@
<?php
try {
$secret_key = 'Aa-1221';
// check for POST request
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
throw new \Exception('FAILED - not POST - '. $_SERVER['REQUEST_METHOD']);
}
// get content type
$content_type = isset($_SERVER['CONTENT_TYPE']) ? strtolower(trim($_SERVER['CONTENT_TYPE'])) : '';
if ($content_type != 'application/json') {
throw new \Exception('FAILED - not application/json - '. $content_type);
}
// get payload
$payload = trim(file_get_contents("php://input"));
if (empty($payload)) {
throw new \Exception('FAILED - no payload');
}
// get header signature
$header_signature = isset($_SERVER['HTTP_X_GITEA_SIGNATURE']) ? $_SERVER['HTTP_X_GITEA_SIGNATURE'] : '';
if (empty($header_signature)) {
throw new \Exception('FAILED - header signature missing');
}
// calculate payload signature
$payload_signature = hash_hmac('sha256', $payload, $secret_key, false);
// check payload signature against header signature
if ($header_signature !== $payload_signature) {
throw new \Exception('FAILED - payload signature');
}
// convert json to array
$decoded = json_decode($payload, true);
// check for json decode errors
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \Exception('FAILED - json decode - '. json_last_error());
}
exec('git pull origin dev --rebase 2>&1', $result);
var_export($result);exit;
} catch (\Throwable $th) {
var_export($th->getMessage());
}

View File

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

View File

@@ -23,7 +23,7 @@
.iotbt1 {
font-size: 18px;
font-family: Montserrat-Bold, Montserrat;
font-family: HarmonyOS-Bold, HarmonyOS;
padding-bottom: 24px;
padding-top: 40px;
font-weight: 700;
@@ -60,7 +60,7 @@
.iotbtp1 {
font-size: 14px;
font-family: Montserrat-Bold, Montserrat;
font-family: HarmonyOS-Bold, HarmonyOS;
font-weight: bold;
padding-bottom: 11px;
word-break: break-word;
@@ -69,7 +69,7 @@
.iotbts1 {
text-align: center;
font-size: 12px;
font-family: Montserrat-Medium, Montserrat;
font-family: HarmonyOS-Medium, HarmonyOS;
color: #9e9e9f;
word-break: break-word;
}
@@ -140,7 +140,7 @@
font-size: 14px;
padding-top: 12px;
text-align: center;
font-family: Montserrat-Medium, Montserrat;
font-family: HarmonyOS-Medium, HarmonyOS;
overflow-wrap: break-word;
word-break: break-word;
}
@@ -152,7 +152,7 @@
.sfbt1 {
text-align: center;
font-size: 18px;
font-family: Montserrat-Bold, Montserrat;
font-family: HarmonyOS-Bold, HarmonyOS;
font-weight: bold;
padding-bottom: 24px;
padding-top: 24px;
@@ -183,7 +183,7 @@
.cit {
width: 100%;
font-size: 14px;
font-family: Montserrat-Regular, Montserrat;
font-family: HarmonyOS-Regular, HarmonyOS;
color: #000;
display: flex;
flex-direction: row;
@@ -237,7 +237,7 @@
.wcu_s1 {
color: #000;
font: 16px;
font-family: Montserrat-Medium, Montserrat;
font-family: HarmonyOS-Medium, HarmonyOS;
font-weight: 500;
padding: 20px 24px;
}

View File

@@ -598,7 +598,7 @@
margin: auto;
font-size: 1rem;
color: #707070;
font-family: "Montserrat-Medium";
font-family: "HarmonyOS-Medium";
}
.oricoCnLc .gallery-thumbs .swiper-slide-thumb-active {
@@ -632,14 +632,14 @@
.oricoCnLc .info h5 {
font-size: #000;
font-size: 1rem;
font-family: "Montserrat-Bold";
font-family: "HarmonyOS-Bold";
padding: 2rem 2rem 0 1rem;
margin: 0;
}
.oricoCnLc .info p {
color: #707070;
font-family: "Montserrat-Regular";
font-family: "HarmonyOS-Regular";
padding: 1rem;
}
@@ -651,7 +651,7 @@
.oricoCnLc .m_ach-b .title {
font-size: 1.125rem;
font-family: "Montserrat-Bold";
font-family: "HarmonyOS-Bold";
width: 98%;
margin: auto;
position: relative;
@@ -660,7 +660,7 @@
.oricoCnLc .m_ach-b .chtitle {
font-size: 1.125rem;
font-family: "Montserrat-Bold";
font-family: "HarmonyOS-Bold";
width: 98%;
margin: auto;
position: relative;
@@ -677,7 +677,7 @@
.oricoCnLc .m_ch-title {
font-size: 1rem;
font-family: "Montserrat-Bold";
font-family: "HarmonyOS-Bold";
width: 98%;
margin: 1rem auto 0;
padding: 1rem 0 0;
@@ -690,7 +690,7 @@
font-size: 0.875;
line-height: 1.5rem;
color: #707070;
font-family: "Montserrat-Regular";
font-family: "HarmonyOS-Regular";
width: 98%;
margin: 1rem auto;
padding: 0;

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