mirror of
https://github.com/fireinrain/JHS-enhance.git
synced 2026-11-13 00:34:24 +08:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9d81f6a13a | |||
| 0425ebf7c7 | |||
| d636a2f683 | |||
| 171ee3b9d7 | |||
| 9d322cc76d | |||
| 89ab8bcff8 | |||
| fde1eadac9 | |||
| b81922103a | |||
| e74f2cbdc8 | |||
| 8396e3825d | |||
| e4792cd55f | |||
| 72ec9a0e83 | |||
| 4339f1b80f | |||
| 20d199f53a | |||
| a9e88cda88 | |||
| 032dcf1fdc | |||
| 38221bc78d | |||
| 4230176ce4 | |||
| b5bdec2c35 | |||
| 11c5650efb | |||
| 080cbb00ee | |||
| d5c59ba6ac | |||
| 6a12b45f86 | |||
| 1e3c4d9718 | |||
| 2b8c925fed | |||
| 7005b528a3 |
@@ -27,11 +27,15 @@ jobs:
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Get version
|
||||
id: version
|
||||
run: echo "VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Upload to Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: v${{ github.run_number }}
|
||||
name: Release v${{ github.run_number }}
|
||||
tag_name: v${{ steps.version.outputs.VERSION }}
|
||||
name: Release v${{ steps.version.outputs.VERSION }}
|
||||
files: dist/jhs-enhance.user.js
|
||||
draft: false
|
||||
prerelease: false
|
||||
|
||||
@@ -42,11 +42,12 @@
|
||||
- **磁力排序与过滤(JavDB)**:按发布日期/文件大小/文件数量拖拽排序,勾选启用;高清/4K/字幕/无码多条件并集过滤,4K 磁力行高亮显示
|
||||
- 磁力链接高亮匹配已收藏/已下载状态
|
||||
- DMM 多画质预览视频
|
||||
- **多源视频预览**:Javxy 聚合 API 独立按钮(番号/识别码右侧),多源 fallback(JavTrailers / JavDB 等),HLS 支持、播放进度记忆、画质切换
|
||||
- **多源视频预览**:DMMRSC 聚合 API 独立按钮(番号/识别码右侧),HLS 支持、播放进度记忆、画质切换
|
||||
- **标题翻译**:Google 翻译,支持开关多次切换不失效
|
||||
- **字幕搜索**:合并迅雷 + SubTitleCat 为单一入口,支持 115 网盘直传、详情页预匹配目录、多目录选择上传、长目录名截断展示、字幕预览绿色字体
|
||||
- **多源预览图**:javfree / projectjav / javstore 三源切换,来源按钮绿色高亮,sessionStorage 缓存,错误提示弹窗内显示
|
||||
- 演员信息展示、相关清单、评论查看
|
||||
- **下载高清封面**:获取 DMM 高清封面直链并下载,支持番号格式校验(排除 FC2/无码作品)
|
||||
- 以图识图、第三方站点跳转
|
||||
|
||||
### 115 网盘集成
|
||||
@@ -109,7 +110,7 @@ JHS-enhance/
|
||||
│ │ ├── javdb.js # JavDB API 封装(签名算法、搜索、评论、磁力列表)
|
||||
│ │ ├── dmm.js # DMM 预览视频获取(多画质、默认画质选择)
|
||||
│ │ ├── dmm-graphql.js # DMM GraphQL API(备选视频源回退)
|
||||
│ │ └── javxy.js # Javxy 聚合视频 API(多源解析、签名生成)
|
||||
│ │ └── dmmrsc.js # DMMRSC API(视频多源解析、高清封面获取)
|
||||
│ ├── lib/ # 第三方补丁库
|
||||
│ │ ├── gm-xhr-parallel.js # Tampermonkey MV3 并行请求修复(redirect: manual)
|
||||
│ │ └── hls-runtime.js # HLS 视频播放运行时(hls.js 封装、进度记忆、画质切换)
|
||||
@@ -117,7 +118,7 @@ JHS-enhance/
|
||||
│ ├── list-page.js # 列表页过滤与状态标签渲染
|
||||
│ ├── list-page-button.js # 列表页功能按钮(待鉴定/已收藏/新作品/黑名单管理)
|
||||
│ ├── detail-page.js # 详情页数据加载与基础增强
|
||||
│ ├── detail-page-button.js# 详情页操作按钮(115 目录预加载 + 磁力排序过滤面板)
|
||||
│ ├── detail-page-button.js# 详情页操作按钮(下载高清封面 + 115 目录预加载 + 磁力排序过滤面板)
|
||||
│ ├── setting.js # 设置面板(Tab 页:基础/任务/域名/快捷键/屏蔽/缓存/标记删除/打赏作者;含 115 自动重命名开关 + 范围选择)
|
||||
│ ├── translate.js # 标题翻译(Google 翻译 API,原始标题缓存)
|
||||
│ ├── preview-video.js # DMM 预览视频播放器
|
||||
@@ -152,7 +153,7 @@ JHS-enhance/
|
||||
│ ├── magnet-hub.js # MagnetHub 磁力搜索(6 引擎聚合、质量标签、验车截图、115 离线)
|
||||
│ ├── other-site.js # 第三方站点跳转链接
|
||||
│ ├── jav-trailers.js # JavTrailers 站点处理
|
||||
│ ├── javxy-preview-video.js# Javxy 多源视频预览(独立按钮、聚合 API、HLS 支持)
|
||||
│ ├── javxy-preview-video.js# DMMRSC 多源视频预览(独立按钮、聚合 API、HLS 支持)
|
||||
│ ├── subtitle-cat.js # SubTitleCat 字幕搜索(已整合,保留原文件)
|
||||
│ ├── filter-title-keyword.js # 标题关键词过滤
|
||||
│ └── want-watched.js # 想看/已看视频列表
|
||||
@@ -317,11 +318,11 @@ window.show.ok('操作成功'); // Toast 通知
|
||||
- 优化:`searchFiles` 增加 `type:4` 参数,搜索仅返回视频文件,避免目录占用 30 条槽位
|
||||
|
||||
- **v3.3.8**
|
||||
- 新增:Javxy 多源视频预览独立按钮(番号/识别码右侧),基于 Javxy 聚合 API,支持 JavTrailers / JavDB 等多源回退
|
||||
- 新增:DMMRSC 多源视频预览独立按钮(番号/识别码右侧),基于 DMMRSC 聚合 API
|
||||
- 新增:HLS 视频播放运行时(hls.js 封装),支持 .m3u8 格式、播放进度记忆、画质切换
|
||||
- 新增:DMM GraphQL API 模块,作为备选视频源回退方案
|
||||
- 优化:`bus-preview-video.js` 和 `preview-video.js` 清理移植代码,保持原有播放逻辑不变
|
||||
- 优化:`dmm.js` 回退至仅 DMM Affiliate API + GraphQL API 双通道,移除 Javxy 耦合
|
||||
- 优化:`dmm.js` 回退至仅 DMM Affiliate API + GraphQL API 双通道
|
||||
|
||||
- **v3.3.7**
|
||||
- 新增:JavDB 磁力排序与过滤(拖拽排序、多条件并集过滤、4K 高亮)
|
||||
|
||||
-251
@@ -1,251 +0,0 @@
|
||||
好的,让我先全面分析这个 11000 行的脚本。我会分段读取,理解它的整体结构和功能模块。
|
||||
|
||||
|
||||
|
||||
|
||||
The user wants me to analyze the JHS-origin.js file (about 11,000 lines) and provide a detailed report on how to modularize it. Let me first read through the entire file to understand its structure, then provide a comprehensive refactoring plan.
|
||||
|
||||
Since the file is 10,962 lines, I need to read it in chunks. Let me start by reading several sections to understand the code structure.
|
||||
|
||||
Let me read the file in multiple chunks to understand:
|
||||
1. The beginning (already read some)
|
||||
2. Key sections throughout
|
||||
3. The end
|
||||
|
||||
I'll read multiple sections in parallel.
|
||||
|
||||
Let me continue reading more sections to get a complete picture of the codebase.
|
||||
|
||||
Let me also read the end of the file to see the initialization/entry point.
|
||||
|
||||
Now I have a very comprehensive understanding of the codebase. Let me also read the very end to see the initialization.
|
||||
|
||||
Now I have a comprehensive understanding of the entire codebase. Let me write a detailed analysis report.
|
||||
|
||||
The code is approximately 10,962 lines, with a well-defined plugin architecture:
|
||||
- PluginManager: manages plugins
|
||||
- BasePlugin: base class for all plugins
|
||||
- ~40 plugins extending BasePlugin
|
||||
|
||||
The code also contains:
|
||||
- Utility classes (Utils, gmHttp, StorageManager, show, clog, etc.)
|
||||
- CSS styles
|
||||
- Constants and configuration
|
||||
- API interfaces (JavDbApi, etc.)
|
||||
- A plugin system with registration and execution
|
||||
|
||||
Let me now write a comprehensive refactoring report.
|
||||
现在我已经完整分析了整个代码库。以下是详细的结构分析报告:
|
||||
|
||||
---
|
||||
|
||||
## 🔍 JHS-enhance 代码结构分析报告
|
||||
|
||||
### 📊 总体概况
|
||||
|
||||
| 指标 | 数据 |
|
||||
|------|------|
|
||||
| 总行数 | **10,962 行** |
|
||||
| 核心类/插件 | **40+ 个** |
|
||||
| 支持站点 | JavDB、JavBus、JavTrailers、SubTitleCat、阿里云盘、115网盘 |
|
||||
| 外部依赖 | jQuery、Tabulator、layui-layer、MD5、Toastify、localForage、ViewerJS、QRCodeJS |
|
||||
|
||||
---
|
||||
|
||||
### 🏗️ 现有架构
|
||||
|
||||
代码已经有一个**不错的插件架构**,只是全部写在一个文件里:
|
||||
|
||||
```
|
||||
入口(最后100行)
|
||||
├── 初始化 pluginManager
|
||||
├── 检测当前页面类型(isDetailPage / isListPage / isFc2Page)
|
||||
├── 按站点注册插件
|
||||
├── pluginManager.processCss() → 加载所有插件CSS
|
||||
└── pluginManager.processPlugins() → 执行所有插件
|
||||
```
|
||||
|
||||
插件基类 `BasePlugin` 提供了:
|
||||
- `getName()` — 插件名
|
||||
- `initCss()` — 返回CSS字符串
|
||||
- `handle()` — 主逻辑入口
|
||||
- `getPageInfo()` — 获取当前页面信息
|
||||
- `getBean(name)` — 获取其他插件实例
|
||||
|
||||
---
|
||||
|
||||
### 📦 代码功能模块划分
|
||||
|
||||
我将 11000 行代码按功能分为以下 **8 大模块**,建议拆分为独立文件:
|
||||
|
||||
---
|
||||
|
||||
#### 模块一:🛠️ 基础设施层(~1500 行)
|
||||
**建议目录:`src/core/`**
|
||||
|
||||
| 文件 | 内容 | 说明 |
|
||||
|------|------|------|
|
||||
| `utils.js` | `Utils` 类(~300行) | 通用工具函数:下载、滚动、剪贴板、URL解析、排序等 |
|
||||
| `gmHttp.js` | `gmHttp` 类(~200行) | 基于 `GM_xmlhttpRequest` 的 HTTP 封装 |
|
||||
| `storage.js` | `StorageManager` 类(~500行) | IndexedDB 存储管理:收藏、屏蔽、设置、演员等 |
|
||||
| `show.js` | `show` / `clog` 对象(~100行) | Toast 消息提示、控制台日志 |
|
||||
| `constants.js` | 所有常量(~200行) | 状态枚举、画质选项、翻译映射表、标签样式等 |
|
||||
| `styles.js` | CSS 样式(~300行) | JavDB/JavBus 站点样式、全局样式、滚动条样式 |
|
||||
|
||||
---
|
||||
|
||||
#### 模块二:🔌 插件系统(~200 行)
|
||||
**建议目录:`src/core/`**
|
||||
|
||||
| 文件 | 内容 | 说明 |
|
||||
|------|------|------|
|
||||
| `plugin-manager.js` | `PluginManager` 类 | 插件注册、CSS加载、插件执行 |
|
||||
| `base-plugin.js` | `BasePlugin` 类 | 插件基类,提供 `getName()`、`handle()`、`initCss()` 等 |
|
||||
|
||||
---
|
||||
|
||||
#### 模块三:🌐 API 接口层(~200 行)
|
||||
**建议目录:`src/api/`**
|
||||
|
||||
| 文件 | 内容 | 说明 |
|
||||
|------|------|------|
|
||||
| `javdb-api.js` | `javDbApi` 对象 | JavDB API:获取评论、搜索电影、电影详情、磁力链接 |
|
||||
|
||||
---
|
||||
|
||||
#### 模块四:📋 列表页插件(~2500 行)
|
||||
**建议目录:`src/plugins/list/`**
|
||||
|
||||
| 文件 | 类名 | 功能 |
|
||||
|------|------|------|
|
||||
| `list-page.js` | `ListPagePlugin` | 列表页核心:状态标签渲染、屏蔽过滤、演员屏蔽、排序 |
|
||||
| `list-page-button.js` | `ListPageButtonPlugin` | 列表页工具栏按钮:一键屏蔽、收藏、随机打开等 |
|
||||
| `auto-page.js` | `AutoPagePlugin` | 自动翻页 |
|
||||
| `fold-category.js` | `FoldCategoryPlugin` | 折叠/展开分类标签区域 |
|
||||
| `cover-button.js` | `CoverButtonPlugin` | 封面图上的操作按钮(屏蔽、收藏等) |
|
||||
| `history.js` | `HistoryPlugin` | 鉴定记录面板 |
|
||||
| `filter-title-keyword.js` | `FilterTitleKeywordPlugin` | 标题关键词屏蔽 |
|
||||
| `blacklist.js` | `BlacklistPlugin` | 黑名单管理(屏蔽演员/标签) |
|
||||
| `hit-show.js` | `HitShowPlugin` | 热播榜 |
|
||||
| `top250.js` | `TOP250Plugin` | TOP250 排行榜 |
|
||||
|
||||
---
|
||||
|
||||
#### 模块五:🎬 详情页插件(~2000 行)
|
||||
**建议目录:`src/plugins/detail/`**
|
||||
|
||||
| 文件 | 类名 | 功能 |
|
||||
|------|------|------|
|
||||
| `detail-page.js` | `DetailPagePlugin` | 详情页核心:FC2/普通影片信息展示 |
|
||||
| `detail-page-button.js` | `DetailPageButtonPlugin` | 详情页按钮:屏蔽、收藏、已下载、已观看、磁力搜索、字幕 |
|
||||
| `bus-detail-page.js` | `BusDetailPagePlugin` | JavBus 详情页 |
|
||||
| `review.js` | `ReviewPlugin` | 评论查看 |
|
||||
| `related.js` | `RelatedPlugin` | 相关清单 |
|
||||
| `highlight-magnet.js` | `HighlightMagnetPlugin` | 磁力链接高亮过滤 |
|
||||
| `translate.js` | `TranslatePlugin` | 标题翻译(日→中) |
|
||||
| `want-watched.js` | `WantAndWatchedVideosPlugin` | 想看/已看视频 |
|
||||
|
||||
---
|
||||
|
||||
#### 模块六:🎥 视频与媒体插件(~1500 行)
|
||||
**建议目录:`src/plugins/media/`**
|
||||
|
||||
| 文件 | 类名 | 功能 |
|
||||
|------|------|------|
|
||||
| `preview-video.js` | `PreviewVideoPlugin` | JavDB 预览视频播放 |
|
||||
| `bus-preview-video.js` | `BusPreviewVideoPlugin` | JavBus 预览视频播放 |
|
||||
| `screen-shot.js` | `ScreenShotPlugin` | 缩略图加载 |
|
||||
| `bus-img.js` | `BusImgPlugin` | JavBus 图片处理 |
|
||||
| `image-recognition.js` | `ImageRecognitionPlugin` | 以图识图 |
|
||||
|
||||
---
|
||||
|
||||
#### 模块七:🔗 外部站点与工具插件(~2000 行)
|
||||
**建议目录:`src/plugins/external/`**
|
||||
|
||||
| 文件 | 类名 | 功能 |
|
||||
|------|------|------|
|
||||
| `magnet-hub.js` | `MagnetHubPlugin` | 多站点磁力搜索聚合 |
|
||||
| `other-site.js` | `OtherSitePlugin` | 其他站点入口(JavStore、MissAV等) |
|
||||
| `fc2.js` | `Fc2Plugin` | FC2 影片页面 |
|
||||
| `fc2-123av.js` | `Fc2By123AvPlugin` | 123AV 的 FC2 页面 |
|
||||
| `wangpan-115.js` | `WangPan115Plugin` / `WangPan115TaskPlugin` / `WangPan115MatchPlugin` | 115网盘离线下载 |
|
||||
| `aliyun-pan.js` | `AliyunPanPlugin` | 阿里云盘 |
|
||||
| `jav-trailers.js` | `JavTrailersPlugin` | JavTrailers 站点 |
|
||||
| `subtitle-cat.js` | `SubTitleCatPlugin` | SubTitleCat 字幕搜索 |
|
||||
|
||||
---
|
||||
|
||||
#### 模块八:👤 演员与任务插件(~2000 行)
|
||||
**建议目录:`src/plugins/actress/`**
|
||||
|
||||
| 文件 | 类名 | 功能 |
|
||||
|------|------|------|
|
||||
| `actress-info.js` | `ActressInfoPlugin` | 演员信息面板 |
|
||||
| `favorite-actresses.js` | `FavoriteActressesPlugin` | 收藏演员管理 |
|
||||
| `new-video.js` | `NewVideoPlugin` | 新作品检测 |
|
||||
| `task.js` | `TaskPlugin` | 定时任务:检测黑名单、同步演员、新作品检测 |
|
||||
| `nav-bar.js` | `NavBarPlugin` / `BusNavBarPlugin` | 导航栏增强 |
|
||||
| `setting.js` | `SettingPlugin` | 设置面板 |
|
||||
|
||||
---
|
||||
|
||||
### 🎯 建议的项目目录结构
|
||||
|
||||
```
|
||||
JHS-enhance/
|
||||
├── src/
|
||||
│ ├── main.js # 入口:初始化 + 插件注册
|
||||
│ ├── core/
|
||||
│ │ ├── utils.js # 通用工具函数
|
||||
│ │ ├── gmHttp.js # GM_xmlhttpRequest 封装
|
||||
│ │ ├── storage.js # IndexedDB 存储管理
|
||||
│ │ ├── show.js # Toast 消息提示
|
||||
│ │ ├── constants.js # 所有常量
|
||||
│ │ ├── styles.js # CSS 样式
|
||||
│ │ ├── plugin-manager.js # 插件管理器
|
||||
│ │ └── base-plugin.js # 插件基类
|
||||
│ ├── api/
|
||||
│ │ └── javdb-api.js # JavDB API 接口
|
||||
│ ├── plugins/
|
||||
│ │ ├── list/ # 列表页插件 (10个)
|
||||
│ │ ├── detail/ # 详情页插件 (8个)
|
||||
│ │ ├── media/ # 视频/媒体插件 (5个)
|
||||
│ │ ├── external/ # 外部站点插件 (8个)
|
||||
│ │ └── actress/ # 演员/任务插件 (6个)
|
||||
│ └── styles/
|
||||
│ └── ... (可选,如果CSS拆出来)
|
||||
├── vite.config.mjs
|
||||
├── package.json
|
||||
└── JHS-origin.js # 保留原始文件作为参考
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ⚠️ 拆分时的注意事项
|
||||
|
||||
1. **全局变量依赖**:当前代码大量使用 `unsafeWindow.xxx = window.xxx`,拆分为 ES Module 后需要改为 `export`/`import`,同时通过 `window` 暴露给油猴全局作用域
|
||||
|
||||
2. **插件间依赖**:插件通过 `this.getBean(name)` 互相调用,拆分后需确保 `PluginManager` 先初始化
|
||||
|
||||
3. **CDN 外部依赖**:jQuery、Tabulator 等通过 `@require` 加载,在模块中直接使用 `$`、`Tabulator` 等全局变量即可
|
||||
|
||||
4. **CSS 注入**:`insertStyle()` 和 `initCss()` 需要 `document.head` 可用后才能执行
|
||||
|
||||
5. **循环依赖**:注意 `TaskPlugin` ↔ `BlacklistPlugin`、`ListPagePlugin` ↔ `BlacklistPlugin` 等之间的双向引用
|
||||
|
||||
---
|
||||
|
||||
### 🚀 建议的实施顺序
|
||||
|
||||
| 优先级 | 步骤 | 预计工作量 |
|
||||
|--------|------|-----------|
|
||||
| P0 | 拆分 `core/` 基础设施(utils, gmHttp, storage, show, constants, styles) | 1-2小时 |
|
||||
| P1 | 拆分插件系统(plugin-manager, base-plugin)和入口 `main.js` | 30分钟 |
|
||||
| P2 | 拆分 API 层(javdb-api) | 15分钟 |
|
||||
| P3 | 分批拆分插件,每批 3-5 个,逐个验证构建 | 3-5小时 |
|
||||
| P4 | 清理全局变量,统一为 ES Module 导入导出 | 1小时 |
|
||||
|
||||
---
|
||||
|
||||
需要我开始执行拆分吗?建议从 **P0(基础设施层)** 开始,这是最独立、最不容易出错的模块。
|
||||
Vendored
+25037
-543
File diff suppressed because it is too large
Load Diff
+993
@@ -0,0 +1,993 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - JavBus</title>
|
||||
<meta name="keywords" content="NIMA-086,肉漫,潮吹,中出,高畫質,原作コラボ,巨乳,アクメ・オーガズム,單體作品,DMM獨家">
|
||||
<meta name="description"
|
||||
content="【發行日期】2026-09-25,【長度】120分鐘,(NIMA-086)実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒">
|
||||
<link rel="alternate" href="https://www.javbus.com/en/NIMA-086" hreflang="en"/>
|
||||
<link rel="alternate" href="https://www.javbus.com/ja/NIMA-086" hreflang="ja"/>
|
||||
<link rel="alternate" href="https://www.javbus.com/ko/NIMA-086" hreflang="ko"/>
|
||||
<link rel="alternate" href="https://www.javbus.com/NIMA-086" hreflang="zh"/>
|
||||
<link rel="alternate" href="https://www.javbus.com/NIMA-086" hreflang="x-default"/>
|
||||
<link rel="canonical" href="https://www.javbus.com/NIMA-086"/>
|
||||
<link rel="preconnect" href="https://poweredby.jads.co" crossorigin>
|
||||
<link rel="dns-prefetch" href="https://poweredby.jads.co">
|
||||
<link rel="stylesheet" href="https://www.javbus.com/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://www.javbus.com/css/bootstrap-theme.min.css">
|
||||
<link rel="stylesheet" href="https://www.javbus.com/css/css-slider.css?v=9.3">
|
||||
<link rel="stylesheet" href="https://www.javbus.com/css/nav.overlay.css?v=3.9.8">
|
||||
<link rel="stylesheet" href="https://www.javbus.com/css/magnific-popup.css">
|
||||
<link rel="stylesheet" href="https://www.javbus.com/css/base.css?v=7.15">
|
||||
<script src="https://www.javbus.com/js/jquery.min.js"></script>
|
||||
<script src="https://www.javbus.com/js/jquery.magnific-popup.min.js"></script>
|
||||
<script src="https://www.javbus.com/js/bootstrap.min.js" defer></script>
|
||||
<script src="https://www.javbus.com/js/jquery.cookie.min.js" defer></script>
|
||||
<script src="https://www.javbus.com/js/base.js" defer></script>
|
||||
<script src="https://www.javbus.com/js/bootstrap-hover-dropdown.js" defer></script>
|
||||
<script src="https://www.javbus.com/js/nav.overlay.js?v=10.30.3" defer></script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://www.javbus.com/js/html5shiv.min.js"></script>
|
||||
<script src="https://www.javbus.com/js/respond.min.js"></script><![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<script language="JavaScript">
|
||||
var mod = 0;
|
||||
var lang = 'zh';
|
||||
var info = '搜尋 識別碼, 影片, 演員';
|
||||
|
||||
function searchs(obj) {
|
||||
var searchinput = $("#" + obj);
|
||||
if (searchinput.val() == '') {
|
||||
$('#magnet-url-post').trigger("click");
|
||||
return false;
|
||||
} else {
|
||||
//$('#search-loading').show();str.replace(/ /g, "-")
|
||||
window.open("https://www.javbus.com/search/" + encodeURIComponent($.trim(searchinput.val()).replace(/ /g, "+")) + "&type=&parent=ce");
|
||||
}
|
||||
}
|
||||
|
||||
$(function () {
|
||||
|
||||
var url = 'https://www.javbus.com/ajax/search-modal.php?floor=' + Math.floor(Math.random() * 1000 + 1) + '&lang=' + lang;
|
||||
$.ajax({
|
||||
url: url, type: 'GET', success: function (msg) {
|
||||
$("#searchModal").append(msg);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<div id="search-loading">
|
||||
<table class="search-loading-box" border="0" cellpadding="0" cellspacing="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<table height="80" width="100%" border="0" cellpadding="0" cellspacing="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td height="40" align="center">
|
||||
<div class="search-loading-text">搜尋中...</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td height="40" align="center">
|
||||
<img src="https://www.javbus.com/images/search_loading.gif" border="0">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Modal Search -->
|
||||
<div id="searchModal" class="modal fade" tabindex="-1" role="dialog"></div>
|
||||
|
||||
<nav class="navbar navbar-default navbar-fixed-top top-bar" style="z-index:900">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header mh50">
|
||||
<a href="https://www.javbus.com/">
|
||||
<img class="hidden-xs" height="50" alt="JavBus" src="https://www.javbus.com/images/logo.png"
|
||||
style="height:40px; margin-top:5px;">
|
||||
<img class="visible-xs-inline" height="50" alt="JavBus" src="https://www.javbus.com/images/logo.png">
|
||||
</a>
|
||||
|
||||
<div class="btn-group pull-right visible-xs-inline" role="group" style="margin:8px 8px 0 0;"
|
||||
onclick="window.location.href= '/forum/member.php?mod=logging&action=login&referer=%2F%2Fwww.javbus.com%2FNIMA-086'">
|
||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"
|
||||
aria-expanded="false">
|
||||
<img class="avatar" style="width:22px; height:22px;"
|
||||
src="https://uc.javbus22.com/uc/avatar.php?uid=0&size=small"></button>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="btn-group pull-right visible-xs-inline" role="group" style="margin:8px 8px 0 0;">
|
||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"
|
||||
aria-expanded="false">
|
||||
<span class="glyphicon glyphicon-globe"></span> <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://www.javbus.com/en/NIMA-086">English</a></li>
|
||||
<li><a href="https://www.javbus.com/ja/NIMA-086">日本语</a></li>
|
||||
<li><a href="https://www.javbus.com/ko/NIMA-086">한국의</a></li>
|
||||
<li><a href="https://www.javbus.com/NIMA-086">中文</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div id="navbar" class="collapse navbar-collapse">
|
||||
<div class="navbar-form navbar-left fullsearch-form">
|
||||
<div class="input-group">
|
||||
<input id="search-input" type="text" class="form-control" placeholder="搜尋 識別碼, 影片, 演員">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" type="submit" onClick="searchs('search-input')">搜尋</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="https://www.javbus.com/">有碼</a></li>
|
||||
<li><a href="https://www.javbus.com/uncensored">無碼</a></li>
|
||||
<li class="hidden-md hidden-sm"><!-- <div class="icon-new"></div> --><a href="https://www.javbus.hair/">歐美</a>
|
||||
</li>
|
||||
<li class="hidden-sm"><a href="https://www.javbus.com/forum/">論壇</a></li>
|
||||
<li class="dropdown hidden-sm ">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" data-hover="dropdown" role="button"
|
||||
aria-expanded="false">類別 <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://www.javbus.com/genre">有碼類別</a></li>
|
||||
<li><a href="https://www.javbus.com/uncensored/genre">無碼類別</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown hidden-sm ">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" data-hover="dropdown" role="button"
|
||||
aria-expanded="false">女優 <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://www.javbus.com/actresses">有碼女優</a></li>
|
||||
<li><a href="https://www.javbus.com/uncensored/actresses">無碼女優</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown"><a href="https://www.javbus.com/" class="dropdown-toggle" data-toggle="dropdown"
|
||||
data-hover="dropdown" role="button" aria-expanded="false"><span
|
||||
class="glyphicon glyphicon-menu-hamburger"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li class="visible-md-block visible-sm-block"><a href="https://www.javbus.hair/">歐美</a></li>
|
||||
<li class="visible-sm-block"><a href="https://www.javbus.com/forum/">論壇</a></li>
|
||||
<li class="visible-sm-block"><a href="https://www.javbus.com/genre">有碼類別</a></li>
|
||||
<li class="visible-sm-block"><a href="https://www.javbus.com/uncensored/genre">無碼類別</a></li>
|
||||
<li class="visible-sm-block"><a href="https://www.javbus.com/actresses">有碼女優</a></li>
|
||||
<li class="visible-sm-block"><a href="https://www.javbus.com/uncensored/actresses">無碼女優</a>
|
||||
</li>
|
||||
<li><a href="https://www.javbus.com/genre/hd">高清</a></li>
|
||||
<li><a href="https://www.javbus.com/genre/sub">字幕</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right"
|
||||
onclick="window.location.href= '/forum/member.php?mod=logging&action=login&referer=%2F%2Fwww.javbus.com%2FNIMA-086'">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" data-hover="dropdown" role="button"
|
||||
aria-expanded="false"><img class="avatar"
|
||||
src="https://uc.javbus22.com/uc/avatar.php?uid=0&size=small"><span
|
||||
class="hidden-md hidden-sm ml5">登入</span> </a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" data-hover="dropdown" role="button"
|
||||
aria-expanded="false"><span class="glyphicon glyphicon-globe" style="font-size:12px;"></span>
|
||||
<span class="hidden-md hidden-sm">English</span> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://www.javbus.com/en/NIMA-086">English</a></li>
|
||||
<li><a href="https://www.javbus.com/ja/NIMA-086">日本语</a></li>
|
||||
<li><a href="https://www.javbus.com/ko/NIMA-086">한국의</a></li>
|
||||
<li><a href="https://www.javbus.com/NIMA-086">中文</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
</div>
|
||||
</nav>
|
||||
<div class="row visible-xs-inline footer-bar">
|
||||
<div class="col-xs-3 text-center">
|
||||
<a id="menu" class="btn btn-default trigger-overlay"><span class="glyphicon glyphicon-align-justify"></span></a>
|
||||
</div>
|
||||
<div class="col-xs-3 text-center">
|
||||
</div>
|
||||
<div class="col-xs-3 text-center">
|
||||
</div>
|
||||
<div class="col-xs-3 text-center">
|
||||
<a id="back" class="btn btn-default" href="javascript:window.history.back()"><span
|
||||
class="glyphicon glyphicon-share-alt flipx"></span></a>
|
||||
</div>
|
||||
</div>
|
||||
<script src='https://www.javbus.com/js/focus.js?v=8.7'></script>
|
||||
<link rel='stylesheet' type='text/css' href='https://www.javbus.com/css/movie.css?v=2.8'>
|
||||
<link rel='stylesheet' type='text/css' href='https://www.javbus.com/css/movie-box.css'>
|
||||
<script>
|
||||
var gid = 70147716068;
|
||||
var uc = 0;
|
||||
var img = '/pics/cover/ckd7_b.jpg';
|
||||
</script>
|
||||
|
||||
<div class="ad-box all-top">
|
||||
<div class="ad-item">
|
||||
<div class="ad-juicy">
|
||||
<script type="text/javascript" data-cfasync="false" async
|
||||
src="https://poweredby.jads.co/js/jads.js"></script>
|
||||
<ins id="1024549" data-width="728" data-height="90"></ins>
|
||||
<script type="text/javascript" data-cfasync="false"
|
||||
async>(adsbyjuicy = window.adsbyjuicy || []).push({"adzone": 1024549});</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ad-item">
|
||||
<div class="ad-juicy">
|
||||
<script type="text/javascript" data-cfasync="false" async
|
||||
src="https://poweredby.jads.co/js/jads.js"></script>
|
||||
<ins id="1024550" data-width="728" data-height="90"></ins>
|
||||
<script type="text/javascript" data-cfasync="false"
|
||||
async>(adsbyjuicy = window.adsbyjuicy || []).push({"adzone": 1024550});</script>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ky" class="ad-item">
|
||||
<div class='csslider1 autoplay'>
|
||||
<input name="cs_anchor1" id='cs_play1' type="radio" class='cs_anchor' checked>
|
||||
<ul>
|
||||
<li class="cs_skeleton"><img src="/forum/data/attachment/forum/ads/ky_20260923_3.jpg"
|
||||
style="width: 100%;"></li>
|
||||
<li class="num0 img slide"><a href="https://www.3jnbdg.vip:9553/?i_code=14698475" target="_blank"><img
|
||||
src="/forum/data/attachment/forum/ads/ky_20260923_3.jpg"/></a></li>
|
||||
<li class="num1 img slide"><a href="https://www.3jnbdg.vip:9553/?i_code=14698475" target="_blank"><img
|
||||
src="/forum/data/attachment/forum/ads/ky_20260923_5.jpg"/></a></li>
|
||||
<li class="num2 img slide"><a href="https://www.3jnbdg.vip:9553/?i_code=14698475" target="_blank"><img
|
||||
src="/forum/data/attachment/forum/ads/ky_20260923_1.jpg"/></a></li>
|
||||
<li class="num3 img slide"><a href="https://www.3jnbdg.vip:9553/?i_code=14698475" target="_blank"><img
|
||||
src="/forum/data/attachment/forum/ads/ky_20260923_2.jpg"/></a></li>
|
||||
<li class="num4 img slide"><a href="https://www.3jnbdg.vip:9553/?i_code=14698475" target="_blank"><img
|
||||
src="/forum/data/attachment/forum/ads/ky_20260923_4.jpg"/></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div id="kok" class="ad-item">
|
||||
<div class='csslider1 autoplay'>
|
||||
<input name="cs_anchor2" id='cs_play2' type="radio" class='cs_anchor' checked>
|
||||
<ul>
|
||||
<li class="cs_skeleton"><img src="/forum/data/attachment/forum/ads/zo_20260923_2.jpg"
|
||||
style="width: 100%;"></li>
|
||||
<li class="num0 img slide"><a href="https://120406.zoty2508.com:30501/?i_code=3354655"
|
||||
target="_blank"><img
|
||||
src="/forum/data/attachment/forum/ads/zo_20260923_2.jpg"/></a></li>
|
||||
<li class="num1 img slide"><a href="https://120406.zoty2508.com:30501/?i_code=3354655"
|
||||
target="_blank"><img
|
||||
src="/forum/data/attachment/forum/ads/zo_20260923_1.jpg"/></a></li>
|
||||
<li class="num2 img slide"><a href="https://120406.zoty2508.com:30501/?i_code=3354655"
|
||||
target="_blank"><img
|
||||
src="/forum/data/attachment/forum/ads/zo_20260923_5.jpg"/></a></li>
|
||||
<li class="num3 img slide"><a href="https://120406.zoty2508.com:30501/?i_code=3354655"
|
||||
target="_blank"><img
|
||||
src="/forum/data/attachment/forum/ads/zo_20260923_3.jpg"/></a></li>
|
||||
<li class="num4 img slide"><a href="https://120406.zoty2508.com:30501/?i_code=3354655"
|
||||
target="_blank"><img
|
||||
src="/forum/data/attachment/forum/ads/zo_20260923_4.jpg"/></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input id="token" type="hidden" name="token"
|
||||
value="c738pomVJo1m19OjPoW3yyugBlnubpVPF1MM7fQqG5T34oAOtWShxw11DbmlgOiBYN4XPjFHM+hZU4ePIlpK3osjclQs/ULQEZbJ">
|
||||
<div class="container">
|
||||
<h3>NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒</h3>
|
||||
<div class="row movie">
|
||||
<div class="col-md-9 screencap">
|
||||
<a class="bigImage" href="/pics/cover/ckd7_b.jpg"><img src="/pics/cover/ckd7_b.jpg"
|
||||
title="実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒"></a>
|
||||
</div>
|
||||
<div class="col-md-3 info">
|
||||
<p><span class="header">識別碼:</span> <span style="color:#CC0000;">NIMA-086</span>
|
||||
</p>
|
||||
<p><span class="header">發行日期:</span> 2026-09-25</p>
|
||||
<p><span class="header">長度:</span> 120分鐘</p>
|
||||
<p><span class="header">導演:</span> <a href="https://www.javbus.com/director/a3">ドラゴン西川</a></p>
|
||||
<p><span class="header">製作商:</span> <a href="https://www.javbus.com/studio/dk">Fitch</a>
|
||||
</p>
|
||||
<p><span class="header">發行商:</span> <a href="https://www.javbus.com/label/1oe">肉漫</a>
|
||||
</p>
|
||||
<p class="header">類別:<span id="genre-toggle" class="glyphicon glyphicon-plus"
|
||||
style="cursor: pointer;"></span></p>
|
||||
<p><span class="genre"><label><input type="checkbox" name="gr_sel" value="1z"><a
|
||||
href="https://www.javbus.com/genre/1z">潮吹</a></label></span>
|
||||
<span class="genre"><label><input type="checkbox" name="gr_sel" value="4"><a
|
||||
href="https://www.javbus.com/genre/4">中出</a></label></span>
|
||||
<span class="genre"><label><input type="checkbox" name="gr_sel" value="4o"><a
|
||||
href="https://www.javbus.com/genre/4o">高畫質</a></label></span>
|
||||
<span class="genre"><label><input type="checkbox" name="gr_sel" value="6l"><a
|
||||
href="https://www.javbus.com/genre/6l">原作コラボ</a></label></span>
|
||||
<span class="genre"><label><input type="checkbox" name="gr_sel" value="e"><a
|
||||
href="https://www.javbus.com/genre/e">巨乳</a></label></span>
|
||||
<span class="genre"><label><input type="checkbox" name="gr_sel" value="e3"><a
|
||||
href="https://www.javbus.com/genre/e3">アクメ・オーガズム</a></label></span>
|
||||
<span class="genre"><label><input type="checkbox" name="gr_sel" value="f"><a
|
||||
href="https://www.javbus.com/genre/f">單體作品</a></label></span>
|
||||
<span class="genre"><label><input type="checkbox" name="gr_sel" value="g"><a
|
||||
href="https://www.javbus.com/genre/g">DMM獨家</a></label></span>
|
||||
<span class="genre"><button id="gr_btn" type="button" class="btn">多選提交</button></span>
|
||||
</p>
|
||||
<p class="star-show"><span class="header" style="cursor: pointer;">演員</span>:<span id="star-toggle"
|
||||
class="glyphicon glyphicon-minus"
|
||||
style="cursor: pointer;"></span>
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<div id="star_11wm" class="star-box star-box-common star-box-up idol-box">
|
||||
<li>
|
||||
<a href="https://www.javbus.com/star/11wm"><img src="/pics/actress/11wm_a.jpg" title="彩月七緒"></a>
|
||||
<div class="star-name"><a href="https://www.javbus.com/star/11wm" title="彩月七緒">彩月七緒</a>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<span class="genre" onmouseover="hoverdiv(event,'star_11wm')"
|
||||
onmouseout="hoverdiv(event,'star_11wm')">
|
||||
<a href="https://www.javbus.com/star/11wm">彩月七緒</a>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="star-div">
|
||||
<h4 id="star-hide" style="cursor: pointer;">演員 <span class="glyphicon glyphicon-minus"></span></h4>
|
||||
<div id="avatar-waterfall">
|
||||
<a class="avatar-box" href="https://www.javbus.com/star/11wm">
|
||||
<div class="photo-frame">
|
||||
<img src="/pics/actress/11wm_a.jpg" title="彩月七緒">
|
||||
</div>
|
||||
<span>彩月七緒</span>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<h4 id="mag-submit-show" style="cursor: pointer;">磁力連結投稿 <span id="mag-submit-toggle"
|
||||
class="glyphicon glyphicon-plus"></span></h4>
|
||||
<div id="mag-submit" class="movie" style="padding:30px 20px 30px 5px;">
|
||||
<div id="mag-submit-hide" class="close" style="margin:-25px -13px 0 0;">×</div>
|
||||
<div class="col-md-11 col-xs-10">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">magnet地址:</div>
|
||||
<input type="text" class="form-control" id="appendedInputButton">
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-default col-md-1 col-xs-2" onClick="checktxt()" data-toggle="modal"
|
||||
data-target="#magneturlpost">分享
|
||||
</button>
|
||||
</div>
|
||||
<!-- Magnet Verify Modal -->
|
||||
<div id="magneturlpost" class="modal fade" tabindex="-1" role="dialog"></div>
|
||||
<div class="movie" style="padding:12px; margin-top:15px">
|
||||
<table id="magnet-table" class="table table-condensed table-striped table-hover" style="margin-bottom:0;">
|
||||
<tr style="font-weight:bold;">
|
||||
<td>磁力名稱 <span class="glyphicon glyphicon-magnet"></span></td>
|
||||
<td style="text-align:center;white-space:nowrap">檔案大小</td>
|
||||
<td style="text-align:center;white-space:nowrap">分享日期</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div id="movie-loading">
|
||||
<table width="120" border="0" cellpadding="5" cellspacing="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<font class="ajax-text"><img src="https://www.javbus.com/images/movie_loading.gif"
|
||||
border="0"></font>
|
||||
</td>
|
||||
<td align="center">
|
||||
<font class="ajax-text">讀取中...</font>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h4>樣品圖像</h4>
|
||||
<div id="sample-waterfall">
|
||||
<a class="sample-box" href="https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/nima00086/nima00086jp-1.jpg">
|
||||
<div class="photo-frame"><img src="/pics/sample/ckd7_1.jpg"
|
||||
title="NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - 樣品圖像 - 1">
|
||||
</div>
|
||||
</a> <a class="sample-box"
|
||||
href="https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/nima00086/nima00086jp-2.jpg">
|
||||
<div class="photo-frame"><img src="/pics/sample/ckd7_2.jpg"
|
||||
title="NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - 樣品圖像 - 2">
|
||||
</div>
|
||||
</a> <a class="sample-box" href="https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/nima00086/nima00086jp-3.jpg">
|
||||
<div class="photo-frame"><img src="/pics/sample/ckd7_3.jpg"
|
||||
title="NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - 樣品圖像 - 3">
|
||||
</div>
|
||||
</a> <a class="sample-box" href="https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/nima00086/nima00086jp-4.jpg">
|
||||
<div class="photo-frame"><img src="/pics/sample/ckd7_4.jpg"
|
||||
title="NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - 樣品圖像 - 4">
|
||||
</div>
|
||||
</a> <a class="sample-box" href="https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/nima00086/nima00086jp-5.jpg">
|
||||
<div class="photo-frame"><img src="/pics/sample/ckd7_5.jpg"
|
||||
title="NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - 樣品圖像 - 5">
|
||||
</div>
|
||||
</a> <a class="sample-box" href="https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/nima00086/nima00086jp-6.jpg">
|
||||
<div class="photo-frame"><img src="/pics/sample/ckd7_6.jpg"
|
||||
title="NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - 樣品圖像 - 6">
|
||||
</div>
|
||||
</a> <a class="sample-box" href="https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/nima00086/nima00086jp-7.jpg">
|
||||
<div class="photo-frame"><img src="/pics/sample/ckd7_7.jpg"
|
||||
title="NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - 樣品圖像 - 7">
|
||||
</div>
|
||||
</a> <a class="sample-box" href="https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/nima00086/nima00086jp-8.jpg">
|
||||
<div class="photo-frame"><img src="/pics/sample/ckd7_8.jpg"
|
||||
title="NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - 樣品圖像 - 8">
|
||||
</div>
|
||||
</a> <a class="sample-box" href="https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/nima00086/nima00086jp-9.jpg">
|
||||
<div class="photo-frame"><img src="/pics/sample/ckd7_9.jpg"
|
||||
title="NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - 樣品圖像 - 9">
|
||||
</div>
|
||||
</a> <a class="sample-box" href="https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/nima00086/nima00086jp-10.jpg">
|
||||
<div class="photo-frame"><img src="/pics/sample/ckd7_10.jpg"
|
||||
title="NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - 樣品圖像 - 10">
|
||||
</div>
|
||||
</a> <a class="sample-box" href="https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/nima00086/nima00086jp-11.jpg">
|
||||
<div class="photo-frame"><img src="/pics/sample/ckd7_11.jpg"
|
||||
title="NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - 樣品圖像 - 11">
|
||||
</div>
|
||||
</a> <a class="sample-box" href="https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/nima00086/nima00086jp-12.jpg">
|
||||
<div class="photo-frame"><img src="/pics/sample/ckd7_12.jpg"
|
||||
title="NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - 樣品圖像 - 12">
|
||||
</div>
|
||||
</a> <a class="sample-box" href="https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/nima00086/nima00086jp-13.jpg">
|
||||
<div class="photo-frame"><img src="/pics/sample/ckd7_13.jpg"
|
||||
title="NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - 樣品圖像 - 13">
|
||||
</div>
|
||||
</a> <a class="sample-box" href="https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/nima00086/nima00086jp-14.jpg">
|
||||
<div class="photo-frame"><img src="/pics/sample/ckd7_14.jpg"
|
||||
title="NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - 樣品圖像 - 14">
|
||||
</div>
|
||||
</a> <a class="sample-box" href="https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/nima00086/nima00086jp-15.jpg">
|
||||
<div class="photo-frame"><img src="/pics/sample/ckd7_15.jpg"
|
||||
title="NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - 樣品圖像 - 15">
|
||||
</div>
|
||||
</a> <a class="sample-box" href="https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/nima00086/nima00086jp-16.jpg">
|
||||
<div class="photo-frame"><img src="/pics/sample/ckd7_16.jpg"
|
||||
title="NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - 樣品圖像 - 16">
|
||||
</div>
|
||||
</a> <a class="sample-box" href="https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/nima00086/nima00086jp-17.jpg">
|
||||
<div class="photo-frame"><img src="/pics/sample/ckd7_17.jpg"
|
||||
title="NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - 樣品圖像 - 17">
|
||||
</div>
|
||||
</a> <a class="sample-box" href="https://awsimgsrc.dmm.co.jp/pics_dig/digital/video/nima00086/nima00086jp-18.jpg">
|
||||
<div class="photo-frame"><img src="/pics/sample/ckd7_18.jpg"
|
||||
title="NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒 - 樣品圖像 - 18">
|
||||
</div>
|
||||
</a></div>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
<h4 style="position:relative">推薦 <a href="javascript:bootstr(1);"><span id="urad2"
|
||||
class="label label-default"><span
|
||||
class="left-urad2">投放廣告</span><span class="glyphicon glyphicon-envelope"></span></span></a></h4>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-4 text-center ptb10">
|
||||
<script type="text/javascript" data-cfasync="false" async
|
||||
src="https://poweredby.jads.co/js/jads.js"></script>
|
||||
<ins id="1024556" data-width="300" data-height="250"></ins>
|
||||
<script type="text/javascript" data-cfasync="false"
|
||||
async>(adsbyjuicy = window.adsbyjuicy || []).push({"adzone": 1024556});</script>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-4 text-center ptb10">
|
||||
<script type="text/javascript" data-cfasync="false" async
|
||||
src="https://poweredby.jads.co/js/jads.js"></script>
|
||||
<ins id="1024558" data-width="300" data-height="250"></ins>
|
||||
<script type="text/javascript" data-cfasync="false"
|
||||
async>(adsbyjuicy = window.adsbyjuicy || []).push({"adzone": 1024558});</script>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-4 text-center ptb10">
|
||||
<script type="text/javascript" data-cfasync="false" async
|
||||
src="https://poweredby.jads.co/js/jads.js"></script>
|
||||
<ins id="1024557" data-width="300" data-height="250"></ins>
|
||||
<script type="text/javascript" data-cfasync="false"
|
||||
async>(adsbyjuicy = window.adsbyjuicy || []).push({"adzone": 1024557});</script>
|
||||
</div>
|
||||
</div>
|
||||
<h4>同類影片</h4>
|
||||
<div id="related-waterfall" class="mb20">
|
||||
<a title="FANZA同人ランキング1位シリーズ累計10万部突破 実写版 パパ活セーブデータ タイムリープ能力で塩対応女子をデレさせイキ壊れるまで無限攻略! 北岡果林"
|
||||
class="movie-box" href="https://www.javbus.com/MIMK-291" style="display:inline-block; margin:5px;">
|
||||
<div class="photo-frame">
|
||||
<img src="/pics/thumb/cj4u.jpg">
|
||||
</div>
|
||||
<div class="photo-info" style="height:36px; overflow:hidden; text-align:center;">
|
||||
<span>FANZA同人ランキング1位シリーズ累計10万部突破 実写版 パパ活セーブデータ タイムリープ能力で塩対応女子をデレさせイキ壊れるまで無限攻略! 北岡果林</span>
|
||||
</div>
|
||||
</a>
|
||||
<a title="スペンス乳腺開発クリニックSpecial あんづ杏" class="movie-box" href="https://www.javbus.com/PPPE-442"
|
||||
style="display:inline-block; margin:5px;">
|
||||
<div class="photo-frame">
|
||||
<img src="/pics/thumb/cj74.jpg">
|
||||
</div>
|
||||
<div class="photo-info" style="height:36px; overflow:hidden; text-align:center;">
|
||||
<span>スペンス乳腺開発クリニックSpecial あんづ杏</span>
|
||||
</div>
|
||||
</a>
|
||||
<a title="ドコでも即ハメおねだり中出しOKレンタル彼女~恋人代行なのに利用時間が過ぎても帰してくれない性欲ビースト24時~ 美園和花"
|
||||
class="movie-box" href="https://www.javbus.com/MNGS-076" style="display:inline-block; margin:5px;">
|
||||
<div class="photo-frame">
|
||||
<img src="/pics/thumb/cgx2.jpg">
|
||||
</div>
|
||||
<div class="photo-info" style="height:36px; overflow:hidden; text-align:center;">
|
||||
<span>ドコでも即ハメおねだり中出しOKレンタル彼女~恋人代行なのに利用時間が過ぎても帰してくれない性欲ビースト24時~ 美園和花</span>
|
||||
</div>
|
||||
</a>
|
||||
<a title="12時間ノンストップ性感開発モニタリング痙攣・潮吹き・エビ反り失神アクメフルコース 楪カレン"
|
||||
class="movie-box" href="https://www.javbus.com/PPPE-433" style="display:inline-block; margin:5px;">
|
||||
<div class="photo-frame">
|
||||
<img src="/pics/thumb/cgxy.jpg">
|
||||
</div>
|
||||
<div class="photo-info" style="height:36px; overflow:hidden; text-align:center;">
|
||||
<span>12時間ノンストップ性感開発モニタリング痙攣・潮吹き・エビ反り失神アクメフルコース 楪カレン</span>
|
||||
</div>
|
||||
</a>
|
||||
<a title="新・世界一媚薬でキマる変態女のトランス失禁キメセク大絶頂FUCK!! 響蓮" class="movie-box"
|
||||
href="https://www.javbus.com/RKI-747" style="display:inline-block; margin:5px;">
|
||||
<div class="photo-frame">
|
||||
<img src="/pics/thumb/c8dw.jpg">
|
||||
</div>
|
||||
<div class="photo-info" style="height:36px; overflow:hidden; text-align:center;">
|
||||
<span>新・世界一媚薬でキマる変態女のトランス失禁キメセク大絶頂FUCK!! 響蓮</span>
|
||||
</div>
|
||||
</a>
|
||||
<a title="勝手に住みついてる陰キャ幽霊のカラダを好き勝手する話1・2 幽霊だからいくら中出ししたって妊娠しない! それなら毎日、生ハメ・中出しヤリまくり! いいことしかないグラマラス幽霊さんとの同居生活! さつき芽衣"
|
||||
class="movie-box" href="https://www.javbus.com/RKI-736" style="display:inline-block; margin:5px;">
|
||||
<div class="photo-frame">
|
||||
<img src="/pics/thumb/c8dy.jpg">
|
||||
</div>
|
||||
<div class="photo-info" style="height:36px; overflow:hidden; text-align:center;">
|
||||
<span>勝手に住みついてる陰キャ幽霊のカラダを好き勝手する話1・2 幽霊だからいくら中出ししたって妊娠しない! それなら毎日、生ハメ・中出しヤリまくり! いいことしかないグラマラス幽霊さんとの同居生活! さつき芽衣</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
<script language="JavaScript">
|
||||
(function ($) {
|
||||
$('img.img').each(function () {
|
||||
var image = new Image();
|
||||
image.src = this.src;
|
||||
if (image.complete) {
|
||||
cutImgz(this);
|
||||
} else {
|
||||
this.onload = function () {
|
||||
cutImgz(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
|
||||
function cutImgz(obj) {
|
||||
var image = new Image();
|
||||
image.src = obj.src;
|
||||
$this = $(obj);
|
||||
var w = image.width;
|
||||
var h = image.height;
|
||||
var p = w / h;
|
||||
if (p > 1.38 && p < 1.40) {
|
||||
$this.addClass("m1000giri");
|
||||
}
|
||||
if (p > 0.99 && p < 1.01) {
|
||||
$this.addClass("mpacopacomama");
|
||||
}
|
||||
if (p > 1.11 && p < 1.13) {
|
||||
$this.addClass("mcaribbeancom");
|
||||
}
|
||||
if (p > 1.77 && p < 1.78) {
|
||||
$this.addClass("mcaribbeancom2");
|
||||
}
|
||||
if (p > 0.59 && p < 0.61) {
|
||||
$this.addClass("m1pondo");
|
||||
}
|
||||
if (p > 0.65 && p < 0.67) {
|
||||
$this.addClass("mtokyohot");
|
||||
}
|
||||
if (p > 1.78 && p < 1.79) {
|
||||
$this.addClass("mheyzo");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<h4>論壇熱帖</h4>
|
||||
<div id="related-waterfall" class="mb20">
|
||||
<a title="极品骚浪人妻张燕不雅视频被曝超美孕妇骚劲" class="movie-box"
|
||||
href="https://www.javbus.com/forum/forum.php?mod=viewthread&tid=176676"
|
||||
style="display:inline-block; margin:5px;">
|
||||
<div class="photo-frame bforum">
|
||||
<img class="mforum" src="https://www.javbus.com/forum/data/attachment/forum/202609/XFHWAI9.jpeg">
|
||||
</div>
|
||||
<div class="photo-info" style="height:36px; overflow:hidden; text-align:center;">
|
||||
<span>极品骚浪人妻张燕不雅视频被曝超美孕妇骚劲</span>
|
||||
</div>
|
||||
</a>
|
||||
<a title="好东西不分享给大家我的良心会痛 四" class="movie-box"
|
||||
href="https://www.javbus.com/forum/forum.php?mod=viewthread&tid=176691"
|
||||
style="display:inline-block; margin:5px;">
|
||||
<div class="photo-frame bforum">
|
||||
<img class="mforum" src="https://www.javbus.com/forum/data/attachment/forum/202609/NuKOXOl.jpeg">
|
||||
</div>
|
||||
<div class="photo-info" style="height:36px; overflow:hidden; text-align:center;">
|
||||
<span>好东西不分享给大家我的良心会痛 四</span>
|
||||
</div>
|
||||
</a>
|
||||
<a title="求一欧美片,必须实用,曾经我的珍藏,丢失" class="movie-box"
|
||||
href="https://www.javbus.com/forum/forum.php?mod=viewthread&tid=176678"
|
||||
style="display:inline-block; margin:5px;">
|
||||
<div class="photo-frame bforum">
|
||||
<img class="mforum" src="https://www.javbus.com/forum/data/attachment/forum/202609/MI4O4K8.jpg">
|
||||
</div>
|
||||
<div class="photo-info" style="height:36px; overflow:hidden; text-align:center;">
|
||||
<span>求一欧美片,必须实用,曾经我的珍藏,丢失</span>
|
||||
</div>
|
||||
</a>
|
||||
<a title="看到一张图想知道名字" class="movie-box"
|
||||
href="https://www.javbus.com/forum/forum.php?mod=viewthread&tid=176686"
|
||||
style="display:inline-block; margin:5px;">
|
||||
<div class="photo-frame bforum">
|
||||
<img class="mforum" src="https://www.javbus.com/forum/data/attachment/forum/202609/wvxEc6L.png">
|
||||
</div>
|
||||
<div class="photo-info" style="height:36px; overflow:hidden; text-align:center;">
|
||||
<span>看到一张图想知道名字</span>
|
||||
</div>
|
||||
</a>
|
||||
<a title="广佛中秋国庆双节出击出击第二弹 长腿御姐" class="movie-box"
|
||||
href="https://www.javbus.com/forum/forum.php?mod=viewthread&tid=176692"
|
||||
style="display:inline-block; margin:5px;">
|
||||
<div class="photo-frame bforum">
|
||||
<img class="mforum" src="https://www.javbus.com/forum/data/attachment/forum/202609/AX1wxZU.jpeg">
|
||||
</div>
|
||||
<div class="photo-info" style="height:36px; overflow:hidden; text-align:center;">
|
||||
<span>广佛中秋国庆双节出击出击第二弹 长腿御姐</span>
|
||||
</div>
|
||||
</a>
|
||||
<a title="求这完整的套图" class="movie-box"
|
||||
href="https://www.javbus.com/forum/forum.php?mod=viewthread&tid=176647"
|
||||
style="display:inline-block; margin:5px;">
|
||||
<div class="photo-frame bforum">
|
||||
<img class="mforum" src="https://www.javbus.com/forum/data/attachment/forum/202609/eblYOrO.jpeg">
|
||||
</div>
|
||||
<div class="photo-info" style="height:36px; overflow:hidden; text-align:center;">
|
||||
<span>求这完整的套图</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function ($) {
|
||||
$('.bigImage').magnificPopup({
|
||||
type: 'image',
|
||||
closeOnContentClick: true,
|
||||
closeBtnInside: false,
|
||||
fixedContentPos: true,
|
||||
mainClass: 'mfp-no-margins mfp-with-zoom',
|
||||
image: {
|
||||
verticalFit: true,
|
||||
titleSrc: function (item) {
|
||||
return "NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒";
|
||||
}
|
||||
},
|
||||
zoom: {
|
||||
enabled: true,
|
||||
duration: 300
|
||||
}
|
||||
});
|
||||
|
||||
$('#sample-waterfall').magnificPopup({
|
||||
delegate: 'a',
|
||||
type: 'image',
|
||||
closeOnContentClick: false,
|
||||
closeBtnInside: false,
|
||||
mainClass: 'mfp-with-zoom mfp-img-mobile',
|
||||
image: {
|
||||
verticalFit: true,
|
||||
titleSrc: function (item) {
|
||||
return "NIMA-086 実写版!ムラムラしたので通勤中にお持ち帰りされてみた 彩月七緒";
|
||||
}
|
||||
},
|
||||
gallery: {
|
||||
enabled: true
|
||||
},
|
||||
zoom: {
|
||||
enabled: true,
|
||||
duration: 300,
|
||||
opener: function (element) {
|
||||
return element.find('img');
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
})(jQuery);
|
||||
|
||||
$("#gr_btn").click(function () {
|
||||
var t = "";
|
||||
$("input[name='gr_sel']:checkbox").each(function () {
|
||||
$(this).is(":checked") && (t += $(this).val() + "-")
|
||||
}), "" != t && (t = t.substring(0, t.length - 1), window.location.href = "genre/" + t)
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
||||
<div class="ad-box">
|
||||
<div class="ad-item">
|
||||
<div class="ad-juicy">
|
||||
<script type="text/javascript" data-cfasync="false" async
|
||||
src="https://poweredby.jads.co/js/jads.js"></script>
|
||||
<ins id="1024551" data-width="728" data-height="90"></ins>
|
||||
<script type="text/javascript" data-cfasync="false"
|
||||
async>(adsbyjuicy = window.adsbyjuicy || []).push({"adzone": 1024551});</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ad-item"><a href="https://hgdj.rezluatfbfvgwjhzfhrkovblo.com/chan/ak0072/acXm7" target="_blank"
|
||||
rel="nofollow"><img src="/ads/hjll_728x90_39.gif" width="728" height="90"></a></div>
|
||||
<div class="ad-item"><a href="https://xn--fwza.168good.cc/#/?ai=157284" target="_blank" rel="nofollow"><img
|
||||
src="/ads/51fl_728x90_2.jpg" width="728" height="90"></a></div>
|
||||
<div class="ad-item"><a href="https://91p.khgnhlzvcisaddwfehlvtnhel.com/chan/GS4670/aBhGW" target="_blank"
|
||||
rel="nofollow"><img src="/ads/hjll_728x90_18.gif" width="728" height="90"></a></div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src='https://www.javbus.com/js/gallery.js?v=2.9'></script>
|
||||
<footer class="footer hidden-xs">
|
||||
<div class="container-fluid">
|
||||
<p><a href="https://www.javbus.com/doc/terms">Terms</a> / <a
|
||||
href="https://www.javbus.com/doc/privacy">Privacy</a> / <a
|
||||
href="https://www.javbus.com/doc/usc">2257</a> / <a href="http://www.rtalabel.org/" target="_blank"
|
||||
rel="external nofollow">RTA</a> / <a
|
||||
href="javascript:bootstr(1);" r>廣告投放</a> / <a href="javascript:bootstr(2);">聯絡我們</a><br/><a
|
||||
href="#formModal" id="adscontact" data-toggle="modal"></a>
|
||||
Copyright © 2013 JavBus. All Rights Reserved. All other trademarks and copyrights are the property of their
|
||||
respective holders. The reviews and comments expressed at or through this website are the opinions of the
|
||||
individual author and do not reflect the opinions or views of JavBus. JavBus is not responsible for the
|
||||
accuracy of any of the information supplied here.</p>
|
||||
</div>
|
||||
</footer>
|
||||
<div class="visible-xs-block footer-bar-placeholder"></div>
|
||||
|
||||
<script language=javascript>
|
||||
function bootstr(type) {
|
||||
ads = "廣告投放";
|
||||
contact = "聯絡我們";
|
||||
translate = "翻譯";
|
||||
$("#adstype").val(type);
|
||||
if (type == 1) {
|
||||
$("#contactModalLab").html(ads);
|
||||
$("#qqskype").show();
|
||||
$("#transinfo").hide();
|
||||
$("#translanguage").hide();
|
||||
$("#mailcontent").show();
|
||||
} else if (type == 2) {
|
||||
$("#contactModalLab").html(contact);
|
||||
$("#qqskype").show();
|
||||
$("#transinfo").hide();
|
||||
$("#translanguage").hide();
|
||||
$("#mailcontent").show();
|
||||
} else if (type == 3) {
|
||||
$("#contactModalLab").html(translate);
|
||||
$("#qqskype").hide();
|
||||
$("#transinfo").show();
|
||||
$("#translanguage").show();
|
||||
$("#mailcontent").hide();
|
||||
}
|
||||
$("#adscontact").trigger("click");
|
||||
getverifycode();
|
||||
};
|
||||
|
||||
function getverifycode() {
|
||||
$('#verify').attr("src", "/post/verify?" + Math.random() * 10000);
|
||||
};
|
||||
|
||||
function IsMail(mail) {
|
||||
var remail = /^([a-zA-Z0-9_-])+(\.)?([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/;
|
||||
return (remail.test(mail));
|
||||
};
|
||||
|
||||
function checkform() {
|
||||
var post = true;
|
||||
if ($("#verifycode").val().length != 5) {
|
||||
alert("驗證碼輸入錯誤!")
|
||||
$("#verifycode").focus();
|
||||
post = false;
|
||||
}
|
||||
if ($("#contact").val().length > 255) {
|
||||
alert("聯繫方式字數過多!")
|
||||
$("#contact").focus();
|
||||
post = false;
|
||||
}
|
||||
|
||||
if (!IsMail($("#mail").val())) {
|
||||
alert("請輸入正確的電郵地址!")
|
||||
$("#mail").focus();
|
||||
post = false;
|
||||
}
|
||||
|
||||
if ($("#intention").val().length > 25500) {
|
||||
alert("投放意向字數過多!")
|
||||
$("#intention").focus();
|
||||
post = false;
|
||||
}
|
||||
|
||||
if ($("#trans").val().length > 255) {
|
||||
alert("Too many words in your language textbox!")
|
||||
$("#intention").focus();
|
||||
post = false;
|
||||
}
|
||||
if (post == true) {
|
||||
$("#modalclose").trigger("click");
|
||||
$("#postform").attr("action", "/post/contact");
|
||||
$("#postform").submit();
|
||||
}
|
||||
return post;
|
||||
};
|
||||
</script>
|
||||
|
||||
<script>
|
||||
$("#showmag,#cellshowmag,#resultshowmag").click(function () {
|
||||
$.cookie("existmag", "mag", {expires: 365, path: '/'});
|
||||
location.reload()
|
||||
});
|
||||
|
||||
$("#showall,#cellshowall,#resultshowall").click(function () {
|
||||
$.cookie("existmag", "all", {expires: 365, path: '/'});
|
||||
location.reload()
|
||||
});
|
||||
$("#showonline").click(function () {
|
||||
$.cookie("existmag", "online", {expires: 365, path: '/'});
|
||||
location.reload()
|
||||
});
|
||||
$(".info .mypointer").click(function () {
|
||||
var obj = $(this);
|
||||
var code = obj.attr('value');
|
||||
var token = $("#token").val();
|
||||
var e = "../ajax/addfavorite.php?code=" + encodeURIComponent(code) + "&token=" + encodeURIComponent(token) + "&floor=" + Math.floor(Math.random() * 1e3 + 1);
|
||||
$.ajax({
|
||||
url: e,
|
||||
type: "POST",
|
||||
//dataType: "json",
|
||||
cache: false,
|
||||
success: function (json) {
|
||||
//obj.html(json);
|
||||
ajaxobj = eval("(" + json + ")");
|
||||
if (ajaxobj.act == 'err') {
|
||||
alert('收藏次數達上限,請稍候再試');
|
||||
} else {
|
||||
obj.html(ajaxobj.act);
|
||||
obj.attr('value', ajaxobj.code);
|
||||
obj.attr('title', ajaxobj.title);
|
||||
$("#token").val(ajaxobj.token);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(".glyphicon-heart-empty").hover(function () {
|
||||
$(this).removeClass('glyphicon-heart-empty');
|
||||
$(this).addClass('glyphicon-heart');
|
||||
}, function () {
|
||||
$(this).removeClass('glyphicon-heart');
|
||||
$(this).addClass('glyphicon-heart-empty');
|
||||
});
|
||||
$(".glyphicon-heart").hover(function () {
|
||||
$(this).removeClass('glyphicon-heart');
|
||||
$(this).addClass('glyphicon-heart-empty');
|
||||
}, function () {
|
||||
$(this).removeClass('glyphicon-heart-empty');
|
||||
$(this).addClass('glyphicon-heart');
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Modal Forms -->
|
||||
<div id="formModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="formModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button id="modalclose" type="button" class="close" data-dismiss="modal" aria-label="Close"><span
|
||||
aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="contactModalLab">聯絡我們</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" name="postform" method="post" id="postform" enctype="multipart/form-data">
|
||||
<fieldset>
|
||||
<div class="form-group" id="qqskype">
|
||||
<label class="col-sm-4 control-label" for="contact">Telegram / 電報</label>
|
||||
<div class="col-sm-6">
|
||||
<input id="contact" name="contact" type="text" placeholder="" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label" for="mail">Email</label>
|
||||
<div class="col-sm-6">
|
||||
<input id="mail" name="mail" type="text" placeholder="" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="translanguage">
|
||||
<label class="col-sm-4 control-label" for="trans">Your Language</label>
|
||||
<div class="col-sm-6">
|
||||
<input id="trans" name="trans" type="text" placeholder="" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="mailcontent">
|
||||
<label class="col-sm-4 control-label" for="intention" id="inten-trans">內容</label>
|
||||
<div class="col-sm-6">
|
||||
<textarea id="intention" name="intention" rows="9" class="form-control"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label" for="verify">驗證碼</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" id="verifycode" name="verifycode" style="width:50px"/>
|
||||
<img id="verify" src="" style="cursor: pointer; vertical-align:middle;"
|
||||
onclick="getverifycode()"/>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" id="adstype" name="adstype" value="1"/>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" button class="btn btn-primary" onclick="checkform()">送出</button>
|
||||
<button type="button" button class="btn btn-default" data-dismiss="modal">關閉</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- ////////////////////////////////////////////////// -->
|
||||
<div class="overlay overlay-contentscale">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 text-center ptb20">
|
||||
<div class="input-group col-xs-offset-2 col-xs-8">
|
||||
<input id="search-input-mobile" type="text" class="form-control" placeholder="搜尋 識別碼, 影片, 演員">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" type="submit"
|
||||
onClick="searchs('search-input-mobile')">搜尋</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 text-center"><a href="https://www.javbus.com/">有碼</a></div>
|
||||
<div class="col-xs-6 text-center"><a href="https://www.javbus.com/uncensored">無碼</a></div>
|
||||
<div class="col-xs-6 text-center"><a href="https://www.javbus.com/genre">有碼類別</a></div>
|
||||
<div class="col-xs-6 text-center"><a href="https://www.javbus.com/uncensored/genre">無碼類別</a></div>
|
||||
<div class="col-xs-6 text-center"><a href="https://www.javbus.com/actresses">有碼女優</a></div>
|
||||
<div class="col-xs-6 text-center"><a href="https://www.javbus.com/uncensored/actresses">無碼女優</a></div>
|
||||
<div class="col-xs-6 text-center"><a href="https://www.javbus.hair/">歐美</a></div>
|
||||
<div class="col-xs-6 text-center"><a href="https://www.javbus.com/forum/">論壇</a></div>
|
||||
|
||||
<div class="col-xs-12 text-center overlay-close">
|
||||
<i class="glyphicon glyphicon-remove"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
+1248
File diff suppressed because it is too large
Load Diff
Generated
+5
-3
@@ -1,17 +1,16 @@
|
||||
{
|
||||
"name": "jhs-enhance",
|
||||
"version": "3.3.6",
|
||||
"version": "3.3.10",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "jhs-enhance",
|
||||
"version": "3.3.6",
|
||||
"version": "3.3.10",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"blueimp-md5": "^2.19.0",
|
||||
"jquery": "^4.0.0",
|
||||
"layui-layer": "^1.0.9",
|
||||
"localforage": "^1.10.0",
|
||||
"qrcodejs": "^1.0.0",
|
||||
"tabulator-tables": "^6.5.2",
|
||||
@@ -19,6 +18,7 @@
|
||||
"viewerjs": "^1.12.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"layui-layer": "^1.0.9",
|
||||
"vite": "^6.0.0",
|
||||
"vite-plugin-monkey": "^5.0.0"
|
||||
}
|
||||
@@ -1204,6 +1204,7 @@
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmmirror.com/layui-layer/-/layui-layer-1.0.9.tgz",
|
||||
"integrity": "sha512-CzPVtG0D4IvmISUyLTzzbz2Uxfaoqch+87lHqVmO53ie8ZKOfOkENbBl7ssiLna1lAnv4M1SycmH62NbtndtDQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"jquery": "^3.1.1"
|
||||
@@ -1213,6 +1214,7 @@
|
||||
"version": "3.7.1",
|
||||
"resolved": "https://registry.npmmirror.com/jquery/-/jquery-3.7.1.tgz",
|
||||
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lie": {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jhs-enhance",
|
||||
"version": "3.3.6",
|
||||
"version": "3.3.18",
|
||||
"description": "Jav-鉴黄师 油猴脚本 - 工程化版本",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
const COVER_API_URL = [77, 81, 81, 85, 86, 31, 10, 10, 68, 85, 76, 8, 65, 72, 72, 87, 86, 70, 11, 20, 22, 20, 17, 22, 22, 11, 93, 92, 95, 10, 68, 85, 76, 10, 70, 74, 83, 64, 87]
|
||||
.map(v => String.fromCharCode(v ^ 0x25)).join('');
|
||||
|
||||
const TRAILER_API_URL = [77, 81, 81, 85, 86, 31, 10, 10, 68, 85, 76, 8, 65, 72, 72, 87, 86, 70, 11, 20, 22, 20, 17, 22, 22, 11, 93, 92, 95, 10, 68, 85, 76, 10, 81, 87, 68, 76, 73, 64, 87]
|
||||
.map(v => String.fromCharCode(v ^ 0x25)).join('');
|
||||
|
||||
const BASE_URL = [77, 81, 81, 85, 86, 31, 10, 10, 68, 85, 76, 8, 65, 72, 72, 87, 86, 70, 11, 20, 22, 20, 17, 22, 22, 11, 93, 92, 95]
|
||||
.map(v => String.fromCharCode(v ^ 0x25)).join('');
|
||||
|
||||
const COVER_API_TOKEN = [18, 28, 19, 19, 65, 65, 70, 28, 64, 29, 23, 21, 17, 29, 67, 70, 18, 64, 21, 22, 64, 16, 65, 29, 22, 19, 16, 28, 16, 17, 64, 29]
|
||||
.map(v => String.fromCharCode(v ^ 0x25)).join('');
|
||||
|
||||
const getCover = async (code) => {
|
||||
const query = String(code || '').trim();
|
||||
if (!query) return null;
|
||||
|
||||
try {
|
||||
const r = await gmHttp.get(`${COVER_API_URL}/${encodeURIComponent(query)}`, null, {
|
||||
'Authorization': `Bearer ${COVER_API_TOKEN}`,
|
||||
}, {timeout: 15000});
|
||||
|
||||
if (r?.cover?.large) {
|
||||
//clog.log('高清封面地址:', r.cover.large);
|
||||
return r.cover.large;
|
||||
}
|
||||
return null;
|
||||
} catch (e) {
|
||||
clog.error('获取封面失败:', e.message);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const getTrailer = async (code) => {
|
||||
const query = String(code || '').trim();
|
||||
if (!query) return null;
|
||||
|
||||
try {
|
||||
const r = await gmHttp.get(`${TRAILER_API_URL}/${encodeURIComponent(query)}`, null, {
|
||||
'Authorization': `Bearer ${COVER_API_TOKEN}`,
|
||||
}, {timeout: 15000});
|
||||
|
||||
if (r?.trailers && Array.isArray(r.trailers) && r.trailers.length > 0) {
|
||||
const qualityMap = {};
|
||||
r.trailers.forEach((item) => {
|
||||
if (item.proxy && item.quality) {
|
||||
qualityMap[item.quality] = `${BASE_URL}${item.proxy}`;
|
||||
}
|
||||
});
|
||||
if (Object.keys(qualityMap).length > 0) {
|
||||
clog.log('预告片播放地址:', JSON.stringify(qualityMap));
|
||||
return qualityMap;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} catch (e) {
|
||||
clog.error('获取预告片失败:', e.message);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export {getCover, getTrailer};
|
||||
@@ -211,10 +211,36 @@ const getJavxyVideoUrls = async (code, failedSources = []) => {
|
||||
return null;
|
||||
};
|
||||
|
||||
const getJavxyCover = async (code) => {
|
||||
const query = String(code || '').trim();
|
||||
if (!query) return null;
|
||||
|
||||
for (const endpoint of JAVXY_ENDPOINTS) {
|
||||
const params = new URLSearchParams({client: 'laosiji-new'});
|
||||
const apiUrl = `https://${endpoint.host}/covers/${encodeURIComponent(query)}?${params}`;
|
||||
|
||||
let r;
|
||||
try {
|
||||
r = await gmHttp.get(apiUrl, null, {
|
||||
'Accept': 'application/json,text/plain,*/*',
|
||||
'X-Javxy-Token': JAVXY_TOKEN,
|
||||
}, {timeout: 15000});
|
||||
} catch (e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!r) continue;
|
||||
if (r?.found && (r.url || r.cover || r.highCover)) return r;
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export {
|
||||
fromJavxyCcCd,
|
||||
fallbackJavxyResult,
|
||||
getJavxyVideoUrls,
|
||||
getJavxyCover,
|
||||
normalizeJavxySource,
|
||||
isJpSourceTemporarilyFailed,
|
||||
markJpSourceTemporarilyFailed,
|
||||
|
||||
@@ -145,10 +145,7 @@ class BasePlugin {
|
||||
carNum2 = dateElements.find((i => !isDate(i))) || null;
|
||||
}
|
||||
if (!carNum2) {
|
||||
const msg = "提取番号信息失败: carNum 为空";
|
||||
console.error("Error in getBoxCarInfo:", msg, "Box Element:", $box2.get(0));
|
||||
show.error(msg);
|
||||
throw new Error(msg);
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
carNum: carNum2,
|
||||
|
||||
@@ -63,6 +63,16 @@ const currentHref = window.location.href,
|
||||
quality: "mmb",
|
||||
text: "中画质 (432p)",
|
||||
canSelect: !0
|
||||
}, {
|
||||
id: "video-dm",
|
||||
quality: "dm",
|
||||
text: "低画质 (1000kbps)",
|
||||
canSelect: !0
|
||||
}, {
|
||||
id: "video-dmb",
|
||||
quality: "dmb",
|
||||
text: "中画质 (1500kbps)",
|
||||
canSelect: !0
|
||||
}, {
|
||||
id: "video-mhb",
|
||||
quality: "mhb",
|
||||
@@ -577,6 +587,23 @@ const mainCss = `
|
||||
color: #f40 !important;
|
||||
}
|
||||
|
||||
#magnets-content .item[data-rank] {
|
||||
position: relative !important;
|
||||
}
|
||||
#magnets-content .item[data-rank] .buttons {
|
||||
position: absolute !important;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
margin: 0 !important;
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
}
|
||||
#magnets-content .item[data-rank] .name {
|
||||
display: block;
|
||||
padding-right: 260px;
|
||||
}
|
||||
|
||||
.msf-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
@@ -1043,6 +1070,16 @@ insertStyle(
|
||||
insertStyle(mainCss);
|
||||
insertStyle(subtitleModalCss);
|
||||
|
||||
const isEligibleDmmCoverCode = (value) => {
|
||||
const raw = String(value || '').trim().toUpperCase();
|
||||
if (!/^[A-Z0-9]{2,10}-\d{1,6}$/.test(raw)) return false;
|
||||
const code = raw.replace(/\s+/g, '-').toUpperCase();
|
||||
if (!/^[A-Z0-9]{2,10}-\d{1,6}$/.test(code) || /^FC2-/.test(code)) return false;
|
||||
if (/^\d{6}[-_]\d{2,3}$/.test(code)) return false;
|
||||
if (/^(DUGA|MYWIFE|HEYZO|PACO|10MU|1PONDO|CARIBBEAN|CARIB|TOKYO|GACHI|REAL|JUKU|AKA|NTR)-/.test(code)) return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
export {
|
||||
__defProp,
|
||||
__typeError,
|
||||
@@ -1052,6 +1089,7 @@ export {
|
||||
isJavDb,
|
||||
isJavBus,
|
||||
isSearchPage,
|
||||
isEligibleDmmCoverCode,
|
||||
Status_RUNNING,
|
||||
Status_SUCCESS,
|
||||
Status_FAIL,
|
||||
|
||||
+10
-3
@@ -6,6 +6,9 @@ import { Utils } from './core/utils.js';
|
||||
import { GmHttp } from './core/gmHttp.js';
|
||||
import { PluginManager } from './core/plugin-manager.js';
|
||||
import { BasePlugin } from './core/base-plugin.js';
|
||||
import {TabulatorFull as Tabulator} from 'tabulator-tables';
|
||||
|
||||
window.Tabulator = Tabulator;
|
||||
|
||||
import { javDbApi, buildSignature, apiUrl } from './api/javdb.js';
|
||||
window.javDbApi = javDbApi;
|
||||
@@ -29,7 +32,7 @@ import { TOP250Plugin } from './plugins/top250.js';
|
||||
import { NavBarPlugin } from './plugins/nav-bar.js';
|
||||
import { BusDetailPagePlugin } from './plugins/bus-detail-page.js';
|
||||
import { BusPreviewVideoPlugin } from './plugins/bus-preview-video.js';
|
||||
import {JavxyPreviewVideoPlugin} from './plugins/javxy-preview-video.js';
|
||||
import {JavopenPreviewVideoPlugin} from './plugins/javopen-preview-video.js';
|
||||
import { ImageRecognitionPlugin } from './plugins/image-recognition.js';
|
||||
import { BusNavBarPlugin } from './plugins/bus-nav-bar.js';
|
||||
import { RelatedPlugin } from './plugins/related.js';
|
||||
@@ -52,6 +55,7 @@ import { DetailPageButtonPlugin } from './plugins/detail-page-button.js';
|
||||
import { BlacklistPlugin } from './plugins/blacklist.js';
|
||||
import { ListPagePlugin } from './plugins/list-page.js';
|
||||
import { AutoPagePlugin } from './plugins/auto-page.js';
|
||||
import {ArticlePagePlugin} from './plugins/article-page.js';
|
||||
|
||||
const _unsafeWindow = (() => typeof unsafeWindow !== 'undefined' ? unsafeWindow : window)();
|
||||
|
||||
@@ -861,6 +865,7 @@ const pluginManager = function() {
|
||||
if (isJavDb) {
|
||||
pluginManager2.register(ListPagePlugin);
|
||||
pluginManager2.register(AutoPagePlugin);
|
||||
pluginManager2.register(ArticlePagePlugin);
|
||||
pluginManager2.register(Fc2Plugin);
|
||||
pluginManager2.register(FoldCategoryPlugin);
|
||||
pluginManager2.register(ListPageButtonPlugin);
|
||||
@@ -879,7 +884,7 @@ const pluginManager = function() {
|
||||
pluginManager2.register(DetailPageButtonPlugin);
|
||||
pluginManager2.register(HighlightMagnetPlugin);
|
||||
pluginManager2.register(PreviewVideoPlugin);
|
||||
pluginManager2.register(JavxyPreviewVideoPlugin);
|
||||
pluginManager2.register(JavopenPreviewVideoPlugin);
|
||||
pluginManager2.register(FilterTitleKeywordPlugin);
|
||||
pluginManager2.register(ActressInfoPlugin);
|
||||
pluginManager2.register(OtherSitePlugin);
|
||||
@@ -910,13 +915,15 @@ const pluginManager = function() {
|
||||
pluginManager2.register(FilterTitleKeywordPlugin);
|
||||
pluginManager2.register(HighlightMagnetPlugin);
|
||||
pluginManager2.register(BusPreviewVideoPlugin);
|
||||
pluginManager2.register(JavxyPreviewVideoPlugin);
|
||||
pluginManager2.register(JavopenPreviewVideoPlugin);
|
||||
pluginManager2.register(MagnetHubPlugin);
|
||||
pluginManager2.register(ScreenShotPlugin);
|
||||
pluginManager2.register(OtherSitePlugin);
|
||||
pluginManager2.register(WangPan115TaskPlugin);
|
||||
pluginManager2.register(TranslatePlugin);
|
||||
pluginManager2.register(BlacklistPlugin);
|
||||
pluginManager2.register(FavoriteActressesPlugin);
|
||||
pluginManager2.register(FoldCategoryPlugin);
|
||||
pluginManager2.register(TaskPlugin);
|
||||
}
|
||||
hostname.includes("javtrailers") && pluginManager2.register(JavTrailersPlugin);
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
import {BasePlugin} from '../core/base-plugin.js';
|
||||
import {insertStyle} from '../core/constants.js';
|
||||
|
||||
class ArticlePagePlugin extends BasePlugin {
|
||||
getName() {
|
||||
return "ArticlePagePlugin";
|
||||
}
|
||||
|
||||
handle() {
|
||||
const href = window.location.href;
|
||||
if (!href.includes("/articles")) {
|
||||
return;
|
||||
}
|
||||
this.optimizeArticleLayout();
|
||||
this.bindClick();
|
||||
}
|
||||
|
||||
bindClick() {
|
||||
// 使用 MutationObserver 监听 DOM 变化,尽早绑定事件
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
for (const mutation of mutations) {
|
||||
if (mutation.addedNodes.length > 0) {
|
||||
this.attachClickHandler();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 立即尝试绑定一次
|
||||
this.attachClickHandler();
|
||||
|
||||
// 监听整个 document 的 DOM 变化
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
}
|
||||
|
||||
attachClickHandler() {
|
||||
const $articleList = $('.article-list');
|
||||
if ($articleList.length === 0) return;
|
||||
|
||||
// 检查是否已经绑定过
|
||||
if ($articleList.data('click-bound')) return;
|
||||
$articleList.data('click-bound', true);
|
||||
|
||||
// 方法1:移除所有 a 标签的 href 属性,从根本上阻止跳转
|
||||
$articleList.find('a').each(function () {
|
||||
const $a = $(this);
|
||||
const href = $a.attr('href');
|
||||
if (href) {
|
||||
$a.attr('data-href', href).removeAttr('href');
|
||||
$a.css('cursor', 'pointer');
|
||||
}
|
||||
});
|
||||
|
||||
// 方法2:使用事件捕获阶段绑定(优先级最高)
|
||||
document.querySelector('.article-list').addEventListener('click', (e) => {
|
||||
// 简化选择器,closest 不支持 > div 这样的子选择器
|
||||
let target = e.target.closest('.article-item, a, [data-href]');
|
||||
|
||||
// 如果没找到,尝试向上找 .article-list 的直接子元素
|
||||
if (!target) {
|
||||
let el = e.target;
|
||||
const articleList = document.querySelector('.article-list');
|
||||
while (el && el !== articleList) {
|
||||
if (el.parentElement === articleList) {
|
||||
target = el;
|
||||
break;
|
||||
}
|
||||
el = el.parentElement;
|
||||
}
|
||||
}
|
||||
|
||||
if (!target) return;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
|
||||
const $target = $(target);
|
||||
const $link = $target.find('a[data-href]').first().length > 0
|
||||
? $target.find('a[data-href]').first()
|
||||
: $target.closest('a[data-href]');
|
||||
|
||||
const articleUrl = $link.attr('data-href') || $target.attr('data-href');
|
||||
if (!articleUrl) return;
|
||||
|
||||
layer.open({
|
||||
type: 2,
|
||||
title: $target.text().trim().substring(0, 50) || '文章详情',
|
||||
content: articleUrl,
|
||||
area: ['80%', '85%'],
|
||||
shadeClose: true,
|
||||
maxmin: true,
|
||||
scrollbar: false
|
||||
});
|
||||
|
||||
return false;
|
||||
}, true); // true = 捕获阶段,优先级最高
|
||||
}
|
||||
|
||||
optimizeArticleLayout() {
|
||||
const css = `
|
||||
/* 文章列表容器改为 grid 布局,每行3个 */
|
||||
.article-list {
|
||||
display: grid !important;
|
||||
grid-template-columns: repeat(3, 1fr) !important;
|
||||
gap: 20px !important;
|
||||
}
|
||||
/* 每个文章卡片改为纵向布局 */
|
||||
.article-list > div {
|
||||
display: flex !important;
|
||||
flex-direction: column !important;
|
||||
overflow: hidden !important;
|
||||
border-radius: 8px !important;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important;
|
||||
transition: transform 0.2s, box-shadow 0.2s !important;
|
||||
background: #fff !important;
|
||||
}
|
||||
.article-list > div:hover {
|
||||
transform: translateY(-4px) !important;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.15) !important;
|
||||
}
|
||||
/* 封面图片 */
|
||||
.article-list > div img {
|
||||
width: 100% !important;
|
||||
height: auto !important;
|
||||
aspect-ratio: 3/4 !important;
|
||||
object-fit: cover !important;
|
||||
border-radius: 8px 8px 0 0 !important;
|
||||
display: block !important;
|
||||
}
|
||||
/* 内容区域 */
|
||||
.article-list > div > div:not(:first-child) {
|
||||
padding: 12px !important;
|
||||
display: flex !important;
|
||||
flex-direction: column !important;
|
||||
gap: 8px !important;
|
||||
}
|
||||
/* 标题完全显示,不截断 */
|
||||
.article-list > div > a,
|
||||
.article-list > div > h3,
|
||||
.article-list > div > p {
|
||||
font-size: 14px !important;
|
||||
line-height: 1.5 !important;
|
||||
display: block !important;
|
||||
overflow: visible !important;
|
||||
text-overflow: clip !important;
|
||||
-webkit-line-clamp: unset !important;
|
||||
-webkit-box-orient: unset !important;
|
||||
min-height: unset !important;
|
||||
color: #333 !important;
|
||||
word-break: break-word !important;
|
||||
}
|
||||
/* 底部信息 */
|
||||
.article-list > div > div:last-child {
|
||||
margin-top: auto !important;
|
||||
font-size: 12px !important;
|
||||
color: #999 !important;
|
||||
display: flex !important;
|
||||
justify-content: space-between !important;
|
||||
align-items: center !important;
|
||||
}
|
||||
/* 标签 */
|
||||
.article-list > div span[class*="tag"],
|
||||
.article-list > div span[class*="label"] {
|
||||
background: #f0f0f0 !important;
|
||||
padding: 2px 8px !important;
|
||||
border-radius: 4px !important;
|
||||
font-size: 11px !important;
|
||||
}
|
||||
`;
|
||||
insertStyle(css);
|
||||
}
|
||||
}
|
||||
|
||||
export {ArticlePagePlugin};
|
||||
@@ -55,9 +55,6 @@ class AutoPagePlugin extends BasePlugin {
|
||||
const nextLink = document.querySelector(selector.nextPageSelector);
|
||||
this.nextUrl = null == nextLink ? void 0 : nextLink.href;
|
||||
this.hasMore = !!this.nextUrl;
|
||||
setTimeout((() => {
|
||||
this.checkLoad();
|
||||
}), 1e3);
|
||||
this.hasMore || this.setState("waterfall-no-more", "已经到底了");
|
||||
}
|
||||
async loadNextPage() {
|
||||
@@ -128,7 +125,9 @@ class AutoPagePlugin extends BasePlugin {
|
||||
clog.error("加载失败:", e);
|
||||
this.setState("waterfall-error", "加载失败,点击重试");
|
||||
} finally {
|
||||
this.isLoading = !1;
|
||||
setTimeout((() => {
|
||||
this.isLoading = !1;
|
||||
}), 600);
|
||||
}
|
||||
}
|
||||
checkScrollPosition() {
|
||||
@@ -145,13 +144,15 @@ class AutoPagePlugin extends BasePlugin {
|
||||
}
|
||||
}
|
||||
checkLoad() {
|
||||
if (!this.loader) return;
|
||||
this.loader.getBoundingClientRect().top < window.innerHeight + this.preloadDistance && this.loadNextPage().then();
|
||||
if (!this.loader || this.isLoading || !this.hasMore) return;
|
||||
if (window.scrollY < 100) return;
|
||||
const triggerDistance = 200;
|
||||
this.loader.getBoundingClientRect().top < window.innerHeight + triggerDistance && this.loadNextPage().then();
|
||||
}
|
||||
async shouldDisablePaging() {
|
||||
if (!window.isListPage) return !0;
|
||||
await storageManager.getSetting("autoPage", YES);
|
||||
return [ "search?q", "handlePlayback=1", "handleTop=1", "/want_watch_videos", "/watched_videos", "/advanced_search?type=100" ].some((path => currentHref.includes(path)));
|
||||
return ["search?q", "/rankings/playback", "/rankings/top", "/want_watch_videos", "/watched_videos", "/advanced_search?type=100"].some((path => currentHref.includes(path)));
|
||||
}
|
||||
updatePageUrl_old(href) {
|
||||
window.history.pushState({}, "", href);
|
||||
|
||||
@@ -1,6 +1,19 @@
|
||||
import { BasePlugin } from '../core/base-plugin.js';
|
||||
import { __publicField, isJavBus, isJavDb, Status_FILTER, Status_FAVORITE, Status_HAS_DOWN, Status_HAS_WATCH, NO, YES } from '../core/constants.js';
|
||||
import {
|
||||
__publicField,
|
||||
isJavBus,
|
||||
isJavDb,
|
||||
isEligibleDmmCoverCode,
|
||||
Status_FILTER,
|
||||
Status_FAVORITE,
|
||||
Status_HAS_DOWN,
|
||||
Status_HAS_WATCH,
|
||||
NO,
|
||||
YES
|
||||
} from '../core/constants.js';
|
||||
import { HotkeyManager } from './preview-video.js';
|
||||
import {GM_xmlhttpRequest} from 'vite-plugin-monkey/dist/client';
|
||||
import {getCover} from '../api/dmmrsc.js';
|
||||
|
||||
class DetailPageButtonPlugin extends BasePlugin {
|
||||
getName() {
|
||||
@@ -23,7 +36,7 @@ class DetailPageButtonPlugin extends BasePlugin {
|
||||
}
|
||||
async createMenuBtn() {
|
||||
const pageInfo = this.getPageInfo(), carNum2 = pageInfo.carNum,
|
||||
buttonsHtml = '\n <div style="margin: 10px auto; display: flex; justify-content: space-between; align-items: center; flex-wrap:wrap;gap: 20px;">\n <div style="display: flex; gap: 10px; flex-wrap:wrap;">\n <a id="filterBtn" class="menu-btn" style="width: 120px; background-color:#de3333; color: white; text-align: center; padding: 8px 0;">\n <span>🚫 屏蔽</span>\n </a>\n <a id="favoriteBtn" class="menu-btn" style="width: 120px; background-color:#25b1dc; color: white; text-align: center; padding: 8px 0;">\n <span>⭐ 收藏</span>\n </a>\n <a id="hasDownBtn" class="menu-btn" style="width: 120px; background-color:#7bc73b; color: white; text-align: center; padding: 8px 0;">\n <span>📥️ 已下载</span>\n </a>\n <a id="hasWatchBtn" class="menu-btn" style="width: 120px; background-color:#d7a80c; color: white; text-align: center; padding: 8px 0;">\n <span>🔍 已观看</span>\n </a>\n </div>\n \n <div style="display: flex; gap: 10px; flex-wrap:wrap;">\n <a id="enable-magnets-filter" class="menu-btn" style="width: 140px; background-color: #c2bd4c; color: white; text-align: center; padding: 8px 0;">\n <span id="magnets-span">排序与过滤</span>\n </a>\n <a id="magnetSearchBtn" class="menu-btn" style="width: 120px; background: linear-gradient(to right, rgb(245,140,1), rgb(84,161,29)); color: white; text-align: center; padding: 8px 0;">\n <span>磁力搜索</span>\n </a>\n <a id="subtitleSearchBtn" class="menu-btn" style="width: 120px; background: linear-gradient(to left, #375f7c, #2196F3); color: white; text-align: center; padding: 8px 0;">\n <span>字幕搜索</span>\n </a>\n <!--\n <a id="xunLeiSubtitleBtn" class="menu-btn" style="width: 120px; background: linear-gradient(to left, #375f7c, #2196F3); color: white; text-align: center; padding: 8px 0;">\n <span>字幕 (迅雷)</span>\n </a>\n <a id="search-subtitle-btn" class="menu-btn" style="width: 160px; background: linear-gradient(to bottom, #8d5656, rgb(196,159,91)); color: white; text-align: center; padding: 8px 0;">\n <span>字幕 (SubTitleCat)</span>\n </a>\n -->\n </div>\n </div>\n ';
|
||||
buttonsHtml = '\n <div style="margin: 10px auto; display: flex; justify-content: space-between; align-items: center; flex-wrap:wrap;gap: 20px;">\n <div style="display: flex; gap: 10px; flex-wrap:wrap;">\n <a id="filterBtn" class="menu-btn" style="width: 120px; background-color:#de3333; color: white; text-align: center; padding: 8px 0;">\n <span>🚫 屏蔽</span>\n </a>\n <a id="favoriteBtn" class="menu-btn" style="width: 120px; background-color:#25b1dc; color: white; text-align: center; padding: 8px 0;">\n <span>⭐ 收藏</span>\n </a>\n <a id="hasDownBtn" class="menu-btn" style="width: 120px; background-color:#7bc73b; color: white; text-align: center; padding: 8px 0;">\n <span>📥️ 已下载</span>\n </a>\n <a id="hasWatchBtn" class="menu-btn" style="width: 120px; background-color:#d7a80c; color: white; text-align: center; padding: 8px 0;">\n <span>🔍 已观看</span>\n </a>\n </div>\n \n <div style="display: flex; gap: 10px; flex-wrap:wrap;">\n <a id="downloadCoverBtn" class="menu-btn" style="width: 140px; background-color: #9b59b6; color: white; text-align: center; padding: 8px 0;">\n <span>下载高清封面</span>\n </a>\n <a id="enable-magnets-filter" class="menu-btn" style="width: 140px; background-color: #c2bd4c; color: white; text-align: center; padding: 8px 0;">\n <span id="magnets-span">排序与过滤</span>\n </a>\n <a id="magnetSearchBtn" class="menu-btn" style="width: 120px; background: linear-gradient(to right, rgb(245,140,1), rgb(84,161,29)); color: white; text-align: center; padding: 8px 0;">\n <span>磁力搜索</span>\n </a>\n <a id="subtitleSearchBtn" class="menu-btn" style="width: 120px; background: linear-gradient(to left, #375f7c, #2196F3); color: white; text-align: center; padding: 8px 0;">\n <span>字幕搜索</span>\n </a>\n <!--\n <a id="xunLeiSubtitleBtn" class="menu-btn" style="width: 120px; background: linear-gradient(to left, #375f7c, #2196F3); color: white; text-align: center; padding: 8px 0;">\n <span>字幕 (迅雷)</span>\n </a>\n <a id="search-subtitle-btn" class="menu-btn" style="width: 160px; background: linear-gradient(to bottom, #8d5656, rgb(196,159,91)); color: white; text-align: center; padding: 8px 0;">\n <span>字幕 (SubTitleCat)</span>\n </a>\n -->\n </div>\n </div>\n ';
|
||||
isJavDb && $(".tabs").after(buttonsHtml);
|
||||
isJavBus && $("#mag-submit-show").before(buttonsHtml);
|
||||
$("#favoriteBtn").on("click", (() => this.favoriteOne()));
|
||||
@@ -87,6 +100,50 @@ class DetailPageButtonPlugin extends BasePlugin {
|
||||
$("#subtitleSearchBtn").on("click", (() => {
|
||||
window.JavPackSubtitle.openSearchModal({details: {code: carNum2}});
|
||||
}));
|
||||
$("#downloadCoverBtn").on("click", (async () => {
|
||||
if (!isEligibleDmmCoverCode(carNum2)) {
|
||||
show.error("当前番号不支持下载高清封面");
|
||||
return;
|
||||
}
|
||||
const $btn = $("#downloadCoverBtn");
|
||||
$btn.addClass("is-loading").prop("disabled", true);
|
||||
try {
|
||||
const coverUrl = await getCover(carNum2);
|
||||
if (!coverUrl) {
|
||||
show.error("未找到高清封面");
|
||||
return;
|
||||
}
|
||||
const fileName = `${carNum2}-cover.jpg`;
|
||||
GM_xmlhttpRequest({
|
||||
method: 'GET',
|
||||
url: coverUrl,
|
||||
responseType: 'blob',
|
||||
onload: (response) => {
|
||||
if (response.status === 200) {
|
||||
const blobUrl = URL.createObjectURL(response.response);
|
||||
const a = document.createElement('a');
|
||||
a.href = blobUrl;
|
||||
a.download = fileName;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(blobUrl);
|
||||
}, 100);
|
||||
show.ok("封面下载已开始");
|
||||
} else {
|
||||
show.error(`封面下载失败: ${response.status}`);
|
||||
}
|
||||
},
|
||||
onerror: () => show.error("封面下载网络错误"),
|
||||
ontimeout: () => show.error("封面下载超时"),
|
||||
});
|
||||
} catch (e) {
|
||||
show.error("获取封面信息失败");
|
||||
} finally {
|
||||
$btn.removeClass("is-loading").prop("disabled", false);
|
||||
}
|
||||
}));
|
||||
window.JavPackSubtitle.preload115Matches(carNum2);
|
||||
// $("#search-subtitle-btn").on("click", (event => utils.openPage(`https://subtitlecat.com/index.php?search=${carNum2}`, carNum2, !1, event)));
|
||||
// $("#xunLeiSubtitleBtn").on("click", (() => this.searchXunLeiSubtitle(carNum2)));
|
||||
|
||||
@@ -5,6 +5,13 @@ class FavoriteActressesPlugin extends BasePlugin {
|
||||
getName() {
|
||||
return "FavoriteActressesPlugin";
|
||||
}
|
||||
|
||||
async initCss() {
|
||||
const settingObj = await storageManager.getSetting();
|
||||
const tagNumber = settingObj.highlightedTagNumber || 1;
|
||||
const tagColor = settingObj.highlightedTagColor || "#ce2222";
|
||||
return `\n <style>\n .highlighted {\n border: ${tagNumber}px solid ${tagColor} !important;\n }\n </style>\n `;
|
||||
}
|
||||
async handle() {
|
||||
this.bindEvent();
|
||||
await this.highlightActress();
|
||||
|
||||
@@ -7,7 +7,10 @@ class FoldCategoryPlugin extends BasePlugin {
|
||||
}
|
||||
async initCss() {
|
||||
const settingObj = await storageManager.getSetting();
|
||||
return `\n <style>\n #tags a.tag, .tags a.tag {\n position:relative;\n }\n .highlight-btn {\n position: absolute;\n top: -10px;\n right: -10px;\n background-color: #4CAF50;\n color: white;\n border: none;\n border-radius: 50%;\n width: 24px;\n height: 24px;\n font-size: 14px;\n line-height: 24px;\n text-align: center;\n cursor: pointer;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n display: none;\n z-index: 999;\n }\n /* 当父元素被高亮时,按钮变为其他颜色 */\n .highlighted .highlight-btn {\n background-color: #FF5722;\n }\n /* 高亮状态下的标签样式 */\n .highlighted {\n /* 浅黄色 */\n border: ${settingObj.highlightedTagNumber || 1}px solid ${settingObj.highlightedTagColor || "#ce2222"};\n }\n </style>\n `;
|
||||
return `\n <style>\n #tags a.tag, .tags a.tag {\n position:relative;\n }\n .highlight-btn {\n position: absolute;\n top: -10px;\n right: -10px;\n background-color: #4CAF50;\n color: white;\n border: none;\n border-radius: 50%;\n width: 24px;\n height: 24px;\n font-size: 14px;\n line-height: 24px;\n text-align: center;\n cursor: pointer;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n display: none;\n z-index: 999;\n }\n /* 当父元素被高亮时,按钮变为其他颜色 */\n .highlighted .highlight-btn {\n background-color: #FF5722;\n }\n /* 高亮状态下的标签样式 */\n .highlighted {
|
||||
/* 浅黄色 */
|
||||
border: ${settingObj.highlightedTagNumber || 1}px solid ${settingObj.highlightedTagColor || "#ce2222"} !important;
|
||||
}\n </style>\n `;
|
||||
}
|
||||
async handle() {
|
||||
if (window.isListPage && !currentHref.includes("advanced_search")) {
|
||||
@@ -82,4 +85,4 @@ class FoldCategoryPlugin extends BasePlugin {
|
||||
}
|
||||
|
||||
|
||||
export { FoldCategoryPlugin };
|
||||
export { FoldCategoryPlugin };
|
||||
@@ -222,7 +222,9 @@ class HistoryPlugin extends BasePlugin {
|
||||
ajaxURL: "queryRealm",
|
||||
dataLoader: !1,
|
||||
ajaxRequestFunc: async (url, ajaxConfig, params) => {
|
||||
const page = params.page, size = params.size, sort = params.sort;
|
||||
const page = (null == params ? void 0 : params.page) || 1,
|
||||
size = (null == params ? void 0 : params.size) || 50,
|
||||
sort = (null == params ? void 0 : params.sort) || [];
|
||||
return await this.getDataList(page, size, sort);
|
||||
},
|
||||
dataReceiveParams: {
|
||||
@@ -476,4 +478,4 @@ class HistoryPlugin extends BasePlugin {
|
||||
}
|
||||
|
||||
|
||||
export { HistoryPlugin };
|
||||
export { HistoryPlugin };
|
||||
@@ -14,7 +14,7 @@ class HitShowPlugin extends BasePlugin {
|
||||
$('a[href*="rankings/playback"]').on("click", (event => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
window.location.href = "/advanced_search?handlePlayback=1&period=daily";
|
||||
window.location.href = "/rankings/playback";
|
||||
}));
|
||||
this.handlePlayback().then();
|
||||
}
|
||||
@@ -29,7 +29,7 @@ class HitShowPlugin extends BasePlugin {
|
||||
this.$contentBox.append('<div class="movie-list h cols-4 vcols-8" style="margin-top: 10px"></div>');
|
||||
}
|
||||
async handlePlayback() {
|
||||
if (!window.location.href.includes("handlePlayback=1")) return;
|
||||
if (!window.location.href.includes("rankings/playback")) return;
|
||||
let period = new URLSearchParams(window.location.search).get("period");
|
||||
this.toolBar(period);
|
||||
this.hookPage();
|
||||
@@ -40,6 +40,7 @@ class HitShowPlugin extends BasePlugin {
|
||||
const movies = await javDbApi.playback(period);
|
||||
let moviesHtml = javDbApi.markDataListHtml(movies);
|
||||
$movieBox.html(moviesHtml);
|
||||
this.pluginManager.getBean("ListPagePlugin").doFilter();
|
||||
} catch (e) {
|
||||
clog.error("发生错误:", e);
|
||||
} finally {
|
||||
@@ -47,7 +48,7 @@ class HitShowPlugin extends BasePlugin {
|
||||
}
|
||||
}
|
||||
toolBar(period) {
|
||||
let conditionHtml = `\n <div class="button-group" style="margin-top:18px">\n <div class="buttons has-addons" id="conditionBox">\n <a style="padding:18px 18px !important;" class="button is-small ${"daily" === period ? "is-info" : ""}" href="/advanced_search?handlePlayback=1&period=daily">日榜</a>\n <a style="padding:18px 18px !important;" class="button is-small ${"weekly" === period ? "is-info" : ""}" href="/advanced_search?handlePlayback=1&period=weekly">周榜</a>\n <a style="padding:18px 18px !important;" class="button is-small ${"monthly" === period ? "is-info" : ""}" href="/advanced_search?handlePlayback=1&period=monthly">月榜</a>\n </div>\n </div>\n `;
|
||||
let conditionHtml = `\n <div class="button-group" style="margin-top:18px">\n <div class="buttons has-addons" id="conditionBox">\n <a style="padding:18px 18px !important;" class="button is-small ${"daily" === period ? "is-info" : ""}" href="/rankings/playback?period=daily">日榜</a>\n <a style="padding:18px 18px !important;" class="button is-small ${"weekly" === period ? "is-info" : ""}" href="/rankings/playback?period=weekly">周榜</a>\n <a style="padding:18px 18px !important;" class="button is-small ${"monthly" === period ? "is-info" : ""}" href="/rankings/playback?period=monthly">月榜</a>\n </div>\n </div>\n `;
|
||||
this.$contentBox.append(conditionHtml);
|
||||
}
|
||||
getStarRating(score) {
|
||||
|
||||
@@ -162,10 +162,17 @@ class ImageRecognitionPlugin extends BasePlugin {
|
||||
type: mimeType
|
||||
}), formData = new FormData;
|
||||
formData.append("image", blob);
|
||||
const idKey = "jhs_imgurClientId";
|
||||
let clientId = localStorage.getItem(idKey);
|
||||
if (!clientId) {
|
||||
clientId = window.prompt("请输入您自己的Imgur Client-ID(可前往 https://api.imgur.com/oauth2/addclient 免费申请)用于图片上传搜索:");
|
||||
if (!clientId) throw new Error("未提供Imgur Client-ID,无法上传图片");
|
||||
localStorage.setItem(idKey, clientId);
|
||||
}
|
||||
const response = await fetch("https://api.imgur.com/3/image", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: "Client-ID d70305e7c3ac5c6"
|
||||
Authorization: `Client-ID ${clientId}`
|
||||
},
|
||||
body: formData
|
||||
}), data = await response.json();
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import {BasePlugin} from '../core/base-plugin.js';
|
||||
import {__publicField, isJavBus, isJavDb, qualityOptions} from '../core/constants.js';
|
||||
import {isM3U8Url, attachHlsToVideo, destroyHls, loadHlsLibrary, getHlsClass} from '../lib/hls-runtime.js';
|
||||
import {getJavxyVideoUrls} from '../api/javxy.js';
|
||||
import {getTrailer} from '../api/dmmrsc.js';
|
||||
|
||||
class JavxyPreviewVideoPlugin extends BasePlugin {
|
||||
class JavopenPreviewVideoPlugin extends BasePlugin {
|
||||
getName() {
|
||||
return "JavxyPreviewVideoPlugin";
|
||||
return "JavopenPreviewVideoPlugin";
|
||||
}
|
||||
|
||||
_attachVideoSrc(videoEl, src) {
|
||||
@@ -17,20 +17,13 @@ class JavxyPreviewVideoPlugin extends BasePlugin {
|
||||
if (HlsClass) {
|
||||
attachHlsToVideo(videoEl, src).catch((err) => {
|
||||
clog.error('视频预览 HLS 加载失败:', err);
|
||||
videoEl.src = src;
|
||||
videoEl.load && videoEl.load();
|
||||
});
|
||||
} else {
|
||||
loadHlsLibrary().then((HlsClass) => {
|
||||
if (videoEl && videoEl.isConnected && HlsClass) {
|
||||
attachHlsToVideo(videoEl, src).catch((err) => {
|
||||
clog.error('视频预览 HLS 延迟加载失败:', err);
|
||||
videoEl.src = src;
|
||||
videoEl.load && videoEl.load();
|
||||
});
|
||||
} else if (videoEl && videoEl.isConnected) {
|
||||
videoEl.src = src;
|
||||
videoEl.load && videoEl.load();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -51,38 +44,38 @@ class JavxyPreviewVideoPlugin extends BasePlugin {
|
||||
|
||||
async initCss() {
|
||||
return `
|
||||
.jhs-javxy-video-modal {
|
||||
.jhs-javopen-video-modal {
|
||||
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
|
||||
background: rgba(0,0,0,0.95); z-index: 12345700;
|
||||
display: flex; justify-content: center; align-items: center;
|
||||
opacity: 0; visibility: hidden; transition: opacity 0.2s;
|
||||
}
|
||||
.jhs-javxy-video-modal.is-open { opacity: 1; visibility: visible; }
|
||||
.jhs-javxy-video-modal-inner {
|
||||
.jhs-javopen-video-modal.is-open { opacity: 1; visibility: visible; }
|
||||
.jhs-javopen-video-modal-inner {
|
||||
display: flex; flex-direction: column; align-items: center;
|
||||
gap: 12px; max-width: 90vw; max-height: 90vh;
|
||||
}
|
||||
.jhs-javxy-video-wrapper {
|
||||
.jhs-javopen-video-wrapper {
|
||||
width: 80vw; max-height: 80vh; aspect-ratio: 16/9;
|
||||
background: #000; position: relative;
|
||||
}
|
||||
.jhs-javxy-video-wrapper video {
|
||||
.jhs-javopen-video-wrapper video {
|
||||
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
|
||||
}
|
||||
.jhs-javxy-quality-bar {
|
||||
.jhs-javopen-quality-bar {
|
||||
display: flex; gap: 8px; flex-wrap: wrap; justify-content: center;
|
||||
}
|
||||
.jhs-javxy-quality-btn {
|
||||
.jhs-javopen-quality-btn {
|
||||
min-width: 60px; padding: 5px 10px; font-size: 13px;
|
||||
background: rgba(255,255,255,0.2); color: #fff;
|
||||
border: 1px solid rgba(255,255,255,0.5); border-radius: 4px;
|
||||
cursor: pointer; transition: background 0.2s;
|
||||
}
|
||||
.jhs-javxy-quality-btn:hover { background: rgba(255,255,255,0.4); }
|
||||
.jhs-javxy-quality-btn.active {
|
||||
.jhs-javopen-quality-btn:hover { background: rgba(255,255,255,0.4); }
|
||||
.jhs-javopen-quality-btn.active {
|
||||
background: #1890ff; border-color: #096dd9; font-weight: bold;
|
||||
}
|
||||
.jhs-javxy-loading {
|
||||
.jhs-javopen-loading {
|
||||
color: #fff; font-size: 16px; text-align: center;
|
||||
}
|
||||
`;
|
||||
@@ -94,10 +87,10 @@ class JavxyPreviewVideoPlugin extends BasePlugin {
|
||||
const carNum = this.getPageInfo().carNum;
|
||||
if (!carNum) return;
|
||||
|
||||
this._addJavxyButton(carNum);
|
||||
this._addJavopenButton(carNum);
|
||||
}
|
||||
|
||||
_addJavxyButton(carNum) {
|
||||
_addJavopenButton(carNum) {
|
||||
let $target = null;
|
||||
|
||||
if (isJavDb) {
|
||||
@@ -128,7 +121,7 @@ class JavxyPreviewVideoPlugin extends BasePlugin {
|
||||
e.stopPropagation();
|
||||
$btn.css("pointer-events", "none").find("span").text("...");
|
||||
try {
|
||||
await this._openJavxyPlayer(carNum);
|
||||
await this._openJavopenPlayer(carNum);
|
||||
} finally {
|
||||
$btn.css("pointer-events", "").find("span").text("视频预览");
|
||||
}
|
||||
@@ -136,23 +129,23 @@ class JavxyPreviewVideoPlugin extends BasePlugin {
|
||||
$target.after($btn);
|
||||
}
|
||||
|
||||
async _openJavxyPlayer(carNum) {
|
||||
if ($("#jhs-javxy-video-modal").length === 0) {
|
||||
async _openJavopenPlayer(carNum) {
|
||||
if ($("#jhs-javopen-video-modal").length === 0) {
|
||||
$("body").append(`
|
||||
<div id="jhs-javxy-video-modal" class="jhs-javxy-video-modal">
|
||||
<div class="jhs-javxy-video-modal-inner">
|
||||
<div class="jhs-javxy-video-wrapper">
|
||||
<video id="jhs-javxy-video" controls playsinline></video>
|
||||
<div id="jhs-javopen-video-modal" class="jhs-javopen-video-modal">
|
||||
<div class="jhs-javopen-video-modal-inner">
|
||||
<div class="jhs-javopen-video-wrapper">
|
||||
<video id="jhs-javopen-video" controls playsinline></video>
|
||||
</div>
|
||||
<div class="jhs-javxy-quality-bar"></div>
|
||||
<div class="jhs-javopen-quality-bar"></div>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
const $modal = $("#jhs-javxy-video-modal");
|
||||
const $modal = $("#jhs-javopen-video-modal");
|
||||
$modal.on("click", (e) => {
|
||||
if (e.target.id === "jhs-javxy-video-modal") {
|
||||
if (e.target.id === "jhs-javopen-video-modal") {
|
||||
$modal.removeClass("is-open");
|
||||
const videoEl = document.getElementById("jhs-javxy-video");
|
||||
const videoEl = document.getElementById("jhs-javopen-video");
|
||||
if (videoEl) {
|
||||
destroyHls(videoEl);
|
||||
videoEl.pause();
|
||||
@@ -162,7 +155,7 @@ class JavxyPreviewVideoPlugin extends BasePlugin {
|
||||
$(document).on("keydown", (e) => {
|
||||
if (e.key === "Escape" && $modal.hasClass("is-open")) {
|
||||
$modal.removeClass("is-open");
|
||||
const videoEl = document.getElementById("jhs-javxy-video");
|
||||
const videoEl = document.getElementById("jhs-javopen-video");
|
||||
if (videoEl) {
|
||||
destroyHls(videoEl);
|
||||
videoEl.pause();
|
||||
@@ -171,23 +164,23 @@ class JavxyPreviewVideoPlugin extends BasePlugin {
|
||||
});
|
||||
}
|
||||
|
||||
const $modal = $("#jhs-javxy-video-modal");
|
||||
const $wrapper = $modal.find(".jhs-javxy-video-wrapper");
|
||||
const $qualityBar = $modal.find(".jhs-javxy-quality-bar");
|
||||
$wrapper.html('<div class="jhs-javxy-loading">视频预览加载中...</div>');
|
||||
const $modal = $("#jhs-javopen-video-modal");
|
||||
const $wrapper = $modal.find(".jhs-javopen-video-wrapper");
|
||||
const $qualityBar = $modal.find(".jhs-javopen-quality-bar");
|
||||
$wrapper.html('<div class="jhs-javopen-loading">视频预览加载中...</div>');
|
||||
$qualityBar.empty();
|
||||
$modal.addClass("is-open");
|
||||
|
||||
let videoMap = null;
|
||||
try {
|
||||
videoMap = await getJavxyVideoUrls(carNum);
|
||||
videoMap = await getTrailer(carNum);
|
||||
} catch (err) {
|
||||
$wrapper.html(`<div class="jhs-javxy-loading">视频预览请求失败: ${err.message}</div>`);
|
||||
$wrapper.html(`<div class="jhs-javopen-loading">视频预览请求失败: ${err.message}</div>`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!videoMap || Object.keys(videoMap).length === 0) {
|
||||
$wrapper.html('<div class="jhs-javxy-loading">未找到可用的视频源</div>');
|
||||
$wrapper.html('<div class="jhs-javopen-loading">未找到可用的视频源</div>');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -195,10 +188,10 @@ class JavxyPreviewVideoPlugin extends BasePlugin {
|
||||
const defaultQuality = this._selectDefaultQuality(qualityList, '720p');
|
||||
const defaultUrl = videoMap[defaultQuality];
|
||||
|
||||
$wrapper.html(`<video id="jhs-javxy-video" controls playsinline>
|
||||
$wrapper.html(`<video id="jhs-javopen-video" controls playsinline>
|
||||
<source src="${defaultUrl}" />
|
||||
</video>`);
|
||||
const videoEl = document.getElementById("jhs-javxy-video");
|
||||
const videoEl = document.getElementById("jhs-javopen-video");
|
||||
if (!videoEl) return;
|
||||
|
||||
if (isM3U8Url(defaultUrl)) {
|
||||
@@ -209,13 +202,13 @@ class JavxyPreviewVideoPlugin extends BasePlugin {
|
||||
qualityOptions.forEach((option) => {
|
||||
const url = videoMap[option.quality];
|
||||
if (url) {
|
||||
buttonsHtml += `<button class="jhs-javxy-quality-btn${option.quality === defaultQuality ? ' active' : ''}"
|
||||
buttonsHtml += `<button class="jhs-javopen-quality-btn${option.quality === defaultQuality ? ' active' : ''}"
|
||||
data-quality="${option.quality}" data-video-src="${url}">${option.text}</button>`;
|
||||
}
|
||||
});
|
||||
$qualityBar.html(buttonsHtml);
|
||||
|
||||
$qualityBar.off("click").on("click", ".jhs-javxy-quality-btn", (e) => {
|
||||
$qualityBar.off("click").on("click", ".jhs-javopen-quality-btn", (e) => {
|
||||
const $btn = $(e.currentTarget);
|
||||
if ($btn.hasClass("active")) return;
|
||||
const src = $btn.attr("data-video-src");
|
||||
@@ -228,7 +221,7 @@ class JavxyPreviewVideoPlugin extends BasePlugin {
|
||||
}
|
||||
videoEl.play().catch(() => {
|
||||
});
|
||||
$qualityBar.find(".jhs-javxy-quality-btn").removeClass("active");
|
||||
$qualityBar.find(".jhs-javopen-quality-btn").removeClass("active");
|
||||
$btn.addClass("active");
|
||||
});
|
||||
|
||||
@@ -236,4 +229,4 @@ class JavxyPreviewVideoPlugin extends BasePlugin {
|
||||
}
|
||||
}
|
||||
|
||||
export {JavxyPreviewVideoPlugin};
|
||||
export {JavopenPreviewVideoPlugin};
|
||||
@@ -151,7 +151,20 @@ class ListPagePlugin extends BasePlugin {
|
||||
await Promise.all(movieList.map((async ele => {
|
||||
let $box2 = $(ele);
|
||||
if (isJavBus && $box2.find(".avatar-box").length > 0) return;
|
||||
const {carNum: carNum2, title: title} = this.getBoxCarInfo($box2), {filter: filter, favorite: favorite, hasDown: hasDown, hasWatch: hasWatch} = carNumSets, isFavorite = favorite.has(carNum2), isHasDown = hasDown.has(carNum2), isHasWatch = hasWatch.has(carNum2), isFiltered = filter.has(carNum2), isFilterActorMale = actorCarNumToNameMap.has(carNum2), isFilterActorFemale = actressCarNumToNameMap.has(carNum2), isFilterActor = isFilterActorMale || isFilterActorFemale, foundKeyword = filterKeywordList.find((kw => title.includes(kw) || carNum2.startsWith(kw))), isFilterKeyword = !!foundKeyword;
|
||||
const boxInfo = this.getBoxCarInfo($box2);
|
||||
if (!boxInfo) return;
|
||||
const {carNum: carNum2, title: title} = boxInfo, {
|
||||
filter: filter,
|
||||
favorite: favorite,
|
||||
hasDown: hasDown,
|
||||
hasWatch: hasWatch
|
||||
} = carNumSets, isFavorite = favorite.has(carNum2), isHasDown = hasDown.has(carNum2),
|
||||
isHasWatch = hasWatch.has(carNum2), isFiltered = filter.has(carNum2),
|
||||
isFilterActorMale = actorCarNumToNameMap.has(carNum2),
|
||||
isFilterActorFemale = actressCarNumToNameMap.has(carNum2),
|
||||
isFilterActor = isFilterActorMale || isFilterActorFemale,
|
||||
foundKeyword = filterKeywordList.find((kw => title.includes(kw) || carNum2.startsWith(kw))),
|
||||
isFilterKeyword = !!foundKeyword;
|
||||
if (!isSearchPage) {
|
||||
let shouldHide = settings.showFavoriteItem === NO && isFavorite || settings.showHasDownItem === NO && isHasDown || settings.showHasWatchItem === NO && isHasWatch || settings.showFilterItem === NO && isFiltered && !(isFavorite || isHasDown || isHasWatch) || settings.showFilterActorItem === NO && isFilterActor || settings.showFilterKeywordItem === NO && isFilterKeyword;
|
||||
if ($box2.attr("data-movieShowType") !== settings.movieShowType) {
|
||||
|
||||
@@ -580,6 +580,8 @@ class MagnetHubPlugin extends BasePlugin {
|
||||
}
|
||||
|
||||
searchEngine($container, $sortSelect, engine, keyword) {
|
||||
this.currentEngine = engine;
|
||||
this.currentKeyword = keyword;
|
||||
$container.html(`<div class="magnet-loading">正在从 ${engine.name} 搜索 "${keyword}"...</div>`);
|
||||
const cacheKey = `${engine.name}_${keyword}`;
|
||||
sessionStorage.getItem(cacheKey);
|
||||
@@ -597,11 +599,11 @@ class MagnetHubPlugin extends BasePlugin {
|
||||
$sortSelect.prop("disabled", results.length === 0);
|
||||
this.displayResults($container, results, engine.name);
|
||||
} catch (e) {
|
||||
$container.html(`<div class="magnet-error">解析 ${engine.name} 结果失败: ${e.message}</div>`);
|
||||
this.showError($container, `解析 ${engine.name} 结果失败: ${e.message}`);
|
||||
}
|
||||
},
|
||||
onerror: error => {
|
||||
$container.html(`<div class="magnet-error">从 ${engine.name} 获取数据失败: ${error.statusText}</div>`);
|
||||
this.showError($container, `从 ${engine.name} 获取数据失败: ${error.statusText}`);
|
||||
}
|
||||
}));
|
||||
}
|
||||
@@ -611,6 +613,15 @@ class MagnetHubPlugin extends BasePlugin {
|
||||
}));
|
||||
}
|
||||
|
||||
showError($container, message) {
|
||||
$container.html(`<div class="magnet-error">${message} <a id="retrySearch" href="#">🔄 刷新</a></div>`);
|
||||
const $select = $container.closest(".magnet-container").find(".magnet-sort-select");
|
||||
$container.find("#retrySearch").on("click", (e => {
|
||||
e.preventDefault();
|
||||
this.searchEngine($container, $select, this.currentEngine, this.currentKeyword);
|
||||
}));
|
||||
}
|
||||
|
||||
displayResults($container, results, engineName) {
|
||||
$container.empty();
|
||||
const sortMode = localStorage.getItem("jhs_magnetSort") || "size";
|
||||
@@ -1000,11 +1011,11 @@ class MagnetHubPlugin extends BasePlugin {
|
||||
$sortSelect.prop("disabled", results.length === 0);
|
||||
_this.displayResults($container, results, engine.name);
|
||||
} catch (e) {
|
||||
$container.html(`<div class="magnet-error">解析 ${engine.name} 结果失败: ${e.message}</div>`);
|
||||
_this.showError($container, `解析 ${engine.name} 结果失败: ${e.message}`);
|
||||
}
|
||||
},
|
||||
onerror: error => {
|
||||
$container.html(`<div class="magnet-error">从 ${engine.name} 获取数据失败: ${error.statusText}</div>`);
|
||||
_this.showError($container, `从 ${engine.name} 获取数据失败: ${error.statusText}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+16
-2
File diff suppressed because one or more lines are too long
+19
-6
@@ -29,6 +29,9 @@ class TOP250Plugin extends BasePlugin {
|
||||
$("h2.section-title").contents().first().replaceWith("Top250");
|
||||
$(".empty-message").remove();
|
||||
$(".section .container .box").remove();
|
||||
$(".section .container .movie-list").remove();
|
||||
$(".section .container .pagination").remove();
|
||||
$(".section .container select").remove();
|
||||
$("#sort-toggle-btn").remove();
|
||||
this.$contentBox.append('<div class="tool-box" style="margin-top: 10px"></div>');
|
||||
this.$contentBox.append('<div class="movie-list h cols-4 vcols-8" style="margin-top: 10px"></div>');
|
||||
@@ -56,9 +59,16 @@ class TOP250Plugin extends BasePlugin {
|
||||
}));
|
||||
}
|
||||
async handleTop() {
|
||||
if (!window.location.href.includes("handleTop=1")) return;
|
||||
if (!window.location.href.includes("/rankings/top")) return;
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
let type = urlParams.get("handleType") || "all", type_value = urlParams.get("type_value") || "";
|
||||
let t = urlParams.get("t") || "", type = "all", type_value = "";
|
||||
if (/^y\d+$/.test(t)) {
|
||||
type = "year";
|
||||
type_value = t.substring(1);
|
||||
} else if ("" !== t) {
|
||||
type = "video_type";
|
||||
type_value = t;
|
||||
}
|
||||
this.has_cnsub = urlParams.get("has_cnsub") || "";
|
||||
let page = urlParams.get("page") || 1;
|
||||
this.toolBar(type, type_value, page);
|
||||
@@ -80,6 +90,7 @@ class TOP250Plugin extends BasePlugin {
|
||||
const filter_movies = dataList.filter((item => "1" === this.has_cnsub ? item.has_cnsub : "0" !== this.has_cnsub || !item.has_cnsub));
|
||||
let moviesHtml = javDbApi.markDataListHtml(filter_movies);
|
||||
$movieBox.html(moviesHtml);
|
||||
this.pluginManager.getBean("ListPagePlugin").doFilter();
|
||||
} else {
|
||||
clog.error(res);
|
||||
$movieBox.html(`<h3>${message}</h3>`);
|
||||
@@ -101,9 +112,10 @@ class TOP250Plugin extends BasePlugin {
|
||||
$(".pagination-list li a").each((function() {
|
||||
parseInt($(this).text()) > 5 && $(this).closest("li").remove();
|
||||
}));
|
||||
const currentTParam = "all" === type ? "" : "year" === type ? `y${type_value}` : type_value;
|
||||
let yearHtml = "";
|
||||
for (let year = (new Date).getFullYear(); year >= 2008; year--) yearHtml += `\n <a style="padding:18px 18px !important;" \n class="button is-small ${type_value === year.toString() ? "is-info" : ""}" \n href="/advanced_search?handleTop=1&handleType=year&type_value=${year}&has_cnsub=${this.has_cnsub}">\n ${year}\n </a>\n `;
|
||||
let conditionHtml = `\n <div class="button-group">\n <div class="buttons has-addons" id="conditionBox" style="margin-bottom: 0!important;">\n <a style="padding:18px 18px !important;" class="button is-small ${"all" === type ? "is-info" : ""}" href="/advanced_search?handleTop=1&handleType=all&type_value=&has_cnsub=${this.has_cnsub}">全部</a>\n <a style="padding:18px 18px !important;" class="button is-small ${"0" === type_value ? "is-info" : ""}" href="/advanced_search?handleTop=1&handleType=video_type&type_value=0&has_cnsub=${this.has_cnsub}">有码</a>\n <a style="padding:18px 18px !important;" class="button is-small ${"1" === type_value ? "is-info" : ""}" href="/advanced_search?handleTop=1&handleType=video_type&type_value=1&has_cnsub=${this.has_cnsub}">无码</a>\n <a style="padding:18px 18px !important;" class="button is-small ${"2" === type_value ? "is-info" : ""}" href="/advanced_search?handleTop=1&handleType=video_type&type_value=2&has_cnsub=${this.has_cnsub}">欧美</a>\n <a style="padding:18px 18px !important;" class="button is-small ${"3" === type_value ? "is-info" : ""}" href="/advanced_search?handleTop=1&handleType=video_type&type_value=3&has_cnsub=${this.has_cnsub}">Fc2</a>\n \n <a style="padding:18px 18px !important;margin-left: 50px" class="button is-small ${"1" === this.has_cnsub ? "is-info" : ""}" data-cnsub-value="1">含中字磁鏈</a>\n <a style="padding:18px 18px !important;" class="button is-small ${"0" === this.has_cnsub ? "is-info" : ""}" data-cnsub-value="0">无字幕</a>\n <a style="padding:18px 18px !important;" class="button is-small" data-cnsub-value="">重置</a>\n </div>\n \n <div class="buttons has-addons" id="conditionBox">\n ${yearHtml}\n </div>\n </div>\n `;
|
||||
for (let year = (new Date).getFullYear(); year >= 2008; year--) yearHtml += `\n <a style="padding:18px 18px !important;" \n class="button is-small ${type_value === year.toString() ? "is-info" : ""}" \n href="/rankings/top?t=y${year}&has_cnsub=${this.has_cnsub}">\n ${year}\n </a>\n `;
|
||||
let conditionHtml = `\n <div class="button-group">\n <div class="buttons has-addons" id="conditionBox" style="margin-bottom: 0!important;">\n <a style="padding:18px 18px !important;" class="button is-small ${"all" === type ? "is-info" : ""}" href="/rankings/top?has_cnsub=${this.has_cnsub}">全部</a>\n <a style="padding:18px 18px !important;" class="button is-small ${"0" === type_value ? "is-info" : ""}" href="/rankings/top?t=0&has_cnsub=${this.has_cnsub}">有码</a>\n <a style="padding:18px 18px !important;" class="button is-small ${"1" === type_value ? "is-info" : ""}" href="/rankings/top?t=1&has_cnsub=${this.has_cnsub}">无码</a>\n <a style="padding:18px 18px !important;" class="button is-small ${"2" === type_value ? "is-info" : ""}" href="/rankings/top?t=2&has_cnsub=${this.has_cnsub}">欧美</a>\n <a style="padding:18px 18px !important;" class="button is-small ${"3" === type_value ? "is-info" : ""}" href="/rankings/top?t=3&has_cnsub=${this.has_cnsub}">Fc2</a>\n \n <a style="padding:18px 18px !important;margin-left: 50px" class="button is-small ${"1" === this.has_cnsub ? "is-info" : ""}" data-cnsub-value="1">含中字磁鏈</a>\n <a style="padding:18px 18px !important;" class="button is-small ${"0" === this.has_cnsub ? "is-info" : ""}" data-cnsub-value="0">无字幕</a>\n <a style="padding:18px 18px !important;" class="button is-small" data-cnsub-value="">重置</a>\n </div>\n \n <div class="buttons has-addons" id="conditionBox">\n ${yearHtml}\n </div>\n </div>\n `;
|
||||
this.$contentBox.append(conditionHtml);
|
||||
$("a[data-cnsub-value]").on("click", (event => {
|
||||
const cnsubValue = $(event.currentTarget).data("cnsub-value");
|
||||
@@ -134,7 +146,8 @@ class TOP250Plugin extends BasePlugin {
|
||||
type = "video_type";
|
||||
type_value = t;
|
||||
}
|
||||
let url = `/advanced_search?handleTop=1&handleType=${type}&type_value=${type_value}`;
|
||||
let tParam = "year" === type ? `y${type_value}` : "all" === type ? "" : type_value;
|
||||
let url = `/rankings/top${tParam ? `?t=${tParam}` : ""}`;
|
||||
event && (event.ctrlKey || event.metaKey) ? GM_openInTab(window.location.origin + url, {
|
||||
insert: 0
|
||||
}) : window.location.href = url;
|
||||
@@ -167,7 +180,7 @@ class TOP250Plugin extends BasePlugin {
|
||||
await localStorage.setItem("jhs_appAuthorization", token);
|
||||
show.ok("登录成功");
|
||||
layer.close(index);
|
||||
window.location.href = "/advanced_search?handleTop=1&period=daily";
|
||||
window.location.href = "/rankings/top";
|
||||
}
|
||||
}
|
||||
})).catch((err => {
|
||||
|
||||
@@ -18,30 +18,49 @@ class WangPan115TaskPlugin extends BasePlugin {
|
||||
}
|
||||
async handle() {
|
||||
$(".buttons button[data-clipboard-text*='magnet:']").each(((i, el) => {
|
||||
$(el).parent().append($("<button>").text("115离线下载").addClass("button is-info is-small").click((async event => {
|
||||
const $copyBtn = $(el);
|
||||
const magnet = $copyBtn.attr("data-clipboard-text");
|
||||
$copyBtn.css("margin-right", (parseInt($copyBtn.css("margin-right")) - 4) + "px");
|
||||
const $downloadBtn = $copyBtn.siblings("a.button, button").first();
|
||||
if ($downloadBtn.length) {
|
||||
$downloadBtn.css("margin-right", (parseInt($downloadBtn.css("margin-right")) + 3) + "px");
|
||||
}
|
||||
$("<button>").text("验车").addClass("button is-small").attr("style", "background-color:#2b6cb0 !important;color:#fff !important;border:none !important;cursor:pointer;border-radius:4px;font-size:12px;padding:2px 8px;").click((event => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
this.getBean("MagnetHubPlugin").checkWhatslink(magnet);
|
||||
})).appendTo($copyBtn.parent());
|
||||
$("<button>").text("115离线下载").addClass("button is-small").attr("style", "background-color:#4a90e2 !important;color:#fff !important;border:none !important;cursor:pointer;border-radius:4px;font-size:12px;padding:2px 8px;").click((async event => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
let loadObj = loading();
|
||||
try {
|
||||
await this.handleAddTask($(el).attr("data-clipboard-text"));
|
||||
await this.handleAddTask(magnet);
|
||||
} catch (e) {
|
||||
show.error("发生错误:" + e);
|
||||
console.error(e);
|
||||
} finally {
|
||||
loadObj.close();
|
||||
}
|
||||
})));
|
||||
})).appendTo($copyBtn.parent());
|
||||
}));
|
||||
isJavBus && window.isDetailPage && utils.loopDetector((() => $("#magnet-table td a").length > 0), (() => {
|
||||
this.bus115Down();
|
||||
}));
|
||||
}
|
||||
async bus115Down() {
|
||||
const $headerRow = $("#magnet-table tr").first();
|
||||
$("#magnet-table tr").each(((i, row) => {
|
||||
if (row === $headerRow[0]) return;
|
||||
const magnetLink = $(row).find("td:nth-child(1) a").attr("href");
|
||||
if (magnetLink && magnetLink.includes("magnet:")) {
|
||||
const actionCell = $("<td>").addClass("action-cell");
|
||||
$("<button>").text("115离线下载").addClass("button is-info is-small").click((async event => {
|
||||
$("<button>").text("验车").addClass("button is-small").attr("style", "background-color:#2b6cb0 !important;color:#fff !important;border:none !important;margin-right:4px;cursor:pointer;border-radius:4px;font-size:12px;padding:2px 8px;").click((event => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
this.getBean("MagnetHubPlugin").checkWhatslink(magnetLink);
|
||||
})).appendTo(actionCell);
|
||||
$("<button>").text("115离线下载").addClass("button is-small").attr("style", "background-color:#4a90e2 !important;color:#fff !important;border:none !important;cursor:pointer;border-radius:4px;font-size:12px;padding:2px 8px;").click((async event => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
let loadObj = loading();
|
||||
@@ -57,9 +76,109 @@ class WangPan115TaskPlugin extends BasePlugin {
|
||||
$(row).append(actionCell);
|
||||
}
|
||||
}));
|
||||
$("#magnet-table tbody").length > 0 && $("#magnet-table tbody tr").append($("<td>").text("操作"));
|
||||
if ($headerRow.find("td, th").last().text().trim() !== "操作") {
|
||||
$headerRow.append($("<td>").text("操作"));
|
||||
}
|
||||
}
|
||||
|
||||
static sanitizeDirName(str) {
|
||||
if (!str) return "";
|
||||
return str.replace(/[\\/:*?"<>|]/g, "").replace(/\s+/g, " ").trim();
|
||||
}
|
||||
|
||||
static parseOfflineDirTemplate(str, params) {
|
||||
if (!str || !params) return str;
|
||||
return str.replace(/\$\{(\w+)\}/g, (match, key) => {
|
||||
if (!params.hasOwnProperty(key)) return match;
|
||||
const value = params[key] || "";
|
||||
return WangPan115TaskPlugin.sanitizeDirName(String(value));
|
||||
});
|
||||
}
|
||||
|
||||
static async ensureDir(dirName, pid = 0) {
|
||||
const result = await gmHttp.postFileFormData("https://webapi.115.com/files/add", {
|
||||
pid: pid,
|
||||
cname: dirName
|
||||
});
|
||||
if (result && result.file_id) return result.file_id;
|
||||
const searchRes = await searchFiles(dirName, 0, 1, {fc: 1});
|
||||
if (searchRes && searchRes.data && searchRes.data.length > 0) {
|
||||
const match = searchRes.data.find(d => d.pid === pid || d.pid === String(pid));
|
||||
if (match) return match.fid || match.file_id;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static async registerDirAsDownPath(fileId, dirName) {
|
||||
await gmHttp.postFileFormData("https://webapi.115.com/offine/downpath", {
|
||||
file_id: fileId
|
||||
});
|
||||
const list = await getDownPathList();
|
||||
const created = list ? list.find(d => d.file_id === fileId || String(d.file_id) === String(fileId)) : null;
|
||||
return created ? created.id : null;
|
||||
}
|
||||
|
||||
static async createMultiLevelDownPath(templatePath) {
|
||||
const segments = templatePath.split("/").filter(s => s.trim());
|
||||
if (segments.length === 0) return null;
|
||||
let pid = 0;
|
||||
let fileId = null;
|
||||
for (const seg of segments) {
|
||||
fileId = await WangPan115TaskPlugin.ensureDir(seg.trim(), pid);
|
||||
if (!fileId) {
|
||||
console.error("[115离线] 创建目录失败:", seg);
|
||||
return null;
|
||||
}
|
||||
pid = fileId;
|
||||
}
|
||||
const lastDirName = segments[segments.length - 1].trim();
|
||||
const downPathId = await WangPan115TaskPlugin.registerDirAsDownPath(fileId, lastDirName);
|
||||
console.log("[115离线] 多级目录创建完成:", templatePath, "→ downPathId=" + downPathId);
|
||||
return downPathId;
|
||||
}
|
||||
|
||||
getPageInfoForOffline() {
|
||||
const baseInfo = this.getPageInfo();
|
||||
const carNum = baseInfo.carNum || "";
|
||||
let title = "", maker = "", actor = "";
|
||||
if (isJavBus) {
|
||||
title = $("h3").first().text().trim();
|
||||
maker = $('span.header:contains("製作商:")').parent("p").text().replace("製作商:", "").trim() ||
|
||||
$('span.header:contains("制作商:")').parent("p").text().replace("制作商:", "").trim();
|
||||
const actorEl = $('span.genre a[href*="/star/"]').first();
|
||||
actor = actorEl.length ? actorEl.text().trim() : "";
|
||||
} else {
|
||||
title = $(".current-title").first().text().trim() || $("h2.title.is-4 .current-title").first().text().trim() || $(".movie-title").first().text().trim();
|
||||
maker = $('strong:contains("片商:")').parent().find(".value").text().trim() ||
|
||||
$('strong:contains("片商:")').parent().find(".value").text().trim();
|
||||
actor = $('.actor-female').first().text().trim() || $('strong:contains("演員:"), strong:contains("演员:")').parent().find('.value a').first().text().trim() || "";
|
||||
}
|
||||
const now = new Date();
|
||||
if (carNum && title) {
|
||||
const upperTitle = title.toUpperCase();
|
||||
const upperCode = carNum.toUpperCase();
|
||||
if (upperTitle.startsWith(upperCode)) {
|
||||
title = title.substring(carNum.length).replace(/^[\s\-_]+/, "").trim();
|
||||
}
|
||||
}
|
||||
console.log("[115离线] 页面信息提取:", {code: carNum, title, maker, actor});
|
||||
return {
|
||||
code: carNum,
|
||||
title: title,
|
||||
maker: maker,
|
||||
actor: actor,
|
||||
date: utils.formatDate(now).split(" ")[0]
|
||||
};
|
||||
}
|
||||
async getSavePathId(nyName) {
|
||||
const enableCustom = await storageManager.getSetting("enable115OfflineFormat", NO);
|
||||
if (enableCustom === YES) {
|
||||
const template = await storageManager.getSetting("offlineFolderFormat", "");
|
||||
if (template && template.includes("${")) {
|
||||
const pageInfo = this.getPageInfoForOffline();
|
||||
return WangPan115TaskPlugin.parseOfflineDirTemplate(template, pageInfo);
|
||||
}
|
||||
}
|
||||
let savePath115 = await storageManager.getSetting("savePath115", "云下载");
|
||||
nyName && (savePath115 = savePath115.replaceAll("{ny}", nyName));
|
||||
savePath115 = savePath115.replaceAll("{date}", utils.formatDate(new Date));
|
||||
@@ -80,7 +199,35 @@ class WangPan115TaskPlugin extends BasePlugin {
|
||||
});
|
||||
return;
|
||||
}
|
||||
const sign = singInfo.sign, time = singInfo.time, userId = this.getUserId(), result = await (async (magnet, wp_path_id = "", uid, sign, time) => {
|
||||
const sign = singInfo.sign, time = singInfo.time, userId = this.getUserId();
|
||||
|
||||
let wp_path_id = savePath || "";
|
||||
if (!wp_path_id) {
|
||||
const fullPath = await this.getSavePathId();
|
||||
console.log("[115离线] 目录模板解析结果:", fullPath);
|
||||
if (fullPath) {
|
||||
if (fullPath.includes("/")) {
|
||||
console.log("[115离线] 检测到多级目录,逐级创建:", fullPath);
|
||||
const newId = await WangPan115TaskPlugin.createMultiLevelDownPath(fullPath);
|
||||
if (newId) wp_path_id = newId;
|
||||
} else {
|
||||
const downPathList = await getDownPathList();
|
||||
if (downPathList && downPathList.length > 0) {
|
||||
const matched = downPathList.find((d => d.name === fullPath));
|
||||
if (matched) {
|
||||
wp_path_id = matched.id;
|
||||
console.log("[115离线] 目录匹配结果: 匹配到 \"" + matched.name + "\" -> id=" + matched.id);
|
||||
} else {
|
||||
console.log("[115离线] 目录匹配结果: 未匹配到 \"" + fullPath + "\",自动创建并注册");
|
||||
const newId = await WangPan115TaskPlugin.createMultiLevelDownPath(fullPath);
|
||||
if (newId) wp_path_id = newId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const result = await (async (magnet, wp_path_id = "", uid, sign, time) => {
|
||||
const data = {
|
||||
url: encodeURIComponent(magnet),
|
||||
wp_path_id: wp_path_id,
|
||||
@@ -89,7 +236,7 @@ class WangPan115TaskPlugin extends BasePlugin {
|
||||
time: time
|
||||
};
|
||||
return await gmHttp.postForm("https://115.com/web/lixian/?ct=lixian&ac=add_task_url", data);
|
||||
})(magnetLink, savePath || "", userId, sign, time);
|
||||
})(magnetLink, wp_path_id, userId, sign, time);
|
||||
console.log("离线下载返回值:", result);
|
||||
let infoHash = result.info_hash, fileId = await this.getFileId(userId, sign, time, infoHash), openUrl = "https://115.com/?tab=offline&mode=wangpan";
|
||||
fileId && (openUrl = `https://115.com/?cid=${fileId}&offset=0&mode=wangpan`);
|
||||
|
||||
+3
-5
@@ -6,9 +6,9 @@ export default defineConfig({
|
||||
monkey({
|
||||
entry: 'src/main.js',
|
||||
userscript: {
|
||||
name: 'JHS-enhance',
|
||||
namespace: 'JHS-enhance',
|
||||
version: '3.3.10',
|
||||
name: 'JHS-enhance',
|
||||
namespace: 'JHS-enhance',
|
||||
version: '3.3.18',
|
||||
author: 'xiebro,fireinrain',
|
||||
description: 'Jav-鉴黄师 增强脚本。列表页:作品状态标签、一键筛选、新作品检测、演员黑名单过滤;详情页:磁力链接高亮、DMM 多画质预览视频、标题翻译、整合字幕搜索(迅雷+SubTitleCat)并支持 115 直传、多源预览图(javfree/projectjav/javstore)含来源切换;数据:115 网盘目录匹配与多目录选择、云盘备份/恢复、跨 Tab 同步;其他:自动翻页、分类折叠、Top250、以图识图、热门榜单、评论查看、相关清单。支持 JavDB / JavBus / JavSee / SeeJav / FC2 / JavTrailers',
|
||||
license: 'MIT',
|
||||
@@ -38,7 +38,6 @@ export default defineConfig({
|
||||
],
|
||||
require: [
|
||||
'https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js',
|
||||
'https://cdn.jsdelivr.net/npm/tabulator-tables@6.5.2/dist/js/tabulator.min.js',
|
||||
'https://cdn.jsdelivr.net/npm/layui-layer@1.0.9/dist/layer.min.js',
|
||||
'https://cdn.jsdelivr.net/npm/blueimp-md5@2.19.0/js/md5.min.js',
|
||||
'https://cdn.jsdelivr.net/npm/toastify-js@1.12.0/src/toastify.min.js',
|
||||
@@ -96,7 +95,6 @@ export default defineConfig({
|
||||
'localforage': 'localforage',
|
||||
'toastify-js': 'Toastify',
|
||||
'blueimp-md5': 'md5',
|
||||
'tabulator-tables': 'Tabulator',
|
||||
'viewerjs': 'Viewer',
|
||||
'qrcodejs': 'QRCode',
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user