码桶
发现社区成员的开源项目
版本历史
3 次提交提交详情
b0e33fe提交编号
b0e33fe3480a7a8d577d61f8ca3308220fe60713提交作者开心<codebucket@localhost>
提交时间2026-07-29 13:05:17 +0800
更新说明更新项目文件
文件变更 51 个文件
文件新增删除
README.md+398-1ajax.php+396-0assets/cache/.gitkeep+0-0assets/css/admin-fix.css+130-0assets/css/houtai.css+354-0assets/css/style.css+1279-0assets/css/style.min.css+1-0assets/img/default-avatar.svg+1-0assets/js/app.min.js+1460-0assets/js/app.v2.js+1512-0assets/js/houtai.js+54-0assets/lib/fancybox/fancybox.css+1-0assets/lib/fancybox/fancybox.umd.min.js+7-0assets/lib/prism/prism-bash.min.js+1-0assets/lib/prism/prism-c.min.js+1-0assets/lib/prism/prism-cpp.min.js+1-0assets/lib/prism/prism-css.min.js+1-0assets/lib/prism/prism-go.min.js+1-0assets/lib/prism/prism-html.min.js+1-0assets/lib/prism/prism-java.min.js+1-0assets/lib/prism/prism-javascript.min.js+1-0assets/lib/prism/prism-json.min.js+1-0assets/lib/prism/prism-kotlin.min.js+1-0assets/lib/prism/prism-line-numbers.min.css+1-0assets/lib/prism/prism-line-numbers.min.js+1-0assets/lib/prism/prism-markup.min.js+1-0assets/lib/prism/prism-php.min.js+1-0assets/lib/prism/prism-python.min.js+1-0assets/lib/prism/prism-ruby.min.js+1-0assets/lib/prism/prism-rust.min.js+1-0assets/lib/prism/prism-sql.min.js+1-0assets/lib/prism/prism-swift.min.js+1-0assets/lib/prism/prism-typescript.min.js+1-0assets/lib/prism/prism.css+1-0assets/lib/prism/prism.min.js+16-0assets/lib/qrcode/qrcode.min.js+8-0comments.php+13-0footer.php+100-0functions.php+495-0header.php+189-0img-proxy.php+169-0index.php+71-0lib/Meting.php+1535-0lib/ip2region/xdb/Searcher.class.php+573-0music-proxy.php+65-0page-about.php+125-0page-archive.php+134-0page-links.php+76-0page.php+21-0post.php+65-0setting.php+162-0文件差异 逐行查看本次提交的修改
README.md+398-1
@@ -1 +1,398 @@1
-# kxpyq1
+# Pyq 主题 — 详细功能总结与技术文档2
+3
+> **主题名称:** Pyq4
+> **作者:** 清酒5
+> **版本:** 1.0.0 (2026-06-28)6
+> **适配程序:** Typecho 1.3.07
+> **运行环境:** PHP 8.2 + MySQL 5.78
+> **站点地址:** https://p.qu.pw/9
+> **主题目录:** `/www/wwwroot/p.qu.pw/usr/themes/pyq/`10
+11
+---12
+13
+## 一、主题概述14
+15
+Pyq 是一款仿朋友圈风格的 Typecho 主题,以说说(短文)为核心,支持图文、音乐、视频、链接等多种内容形式。移动端优先设计,支持深色模式、PJAX 无刷新导航、LRC 歌词滚动等高级功能。16
+17
+参考主题:wutoutu(同目录下),在此基础上进行了大量功能增强和 UI 优化。18
+19
+---20
+21
+## 二、文件结构22
+23
+```24
+pyq/25
+├── index.php # 首页模板(说说列表 + 分页 + AJAX加载更多)26
+├── post.php # 文章详情页(单篇说说 + 评论区)27
+├── page.php # 通用页面模板28
+├── page-about.php # 关于页面(社交账号弹窗)29
+├── page-links.php # 友链页面30
+├── page-archive.php # 归档页面(按月分组)31
+├── header.php # 公共头部(导航栏 + 封面 + 公告 + 音乐播放器)32
+├── footer.php # 公共底部(弹窗公告 + 返回顶部 + JS加载)33
+├── comments.php # 评论模板34
+├── functions.php # 主题函数(自定义字段 + 工具函数)35
+├── setting.php # 后台设置页(Tab式界面)36
+├── ajax.php # AJAX接口(加载更多 + 评论提交 + 点赞)37
+├── music-proxy.php # 音乐代理(本地Meting库 + 流式传输)38
+├── img-proxy.php # 图片代理(防盗链处理)39
+├── assets/40
+│ ├── css/41
+│ │ ├── style.css # 前台主样式(1193行)42
+│ │ ├── houtai.css # 后台设置页样式(354行)43
+│ │ └── admin-fix.css # 后台全局修复CSS(130行)44
+│ ├── js/45
+│ │ ├── app.js # 前台主逻辑(1250行)46
+│ │ └── houtai.js # 后台设置页逻辑(54行)47
+│ └── img/ # 主题图片资源48
+├── lib/49
+│ └── Meting.php # Metowolf Meting 音乐API库50
+└── static/51
+ └── prism/ # Prism.js 代码高亮(22个文件,16种语言)52
+```53
+54
+**总代码量:** 5266 行55
+56
+---57
+58
+## 三、功能特性59
+60
+### 3.1 内容类型61
+62
+| 类型 | 自定义字段 | 说明 |63
+|------|-----------|------|64
+| 图文 | `images`(多行文本) | 多图URL,每行一张,支持懒加载 |65
+| 视频 | `video_url`(单行文本) | 视频链接,支持 mp4/embed |66
+| 音乐 | `music_url` + `music_name` + `music_artist` + `music_cover` + `music_lrc` | 音乐卡片,支持封面+歌词 |67
+| 链接 | `link_url` + `link_title` + `link_desc` + `link_thumb` | 外部链接卡片预览 |68
+| 位置 | `location`(单行文本) | 显示位置信息 |69
+| 置顶 | `is_top`(单选:是/否) | 置顶文章 |70
+71
+### 3.2 音乐系统72
+73
+#### 顶部播放器74
+- 导航栏集成迷你播放器(播放/暂停 + 歌名滚动)75
+- 支持两种音源:76
+ - `bgm_url`:直接 MP3 链接(优先)77
+ - `netease_id`:网易云歌曲ID,通过本地 Meting 库代理获取78
+- 音乐代理 `music-proxy.php`:流式传输 + Range 分块请求支持79
+80
+#### 音乐卡片(说说内嵌)81
+- 80px 高度卡片,封面背景 + 歌曲名 + 歌手 + 播放按钮82
+- 底部进度条(3px,hover 6px),支持拖动 seek83
+- LRC 歌词滚动:84
+ - 支持标准 LRC 格式(`[00:12.34]歌词`)85
+ - 支持网易云 JSON 格式(`{"t":0,"c":[{"tx":"歌词"}]}`)86
+ - 歌词区在卡片下方展开,背景使用封面模糊图87
+ - 当前行高亮(白色 15px + 发光阴影)88
+ - `requestAnimationFrame` 同步滚动,使用 `scrollTo` 避免页面抖动89
+ - 展开/收起按钮,可手动控制90
+91
+### 3.3 评论系统92
+93
+- AJAX 无刷新提交评论94
+- 必填昵称 + 邮箱(邮箱格式校验)95
+- 评论 @回复 功能(点击回复按钮自动填充)96
+- 评论邮件通知:97
+ - 直接调用 CommentNotifier 插件的 `refinishComment` 方法98
+ - 绕过异步模式(`yibu=1`),确保邮件即时发送99
+ - 修复 `ownerId` 为 0 的问题,从 `typecho_contents` 查询文章作者100
+- 评论树形渲染(`pyq_render_comments_tree`)101
+102
+### 3.4 交互功能103
+104
+- **点赞:** AJAX 点赞/取消,实时更新按钮状态和点赞列表105
+- **分享:** 8 按钮弹窗(2×4 网格)— 微信/微博/QQ/复制链接/带标题复制/更多106
+- **返回顶部:** 滚动 300px 后显示,平滑滚动107
+- **图片灯箱:** FancyBox 集成,点击图片放大查看108
+- **懒加载:** IntersectionObserver 图片懒加载109
+- **加载更多:** 滚动到底部自动加载下一页(AJAX)110
+111
+### 3.5 PJAX 无刷新导航112
+113
+- 全站 PJAX 实现,音乐播放不中断114
+- `XMLHttpRequest` + `DOMParser` 解析新页面115
+- `history.pushState` / `popstate` 浏览器前进后退支持116
+- 换页后自动重新初始化:FancyBox、Prism.js、懒加载、搜索、加载更多117
+- 内容区域目标:`#pyq-feed`118
+119
+### 3.6 深色模式120
+121
+- 跟随系统 `prefers-color-scheme` 自动切换122
+- CSS 变量体系(`--bg`, `--card`, `--text`, `--text2`, `--text3`, `--border` 等)123
+- 所有组件完整适配深色/浅色124
+125
+### 3.7 代码高亮126
+127
+- Prism.js 集成(16 种语言)128
+- 暗色主题 + 行号 + 一键复制按钮129
+- `pyq_parse_code()` 函数处理代码块130
+131
+---132
+133
+## 四、后台设置134
+135
+### 4.1 设置界面136
+137
+Tab 式布局(5 个标签页):138
+139
+| 标签 | 内容 |140
+|------|------|141
+| 基础设置 | 头像URL、封面图URL、封面高度、用户名、个性签名、ICP备案、说说分类slug、静态资源URL |142
+| 音乐设置 | 背景音乐URL、网易云歌曲ID |143
+| 社交菜单 | GitHub/微博/微信/QQ 链接 + 菜单项配置 |144
+| 功能设置 | 公告文字、公告背景色(色盘选择)、Gravatar源选择、弹窗公告 |145
+| 高级设置 | 自定义CSS/JS 代码注入 |146
+147
+### 4.2 设置备份148
+149
+- 一键备份当前所有设置150
+- 列出历史备份,支持一键恢复/删除151
+- 备份存储在 `typecho_options` 表中152
+153
+### 4.3 自定义字段154
+155
+文章编辑页自定义字段支持:156
+- textarea 高度优化(36px 起,可拖拽调整)157
+- 文字描述改为 placeholder(`$e->input->setAttribute`)158
+- Radio 按钮置顶选择(is_top)159
+- 所有字段支持 JS 拖拽调整宽度(text input)160
+161
+---162
+163
+## 五、页面模板164
+165
+### 5.1 关于页面 (`page-about.php`)166
+167
+- 社交账号展示(QQ/微信/GitHub/微博)168
+- 点击弹窗显示账号信息(QQ 弹窗、微信弹窗)169
+- 复制账号到剪贴板170
+- 弹窗函数在 `app.js` 中定义(PJAX 兼容)171
+172
+### 5.2 友链页面 (`page-links.php`)173
+174
+- 配合links插件使用175
+- 友链列表展示176
+- 卡片式布局177
+178
+### 5.3 归档页面 (`page-archive.php`)179
+180
+- 按年月分组的文章列表181
+- 链接格式:`/archives/slug.html`182
+183
+---184
+185
+## 六、技术实现细节186
+187
+### 6.1 IIFE 架构188
+189
+`app.js` 使用 IIFE(立即执行函数表达式)封装,所有功能通过 `pyq.xxx` 暴露到全局:190
+191
+```javascript192
+;(function(){193
+ // 内部变量194
+ var pyq = window.pyq = {};195
+ // 所有功能定义...196
+ pyq.playCardMusic = function(btn){ ... };197
+ pyq.parseLrc = function(text){ ... };198
+ // ...199
+})();200
+```201
+202
+**关键教训:** IIFE 闭合 `})();` 必须在所有 `pyq.xxx` 定义之后,否则后续代码引用 `pyq` 会 ReferenceError。203
+204
+### 6.2 音乐卡片 HTML 结构205
+206
+```html207
+<div class="pyq-music-wrap" data-bg="封面URL">208
+ <div class="pyq-music-card" data-src="音频URL" data-name="歌名" data-lrc="base64歌词">209
+ <div class="pyq-music-card-bg" style="background-image:url(...)"></div>210
+ <div class="pyq-music-card-left"><img src="封面"></div>211
+ <div class="pyq-music-card-right">212
+ <div class="pyq-music-card-info">213
+ <div class="pyq-music-card-title">歌名</div>214
+ <div class="pyq-music-card-artist">歌手</div>215
+ </div>216
+ <div class="pyq-music-card-play" onclick="pyq.playCardMusic(this)">▶</div>217
+ </div>218
+ <div class="pyq-music-progress" onmousedown="pyq.seekMusic(event,this)">219
+ <div class="pyq-music-progress-bar"></div>220
+ <div class="pyq-music-progress-dot"></div>221
+ </div>222
+ </div>223
+ <div class="pyq-lrc-bar" onclick="pyq.toggleLrc(this)">歌词 ▼</div>224
+ <div class="pyq-music-lrc">225
+ <div class="pyq-lrc-bg" style="background-image:url(...)"></div>226
+ <div class="pyq-lrc-overlay"></div>227
+ <div class="pyq-lrc-lines"></div>228
+ </div>229
+</div>230
+```231
+232
+### 6.3 LRC 歌词解析233
+234
+支持两种格式:235
+236
+**标准 LRC:**237
+```238
+[00:12.34]歌词第一行239
+[00:15.67]歌词第二行240
+```241
+242
+**网易云 JSON:**243
+```json244
+[{"t":0,"c":[{"tx":"作词: "},{"tx":"某某"}]},{"t":4000,"c":[{"tx":"歌词"}]}]245
+```246
+247
+解析流程:248
+1. 检测首字符是否为 `{` 或 `[`249
+2. JSON 格式:解析数组,提取 `t`(毫秒)和 `c[].tx`(文本)250
+3. LRC 格式:正则 `/[(\d{1,2}):(\d{2})(?:\.(\d{1,3}))?](.*)/g` 匹配251
+4. 按时间排序252
+253
+### 6.4 歌词同步机制254
+255
+- `requestAnimationFrame` 高频循环(60fps)256
+- 遍历已排序的歌词数组,找到当前时间对应的行257
+- 高亮当前行(`.active` class)258
+- `scrollTo` 滚动容器到当前行位置(不用 `scrollIntoView`,避免页面抖动)259
+- 暂停时停止循环,恢复时重新启动260
+261
+### 6.5 进度条拖动262
+263
+- `mousedown/touchstart` 记录起始位置264
+- `mousemove/touchmove` 实时计算百分比,更新 `audio.currentTime`265
+- `mouseup/touchend` 清理事件监听266
+- `getBoundingClientRect` 计算相对位置267
+- 拖动中添加 `.dragging` class(白点常显 + 进度条变高)268
+269
+### 6.6 邮件通知修复270
+271
+三层问题修复:272
+273
+1. **插件未初始化:** `ajax.php` 需调用 `Plugin::init()` 初始化插件系统274
+2. **ownerId 为 0:** `typecho_comments.ownerId` 全为 0,需从 `typecho_contents` 查 `authorId` 补全275
+3. **异步模式失效:** CommentNotifier 的 `yibu=1` 模式在 AJAX handler 中不触发,直接调用 `Plugin::refinishComment($feedback)` 绕过276
+277
+### 6.7 后台 CSS 注入278
+279
+通过 `admin/header.php` 直接注入 `admin-fix.css`,修复:280
+- select 下拉框样式(移动端 font-size 16px 防缩放)281
+- textarea 可拖拽(覆盖 Typecho 的 `resize: none`)282
+- 编辑器容器居中(覆盖 `.row { width: 100vw }`)283
+- 移动端自定义字段、提交按钮全宽适配284
+285
+---286
+287
+## 七、CSS 变量288
+289
+```css290
+:root {291
+ --bg: #f0f0f0; /* 页面背景 */292
+ --card: #fff; /* 卡片背景 */293
+ --card2: #f5f5f5; /* 次级卡片 */294
+ --text: #333; /* 主文字 */295
+ --text2: #666; /* 次级文字 */296
+ --text3: #999; /* 辅助文字 */297
+ --border: #eee; /* 边框 */298
+ --accent: #07c160; /* 强调色(微信绿) */299
+ --max-w: 680px; /* 最大宽度 */300
+ --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;301
+}302
+303
+.darkmode {304
+ --bg: #1a1a1a;305
+ --card: #242424;306
+ --card2: #2a2a2a;307
+ --text: #e5e5e5;308
+ --text2: #aaa;309
+ --text3: #777;310
+ --border: #333;311
+}312
+```313
+314
+---315
+316
+## 八、数据库交互317
+318
+### 8.1 表结构319
+320
+- `typecho_contents`:文章内容321
+- `typecho_fields`:自定义字段(`name` + `str_value` + `cid`)322
+- `typecho_comments`:评论323
+- `typecho_users`:用户324
+- `typecho_options`:设置项325
+326
+### 8.2 关键查询327
+328
+```sql329
+-- 获取自定义字段330
+SELECT name, str_value FROM typecho_fields WHERE cid = ?331
+332
+-- 获取评论(带用户信息)333
+SELECT c.*, u.screenName FROM typecho_comments c334
+LEFT JOIN typecho_users u ON c.authorId = u.uid335
+WHERE c.cid = ? ORDER BY c.created ASC336
+337
+-- 文章作者查询(修复 ownerId=0 问题)338
+SELECT authorId FROM typecho_contents WHERE cid = ?339
+```340
+341
+---342
+343
+## 九、插件依赖344
+345
+| 插件 | 状态 | 用途 |346
+|------|------|------|347
+| CommentNotifier | ✅ 已激活 | 评论邮件通知 |348
+| Links | ✅ 已激活 | 友链管理 |349
+| ArticlePoster | ⚠️ 状态未知 | 文章海报生成 |350
+351
+---352
+353
+## 十、备份清单354
+355
+| 备份名 | 时间 | 说明 |356
+|--------|------|------|357
+| pyq_backup_20260627_210104 | 06-27 21:01 | 最初完整备份 |358
+| pyq_backup_20260628_123511 | 06-28 12:35 | Tab式设置界面完成后 |359
+| pyq_backup_20260628_141400 | 06-28 14:14 | LRC功能尝试前 |360
+| pyq_backup_20260628_153600 | 06-28 15:36 | LRC回滚后 |361
+| pyq_backup_20260628_163947 | 06-28 16:39 | 代码清理后 |362
+| pyq_backup_20260628_173800 | 06-28 17:38 | 移动端优化后 |363
+| pyq_backup_20260628_181600 | 06-28 18:16 | LRC首轮修复后 |364
+| pyq_backup_20260628_184200 | 06-28 18:42 | LRC二轮修复后 |365
+| pyq_backup_20260628_185100 | 06-28 18:51 | 进度条前 |366
+| pyq_backup_20260628_190200 | 06-28 19:02 | 最新 |367
+368
+---369
+370
+## 十一、踩坑记录(关键教训)371
+372
+1. **Typecho `.row` 默认 `width: 100vw`** — 导致编辑器容器溢出,需覆盖为 `width: 100%`373
+2. **Typecho `setAttribute()` 设在 `<li>` 上** — 需用 `$e->input->setAttribute()` 设在 `<input>` 上374
+3. **IIFE 闭合位置错误** — `})();` 必须在所有 `pyq.xxx` 定义之后375
+4. **`display:none` 的父容器** — 子元素的 `display:flex` 无效,必须同时检查父容器376
+5. **PJAX 内联 script 不执行** — `innerHTML` 注入的 `<script>` 不会执行,函数必须放外部 JS377
+6. **`height:0;overflow:hidden` 的容器** — 内部元素永远不可交互,按钮必须放外面378
+7. **CSS 变量不能用于伪元素 `background-image`** — 跨浏览器不兼容,用真实 DOM 更可靠379
+8. **`scrollIntoView` 带动页面滚动** — 容器高度动画时使用 `scrollTo` 代替380
+9. **单引号里 `\n` 是字面量** — 不是换行,需用双引号381
+10. **Typecho 插件钩子系统** — 命名空间必须是 `TypechoPlugin\PluginName\ClassName`,手动 SQL 激活不会运行构造函数382
+383
+---384
+385
+## 十二、性能优化386
+387
+- 图片懒加载(IntersectionObserver)388
+- PJAX 无刷新(减少整页重载)389
+- CSS `will-change` 用于动画元素390
+- `requestAnimationFrame` 用于高频更新(歌词同步、进度条)391
+- 音乐代理流式传输(不缓存完整文件)392
+- Prism.js 按需加载(仅代码块页面)393
+394
+---395
+396
+_文档生成时间:2026-06-28 19:02_397
+_主题总代码量:5266 行_398
+_备份总数:10 个_