mirror of
https://github.com/fireinrain/JHS-enhance.git
synced 2026-11-13 00:34:24 +08:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9d81f6a13a | |||
| 0425ebf7c7 | |||
| d636a2f683 |
Vendored
+24543
-239
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jhs-enhance",
|
||||
"version": "3.3.16",
|
||||
"version": "3.3.18",
|
||||
"description": "Jav-鉴黄师 油猴脚本 - 工程化版本",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -55,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)();
|
||||
|
||||
@@ -864,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);
|
||||
|
||||
@@ -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};
|
||||
@@ -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>');
|
||||
|
||||
+1
-3
@@ -8,7 +8,7 @@ export default defineConfig({
|
||||
userscript: {
|
||||
name: 'JHS-enhance',
|
||||
namespace: 'JHS-enhance',
|
||||
version: '3.3.16',
|
||||
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