From 7cdae82357aeda45af9a61f0334acb905d035cc0 Mon Sep 17 00:00:00 2001
From: zhangminghao <2275599059@qq.com>
Date: Fri, 5 Sep 2025 15:14:46 +0800
Subject: [PATCH 1/3] =?UTF-8?q?=E8=8B=8F=E9=9D=92=E5=A3=B3=E9=98=85?=
=?UTF-8?q?=E8=AF=BB=E9=A2=98=EF=BC=8C=E5=8F=8A=E8=AF=AD=E9=9F=B3=E6=92=AD?=
=?UTF-8?q?=E6=8A=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
components/SwipeToNext.vue | 187 ++++++++++++++++
components/SwipeToNext使用文档.md | 293 ++++++++++++++++++++++++++
package-lock.json | 27 ++-
pages.json | 60 ++++++
pages/index/readingBody.vue | 1 +
project.config.json | 25 +++
project.private.config.json | 14 ++
xqk/chapter1/index.vue | 218 +++++++++++++++++++
xqk/chapter2/index.vue | 216 +++++++++++++++++++
xqk/chapter3/index.vue | 244 +++++++++++++++++++++
xqk/chapter4/index.vue | 132 ++++++++++++
xqk/chapter5/index.vue | 188 +++++++++++++++++
xqk/chapter6/index.vue | 216 +++++++++++++++++++
xqk/chapter7/index.vue | 143 +++++++++++++
xqk/chapter8/index.vue | 75 +++++++
xqk/components/NavMenu.vue | 248 ++++++++++++++++++++++
xqk/components/SinglePlayGif.vue | 95 +++++++++
xqk/home/home.vue | 171 +++++++++++++++
18 files changed, 2552 insertions(+), 1 deletion(-)
create mode 100644 components/SwipeToNext.vue
create mode 100644 components/SwipeToNext使用文档.md
create mode 100644 project.config.json
create mode 100644 project.private.config.json
create mode 100644 xqk/chapter1/index.vue
create mode 100644 xqk/chapter2/index.vue
create mode 100644 xqk/chapter3/index.vue
create mode 100644 xqk/chapter4/index.vue
create mode 100644 xqk/chapter5/index.vue
create mode 100644 xqk/chapter6/index.vue
create mode 100644 xqk/chapter7/index.vue
create mode 100644 xqk/chapter8/index.vue
create mode 100644 xqk/components/NavMenu.vue
create mode 100644 xqk/components/SinglePlayGif.vue
create mode 100644 xqk/home/home.vue
diff --git a/components/SwipeToNext.vue b/components/SwipeToNext.vue
new file mode 100644
index 0000000..f918e49
--- /dev/null
+++ b/components/SwipeToNext.vue
@@ -0,0 +1,187 @@
+
+
+
+
+
+ {{ tipText }}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/SwipeToNext使用文档.md b/components/SwipeToNext使用文档.md
new file mode 100644
index 0000000..beb649f
--- /dev/null
+++ b/components/SwipeToNext使用文档.md
@@ -0,0 +1,293 @@
+# SwipeToNext 组件使用文档
+
+## 组件介绍
+
+`SwipeToNext` 是一个通用的触底跳转组件,封装了手势检测、延迟防抖、提示文字等功能,可以在任何需要滑动跳转的页面中使用。
+
+## 组件特性
+
+- ✅ 手势滑动检测
+- ✅ 防误触发机制(延迟允许跳转)
+- ✅ 可配置的滑动阈值
+- ✅ 自定义提示文字
+- ✅ 支持事件监听
+- ✅ 完全可配置的参数
+
+## 使用方法
+
+### 1. 引入组件
+
+```vue
+
+```
+
+### 2. 基础使用
+
+```vue
+
+
+
+
+
+
+
+
+
+
+```
+
+### 3. 完整配置使用
+
+```vue
+
+
+
+
+
+
+
+
+```
+
+## Props 参数
+
+| 参数名 | 类型 | 默认值 | 必填 | 说明 |
+|--------|------|--------|------|------|
+| `isLastSlide` | Boolean | `false` | ✅ | 是否在最后一页/最后一个状态 |
+| `targetPath` | String | - | ✅ | 跳转的目标路径 |
+| `showTip` | Boolean | `true` | ❌ | 是否显示提示文字 |
+| `tipText` | String | `'继续向上滑动进入下一章节'` | ❌ | 提示文字内容 |
+| `swipeThreshold` | Number | `80` | ❌ | 滑动阈值(像素) |
+| `delayTime` | Number | `500` | ❌ | 延迟允许跳转的时间(毫秒) |
+| `enableDelay` | Boolean | `true` | ❌ | 是否启用延迟机制 |
+| `alwaysEnable` | Boolean | `false` | ❌ | 是否总是启用跳转(忽略isLastSlide状态) |
+
+## Events 事件
+
+| 事件名 | 参数 | 说明 |
+|--------|------|------|
+| `swipe-to-next` | `targetPath` | 触发跳转时的回调事件 |
+
+## 使用场景示例
+
+### 场景1:图片轮播页面
+
+```vue
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### 场景2:文章阅读页面
+
+```vue
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### 场景4:单张图片或总是启用触底跳转
+
+```vue
+
+
+
+
+
+
+
+
+
+```
+
+```vue
+
+
+
+
+ 步骤 {{ currentStep + 1 }} / {{ totalSteps }}
+
+
+
+
+
+
+
+```
+
+## 特殊情况处理
+
+### 单张图片问题
+
+当只有一张图片时,传统的 `isLastSlide` 逻辑不适用。这时可以使用 `alwaysEnable` 参数:
+
+```vue
+
+
+
+
+```
+
+### 参数优先级
+
+当 `alwaysEnable="true"` 时:
+- 忽略 `isLastSlide` 的值
+- 总是显示提示文字
+- 总是允许触底跳转
+- 建议设置 `enableDelay="false"` 以获得更好的响应速度
+
+
+
+1. **确保正确设置 `isLastSlide`**:这是控制是否允许跳转的关键属性
+2. **路径格式**:`targetPath` 需要是有效的 uni-app 路由路径
+3. **性能考虑**:如果不需要延迟机制,可以设置 `enableDelay: false` 来提高响应速度
+4. **样式覆盖**:组件内的提示文字样式可以通过全局样式覆盖
+5. **事件监听**:建议监听 `swipe-to-next` 事件进行数据统计或其他操作
+
+## 自定义样式
+
+如果需要自定义提示文字的样式,可以在页面中添加:
+
+```scss
+// 覆盖组件样式
+.swipe-to-next .bottom-tip {
+ bottom: 200rpx !important; // 调整位置
+ background: rgba(255, 255, 255, 0.9) !important; // 改变背景色
+
+ text {
+ color: #333 !important; // 改变文字颜色
+ font-size: 32rpx !important; // 改变字体大小
+ }
+}
+```
+
+这个组件极大地简化了触底跳转功能的实现,让你可以专注于业务逻辑而不用重复编写相同的手势检测代码。
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 50708b2..53483a8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,8 +1,33 @@
{
"name": "cgc_wechat",
"version": "1.0.0",
- "lockfileVersion": 1,
+ "lockfileVersion": 2,
"requires": true,
+ "packages": {
+ "": {
+ "name": "cgc_wechat",
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "moment": "^2.30.1",
+ "ydui-district": "^1.1.0"
+ },
+ "devDependencies": {}
+ },
+ "node_modules/moment": {
+ "version": "2.30.1",
+ "resolved": "https://registry.npmmirror.com/moment/-/moment-2.30.1.tgz",
+ "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ydui-district": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmmirror.com/ydui-district/-/ydui-district-1.1.0.tgz",
+ "integrity": "sha512-MBhvfaR5Gkn6MUmEnrH1A7IFB5igALuDgtIF+gz3dRwNwW9+KOmih7z+xZFfGluMsEbWaT7C3lWOckYsLZQnFg=="
+ }
+ },
"dependencies": {
"moment": {
"version": "2.30.1",
diff --git a/pages.json b/pages.json
index 303bc79..420a58a 100644
--- a/pages.json
+++ b/pages.json
@@ -553,6 +553,66 @@
}
}
]
+ },
+ {
+ "root": "xqk",
+ "pages": [{
+ "path": "home/home",
+ "style": {
+ "navigationBarTitleText": "",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "chapter1/index",
+ "style": {
+ "navigationBarTitleText": "",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "chapter2/index",
+ "style": {
+ "navigationBarTitleText": "",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "chapter3/index",
+ "style": {
+ "navigationBarTitleText": "",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "chapter4/index",
+ "style": {
+ "navigationBarTitleText": "",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "chapter5/index",
+ "style": {
+ "navigationBarTitleText": "",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "chapter6/index",
+ "style": {
+ "navigationBarTitleText": "",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "chapter7/index",
+ "style": {
+ "navigationBarTitleText": "",
+ "navigationStyle": "custom"
+ }
+ }
+ ]
}
],
"tabBar": {
diff --git a/pages/index/readingBody.vue b/pages/index/readingBody.vue
index b31743a..b68e37b 100644
--- a/pages/index/readingBody.vue
+++ b/pages/index/readingBody.vue
@@ -60,6 +60,7 @@
+
diff --git a/project.config.json b/project.config.json
new file mode 100644
index 0000000..3c63362
--- /dev/null
+++ b/project.config.json
@@ -0,0 +1,25 @@
+{
+ "setting": {
+ "es6": true,
+ "postcss": true,
+ "minified": true,
+ "uglifyFileName": false,
+ "enhance": true,
+ "packNpmRelationList": [],
+ "babelSetting": {
+ "ignore": [],
+ "disablePlugins": [],
+ "outputPath": ""
+ },
+ "useCompilerPlugins": false,
+ "minifyWXML": true
+ },
+ "compileType": "miniprogram",
+ "simulatorPluginLibVersion": {},
+ "packOptions": {
+ "ignore": [],
+ "include": []
+ },
+ "appid": "wx8954209bb3ad489e",
+ "editorSetting": {}
+}
\ No newline at end of file
diff --git a/project.private.config.json b/project.private.config.json
new file mode 100644
index 0000000..d64d056
--- /dev/null
+++ b/project.private.config.json
@@ -0,0 +1,14 @@
+{
+ "libVersion": "3.10.0",
+ "projectname": "EpicSoul",
+ "setting": {
+ "urlCheck": true,
+ "coverView": true,
+ "lazyloadPlaceholderEnable": false,
+ "skylineRenderEnable": false,
+ "preloadBackgroundData": false,
+ "autoAudits": false,
+ "showShadowRootInWxmlPanel": true,
+ "compileHotReLoad": true
+ }
+}
\ No newline at end of file
diff --git a/xqk/chapter1/index.vue b/xqk/chapter1/index.vue
new file mode 100644
index 0000000..ab3b9f0
--- /dev/null
+++ b/xqk/chapter1/index.vue
@@ -0,0 +1,218 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/xqk/chapter2/index.vue b/xqk/chapter2/index.vue
new file mode 100644
index 0000000..45dc55b
--- /dev/null
+++ b/xqk/chapter2/index.vue
@@ -0,0 +1,216 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/xqk/chapter3/index.vue b/xqk/chapter3/index.vue
new file mode 100644
index 0000000..8de0ea1
--- /dev/null
+++ b/xqk/chapter3/index.vue
@@ -0,0 +1,244 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 你的
+ {{inputValue}}
+ 已备好
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/xqk/chapter4/index.vue b/xqk/chapter4/index.vue
new file mode 100644
index 0000000..e6b4e0e
--- /dev/null
+++ b/xqk/chapter4/index.vue
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/xqk/chapter5/index.vue b/xqk/chapter5/index.vue
new file mode 100644
index 0000000..3c9132d
--- /dev/null
+++ b/xqk/chapter5/index.vue
@@ -0,0 +1,188 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/xqk/chapter6/index.vue b/xqk/chapter6/index.vue
new file mode 100644
index 0000000..a9ea516
--- /dev/null
+++ b/xqk/chapter6/index.vue
@@ -0,0 +1,216 @@
+
+
+
+
+
+
+
+
+
+
+ {{item}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/xqk/chapter7/index.vue b/xqk/chapter7/index.vue
new file mode 100644
index 0000000..5c804af
--- /dev/null
+++ b/xqk/chapter7/index.vue
@@ -0,0 +1,143 @@
+
+
+
+
+
+
+
+
+ {{info.text1}}
+
+ {{info.text2}}
+
+ {{info.imgTitle}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/xqk/chapter8/index.vue b/xqk/chapter8/index.vue
new file mode 100644
index 0000000..0b339f9
--- /dev/null
+++ b/xqk/chapter8/index.vue
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/xqk/components/NavMenu.vue b/xqk/components/NavMenu.vue
new file mode 100644
index 0000000..ac3e469
--- /dev/null
+++ b/xqk/components/NavMenu.vue
@@ -0,0 +1,248 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/xqk/components/SinglePlayGif.vue b/xqk/components/SinglePlayGif.vue
new file mode 100644
index 0000000..a3d56a8
--- /dev/null
+++ b/xqk/components/SinglePlayGif.vue
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/xqk/home/home.vue b/xqk/home/home.vue
new file mode 100644
index 0000000..3dfbd33
--- /dev/null
+++ b/xqk/home/home.vue
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
From 22da441688e48256efa0854c144a573ad315f1b8 Mon Sep 17 00:00:00 2001
From: zhangminghao <2275599059@qq.com>
Date: Fri, 5 Sep 2025 15:25:26 +0800
Subject: [PATCH 2/3] =?UTF-8?q?=E8=8B=8F=E9=9D=92=E5=A3=B3=20=E5=8F=8A?=
=?UTF-8?q?=E8=AF=AD=E9=9F=B3=E6=92=AD=E6=8A=A5=20josn?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
App.vue | 3 +-
bmzm/chapter1/index.vue | 372 ++--
bmzm/chapter2/index.vue | 5 +-
bmzm/chapter3/index.vue | 5 +-
bmzm/chapter4/index.vue | 5 +-
bmzm/chapter5/index.vue | 5 +-
bmzm/chapter6/index.vue | 5 +-
bmzm/chapter7/index.vue | 5 +-
bmzm/home/home.vue | 5 +-
components/AudioControl.vue | 289 +++
components/AudioControl使用文档.md | 155 ++
components/MusicControl.vue | 65 +-
components/SwipeToNext.vue | 2 +-
.../跨页面音频控制解决方案.md | 225 +++
components/音频背景音乐交互说明.md | 144 ++
main.js | 1 +
pages.json | 7 -
pages/index/readingBody.vue | 16 +-
pig/chapter1/chapter1.vue | 5 +-
pig/chapter2/chapter2.vue | 5 +-
pig/chapter3/chapter3.vue | 5 +-
pig/chapter4/chapter4.vue | 5 +-
pig/home/home.vue | 1749 ++++++++---------
static/js/CommonFunction.js | 96 +-
taozi/chapter1/chapter1.vue | 5 +-
taozi/chapter2/chapter2.vue | 5 +-
taozi/chapter3/chapter3.vue | 5 +-
taozi/chapter4/chapter4.vue | 5 +-
taozi/home/home.vue | 5 +-
utils/globalAudioManager.js | 92 +
xqk/chapter1/index.vue | 206 +-
xqk/chapter2/index.vue | 55 +-
xqk/chapter3/index.vue | 154 +-
xqk/chapter4/index.vue | 164 +-
xqk/chapter5/index.vue | 74 +-
xqk/chapter6/index.vue | 138 +-
xqk/chapter7/index.vue | 143 --
xqk/chapter8/index.vue | 75 -
xqk/components/NavMenu.vue | 6 +-
xqk/home/home.vue | 52 +-
xrcc/chapter1/index.vue | 16 +-
xrcc/chapter2/index.vue | 5 +-
xrcc/chapter3/index.vue | 6 +-
xrcc/chapter4/index.vue | 6 +-
xrcc/chapter5/index.vue | 6 +-
xrcc/chapter6/index.vue | 6 +-
xrcc/chapter7/index.vue | 6 +-
xrcc/chapter8/index.vue | 6 +-
xrcc/home/home.vue | 31 +-
xxdf/chapter1/cover1.vue | 5 +-
xxdf/chapter1/detail1.vue | 4 +-
xxdf/chapter1/detail2.vue | 5 +-
xxdf/chapter1/detail3.vue | 5 +-
xxdf/chapter1/detail4.vue | 5 +-
xxdf/chapter1/detail5.vue | 5 +-
xxdf/chapter2/cover.vue | 5 +-
xxdf/chapter3/cover.vue | 5 +-
xxdf/chapter4/cover.vue | 6 +-
xxdf/home/home.vue | 5 +-
59 files changed, 2758 insertions(+), 1743 deletions(-)
create mode 100644 components/AudioControl.vue
create mode 100644 components/AudioControl使用文档.md
create mode 100644 components/跨页面音频控制解决方案.md
create mode 100644 components/音频背景音乐交互说明.md
create mode 100644 utils/globalAudioManager.js
delete mode 100644 xqk/chapter7/index.vue
delete mode 100644 xqk/chapter8/index.vue
diff --git a/App.vue b/App.vue
index 2e0616a..c8f52ac 100644
--- a/App.vue
+++ b/App.vue
@@ -5,7 +5,8 @@
randomImages: [],
bgMusic: null,
isMusicPlaying: false,
- musicSrc: 'https://static.ticket.sz-trip.com/epicSoul/EpicSouls.mp3'
+ musicSrc: 'https://static.ticket.sz-trip.com/epicSoul/EpicSouls.mp3',
+ currentAudio: null // 全局音频实例
},
onLaunch: function() {
console.warn('当前组件仅支持 uni_modules 目录结构 ,请升级 HBuilderX 到 3.1.0 版本以上!')
diff --git a/bmzm/chapter1/index.vue b/bmzm/chapter1/index.vue
index ca9a618..388a729 100644
--- a/bmzm/chapter1/index.vue
+++ b/bmzm/chapter1/index.vue
@@ -1,147 +1,263 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
-
+
+
+
-
+
+
\ No newline at end of file
diff --git a/bmzm/chapter2/index.vue b/bmzm/chapter2/index.vue
index 15c6f29..de98934 100644
--- a/bmzm/chapter2/index.vue
+++ b/bmzm/chapter2/index.vue
@@ -10,16 +10,19 @@
+
+
+
\ No newline at end of file
diff --git a/components/AudioControl使用文档.md b/components/AudioControl使用文档.md
new file mode 100644
index 0000000..4b2ed0d
--- /dev/null
+++ b/components/AudioControl使用文档.md
@@ -0,0 +1,155 @@
+# AudioControl 音频控制组件使用文档
+
+## 组件功能
+- 在父组件右上角显示音频控制图标
+- 点击图标播放指定音频,同时暂停背景音乐
+- 再次点击暂停音频,恢复背景音乐
+- 音频播放结束后自动恢复背景音乐
+
+## 组件属性 (Props)
+
+| 属性名 | 类型 | 必填 | 默认值 | 说明 |
+|--------|------|------|--------|------|
+| audioSrc | String | 是 | - | 音频文件路径 |
+| visible | Boolean | 否 | true | 是否显示组件 |
+
+## 使用方法
+
+### 1. 在父组件中引入和注册组件
+
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### 2. 使用项目中的showImg方法(推荐)
+
+如果你的音频文件也存储在项目服务器上,可以使用项目的showImg方法:
+
+```vue
+
+```
+
+### 3. 动态控制音频源
+
+你可以根据不同的页面或条件播放不同的音频:
+
+```vue
+
+```
+
+## 样式说明
+
+组件默认定位在父组件的右上角(top: 30rpx, right: 30rpx),如果需要调整位置,可以在父组件中覆盖样式:
+
+```vue
+
+```
+
+## 注意事项
+
+1. **父组件样式**:确保父组件设置了 `position: relative`,这样AudioControl组件才能正确定位
+2. **音频格式**:建议使用 mp3 格式的音频文件,兼容性最好
+3. **音频路径**:确保音频文件路径正确且可访问
+4. **背景音乐**:组件会自动处理与MusicControl组件的交互,无需额外配置
+
+## 图标说明
+
+- 🔊:音频未播放状态
+- 🎧:音频播放中状态,带有脉动动画效果
+
+## 事件处理
+
+组件内部已处理所有音频播放逻辑,包括:
+- 播放音频时自动暂停背景音乐
+- 暂停音频时自动恢复背景音乐
+- 音频播放结束时自动恢复背景音乐
+- 组件销毁时自动清理资源
+
+## 示例场景
+
+适用于以下场景:
+- 章节页面播放对应的音频解说
+- 展示页面播放介绍音频
+- 互动页面播放提示音频
+- 任何需要临时播放音频并暂停背景音乐的场景
\ No newline at end of file
diff --git a/components/MusicControl.vue b/components/MusicControl.vue
index 54b8986..ffb7bf4 100644
--- a/components/MusicControl.vue
+++ b/components/MusicControl.vue
@@ -11,24 +11,35 @@ export default {
name: 'MusicControl',
data() {
return {
- isPlaying: false
+ isPlaying: false,
+ isAudioPlaying: false // 记录音频播放状态
}
},
mounted() {
- console.log('初始化')
+ // console.log('初始化')
// 组件挂载时同步音乐状态
this.syncMusicState();
+ // 检查全局音频状态
+ this.checkGlobalAudioState();
+
// 添加定时器,每秒同步一次状态
this.timer = setInterval(() => {
this.syncMusicState();
+ this.checkGlobalAudioState();
}, 1000);
+
+ // 监听音频播放状态变化
+ uni.$on('audioPlaying', this.handleAudioStateChange);
},
beforeUnmount() {
// 组件卸载前清除定时器
if (this.timer) {
clearInterval(this.timer);
}
+
+ // 移除事件监听
+ uni.$off('audioPlaying', this.handleAudioStateChange);
},
methods: {
syncMusicState() {
@@ -41,19 +52,57 @@ export default {
toggleMusic() {
const app = getApp();
if (!app || !app.globalData || !app.globalData.bgMusic) {
- console.error('背景音乐未初始化');
+ // console.error('背景音乐未初始化');
return;
}
const bgMusic = app.globalData.bgMusic;
- console.log(bgMusic)
+ // console.log(bgMusic)
- // 直接基于当前组件的状态切换
- if (this.isPlaying) {
- bgMusic.pause();
+ // 先发送背景音乐切换事件,通知AudioControl组件(但不要让它恢复背景音乐)
+ if (this.isAudioPlaying) {
+ uni.$emit('backgroundMusicToggle');
+ // 等待一小段时间确保音频已暂停
+ setTimeout(() => {
+ // 直接基于当前组件的状态切换背景音乐
+ if (this.isPlaying) {
+ bgMusic.pause();
+ } else {
+ bgMusic.play();
+ }
+ }, 100);
} else {
- bgMusic.play();
+ // 没有音频在播放时,直接切换背景音乐
+ if (this.isPlaying) {
+ bgMusic.pause();
+ } else {
+ bgMusic.play();
+ }
+ }
+ },
+
+ // 处理音频状态变化
+ handleAudioStateChange(isAudioPlaying) {
+ this.isAudioPlaying = isAudioPlaying;
+ // console.log('音频状态变化:', isAudioPlaying);
+ },
+
+ // 检查全局音频状态
+ checkGlobalAudioState() {
+ try {
+ const app = getApp();
+ if (app && app.globalData && app.globalData.currentAudio) {
+ const globalAudio = app.globalData.currentAudio;
+ // 检查全局音频是否在播放
+ this.isAudioPlaying = !globalAudio.paused;
+ // console.log('检查到全局音频状态:', this.isAudioPlaying);
+ } else {
+ this.isAudioPlaying = false;
+ }
+ } catch (error) {
+ // console.error('检查全局音频状态失败:', error);
+ this.isAudioPlaying = false;
}
}
}
diff --git a/components/SwipeToNext.vue b/components/SwipeToNext.vue
index f918e49..3558f0b 100644
--- a/components/SwipeToNext.vue
+++ b/components/SwipeToNext.vue
@@ -34,7 +34,7 @@ export default {
// 提示文字内容
tipText: {
type: String,
- default: '上滑动进入下一章节'
+ default: '上滑进入下一章节'
},
// 滑动阈值(px)
swipeThreshold: {
diff --git a/components/跨页面音频控制解决方案.md b/components/跨页面音频控制解决方案.md
new file mode 100644
index 0000000..a32147a
--- /dev/null
+++ b/components/跨页面音频控制解决方案.md
@@ -0,0 +1,225 @@
+# 跨页面音频控制解决方案
+
+## 进一步优化:解决跨页面状态同步问题
+
+### 问题描述
+在跨页面场景下,当音频正在播放时跳转到新页面,新页面的MusicControl组件不知道有音频在播放,点击背景音乐按钮时会直接播放背景音乐,导致音频和背景音乐同时播放。
+
+### 解决方案
+
+#### 1. MusicControl组件增强检测
+```javascript
+// 在mounted生命周期中添加全局音频状态检测
+mounted() {
+ this.syncMusicState();
+ this.checkGlobalAudioState(); // 新增:检查全局音频状态
+
+ // 定时器也要检查全局音频状态
+ this.timer = setInterval(() => {
+ this.syncMusicState();
+ this.checkGlobalAudioState();
+ }, 1000);
+}
+
+// 新增方法:检查全局音频状态
+checkGlobalAudioState() {
+ const app = getApp();
+ if (app && app.globalData && app.globalData.currentAudio) {
+ const globalAudio = app.globalData.currentAudio;
+ this.isAudioPlaying = !globalAudio.paused;
+ } else {
+ this.isAudioPlaying = false;
+ }
+}
+```
+
+#### 2. 全局音频管理工具优化
+```javascript
+// 在音频状态变化时发送全局事件
+pauseCurrentAudio() {
+ const audio = this.getCurrentAudio();
+ if (audio && !audio.paused) {
+ audio.pause();
+ this.notifyAudioStateChange(false); // 通知状态变化
+ return true;
+ }
+ return false;
+}
+
+// 新增:通知音频状态变化
+notifyAudioStateChange(isPlaying) {
+ if (typeof uni !== 'undefined') {
+ uni.$emit('audioPlaying', isPlaying);
+ }
+}
+```
+
+### 修复后的交互流程
+```mermaid
+graph TD
+A[跨页面跳转] --> B[MusicControl组件加载]
+B --> C[检查全局音频状态]
+C --> D{有音频在播放?}
+D -->|是| E[设置isAudioPlaying=true]
+D -->|否| F[设置isAudioPlaying=false]
+E --> G[点击背景音乐按钮]
+F --> G
+G --> H{检查isAudioPlaying}
+H -->|有音频| I[先暂停音频再播放背景音乐]
+H -->|无音频| J[直接播放背景音乐]
+```
+
+## 问题描述
+
+AudioControl组件在页面跳转时会出现以下问题:
+1. 组件状态重置,图标显示不正确
+2. 音频实例丢失连接,但音频可能仍在播放
+3. 无法在其他页面控制正在播放的音频
+
+## 解决方案
+
+### 1. 全局音频实例管理
+
+在`App.vue`的`globalData`中添加`currentAudio`属性,用于保存当前的音频实例:
+
+```javascript
+globalData: {
+ // ... 其他属性
+ currentAudio: null // 全局音频实例
+}
+```
+
+### 2. AudioControl组件优化
+
+#### 状态同步机制
+- 组件挂载时检查全局音频状态
+- 复用已存在的音频实例(如果URL匹配)
+- 组件销毁时不销毁全局音频实例
+
+#### 核心方法改进
+```javascript
+// 检查全局音频状态
+checkGlobalAudioState() {
+ const app = getApp();
+ if (app && app.globalData && app.globalData.currentAudio) {
+ const globalAudio = app.globalData.currentAudio;
+ if (globalAudio.src === this.audioSrc) {
+ this.isAudioPlaying = !globalAudio.paused;
+ }
+ }
+}
+
+// 初始化音频时复用全局实例
+initAudio() {
+ const app = getApp();
+ if (app && app.globalData && app.globalData.currentAudio) {
+ if (app.globalData.currentAudio.src === this.audioSrc) {
+ // 复用现有实例
+ this.audioContext = app.globalData.currentAudio;
+ this.isAudioPlaying = !this.audioContext.paused;
+ return;
+ }
+ }
+ // 创建新实例...
+}
+```
+
+### 3. 全局音频管理工具
+
+创建了`utils/globalAudioManager.js`工具类,提供统一的音频控制接口:
+
+```javascript
+// 在任何页面或组件中使用
+uni.$globalAudio.pauseCurrentAudio(); // 暂停当前音频
+uni.$globalAudio.playCurrentAudio(); // 播放当前音频
+uni.$globalAudio.isAudioPlaying(); // 检查播放状态
+uni.$globalAudio.getCurrentAudioSrc(); // 获取当前音频源
+```
+
+## 使用示例
+
+### 在页面中控制音频
+
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### 在其他页面检查音频状态
+
+```javascript
+// 在任何页面的onShow生命周期中
+onShow() {
+ // 检查是否有音频在播放
+ if (uni.$globalAudio.isAudioPlaying()) {
+ console.log('有音频正在播放:', uni.$globalAudio.getCurrentAudioSrc());
+ }
+}
+```
+
+## 技术优势
+
+### ✅ **状态持久化**
+- 音频实例在页面跳转时不会丢失
+- 组件状态能够正确同步全局音频状态
+
+### ✅ **跨页面控制**
+- 在任何页面都可以控制当前播放的音频
+- 提供统一的音频管理接口
+
+### ✅ **资源优化**
+- 避免创建多个音频实例
+- 自动清理无用的音频资源
+
+### ✅ **用户体验**
+- 页面跳转时音频播放不中断
+- 图标状态显示正确
+- 音频控制逻辑一致
+
+## 注意事项
+
+1. **页面生命周期**:音频实例与页面生命周期解耦,需要手动管理
+2. **内存管理**:确保在应用退出时正确清理音频资源
+3. **状态同步**:多个AudioControl组件需要监听相同的全局状态
+4. **错误处理**:增强错误处理机制,确保音频异常时的状态恢复
+
+## 兼容性
+
+- ✅ uni-app
+- ✅ 小程序环境
+- ✅ H5环境
+- ✅ APP环境
\ No newline at end of file
diff --git a/components/音频背景音乐交互说明.md b/components/音频背景音乐交互说明.md
new file mode 100644
index 0000000..c77ad71
--- /dev/null
+++ b/components/音频背景音乐交互说明.md
@@ -0,0 +1,144 @@
+# 音频与背景音乐交互功能说明
+
+## Bug修复记录
+
+### 问题描述
+当音频播放时点击背景音乐按钮,背景音乐暂停音频并开始播放。此时再点击关闭背景音乐,图标显示关闭状态但背景音乐仍在播放。
+
+### 问题原因
+1. 点击背景音乐按钮时会发送事件暂停音频
+2. 音频暂停时会调用restoreBackgroundMusic恢复背景音乐
+3. 然后MusicControl再执行自己的切换逻辑
+4. 导致背景音乐被恢复后又被操作,状态混乱
+
+### 解决方案
+1. **MusicControl组件优化**:
+ - 检测是否有音频在播放
+ - 如有音频,先暂停音频,延迟执行背景音乐切换
+ - 如无音频,直接切换背景音乐状态
+
+2. **AudioControl组件优化**:
+ - 在handleBackgroundMusicToggle中只暂停音频
+ - 不自动恢复背景音乐,让MusicControl自己控制
+
+### 修复后的交互流程
+```mermaid
+graph TD
+A[点击背景音乐按钮] --> B{是否有音频播放?}
+B -->|是| C[发送暂停音频事件]
+C --> D[AudioControl暂停音频\n不恢复背景音乐]
+D --> E[延迟100ms后切换背景音乐]
+B -->|否| F[直接切换背景音乐状态]
+```
+
+## 实现的功能
+
+### 🎵 **背景音乐控制音频**
+当点击背景音乐控制按钮时:
+- 如果有音频正在播放,会自动暂停音频
+- 然后正常切换背景音乐的播放/暂停状态
+
+### 🎧 **音频控制背景音乐**
+当点击音频控制按钮时:
+- 播放音频时自动暂停背景音乐
+- 暂停音频时自动恢复背景音乐
+- 音频播放结束时自动恢复背景音乐
+
+## 技术实现
+
+### 事件通信机制
+使用uni-app的全局事件机制实现组件间通信:
+
+```javascript
+// AudioControl组件发送事件
+uni.$emit('audioPlaying', true/false);
+
+// MusicControl组件发送事件
+uni.$emit('backgroundMusicToggle');
+
+// 组件监听事件
+uni.$on('eventName', this.handlerFunction);
+```
+
+### 交互流程
+
+#### 点击背景音乐按钮:
+```mermaid
+graph TD
+A[点击背景音乐按钮] --> B[发送backgroundMusicToggle事件]
+B --> C[AudioControl收到事件]
+C --> D{音频是否在播放?}
+D -->|是| E[暂停音频]
+D -->|否| F[继续背景音乐操作]
+E --> G[恢复背景音乐]
+F --> H[切换背景音乐状态]
+```
+
+#### 点击音频按钮:
+```mermaid
+graph TD
+A[点击音频按钮] --> B{当前音频状态?}
+B -->|未播放| C[暂停背景音乐]
+C --> D[播放音频]
+D --> E[发送audioPlaying:true事件]
+B -->|正在播放| F[暂停音频]
+F --> G[恢复背景音乐]
+G --> H[发送audioPlaying:false事件]
+```
+
+## 使用方法
+
+在页面中同时使用两个组件:
+
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+## 优势特点
+
+### ✅ **智能交互**
+- 两个组件能够智能感知对方的状态
+- 避免同时播放音频和背景音乐造成的冲突
+- 提供良好的用户体验
+
+### ✅ **解耦设计**
+- 组件间通过事件通信,保持松耦合
+- 每个组件都能独立工作
+- 易于维护和扩展
+
+### ✅ **状态同步**
+- 实时同步音频和背景音乐的播放状态
+- 确保状态的一致性和准确性
+
+## 注意事项
+
+1. **事件监听清理**:组件销毁时会自动清理事件监听,避免内存泄漏
+2. **状态管理**:两个组件都维护各自的状态,通过事件保持同步
+3. **错误处理**:包含完善的错误处理机制,确保功能稳定运行
\ No newline at end of file
diff --git a/main.js b/main.js
index 96732c3..a38e368 100644
--- a/main.js
+++ b/main.js
@@ -4,6 +4,7 @@ import App from './App'
import store from './store'
import '@/static/js/request.js'
import '@/static/js/CommonFunction.js'
+import '@/utils/globalAudioManager.js'
import {myMixins} from '@/mixins/myMixins.js'
Vue.mixin(myMixins)
diff --git a/pages.json b/pages.json
index 420a58a..fcf6767 100644
--- a/pages.json
+++ b/pages.json
@@ -604,13 +604,6 @@
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
- },
- {
- "path": "chapter7/index",
- "style": {
- "navigationBarTitleText": "",
- "navigationStyle": "custom"
- }
}
]
}
diff --git a/pages/index/readingBody.vue b/pages/index/readingBody.vue
index b68e37b..46a71d2 100644
--- a/pages/index/readingBody.vue
+++ b/pages/index/readingBody.vue
@@ -60,7 +60,7 @@
-
+
@@ -110,6 +110,8 @@
app.initBackgroundMusic(); // 初始化背景音乐
uni.$bgMusic.play(); // 播放音乐
}
+ // 暂停所有其他音频(保留背景音乐)
+ this.pauseAllOtherAudio();
},
methods: {
sendRequest() {
@@ -188,6 +190,18 @@
uni.navigateTo({
url:'/subPackages/letter/detail?id='+item.id
})
+ },
+ // 暂停所有其他音频(AudioControl组件的音频)
+ pauseAllOtherAudio() {
+ try {
+ // 暂停全局音频(AudioControl组件的音频)
+ if (uni.$globalAudio && uni.$globalAudio.isAudioPlaying()) {
+ uni.$globalAudio.pauseCurrentAudio();
+ console.log('readingBody: 暂停其他音频,只保留背景音乐');
+ }
+ } catch (error) {
+ console.error('readingBody: 暂停音频失败:', error);
+ }
}
}
}
diff --git a/pig/chapter1/chapter1.vue b/pig/chapter1/chapter1.vue
index 9945e6d..6a34e97 100644
--- a/pig/chapter1/chapter1.vue
+++ b/pig/chapter1/chapter1.vue
@@ -104,10 +104,12 @@
+
+ @font-face {
+ font-family: "SourceHanSerif-Regular";
+ src: url(/static/fonts/SourceHanSerifSC-Regular.otf);
+ }
+
+ .main-swiper {
+ width: 100%;
+ height: 100vh;
+ }
+
+ .page-container {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ position: relative;
+ overflow: hidden;
+ }
+
+ .loadedPages-three {
+ height: 100%;
+ position: relative;
+ background: #efefef;
+ display: flex;
+ align-items: center;
+ flex-direction: column;
+ justify-content: center;
+ }
+
+ .loadedPages-three-content {
+ height: 100%;
+
+ .loadedPages-three-title {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ width: 100%;
+ margin-top: 30rpx;
+
+ .txt {
+ font-size: 24rpx;
+ color: #333;
+ font-family: SourceHanSerif-Regular;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+
+ text {
+ display: block;
+ }
+ }
+
+ .txt:first-child {
+ margin-left: 30rpx;
+ }
+
+ .txt:last-child {
+ margin-right: 30rpx;
+ }
+ }
+
+ .loadedPages-three-center {
+ position: relative;
+
+ .desc {
+ display: flex;
+ flex-direction: column;
+ font-family: SourceHanSerif-Regular;
+ font-size: 90rpx;
+ color: #ec4899;
+
+ text {
+ display: block;
+ }
+ }
+
+ .en-desc {
+ display: flex;
+ flex-direction: column;
+ position: absolute;
+ top: 50%;
+ right: 0;
+ transform: translate(-25%, -50%);
+ font-size: 24rpx;
+ font-style: italic;
+ color: #4b5563;
+
+ text {
+ display: block;
+ }
+ }
+ }
+
+ .loadedPages-three-bottom {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin-bottom: 30rpx;
+
+ .bottom-img {
+ width: 400rpx;
+ height: 120rpx;
+ }
+
+ .bottom-tit {
+ font-size: 38rpx;
+ }
+
+ .bottom-txt {
+ font-size: 24rpx;
+ font-style: italic;
+ color: #4b5563;
+ }
+ }
+ }
+
+ .bg-image {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 1;
+ }
+
+ .content-layer {
+ position: relative;
+ z-index: 2;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ flex-direction: column;
+ }
+
+ .content-layer2 {
+ z-index: 2;
+ position: absolute;
+ bottom: 5%;
+ right: 5%;
+ }
+
+ .layer-img {
+ width: 650rpx;
+ height: 100%;
+ }
+
+ .arrow-down {
+ width: 100rpx;
+ height: 40rpx;
+ animation: bounce 1.5s infinite;
+ }
+
+ .layer-icon {
+ width: 100rpx;
+ height: 100rpx;
+ animation: bounce 1.5s infinite;
+ }
+
+ .overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(0, 0, 0, 0.3);
+ z-index: 10;
+ }
+
+ .fixed-nav {
+ width: 80rpx;
+ height: 80rpx;
+ background-color: rgb(0 0 0 / 0.7);
+ border-radius: 10rpx 0 0 10rpx;
+ position: fixed;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ margin: auto 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 9;
+ transition: transform 0.3s ease, opacity 0.3s ease;
+ }
+
+ .fixed-nav.hidden {
+ transform: translateX(100%);
+ opacity: 0;
+ pointer-events: none;
+ }
+
+ .nav-icon {
+ width: 35rpx;
+ height: 35rpx;
+ transition: transform 0.3s ease;
+ }
+
+ .nav-icon.rotated {
+ transform: rotate(180deg);
+ }
+
+ .nav-icon.bounce-back {
+ animation: bounceRotation 0.5s ease;
+ }
+
+ @keyframes bounceRotation {
+ 0% {
+ transform: rotate(180deg);
+ }
+
+ 50% {
+ transform: rotate(-20deg);
+ }
+
+ 75% {
+ transform: rotate(10deg);
+ }
+
+ 100% {
+ transform: rotate(0deg);
+ }
+ }
+
+ .nav-menu {
+ position: fixed;
+ top: 50%;
+ right: 0;
+ transform: translate(100%, -50%);
+ z-index: 11;
+ background-color: rgba(255, 255, 255, 0.95);
+ border-radius: 16rpx 0 0 16rpx;
+ box-shadow: -4px 0 15px rgba(0, 0, 0, 0.1);
+ transition: transform 0.3s ease;
+ }
+
+ .nav-menu.show {
+ transform: translate(0, -50%);
+ }
+
+ .nav-item {
+ padding: 20rpx;
+ text-align: center;
+
+ text {
+ color: #333;
+ opacity: 0.7;
+ font-size: 28rpx;
+ }
+ }
+
+ .item-active {
+ background-color: rgba(0, 0, 0, 0.1);
+ }
+
+ .nav-item .active {
+ color: #333;
+ opacity: 1;
+ }
+
+ .chapter-text {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ line-height: 1.3;
+ }
+
+ .chapter-title {
+ color: #333;
+ opacity: 0.7;
+ font-size: 24rpx;
+ }
+
+ .chapter-number {
+ color: #333;
+ opacity: 0.7;
+ font-size: 28rpx;
+ margin-top: 8rpx;
+ }
+
+ .item-active .chapter-title,
+ .item-active .chapter-number.active {
+ opacity: 1;
+ }
+
+ @keyframes bounce {
+
+ 0%,
+ 20%,
+ 50%,
+ 80%,
+ 100% {
+ transform: translateY(0);
+ }
+
+ 40% {
+ transform: translateY(-20rpx);
+ }
+
+ 60% {
+ transform: translateY(-10rpx);
+ }
+ }
+
+ .blur-to-clear {
+ animation: blurToClear 1.5s ease-out forwards;
+ }
+
+ @keyframes blurToClear {
+ 0% {
+ filter: blur(10px);
+ opacity: 0.3;
+ }
+
+ 100% {
+ filter: blur(0);
+ opacity: 1;
+ }
+ }
+
+ .hidden {
+ opacity: 0;
+ }
+
+ .bounce-in {
+ animation: bounceIn 1s ease forwards;
+ }
+
+ @keyframes bounceIn {
+ 0% {
+ opacity: 0;
+ transform: scale(0.3) translateY(100px);
+ }
+
+ 50% {
+ opacity: 1;
+ transform: scale(1.05) translateY(-10px);
+ }
+
+ 70% {
+ transform: scale(0.9) translateY(5px);
+ }
+
+ 100% {
+ opacity: 1;
+ transform: scale(1) translateY(0);
+ }
+ }
+
+ .fade-slide-up {
+ animation: fadeSlideUp 1s ease-out forwards;
+ }
+
+ @keyframes fadeSlideUp {
+ 0% {
+ opacity: 0;
+ transform: translateY(30px);
+ }
+
+ 100% {
+ opacity: 1;
+ transform: translateY(0);
+ }
+ }
+
+ .chapterCover-btn {
+ position: absolute;
+ left: 50%;
+ bottom: 10%;
+ transform: translate(-50%, -50%);
+ width: 300rpx;
+ height: 100rpx;
+ z-index: 2;
+ }
+
+ .qrcode-txt {
+ width: 30vw;
+ z-index: 2;
+ position: fixed;
+ left: 0;
+ right: 0;
+ margin: 100rpx auto 0;
+ }
+
+ .qrcode-txts {
+ width: 28vw;
+ z-index: 2;
+ position: fixed;
+ left: 0;
+ right: 0;
+ margin: 335rpx auto 0;
+ }
+
+ .message-board {
+ width: 100%;
+ }
+
+ .qrCode-image {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 192rpx;
+ margin: 0 auto;
+ z-index: 2;
+ width: 30vw;
+ }
+
+ .image-popup-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(0, 0, 0, 0.8);
+ z-index: 9999;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .image-popup-container {
+ position: relative;
+ max-width: 90vw;
+ max-height: 90vh;
+ }
+
+ .popup-image {
+ width: 750rpx;
+ height: 654rpx;
+ max-width: 100%;
+ max-height: 100%;
+ }
+
+ .close-btn {
+ position: absolute;
+ top: -20rpx;
+ right: -20rpx;
+ width: 60rpx;
+ height: 60rpx;
+ background-color: rgba(255, 255, 255, 0.9);
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 40rpx;
+ color: #333;
+ cursor: pointer;
+ }
+
\ No newline at end of file
diff --git a/static/js/CommonFunction.js b/static/js/CommonFunction.js
index e5dd4b1..723a463 100644
--- a/static/js/CommonFunction.js
+++ b/static/js/CommonFunction.js
@@ -167,9 +167,101 @@ Vue.prototype._requestLocation = function(callback) {
// 路由页面跳转
Vue.prototype.gotoPath = path => {
+ console.log(path,'pathpath');
+
+ // 参数验证
+ if (!path || typeof path !== 'string') {
+ console.error('gotoPath: 路径参数无效', path);
+ return;
+ }
+
+ // 清理路径,移除多余的空格和特殊字符
+ path = path.trim();
+
+ // 检查是否为有效路径格式
+ if (!path.startsWith('/')) {
+ console.error('gotoPath: 路径必须以/开头', path);
+ return;
+ }
+
+ // 获取当前页面栈
+ const pages = getCurrentPages();
+ const currentPage = pages[pages.length - 1];
+ const currentPath = currentPage ? currentPage.route : '';
+
+ // 避免重复跳转到同一页面
+ if (currentPath && ('/' + currentPath) === path) {
+ console.warn('gotoPath: 避免重复跳转到当前页面', path);
+ return;
+ }
+
+ // 检查页面栈深度,避免栈溢出
+ if (pages.length >= 10) {
+ console.warn('gotoPath: 页面栈过深,使用redirectTo替代', path);
+ uni.redirectTo({
+ url: path,
+ fail: (err) => {
+ console.error('redirectTo失败:', err, 'path:', path);
+ // 最后尝试reLaunch
+ uni.reLaunch({
+ url: path,
+ fail: (err2) => {
+ console.error('reLaunch也失败:', err2, 'path:', path);
+ }
+ });
+ }
+ });
+ return;
+ }
+
+ // 防抖处理,避免快速重复点击
+ if (Vue.prototype._lastNavigateTime && Date.now() - Vue.prototype._lastNavigateTime < 500) {
+ console.warn('gotoPath: 防抖拦截,请勿频繁点击');
+ return;
+ }
+ Vue.prototype._lastNavigateTime = Date.now();
+
+ // 尝试正常跳转
uni.navigateTo({
- url: path
- })
+ url: path,
+ success: (res) => {
+ console.log('跳转成功:', path);
+ },
+ fail: (err) => {
+ console.error('navigateTo失败:', err, 'path:', path);
+
+ // 如果是tabBar页面,使用switchTab
+ if (err.errMsg && err.errMsg.includes('tabbar')) {
+ console.log('检测到tabBar页面,使用switchTab');
+ uni.switchTab({
+ url: path,
+ fail: (err2) => {
+ console.error('switchTab也失败:', err2, 'path:', path);
+ }
+ });
+ } else if (err.errMsg && err.errMsg.includes('limit exceed')) {
+ // 页面栈超限,使用redirectTo
+ console.log('页面栈超限,使用redirectTo');
+ uni.redirectTo({
+ url: path,
+ fail: (err3) => {
+ console.error('redirectTo也失败:', err3, 'path:', path);
+ }
+ });
+ } else {
+ // 其他错误,尝试延迟重试
+ console.log('延迟重试跳转');
+ setTimeout(() => {
+ uni.navigateTo({
+ url: path,
+ fail: (err4) => {
+ console.error('延迟重试也失败:', err4, 'path:', path);
+ }
+ });
+ }, 300);
+ }
+ }
+ });
}
// 返回上一页
diff --git a/taozi/chapter1/chapter1.vue b/taozi/chapter1/chapter1.vue
index ec711c9..e86bfe4 100644
--- a/taozi/chapter1/chapter1.vue
+++ b/taozi/chapter1/chapter1.vue
@@ -1,6 +1,7 @@
+
@@ -87,10 +88,12 @@
@@ -94,7 +78,15 @@
width: 100vw;
height: 100vh;
}
-
+ .imgJump{
+ position: absolute;
+ bottom:100rpx;
+ left:250rpx;
+ width: 273rpx;
+ height: 85rpx;
+ opacity: 0.8;
+ z-index: 999999;
+ }
.swiper-item {
width: 100vw;
height: 100vh;
@@ -120,7 +112,7 @@
margin: 0 auto;
bottom: 70rpx;
}
-
+
.img3-btn {
width: 558rpx;
line-height: 72rpx;
@@ -135,17 +127,17 @@
margin: 0 auto;
bottom: 180rpx;
}
-
+
.flex-column {
position: absolute;
bottom: 280rpx;
width: 100%;
align-items: center;
-
+
.img5-text {
width: 100%;
}
-
+
.img5-btn {
width: 230rpx;
margin-top: 99rpx;
diff --git a/xqk/chapter6/index.vue b/xqk/chapter6/index.vue
index a9ea516..91e1b20 100644
--- a/xqk/chapter6/index.vue
+++ b/xqk/chapter6/index.vue
@@ -3,109 +3,65 @@
-
-
-
-
-
- {{item}}
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -123,15 +79,32 @@
background-color: #000;
background-repeat: no-repeat;
position: relative;
-
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ .item-box{
+ .box-two{
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ }
+ position: absolute;
+ top:289rpx;
+ left:99rpx;
+ .img2-text{
+ width: 257rpx;
+ }
+ }
.btn-img {
position: absolute;
width: 149.8rpx;
bottom: 290rpx;
left: 84rpx;
}
-
- .img7-1, .img7-2 {
+
+ .img7-1,
+ .img7-2 {
width: 437.67rpx;
position: absolute;
left: 0;
@@ -139,7 +112,7 @@
margin: 0 auto;
top: 365rpx;
}
-
+
.bgm-box {
width: 437.67rpx;
position: absolute;
@@ -148,7 +121,7 @@
bottom: 650rpx;
margin: 0 auto;
flex-wrap: wrap;
-
+
view {
width: 207.89rpx;
line-height: 42.77rpx;
@@ -158,16 +131,17 @@
font-size: 20rpx;
border: 1rpx solid #fff;
}
+
view:nth-child(n+3) {
margin-top: 17rpx;
}
-
+
.bgm-active {
border-color: #00C48C;
color: #00C48C;
}
}
-
+
.img7-btn {
width: 439.66rpx;
position: absolute;
@@ -182,14 +156,14 @@
width: 100vw;
height: 100vh;
}
-
+
.popup-content {
width: 85vw;
background-color: #fff;
border-radius: 16rpx;
padding: 40rpx 30rpx;
box-sizing: border-box;
-
+
.input-area {
width: 100%;
min-height: 180rpx;
@@ -201,14 +175,14 @@
box-sizing: border-box;
margin-bottom: 15rpx;
}
-
+
.word-count {
text-align: right;
font-size: 24rpx;
color: #999;
margin-bottom: 35rpx;
}
-
+
.confirm-btn {
width: 100%;
}
diff --git a/xqk/chapter7/index.vue b/xqk/chapter7/index.vue
deleted file mode 100644
index 5c804af..0000000
--- a/xqk/chapter7/index.vue
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
-
-
-
-
- {{info.text1}}
-
- {{info.text2}}
-
- {{info.imgTitle}}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/xqk/chapter8/index.vue b/xqk/chapter8/index.vue
deleted file mode 100644
index 0b339f9..0000000
--- a/xqk/chapter8/index.vue
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/xqk/components/NavMenu.vue b/xqk/components/NavMenu.vue
index ac3e469..c7b787d 100644
--- a/xqk/components/NavMenu.vue
+++ b/xqk/components/NavMenu.vue
@@ -60,7 +60,7 @@
path: "/xqk/chapter3/index"
},
{
- text: '04 风味人间',
+ text: '04 蟹在人间',
targetIndex: 4,
path: "/xqk/chapter4/index"
},
@@ -72,7 +72,7 @@
{
text: '有感商品',
targetIndex: 6,
- path: "/subPackages/techan/detail?id=39"
+ path: "/subPackages/techan/detail?id=40"
},
{
text: '购物车',
@@ -108,7 +108,7 @@
this.$emit('menu-hide');
},
onJumpToPage(item) {
- console.log(this.navIndex)
+ console.log(this.navIndex,item.targetIndex,item.path)
if(item.path && item.targetIndex != this.navIndex) this.gotoPath(item.path)
this.onCloseMenu();
},
diff --git a/xqk/home/home.vue b/xqk/home/home.vue
index 3dfbd33..a4e39d5 100644
--- a/xqk/home/home.vue
+++ b/xqk/home/home.vue
@@ -1,33 +1,33 @@
-
+
-
+
-
+
+
+
-
+
+
-
+