← 博友圈
template-parts/right.php (单栏布局时跳过)
template-parts/footer-copyright.php
template-parts/footer.php
```
所以左栏、导航、右栏、页脚跟主题的其它页面完全一致,不会多出主题的空正文区域。
**每个片段都先判断文件是否存在**,主题缺哪个就跳过哪个;
主题本身没有 `template-parts/` 结构时,插件直接返回,交回主题正常渲染(此时用短代码兜底)。
4. **短代码仍然是兜底**。页面正文里依然留着 `[youquan]`,万一主题不支持接管(非 ilogs),
把短代码删掉换成主题自己的模板标签即可,不会白屏。
---
## 四、前台四种调用方式
插件同时支持四种方式,**任选其一**即可,互不冲突。
### 1. 独立页面(推荐)
到「设置 → 页面与入口」点「创建并绑定「有圈」页面」,页面上什么都不用写。
启用插件时会自动建好,导航里也会出现带图标的入口。
### 2. 短代码
想在别的页面中间插入博友圈,正文放:
```
[youquan]
```
带参数:
```
[youquan layout="grid" per_page="6" title="博友圈" filter="0"]
```
会自动处理 Markdown 把短代码包成 `
[youquan]
` 的情况,不会显示成代码块。
### 3. 主题模板标签
在主题模板(如 `page.php`、自定义页面模板)里直接写:
```php
'grid', 'per_page' => 6)); ?>
```
取短链接地址:
```php
博友圈
```
### 4. 短链接 `/youquan`
插件通过 `index.php` 的 `begin` 钩子拦截 `/youquan`,302 跳转到绑定好的有圈页面。
- 后缀可在「设置 → 页面与入口 → 页面别名」里改,改成 `friends` 就访问 `/friends`。
- **为什么不用 `Helper::addRoute()`**:`addRoute` 会把路由写进 `options.routingTable` 这个序列化数组,插件卸载残留会导致整站 404。本插件改用 `begin` 钩子拦截,完全不碰路由表。
- 尚未创建页面时:管理员访问 `/youquan` 会**自动建页面**,普通访客会看到一个引导到后台的提示页,不会白屏。
### 可用参数
| 参数 | 可选值 | 默认 | 说明 |
| --- | --- | --- | --- |
| `per_page` / `limit` | 正整数 | 12 | 每页条数 |
| `layout` | `list` / `grid` | list | 列表流 / 卡片流 |
| `title` | 字符串 | 博友圈 | 标题;`title=""` 隐藏标题栏文字 |
| `head` | `0` / `1` | 1 | 是否显示标题栏(含圈友数与文章数) |
| `filter` | `0` / `1` | 1 | 是否显示圈友筛选条 |
| `src` | 圈子 ID | 全部 | 只显示某个圈友的文章 |
| `order` | `published` / `created` | published | 排序方式 |
---
## 五、后台
后台面板(**控制台 → 有圈**)完全按 Typecho 原生风格排版:
`typecho-page-title` 标题栏 + `typecho-option-tabs` 标签页 + 卡片表单 + 表格,
配色沿用 Typecho 的 `#467B96` 主色、`#E9E9E6` 按钮底、`#D9D9D6` 边框,与控制台其它页面一致。
### 圈友
- 表格字段:头像、名称、站点、订阅地址、状态徽章、最近抓取时间、文章数、排序。
- 每行支持 **编辑 / 抓取 / 停用启用 / 删除**;支持勾选后批量停用、启用、删除。
- 状态徽章:`成功`(绿)/ `失败`(红,悬停看错误原因)/ `待抓取`(灰)/ `已停用`(灰)。
- 编辑弹窗里填了站点地址后点 **自动发现**,会自动探测常见 RSS 地址(`/feed`、`/rss.xml`、`/atom.xml`、`/index.xml`、`?feed=rss2` 等),无需手填。
- 工具区:
- **清理重复**:按归一化后的文章链接分组,删除重复项,只保留最早抓到的那条。
- **补全头像**:给没有头像的圈友批量补站点 favicon(每次最多 30 个)。
### 文章
- 汇总所有圈友抓来的文章,支持按**来源圈友**与**关键词**筛选,支持隐藏/显示、删除。
- 不想要某篇文章时用「隐藏」而不是「删除」,否则下次抓取还会再抓回来。
- 「清空文章」只清已抓的文章(订阅保留),重新抓取即可重建。
### 设置
1. **展示设置**:标题、副标题、每页条数、布局(列表/卡片)、摘要字数、是否显示头像 / 来源 / 时间 / 封面 / 筛选条 / 标题栏、时间格式(相对时间 or 日期)、排序、新窗口打开、**隐藏页面标题**(避免页面上出现两个标题)。
2. **页面与入口**:选择要绑定的页面、页面别名(决定短链接)、创建 / 重新绑定有圈页面、**修复页面与图标**(重建页面并补齐 `showPage` / `iconPage`)。
3. **抓取设置**:自动刷新开关与间隔(分钟,默认 30)、超时秒数(默认 8)、**每个圈友保留条数**(默认 20,超出自动裁剪旧文章以控制数据库体积)、排除关键词(逗号分隔,命中则不入库)。
### 调用方式
内置四种调用方式的完整示例、参数表、与 FriendLinks 的配合说明以及常见问题,可直接复制使用。
---
## 六、插件设置页(控制台 → 插件 → 有圈 → 设置)
除了上述管理面板,插件还在 Typecho 的插件列表里提供了原生设置页,放最常改的 8 项:
| 设置项 | 说明 |
| --- | --- |
| 页面大标题 | 前台标题栏大字,说明里带管理面板入口与当前统计 |
| 标题下的说明文字 | 副标题,留空则不显示 |
| 短链接别名 | 决定 `/youquan` 这个短链接 |
| 前台布局 | 列表流 / 卡片流 |
| 每页文章数 | 1 – 50 |
| 自动刷新 | 访客打开页面时顺带抓取过期订阅 |
| 刷新间隔(分钟) | 最低 5 |
| 每个圈友保留条数 | 最高 200,超出自动裁剪 |
保存时会被安全夹取:每页条数上限 50、间隔下限 5、保留条数上限 200、别名只保留字母数字下划线连字符。
> 设置值写入 `youquan_options`,与管理面板共用同一份数据,两处改动都不会冲突,且会互相同步。
>
> 这是通过定义 `configHandle()` 实现的:Typecho 检测到该方法后不会再往 `options.plugins` 里写序列化配置。
> 但 Typecho 渲染设置页时仍会读取 `options` 表里的 `plugin:YouQuan` 行,读不到会直接 500,
> 所以插件会自己维护这一行:启用时创建,之后每次保存设置时**整体覆盖**(不是合并)。
> 从旧版本升级时,那一行里残留的废弃键会被一并清掉。
---
## 七、与 FriendLinks 友链插件的配合
这是本插件主要的数据来源,已做深度适配:
1. **直接读表**:读取 `{prefix}friend_links`(字段 `linkid / nickname / websiteurl / rssurl / avatar / email / email_md5 / personalintro / rssStatus`),无需 FriendLinks 提供接口。未安装时「从友链导入」会提示未检测到友链数据,其余功能不受影响。
2. **一键导入**:弹窗列出所有友链,勾选后导入。RSS 状态为「禁用」的友链会标灰。
3. **RSS 缺失自动补齐**:友链没填 RSS 地址时,导入时会自动到站点首页探测常见 Feed 地址,并在列表里标注「已发现」。
4. **去重**:同一 RSS 地址不会重复导入,已导入的友链标记为「已导入」并禁用勾选。
判断时会把 URL 归一化 —— 忽略 http/https、`www.`、结尾斜杠、`/index.php`、重复斜杠,并把 query 转小写,
所以 `http://www.a.com/feed/` 与 `https://a.com/index.php/feed` 会被视为同一个源。
5. **头像复用**:优先 FriendLinks 上传的头像 → 邮箱 MD5 走 FriendLinks 配置的头像服务 → FriendLinks 的 favicon 缓存。都取不到时回退站点 favicon,最后用站点名首字生成纯色头像。
6. **导入即抓取**:导入完成后自动逐个抓取(最多 5 个),剩下的在圈友页点「全部抓取」。
> 之后在 FriendLinks 里新增友链,回到有圈再导一次即可,「已导入」的不会重复。
---
## 八、支持的 Feed 格式
- RSS 2.0、RSS 1.0(RDF)、Atom 1.0
- 自动识别 `content:encoded` / `description` / `summary` 作为摘要,`dc:creator` / `author` 作为作者
- 封面提取顺序:`media:content` / `media:thumbnail` / `enclosure` → 正文首张 `
![]()
`;相对地址会自动补成绝对地址
- 自动处理 GBK / GB18030 编码、BOM、以及 XML 里的非法控制字符
- 支持条件请求(`If-None-Match` / `If-Modified-Since`),源站没更新时返回 304,不重复写库
- 抓取优先使用 cURL,缺失时自动降级到 `stream`;限制协议为 http/https,响应体上限 3MB
---
## 九、主题样式适配(ilogs)
前台元素全部写在 `.yq-wrap` 作用域内,并对 ilogs 的既有规则做了必要重置,确保视觉一致:
- 直接使用主题的 CSS 变量:`--bs-body-color`、`--bs-border-color-translucent`、`--bs-tertiary-bg`、`--primary-color-rgba`,跟随主题明暗色切换。
- 抵消 ilogs `#post-content a` 的高亮下划线与阴影、`#post-content h1/h2/h3` 的内阴影底色(有圈标题改用 `div[role=heading]`,从根上避让)、`#post-content img` 的 `display:block / height:auto`(头像与封面尺寸需要精确控制)。
- 「隐藏页面标题」开启时,会隐藏主题独立页面的 `#articleTitle` 及其下方描述文字(选择器为 `#post-article #articleTitle`),避免页面上出现两个标题。
- **页头对齐相册页**:标题 `1.75rem / 300` 字重,副标题 13px,右侧 12px 统计文字,底部 1px 分隔线,外框内边距 `34px 32px 48px`,与 ilogs 相册页的 `.album-page-heading` 完全一致。
- 布局与 ilogs 文章列表一致:圆形来源头像 + 标题 + 两行摘要 +「站点 · 时间」元信息 + 右侧缩略图(112×72)。
- 摘要与标题重复时自动省略(去标点后比较;摘要以标题开头则去掉标题前缀)。
- 筛选条会过滤掉 0 篇文章的圈友,最多显示 8 个。
- 响应式:991.98px 以下封面缩小、shell 内边距收到 `24px 20px 36px`;767.98px 以下隐藏封面、内边距收到 `18px 14px 30px`;390px 宽度下无横向溢出。
---
## 十、常见问题
**Q:访问 `/youquan` 404 或提示页面不存在?**
A:到「设置 → 页面与入口」点「创建并绑定「有圈」页面」。若仍未生效,可能是伪静态规则没排除该路径,可在 `.htaccess` / nginx 配置里检查 rewrite 规则。
**Q:左栏导航里有页面但没图标?**
A:到「设置 → 页面与入口」点「修复页面与图标」。若你手动改过 `iconPage` 字段,插件不会覆盖,需要自己补 SVG。
**Q:页面能打开,但完全没有样式(头像变大、筛选挤成一堆)?**
A:这是 1.1.0 及更早版本的已知问题,1.2.0 已修复(原因见「变更记录」)。
确认一下浏览器里页面源码有没有 `