Files
YwxAppThink/docs/guide/haonav_user_guide.md
T
yangwx 18101cf11a feat: 上线前安全加固与发布工程化;appmall 由插件迁移为独立应用
安全(P0)
- 发布包签名:新增 scripts/package_keygen.php、scripts/package_verify.php、
  ywxapp\service\PackageVerifier;FrameworkService::apply() 解压前强制验签
  (ywxapp.framework_package_verify,默认开启)
- JWT 收紧:config/jwt.php 移除公开默认密钥,JwtService::assertStrongSecret()
  校验非空 / 长度≥32 / 已知弱值;.env.production.example 键名由 JWT_SECRET_KEY 修正为 JWT_SECRET
- /api/v1/Article:免登录白名单收窄为只读接口,写操作字段白名单 + assertOwner() 越权校验
- 开发者令牌:查找接口不再回显明文、统一失败文案 + 限流
- TemplateInstaller:文件名白名单 + realpath 归一化 + 目录内断言,修复 Zip Slip;补 use ZipArchive
- 后台登录:接入验证码、失败锁定与登录限流(config/ratelimit.php)
- 缓存 / Session 驱动可由 .env 覆盖(CACHE_DRIVER / SESSION_TYPE),集群部署改 redis
- paycenter 支付日志开关改为 PAY_LOG,不再跟随 APP_DEBUG

工程化 / 交付
- 新增 CHANGELOG.md 与 .env.production.example;composer.lock 入库锁定依赖版本
- 插件离线安装 CLI 增加 --uid,后台上传安装透传 uid,付费插件授权校验可通过
- 授权拒绝文案区分「未携带 uid」与「未找到有效授权」,便于排障
- .gitignore 放行 .env.production.example / .env.addon.example / .gitattributes / public/.htaccess

结构
- appmall 由 addon/appmall 迁移为独立应用 app/appmall(市场 / 开发者中心 / 审核 / 分润)
2026-10-22 00:53:39 +08:00

343 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# haonav 网址导航 — 使用文档
> 面向站长/管理员。开发者请看 [haonav_dev_guide.md](haonav_dev_guide.md)。
- 插件标识:`haonav`
- 版本:1.0.9
- 访问入口:`https://你的域名/haonav`(前台)/ `https://你的域名/haonav/dashboard`(后台)
- 依赖:YwxApp 框架 ≥ PHP 8.0、MySQL 5.7+
---
## 1. 功能总览
| 模块 | 说明 |
|---|---|
| 网址导航首页 | 顶级分类聚合 + 子分类 + 每分类精选链接 + 热门/推荐 |
| 站内搜索 | 关键词/拼音搜索 + 搜索建议(suggest)+ 多引擎跳转 |
| 热门排行 | 按点击量 Top 50 |
| 网址详情页 | 快照预览、评分、JSON-LD 结构化数据(SEO) |
| 分类浏览 | 一级/二级分类,URL 规则化(`/haonav/category/{id}.html`) |
| 申请收录 | 前台投稿 → 后台审核 |
| 广告位 | 首页/详情页广告位管理 + 点击统计 |
| 我的收藏 | 本地收藏(localStorage)+ 云端同步(登录)+ 收藏夹分享页 |
| 实时小组件 | 实时热搜 / 天气(服务端代理 + 缓存) |
| 主题个性化 | 浅色/暗色/跟随系统 + 5 组主色 + 10 组背景渐变 + 自定义背景图 + 随机换色 |
| 节日/节气换装 | **36 项自动检测**(24 节气 + 传统节日 + 公历节日),后台可关,访客可关 |
| PWA 离线 | manifest + Service Worker 缓存(支持添加到主屏幕、离线访问) |
| SEO | sitemap.xml/html、canonical、JSON-LD、拼音搜索 |
| 死链巡检 | 计划任务全量检测 + 前台惰性巡检兜底,可自动下线/恢复 |
---
## 2. 安装与启用
1. 将插件目录放入 `addon/haonav/`
2. 后台 → 应用管理 → 找到「网址导航」→ 安装/启用
3. 首次访问后台配置页时,数据库会自动补种默认配置行(含表主键自愈),无需手工执行 SQL
4. 前台访问 `/haonav` 即可看到空站点,进入后台开始录入
---
## 3. 快速上手(5 分钟建站)
1. **建分类**:后台 → 网址导航 → 分类管理 → 新增一级分类(如「常用工具」),可再挂二级分类
2. **录链接**:链接管理 → 新增 → 选分类、填名称/URL/描述、可选设「热门」「推荐」
3. **看前台**:`/haonav` 首页即展示;点击量自动累计进排行榜
4. **做 SEO**:后台 → 网址导航配置 → 填 SEO 标题/关键词/描述
5. **(可选)开启外观**:同一配置页「外观」分组设置背景图/随机换色/节日换装
---
## 4. 后台管理
### 4.1 数据概览(仪表盘)
`/haonav/dashboard` — 链接/分类/收藏/点击量汇总统计 + 点击热力图。访问时自动为存量链接回填拼音搜索串(每次 300 条,幂等)。
### 4.2 分类管理
- 一级/二级分类、排序(sort 越大越靠前)、启用/禁用
- 删除分类不影响已挂链接(链接保留待重新归类)
### 4.3 链接管理
- 字段:名称、URL、分类、描述、关键词、热门/推荐标记、排序、状态
- 自动抓取 favicon(`/haonav/favicon/...` 代理输出)与网站快照
- **回收站**:删除先进回收站,可恢复/彻底删除
- **死链巡检**:见 §8 计划任务
### 4.4 申请审核(Apply)
前台 `/haonav/apply` 投稿后进入待审列表,可一键通过(转为正式链接)/驳回。
### 4.5 广告位(Ad)
- 按 position 分组投放(如 `home_top`、`detail_side`)
- 支持图片/文字广告、投放时段、排序
- 点击经 `/haonav/ad/click` 跳转并计数
### 4.6 配置(Configs)
分组管理所有配置项,保存即时生效。见下节明细。
---
## 5. 配置项详解
后台 → 网址导航配置。首次访问自动补齐缺失项。
| 分组 | 配置项 | 默认 | 说明 |
|---|---|---|---|
| 基础 | `default_engine` | baidu | 搜索框默认引擎 |
| 基础 | `enable_submit` | 1 | 前台投稿开关 |
| 基础 | `enable_hot_api` | 0 | 实时热搜组件开关 |
| SEO | `seo_title` / `seo_keywords` / `seo_description` | — | 全站 TDK |
| 返利 | `enable_rebate` | 0 | 命中域名自动拼接返利 PID |
| 返利 | `rebate_param` | pid | 返利参数名 |
| 返利 | `rebate_domains` | taobao.com,... | 返利适用域名列表 |
| task | `deadlink_auto` | 0 | 死链连续失败达阈值自动下线 |
| task | `deadlink_threshold` | 2 | 连续失败次数阈值 |
| task | `deadlink_recover` | 0 | 恢复可达后自动重新上线 |
| **外观** | `bg_image` | 空 | 全站默认背景图 URL(空=渐变) |
| **外观** | `bg_mask` | 35 | 背景图遮罩不透明度 0-90(保证文字可读) |
| **外观** | `bg_random` | 0 | 游客随机渐变背景(每次刷新随机) |
| **外观** | `festival_theme` | 1 | 节日/节气自动换装总开关 |
---
## 6. 前台功能说明
| 页面 | URL | 说明 |
|---|---|---|
| 首页 | `/haonav`(`/haonav/index.html`) | 分类聚合 + 热门 18 + 推荐 10 |
| 搜索 | `/haonav/search?q=关键词` | 站内 + 引擎外跳 |
| 排行 | `/haonav/rank` | 点击量 Top 50 |
| 详情 | `/haonav/site/{id}.html` | 快照、评分、JSON-LD |
| 分类 | `/haonav/category/{id}.html` | 单分类列表 |
| 申请 | `/haonav/apply` | 收录/广告合作投稿 |
| 分享页 | `/haonav/favorite/shared/{token}.html` | 只读收藏夹(noindex) |
| 站点地图 | `/haonav/sitemap.xml` | XML + HTML 双格式 |
| Service Worker | `/haonav/sw` | PWA 离线支撑 |
**会员**:`/haonav/account/login|register|logout|profile`。登录后「我的导航」自动云端同步收藏;未登录自动回退本地 localStorage。
---
## 7. 主题与个性化
前台导航栏 🎨 按钮打开主题面板:
| 功能 | 说明 | 记忆 |
|---|---|---|
| 模式 | ☀️ 浅色 / 🌙 暗色 / 🌗 跟随系统 | localStorage |
| 主色 | 5 组色板(紫/绿/蓝/粉/灰) | localStorage |
| 背景 | 10 组渐变色点 + 🎲 随机换色 + 自定义图片 URL | localStorage |
| 恢复默认 | 一键清除以上所有个人偏好 | — |
**自定义背景图**:面板中「粘贴图片地址设为背景」→ 应用(或回车)。图片以 cover 全屏铺满,自动叠加白色遮罩(暗色模式自动改压暗),遮罩强度由后台 `bg_mask` 控制。
**优先级链**(高 → 低):
```
访客自选背景/主色 > 节日/节气主题 > 站点背景图(bg_image) > 随机换色 > 默认渐变
```
---
## 8. 节日 / 节气自动换装
### 8.1 内置条目(共 36 项)
- **24 节气**:立春/雨水/惊蛰/春分/清明/谷雨/立夏/小满/芒种/夏至/小暑/大暑/立秋/处暑/白露/秋分/寒露/霜降/立冬/小雪/大雪/冬至/小寒/大寒 — 公历固定日期,当天自动换季相配色 + 应季粒子(🌱☀️🍂❄️)
- **传统节日(农历)**:除夕 / 春节(初一至初三)/ 元宵 / 小年 / 端午 / 七夕 / 中秋 / 重阳 — 内置 2026-2036 公历换算表
- **公历节日**:元旦 / 情人节 / 国庆(10/1-10/7)/ 万圣节 / 圣诞(12/24-12/26)
### 8.2 效果
命中当天自动:换节日背景渐变 → 换全站主色 → 飘落装饰粒子(emoji 随机大小/速度)→ 右上角徽章(如「🏮 春节快乐」「⚡ 惊蛰」)。
- **时间判定**:浏览器本地时间(`new Date()`)。跨时区访客可能偏移 1 天,国内用户无感
- **访客关闭**:点徽章右上 × 永久关闭(localStorage)
- **站长关闭**:后台 → 外观 → 节日主题自动换装 → 0
### 8.3 「节日不生效」排查
依次检查(Console 执行):
```js
localStorage.getItem('haonav_festival_off') // '1' = 曾点过关闭 → removeItem 后刷新
localStorage.getItem('haonav_bg') // 有值 = 自选背景覆盖了节日背景
window.NavAppearance.festival // 0 = 后台总开关关闭
```
Service Worker 旧缓存干扰时:F12 → Application → Clear site data。
---
## 9. SEO 能力
- `sitemap.xml` / `sitemap.html` 双格式自动生成
- 详情页输出 JSON-LD(WebSite + SearchAction 搜索直达框)
- 全站 canonical 链接
- 链接支持自定义 keywords/description
- 拼音搜索:中文名自动转拼音串,支持拼音首字母检索
---
## 10. 死链检测(计划任务)
两种模式可同时启用:
### 10.1 定时全量(推荐 cron)
```cron
0 3 * * * curl -s "https://你的域名/haonav/task/checklinks?token=你的TOKEN" > /dev/null
```
每日凌晨全量检测所有启用链接。
### 10.2 惰性巡检(无 cron 兜底)
前台页面访问时异步触发 `/haonav/task/autocheck`,带缓存锁限频,自动分批检测。
### 10.3 自动下线/恢复
开启「死链自动下线」后:连续失败 ≥ 阈值 → 自动禁用;开启「恢复自动上线」后:重新可达 → 自动启用(仅对检测器下线的链接生效,手动禁用不受影响)。
---
## 11. 常见问题 FAQ
**Q1:页面 500?**
确认没有模板 include 传参(`{include file="..." var="x" /}` 在 think-template 跨模板作用域不可靠,page-*.css 由各页面手动 `<link>` 引入)。
**Q2:改了背景图后台配置前台不生效?**
浏览器/SW 缓存。F12 → Application → Clear site data;或等 sw 版本升级自动刷新。
**Q3:游客反馈"背景一直没变过"?**
该游客曾点过节日徽章 × 或自选过背景。让其点击面板「↺ 恢复默认」。
**Q4:拼音搜索搜不到?**
旧数据拼音串未回填。访问一次后台仪表盘即自动补(每批 300 条),或多次刷新。
**Q5:收藏在不同设备不同步?**
收藏分本地(未登录)/云端(登录)两套。登录后自动 merge 并以云端为准。
---
## 12. 绑定域名访问
希望独立域名(如 `hao.example.com`)直接访问网址导航,而不是 `example.com/haonav`?YwxApp 通过 `config/app.php` 的 `domain_bind` 支持。
### 12.1 三种使用场景
| 场景 | 配置方式 | URL 形态 |
|---|---|---|
| 默认(路径访问) | 不配 | `example.com/haonav` |
| 二级域名绑定 | `'hao' => 'haonav'` | `hao.example.com`(自动剥 `hao.`) |
| 完整域名绑定 | `'hao.example.com' => 'haonav'` | 直接访问 `hao.example.com` |
### 12.2 启用步骤(5 步)
#### ① 修改 `config/app.php`
```php
'domain_bind' => [
'hao' => 'haonav', // 二级域名 → 插件名(推荐)
// 'hao.example.com' => 'haonav', // 完整域名 → 插件名
],
```
#### ② Web 服务器指向同一项目目录
绑定域名访问本质上是同一份代码,让 DNS 把 `hao.example.com` 解析到与 `example.com` 相同的服务器 / 同一 Web 根。
**Nginx**(在主 server 块外新增或合并):
```nginx
server {
listen 80;
server_name example.com hao.example.com; # 多 server_name 即可
root /www/ywxapp_dev/public;
index index.php;
# 其余 fastcgi / rewrite 规则同主站
location ~ \.php$ {
fastcgi_pass unix:/run/php/php-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
```
**Apache**:`ServerName example.com` → `ServerAlias hao.example.com`。
#### ③ DNS 解析
到域名服务商把 `hao.example.com` 用 A/CNAME 记录指向主站 IP,TTL 选短值便于调试。
#### ④ 清框架运行时缓存
```bash
rm -rf runtime/cache/*
```
#### ⑤ 测试
浏览器访问 `http://hao.example.com` → 应直接呈现 haonav 首页(不再带 `/haonav` 前缀)。
### 12.3 「绑定后无法访问」逐项排查
按下面顺序逐项确认(90% 的问题在第 1/2 步):
| 序号 | 排查点 | 自检命令 / 现象 |
|---|---|---|
| 1 | **DNS 是否解析到服务器** | `ping hao.example.com` 应返回主站 IP;不通就是 DNS 没配 |
| 2 | **Web Server 是否监听该域名** | `curl -H "Host: hao.example.com" http://服务器IP/` 不应返回 404/连接拒绝;Nginx 看 `server_name` 包含子域名,Apache 看 `ServerAlias` |
| 3 | **`config/app.php` 是否正确** | `php -r "print_r(config('app.domain_bind'));"` 确认配置生效(务必重启 php-fpm) |
| 4 | **缓存清理** | 改完配置删 `runtime/cache/*`;TP 路由缓存若有也清 |
| 5 | **插件名与 bind 值一致** | `domain_bind['hao']='haonav'` 中 `haonav` 必须与 `addon/haonav/info.php` 的 `name` 完全一致(区分大小写) |
| 6 | **`addon/haonav/` 存在且有 route** | 验证 `addon/haonav/route/app.php` 可被框架 include |
| 7 | **完整域名是否带协议** | `'hao.example.com'` 不要写成 `'http://hao.example.com'` |
| 8 | **HTTPS** | 绑定后若浏览器强制 HTTPS,请确保子域名也有证书(Let's Encrypt 用 `certbot --expand`) |
| 9 | **SSL 泛域名** | 多子域名绑同一站点,用通配证书 `*.example.com` 最省事 |
| 10 | **框架缓存类** | 部分主机有 OPcache,改完 `config/app.php` 重启 `php-fpm` 才生效 |
**最常见两大坑**:
```
坑 ①:DNS 已解析但 Web Server 没加 server_name → 访问显示「无法访问此网站」/ 默认页
坑 ②:Web Server 已加但 domain_bind 没写 / 拼写错 → 显示「路由不存在 404」
```
### 12.4 多域名绑定同一插件
```php
'domain_bind' => [
'hao' => 'haonav', // hao.example.com
'nav' => 'haonav', // nav.example.com
'hao.dev.example.com' => 'haonav', // 测试子域
],
```
不同域名可分别承担同一插件的「访问入口」与「SEO 镜像」,但**避免一站多域名导致 SEO 重复**——通过 `seo_title` 区分或加 `<link rel="canonical">` 指向主域。
### 12.5 绑定域名后的相对路径影响
| 场景 | 行为 |
|---|---|
| 模板用 `url('haonav/index')` | 生成的 URL 已自动带域名上下文 → `https://hao.example.com/haonav/index.html` |
| 模板用绝对路径 `/static/...` | 不变(推荐) |
| 模板用相对路径 `static/...` | ⚠️ 子域名访问时可能找不到资源 → **统一用绝对路径** |
| 前端 JS 中 `location.href = '/xxx'` | 浏览器会替换为当前域名下的绝对路径,安全 |
| Service Worker | 缓存清单使用绝对路径(已配置),绑定域名后仍正常工作 |
---
## 13. 相关链接
- 开发文档:[haonav_dev_guide.md](haonav_dev_guide.md)
- 框架插件机制:[../插件开发指南.md](../插件开发指南.md)
- 部署指南:`docs/deploy/`