From 43272d25ebcf91708745649fa1783dcb80ede356 Mon Sep 17 00:00:00 2001 From: zhs123 <56161944@qq.com> Date: Fri, 24 Jul 2026 17:48:00 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E6=AD=BB=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=B8=85=E7=90=86=20+=20CDN=20SRI=20=E5=8A=A0=E5=9B=BA=20+=20?= =?UTF-8?q?=E9=9D=A2=E5=8C=85=E5=B1=91=E7=BB=84=E4=BB=B6=20+=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E8=A7=84=E8=8C=83=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除 7 个死模板文件 (products/services/quality/process/projects/customization/rfq) - 删除 13 个旧图片素材 (jpg/png/webp) - 新增 CDN SRI 完整性校验 (Bootstrap CSS/JS) - 新增面包屑导航模板组件 - 新增代码清理方案与代码审查标准文档 - 更新 README.md --- CODE_CLEANUP_PLAN.md | 225 +++++++++++++++ CODE_REVIEW_STANDARD.md | 266 ++++++++++++++++++ README.md | 70 +++-- archive-case.php | 18 +- archive-service.php | 18 +- assets/css/theme.css | 84 +++++- assets/css/vendor.css | 45 +-- .../images/factory-workflow-illustration.webp | Bin 101476 -> 0 bytes assets/images/insta-item1.jpg | Bin 154231 -> 0 bytes assets/images/insta-item2.jpg | Bin 162274 -> 0 bytes assets/images/insta-item3.jpg | Bin 193085 -> 0 bytes assets/images/insta-item4.jpg | Bin 194971 -> 0 bytes assets/images/insta-item5.jpg | Bin 241749 -> 0 bytes assets/images/insta-item6.jpg | Bin 287678 -> 0 bytes assets/images/main-logo.png | Bin 2232 -> 0 bytes assets/images/product-item1.jpg | Bin 157255 -> 0 bytes assets/images/product-item2.jpg | Bin 347642 -> 0 bytes assets/images/product-item3.jpg | Bin 168636 -> 0 bytes assets/images/single-image1.png | Bin 352045 -> 0 bytes assets/js/plugins.js | 84 +----- assets/js/theme.js | 8 - header.php | 6 +- inc/customizer.php | 43 --- inc/helpers.php | 22 ++ inc/inquiry.php | 10 +- inc/setup.php | 57 +++- page-about.php | 18 ++ page-contact.php | 14 + page-faq.php | 18 +- single-case.php | 18 +- single-service.php | 18 +- template-parts/breadcrumb.php | 35 +++ template-parts/home/customization.php | 7 - template-parts/home/process.php | 5 - template-parts/home/products.php | 25 -- template-parts/home/projects.php | 5 - template-parts/home/quality.php | 5 - template-parts/home/rfq.php | 42 --- template-parts/home/services.php | 14 - 39 files changed, 848 insertions(+), 332 deletions(-) create mode 100644 CODE_CLEANUP_PLAN.md create mode 100644 CODE_REVIEW_STANDARD.md delete mode 100644 assets/images/factory-workflow-illustration.webp delete mode 100644 assets/images/insta-item1.jpg delete mode 100644 assets/images/insta-item2.jpg delete mode 100644 assets/images/insta-item3.jpg delete mode 100644 assets/images/insta-item4.jpg delete mode 100644 assets/images/insta-item5.jpg delete mode 100644 assets/images/insta-item6.jpg delete mode 100644 assets/images/main-logo.png delete mode 100644 assets/images/product-item1.jpg delete mode 100644 assets/images/product-item2.jpg delete mode 100644 assets/images/product-item3.jpg delete mode 100644 assets/images/single-image1.png create mode 100644 template-parts/breadcrumb.php delete mode 100644 template-parts/home/customization.php delete mode 100644 template-parts/home/process.php delete mode 100644 template-parts/home/products.php delete mode 100644 template-parts/home/projects.php delete mode 100644 template-parts/home/quality.php delete mode 100644 template-parts/home/rfq.php delete mode 100644 template-parts/home/services.php diff --git a/CODE_CLEANUP_PLAN.md b/CODE_CLEANUP_PLAN.md new file mode 100644 index 0000000..dae1ca4 --- /dev/null +++ b/CODE_CLEANUP_PLAN.md @@ -0,0 +1,225 @@ +# 代码清理方案 + +> 项目:B2B Trade 主题(fragrance-trade) +> 基准:2026-07-24 全量代码扫描 +> 原则:分阶段、可回滚、每步可验证 + +--- + +## 清理范围总览 + +| 类别 | 数量 | 风险 | 说明 | +|------|------|------|------| +| 死模板文件 | 7 个 | 低 | 多页面重构后遗留,无任何 `get_template_part()` 引用 | +| 死 JS 库 | 4 个 | 中 | plugins.js 中 6 个库仅 1 个实际使用 | +| 死 CSS 样式 | ~60% vendor.css | 低 | Jarallax + AOS 样式,对应功能未使用 | +| 死图片资源 | 13 个 | 极低 | 旧模板遗留素材,全项目零引用 | +| 死表单处理器 | 1 个 | 中 | inquiry.php 仍挂在 admin_post 但无表单提交 | +| CDN 安全缺失 | 2 处 | 中 | Bootstrap 无 SRI 完整性校验 | +| jQuery 冗余依赖 | 1 处 | 中 | 仅为 Colorbox 一个函数加载整个 jQuery | + +--- + +## 阶段一:死代码删除(零风险) + +> 删除后不影响任何已上线页面。每步删完刷新全站确认无报错。 + +### 1.1 删除 7 个死模板文件 + +| 文件 | 原用途 | 替代方案 | +|------|--------|----------| +| `template-parts/home/products.php` | 旧 B2B 产品展示 | 已被 CPT `service` + `service-teaser.php` 替代 | +| `template-parts/home/services.php` | 旧服务总览 | 已被 `service-teaser.php` 替代 | +| `template-parts/home/quality.php` | 旧质检流程 | 首页不再展示,内容可在关于页补充 | +| `template-parts/home/process.php` | 旧施工流程 | 首页不再展示 | +| `template-parts/home/projects.php` | 旧项目案例 | 已被 CPT `case` + `case-teaser.php` 替代 | +| `template-parts/home/customization.php` | 旧定制服务 | 首页不再展示 | +| `template-parts/home/rfq.php` | 旧预约表单 | 联系页已改为联系方式卡片,无表单 | + +**验证方法**:删除后逐页访问首页 / 关于 / FAQ / 联系页 / 服务列表 / 案例列表,确认无 500 错误、无模板缺失警告。 + +### 1.2 删除 13 个死图片资源 + +| 文件 | 说明 | +|------|------| +| `assets/images/main-logo.png` | 旧 logo,已用 `placeholder-logo.svg` + WP custom-logo | +| `assets/images/product-item1.jpg` | 旧产品图 ×3 | +| `assets/images/product-item2.jpg` | | +| `assets/images/product-item3.jpg` | | +| `assets/images/insta-item1.jpg` | 旧 Instagram 展示图 ×6 | +| `assets/images/insta-item2.jpg` | | +| `assets/images/insta-item3.jpg` | | +| `assets/images/insta-item4.jpg` | | +| `assets/images/insta-item5.jpg` | | +| `assets/images/insta-item6.jpg` | | +| `assets/images/single-image1.png` | 旧单图素材 | +| `assets/images/factory-workflow-illustration.webp` | 旧流程插图 | + +**验证方法**:全项目 grep 这些文件名,确认零引用(已验证)。 + +--- + +## 阶段二:JS 依赖瘦身(中等风险) + +> 当前 plugins.js 拼接了 6 个库,但只有 Colorbox 真正在用。 +> AOS 虽然在 theme.js 中初始化,但没有任何模板使用 `data-aos` 属性,属于空转。 + +### 2.1 库使用情况核实 + +| 库 | plugins.js 中 | theme.js 调用 | 模板中使用 | 结论 | +|----|--------------|---------------|-----------|------| +| jQuery Easing | 有 | 无 | 无 | **删除** | +| Jarallax v2.0.2 | 有 | 无 | 无 | **删除** | +| Colorbox 1.6.4 | 有 | `$.fn.colorbox()` | `class="youtube"` 在 video.php | **保留** | +| AOS | 有 | `AOS.init()` | 无 `data-aos` 属性 | **删除** | +| anime.js | 有 | 无 | 无 | **删除** | +| HC-Sticky | 有 | 无 | 无 | **删除** | + +### 2.2 操作步骤 + +**步骤 A — 清理 theme.js 中的 AOS 调用** + +删除 `initAnimations()` 函数及其调用(第 19-22 行、第 42 行)。AOS 在空转,删了不影响任何可见效果。 + +**步骤 B — 重写 plugins.js** + +将 plugins.js 从 6 库拼接缩减为仅保留 Colorbox 1.6.4(约 4KB)。其余 5 个库全部移除。 + +**步骤 C — 清理 vendor.css** + +删除 vendor.css 中的 Jarallax 样式(第 6-36 行)和 AOS 样式(第 89 行至文件末尾的大段压缩 CSS)。仅保留 Colorbox 样式(第 39-85 行)。 + +**步骤 D — 评估 jQuery 去留** + +Colorbox 依赖 jQuery。两个选项: + +| 方案 | 改动量 | 效果 | +|------|--------|------| +| **A. 保留 jQuery**(推荐当前阶段) | 无 | 维持现状,Colorbox 正常工作 | +| B. 用原生 lightbox 替代 Colorbox | 中等 | 彻底去掉 jQuery 依赖,减少 ~90KB 加载 | + +> 方案 B 需要找一个不依赖 jQuery 的 lightbox 库(如 GLightbox)并改写 theme.js 的 `initVideoLightbox()`。建议放到独立迭代中做,不在本次清理范围内。 + +**验证方法**: +1. 打开关于门店页,点击施工视频缩略图,确认 Colorbox 弹窗正常弹出 +2. 检查浏览器控制台无 JS 报错 +3. 对比清理前后页面加载时间(预计减少 ~80KB JS 传输) + +--- + +## 阶段三:死表单处理器处理(中等风险) + +### 3.1 现状 + +`inc/inquiry.php` 注册了 `admin_post_fragrance_rfq` 和 `admin_post_nopriv_fragrance_rfq` 两个 hook,但联系页已无表单,这些 hook 永远不会被触发。 + +### 3.2 两个选项 + +| 方案 | 操作 | 理由 | +|------|------|------| +| **A. 保留但标注弃用**(推荐) | 在文件头加 `@deprecated` 注释,保留 hook 注册 | 未来可能恢复预约表单功能,代码本身安全合规,留着不碍事 | +| B. 完全删除 | 删除 inquiry.php + 从 functions.php 移除加载 | 彻底清理,但未来恢复需重写 | + +> 推荐 A:inquiry.php 的安全实现(nonce + honeypot + 速率限制 + 邮件头注入防护)是项目中的优秀范例,删了可惜。标注弃用即可。 + +--- + +## 阶段四:CDN 安全加固(中等风险) + +### 4.1 现状 + +`inc/setup.php` 第 47-54 行从 `cdn.bootcdn.net` 加载 Bootstrap CSS/JS,无 `integrity` 属性(SRI),无本地回退。如果 CDN 被劫持,攻击者可注入恶意代码。 + +### 4.2 操作步骤 + +**步骤 A — 添加 SRI 完整性校验** + +为 Bootstrap CSS 和 JS 添加 `integrity` + `crossorigin` 属性。需要从 [BootCDN](https://www.bootcdn.cn/) 获取对应版本的 SRI 哈希。 + +```php +// 修改前 +wp_enqueue_style( 'fragrance-bootstrap', 'https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.0-alpha3/css/bootstrap.min.css', array(), '5.3.0-alpha3' ); + +// 修改后(需填入实际哈希) +wp_enqueue_style( 'fragrance-bootstrap', 'https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.0-alpha3/css/bootstrap.min.css', array(), '5.3.0-alpha3' ); +// WP 的 wp_enqueue_style 不直接支持 integrity,需用 style_loader_tag 过滤器追加属性 +``` + +由于 WordPress 的 `wp_enqueue_*` 函数不直接支持 `integrity` / `crossorigin` 属性,需要通过 `style_loader_tag` 和 `script_loader_tag` 过滤器注入: + +```php +// 在 inc/setup.php 中添加 +function fragrance_trade_resource_integrity( $html, $handle ) { + $sri = array( + 'fragrance-bootstrap' => 'sha384-XXXXX', // 替换为实际哈希 + ); + if ( isset( $sri[ $handle ] ) ) { + $html = str_replace( '/>', ' integrity="' . $sri[ $handle ] . '" crossorigin="anonymous" />', $html ); + } + return $html; +} +add_filter( 'style_loader_tag', 'fragrance_trade_resource_integrity', 10, 2 ); +``` + +> **注意**:Google Fonts 不支持 SRI(动态生成 CSS),保持现状即可。 + +**步骤 B — 可选:本地回退** + +将 Bootstrap 下载到 `assets/vendor/bootstrap/`,CDN 加载失败时自动回退。此步骤为可选项,当前 CDN 可用性已较高。 + +**验证方法**:浏览器 DevTools → Network → 确认 Bootstrap 资源加载请求携带 `integrity` 头。 + +--- + +## 阶段五:Customizer 配置清理(低风险) + +### 5.1 现状 + +`inc/customizer.php` 中仍有大量为已删除模板配置的 Customizer 字段(products、services、quality、process、projects、customization 等)。这些字段在后台 Customizer 面板中可见但对应的模板已不存在,用户会困惑。 + +### 5.2 操作步骤 + +1. 逐个移除已删除模板对应的 Customizer section + 字段注册代码 +2. 对应的 `inc/defaults.php` 默认值也一并清理 +3. 保留仍在使用的 section:hero、trust、store_info、contact_social、video、documents、faq + +> **注意**:此阶段改动量大且涉及 Customizer 面板结构,建议在测试环境验证后再上线。 + +--- + +## 执行顺序与预估 + +| 阶段 | 内容 | 文件改动数 | 风险 | 建议优先级 | +|------|------|-----------|------|-----------| +| 一 | 删死模板 + 死图片 | 删 20 个文件 | 极低 | 立即执行 | +| 二 | JS 库瘦身 | 改 3 个文件 | 中 | 紧随其后 | +| 三 | 表单处理器标注 | 改 1 个文件 | 极低 | 随手做 | +| 四 | CDN SRI 加固 | 改 1 个文件 | 低 | 本周内 | +| 五 | Customizer 清理 | 改 2 个文件 | 中 | 下次迭代 | + +--- + +## 每阶段完成后的检查清单 + +- [ ] 全站逐页访问无 500 / 404 +- [ ] 浏览器控制台无 JS 报错 +- [ ] WP Debug Log 无 PHP warning/notice +- [ ] Customizer 面板无残留无效 section +- [ ] Git 提交信息标注 `[cleanup]` + 阶段编号 +- [ ] 推送到 Gitea 前本地验证通过 + +--- + +## 回滚方案 + +每个阶段独立提交,如果发现问题: + +```bash +# 查看提交历史 +git log --oneline + +# 回退到指定提交 +git revert +``` + +阶段一和阶段二各自独立 commit,确保可单独回滚。 diff --git a/CODE_REVIEW_STANDARD.md b/CODE_REVIEW_STANDARD.md new file mode 100644 index 0000000..6b17141 --- /dev/null +++ b/CODE_REVIEW_STANDARD.md @@ -0,0 +1,266 @@ +# 代码审查标准与流程 + +> 适用项目:B2B Trade 主题(fragrance-trade) +> 技术栈:WordPress 经典主题 / PHP 7.4+ / Bootstrap 5.3 / jQuery +> 版本:v1.0 | 2026-07-24 + +--- + +## 一、审查原则 + +1. **安全优先** — WordPress 主题的 XSS / SQL 注入 / CSRF 是红线 +2. **就事论事** — 评论针对代码,不针对人 +3. **说清楚为什么** — 不只说"改这个",要解释原因和潜在风险 +4. **给方向不给答案** — 引导作者自己思考,除非是明确的安全漏洞 +5. **赞美好代码** — 发现优秀实践要明确指出,让团队学习 + +--- + +## 二、优先级体系 + +每个审查意见必须标注以下级别之一: + +| 级别 | 标记 | 含义 | 处理要求 | +|------|------|------|----------| +| 🔴 阻断 | Blocker | 安全漏洞 / 数据丢失 / 破坏功能 | **必须修复后才能合并** | +| 🟡 建议 | Suggestion | 输入验证缺失 / 性能问题 / 可维护性 | **应当修复,可协商** | +| 💭 细节 | Nit | 命名 / 风格 / 文档 | 修不修都行,不阻塞 | + +--- + +## 三、WordPress 主题专项审查清单 + +### 🔴 阻断级检查项(必须全部通过) + +#### 3.1 安全性 + +- [ ] **直接访问防护** — 所有 PHP 文件以 `if ( ! defined( 'ABSPATH' ) ) exit;` 开头 +- [ ] **SQL 注入** — 禁止拼接 SQL;必须使用 `$wpdb->prepare()` 或 WP API(`get_posts()`, `WP_Query`) +- [ ] **XSS 防护** — 所有输出必须经过转义: + - HTML 文本 → `esc_html()` + - URL → `esc_url()` + - 属性 → `esc_attr()` + - 富文本 → `wp_kses_post()` +- [ ] **CSRF 防护** — 所有表单提交 / POST 处理必须有 `wp_nonce_field()` + `check_admin_referer()` +- [ ] **输入净化** — 所有 `$_POST` / `$_GET` / `$_SERVER` 必须用 `wp_unslash()` + 对应 `sanitize_*` 函数 +- [ ] **邮件头注入** — 从用户输入构造邮件头时,必须剥离 `\r\n` +- [ ] **文件包含** — 禁止用户输入直接传入 `include` / `require` / `get_template_part()` +- [ ] **权限检查** — 任何管理员操作必须有 `current_user_can()` 检查 + +#### 3.2 功能正确性 + +- [ ] **关键路径错误处理** — 表单提交失败有 fallback(非空白白屏) +- [ ] **数据完整性** — 不会因空值 / 缺失字段导致 fatal error +- [ ] **重定向安全** — 使用 `wp_safe_redirect()` + `wp_validate_redirect()`,禁止直接 `header('Location:')` + +### 🟡 建议级检查项 + +#### 3.3 输入验证与数据 + +- [ ] Customizer 字段是否有对应类型的 `sanitize_callback` +- [ ] `get_theme_mod()` 取值后是否有默认值兜底 +- [ ] 用户上传的 URL 是否用 `esc_url_raw()` 存入、`esc_url()` 输出 + +#### 3.4 性能 + +- [ ] **N+1 查询** — 循环内不执行数据库查询,提前预取 +- [ ] **资源加载** — 脚本用 `wp_enqueue_script`,不硬编码 `', ' integrity="' . esc_attr( $sri[ $handle ] ) . '" crossorigin="anonymous">', $html ); + } + return $html; +} +add_filter( 'script_loader_tag', 'fragrance_trade_script_sri', 10, 2 ); diff --git a/page-about.php b/page-about.php index f732a02..99f748c 100644 --- a/page-about.php +++ b/page-about.php @@ -10,6 +10,24 @@ get_header();
+ +
+ array( + array( 'label' => __( '首页', 'fragrance-trade' ), 'url' => home_url( '/' ) ), + array( 'label' => __( '关于门店', 'fragrance-trade' ), 'url' => null ), + ), + ) + ); + ?> +
+
+
+ array( + array( 'label' => __( '首页', 'fragrance-trade' ), 'url' => home_url( '/' ) ), + array( 'label' => __( '预约联系', 'fragrance-trade' ), 'url' => null ), + ), + ) + ); + ?>
@@ -96,5 +109,6 @@ $map_nav_url = 'https://api.map.baidu.com/geocoder?address='
+
diff --git a/page-faq.php b/page-faq.php index 85a45aa..d93ac47 100644 --- a/page-faq.php +++ b/page-faq.php @@ -8,11 +8,25 @@ get_header(); ?>
-
diff --git a/single-case.php b/single-case.php index 04a4c1f..8d063d8 100644 --- a/single-case.php +++ b/single-case.php @@ -9,11 +9,19 @@ get_header();
- + array( + array( 'label' => __( '首页', 'fragrance-trade' ), 'url' => home_url( '/' ) ), + array( 'label' => __( '案例作品', 'fragrance-trade' ), 'url' => home_url( '/cases/' ) ), + array( 'label' => get_the_title(), 'url' => null ), + ), + ) + ); + ?>
'img-fluid rounded' ) ); ?>
diff --git a/single-service.php b/single-service.php index 0b17301..4c8f1bd 100644 --- a/single-service.php +++ b/single-service.php @@ -13,11 +13,19 @@ get_header(); $img = $image ? $image : fragrance_trade_asset_uri( 'products/placeholder-01.svg' ); ?>
- + array( + array( 'label' => __( '首页', 'fragrance-trade' ), 'url' => home_url( '/' ) ), + array( 'label' => __( '服务项目', 'fragrance-trade' ), 'url' => home_url( '/services/' ) ), + array( 'label' => get_the_title(), 'url' => null ), + ), + ) + ); + ?>
<?php the_title_attribute(); ?> diff --git a/template-parts/breadcrumb.php b/template-parts/breadcrumb.php new file mode 100644 index 0000000..ff16f46 --- /dev/null +++ b/template-parts/breadcrumb.php @@ -0,0 +1,35 @@ + string, 'url' => string|null]. + */ + +if ( empty( $args['items'] ) || ! is_array( $args['items'] ) ) { + return; +} +?> + diff --git a/template-parts/home/customization.php b/template-parts/home/customization.php deleted file mode 100644 index b9072f1..0000000 --- a/template-parts/home/customization.php +++ /dev/null @@ -1,7 +0,0 @@ - -
-
-

-

-
-
diff --git a/template-parts/home/process.php b/template-parts/home/process.php deleted file mode 100644 index 18cb810..0000000 --- a/template-parts/home/process.php +++ /dev/null @@ -1,5 +0,0 @@ - -
-

-

-
diff --git a/template-parts/home/products.php b/template-parts/home/products.php deleted file mode 100644 index 05c9332..0000000 --- a/template-parts/home/products.php +++ /dev/null @@ -1,25 +0,0 @@ - -
-
-

-
- -
-
<?php echo esc_attr( $title ); ?>
-

-
- -
-
-
diff --git a/template-parts/home/projects.php b/template-parts/home/projects.php deleted file mode 100644 index 55c2cbd..0000000 --- a/template-parts/home/projects.php +++ /dev/null @@ -1,5 +0,0 @@ - -
- -
diff --git a/template-parts/home/quality.php b/template-parts/home/quality.php deleted file mode 100644 index 6b4e643..0000000 --- a/template-parts/home/quality.php +++ /dev/null @@ -1,5 +0,0 @@ - -
-

-

-
diff --git a/template-parts/home/rfq.php b/template-parts/home/rfq.php deleted file mode 100644 index 4418259..0000000 --- a/template-parts/home/rfq.php +++ /dev/null @@ -1,42 +0,0 @@ - -
-
-
-
-

-

-

-
-

- -
-
-
-
-
-

-
-
- - -
-
-
-
-
-
-
-
- -

- -
-
-
-
-
-
diff --git a/template-parts/home/services.php b/template-parts/home/services.php deleted file mode 100644 index 27740f7..0000000 --- a/template-parts/home/services.php +++ /dev/null @@ -1,14 +0,0 @@ - -
-
-
-

-

-
-
- - - -
-
-