mirror of
https://github.com/fireinrain/JHS-enhance.git
synced 2026-09-28 07:36:38 +08:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2b8c925fed | |||
| a9e5286c53 | |||
| 7005b528a3 | |||
| 4026b84fc2 | |||
| 76b608ccc0 | |||
| 6c9a4743bb | |||
| ce6cedf164 | |||
| 7840ca6389 | |||
| d03a9d1462 | |||
| b7cfc8541c | |||
| ce59d82ed2 | |||
| 37cf4e1183 | |||
| 8829af0fc3 | |||
| 9db06fba3b | |||
| 06b2497ee1 | |||
| 50581be5a6 |
@@ -36,6 +36,9 @@
|
||||
|
||||
### 详情页增强
|
||||
|
||||
- **磁力搜索聚合(MagnetHub)**:多引擎聚合搜索(Sukebei / U9A9 / U3C3 / BTSearch / SoKitty / ØMagnet),Tab
|
||||
切换引擎,结果表格展示(名称/大小/日期/操作),支持按大小/最新/最旧排序,质量标签自动识别(中字/4K/破解),一键复制磁力链接(含番号提取码),验车功能(Whatslink
|
||||
API 截图预览、键盘/缩放导航),115 离线下载快捷按钮
|
||||
- **磁力排序与过滤(JavDB)**:按发布日期/文件大小/文件数量拖拽排序,勾选启用;高清/4K/字幕/无码多条件并集过滤,4K 磁力行高亮显示
|
||||
- 磁力链接高亮匹配已收藏/已下载状态
|
||||
- DMM 多画质预览视频
|
||||
@@ -48,11 +51,17 @@
|
||||
|
||||
### 115 网盘集成
|
||||
|
||||
- **番号智能匹配**:双阶段搜索策略 — 第一阶段精准搜索(完整番号 + `type:4`),未命中时第二阶段模糊兜底(尾号 +
|
||||
正则匹配),支持不规则文件名(如 `MIVR00345-5.mp4`、`ABP001.mp4`)
|
||||
- **磁力离线下载**:MagnetHub 磁力搜索结果支持一键添加至 115 离线下载
|
||||
- **不规则文件名自动重命名**
|
||||
:检测到需第二阶段才能匹配的作品时,自动将文件重命名为标准番号格式(如 `mdvr00317-3.mp4` → `MDVR-317-3.mp4`
|
||||
),设置面板可开关 + 选择范围(仅VR / 全部)
|
||||
- 作品目录匹配与详情页预加载
|
||||
- 多目录选择上传字幕
|
||||
- 字幕一键直传至匹配目录
|
||||
- **作品删除增强**:删除整个文件夹(非仅视频),支持标记删除批量操作,删除后字幕目录列表联动;批量删除含风控保护(1~3s
|
||||
随机延迟 + 触发风控自动重试退避)
|
||||
随机延迟 + 触发风控自动重试退避);删除安全检查使用 `codeParse` 正则匹配番号
|
||||
|
||||
### 数据管理
|
||||
|
||||
@@ -70,7 +79,8 @@
|
||||
### 其他
|
||||
|
||||
- FC2 站点支持(含 123AV 补全)
|
||||
- MagnetHub 磁力搜索
|
||||
- **MagnetHub 磁力搜索**:6 引擎聚合(Sukebei/U9A9/U3C3/BTSearch/SoKitty/ØMagnet),质量标签(中字/4K/破解),验车截图预览(Whatslink
|
||||
API,键盘导航),排序切换,115 离线一键下载
|
||||
- JavTrailers 站点处理
|
||||
- 设置面板:快捷键配置、域名配置、缓存清理、标记删除列表、打赏作者(二维码/钱包地址可自定义)
|
||||
- 浏览历史、想看/已看列表
|
||||
@@ -108,7 +118,7 @@ JHS-enhance/
|
||||
│ ├── list-page-button.js # 列表页功能按钮(待鉴定/已收藏/新作品/黑名单管理)
|
||||
│ ├── detail-page.js # 详情页数据加载与基础增强
|
||||
│ ├── detail-page-button.js# 详情页操作按钮(115 目录预加载 + 磁力排序过滤面板)
|
||||
│ ├── setting.js # 设置面板(Tab 页:基础/任务/域名/快捷键/屏蔽/缓存/标记删除/打赏作者)
|
||||
│ ├── setting.js # 设置面板(Tab 页:基础/任务/域名/快捷键/屏蔽/缓存/标记删除/打赏作者;含 115 自动重命名开关 + 范围选择)
|
||||
│ ├── translate.js # 标题翻译(Google 翻译 API,原始标题缓存)
|
||||
│ ├── preview-video.js # DMM 预览视频播放器
|
||||
│ ├── highlight-magnet.js # 磁力链接高亮 + 排序 + 过滤(多键排序、并集过滤、4K 高亮)
|
||||
@@ -118,7 +128,7 @@ JHS-enhance/
|
||||
│ ├── new-video.js # 新作品检测与通知
|
||||
│ ├── task.js # 后台任务调度(黑名单/收藏演员/新作品定时执行)
|
||||
│ ├── history.js # 浏览历史表格
|
||||
│ ├── wangpan-115.js # 115 网盘匹配/标签/删除(含风控保护的批量删除)
|
||||
│ ├── wangpan-115.js # 115 网盘匹配/标签/删除(含 codeParse 正则匹配、双阶段搜索、自动重命名)
|
||||
│ ├── wangpan-115-task.js # 115 网盘任务处理(文件搜索 API 封装)
|
||||
│ ├── aliyun-pan.js # 阿里云盘备份/恢复
|
||||
│ ├── fc2.js # FC2 页面处理
|
||||
@@ -139,7 +149,7 @@ JHS-enhance/
|
||||
│ ├── screenshot.js # 多源预览图(javfree/projectjav/javstore + 来源切换弹窗)
|
||||
│ ├── subtitles.js # 字幕搜索(整合迅雷+SubTitleCat)+ 115 多目录直传
|
||||
│ ├── req115.js # 115 网盘 API 封装(Req 基类 + Drive115 + Req115)
|
||||
│ ├── magnet-hub.js # MagnetHub 磁力搜索
|
||||
│ ├── magnet-hub.js # MagnetHub 磁力搜索(6 引擎聚合、质量标签、验车截图、115 离线)
|
||||
│ ├── other-site.js # 第三方站点跳转链接
|
||||
│ ├── jav-trailers.js # JavTrailers 站点处理
|
||||
│ ├── javxy-preview-video.js# Javxy 多源视频预览(独立按钮、聚合 API、HLS 支持)
|
||||
@@ -297,6 +307,15 @@ window.show.ok('操作成功'); // Toast 通知
|
||||
|
||||
## 版本历史
|
||||
|
||||
- **v3.3.9**
|
||||
- 新增:115 番号智能匹配 — `codeParse` 正则匹配引擎,双阶段搜索策略(精准 →
|
||||
模糊兜底),支持不规则文件名(如 `MIVR00345-5.mp4`、`ABP001.mp4`)
|
||||
- 新增:115 不规则文件名自动重命名 —
|
||||
检测到需模糊匹配的作品时自动批量重命名为标准格式(如 `mdvr00317-3.mp4` → `MDVR-317-3.mp4`),设置面板可开关 +
|
||||
范围选择(仅VR / 全部)
|
||||
- 优化:删除安全检查改用 `codeParse` 正则匹配,消除 `includes` 方式对不规则文件名的误判
|
||||
- 优化:`searchFiles` 增加 `type:4` 参数,搜索仅返回视频文件,避免目录占用 30 条槽位
|
||||
|
||||
- **v3.3.8**
|
||||
- 新增:Javxy 多源视频预览独立按钮(番号/识别码右侧),基于 Javxy 聚合 API,支持 JavTrailers / JavDB 等多源回退
|
||||
- 新增:HLS 视频播放运行时(hls.js 封装),支持 .m3u8 格式、播放进度记忆、画质切换
|
||||
|
||||
Vendored
+15430
-12979
File diff suppressed because one or more lines are too long
+4
-3
@@ -12,6 +12,9 @@ if (typeof $.trim !== 'function') {
|
||||
return text == null ? '' : (text + '').trim();
|
||||
};
|
||||
}
|
||||
if (typeof jQuery !== 'undefined' && typeof layer === 'undefined') {
|
||||
await import('layui-layer');
|
||||
}
|
||||
window.localforage = localforage;
|
||||
window.Toastify = Toastify;
|
||||
window.md5 = md5;
|
||||
@@ -31,6 +34,4 @@ window.Status_FAVORITE = Status_FAVORITE;
|
||||
window.Status_HAS_DOWN = Status_HAS_DOWN;
|
||||
window.Status_HAS_WATCH = Status_HAS_WATCH;
|
||||
window.NO = NO;
|
||||
window.YES = YES;
|
||||
|
||||
import 'layui-layer';
|
||||
window.YES = YES;
|
||||
+1
-1
@@ -98,7 +98,7 @@ class Utils {
|
||||
}
|
||||
if (!viewerExists) {
|
||||
this.layerIndexStack.pop();
|
||||
layer.close(topLayerIndex);
|
||||
typeof layer !== 'undefined' && layer.close(topLayerIndex);
|
||||
}
|
||||
}
|
||||
setupEscClose(layerIndex) {
|
||||
|
||||
+23
-21
@@ -820,29 +820,31 @@ window.ImageHoverPreview = class {
|
||||
}));
|
||||
}();
|
||||
|
||||
const originalLayerClose = layer.close;
|
||||
if (typeof layer !== 'undefined') {
|
||||
const originalLayerClose = layer.close;
|
||||
|
||||
layer.close = function(index) {
|
||||
const result = originalLayerClose.call(this, index);
|
||||
!function(waitTime = 10) {
|
||||
setTimeout((() => {
|
||||
const openLayerCount = document.querySelectorAll(".layui-layer-shade").length;
|
||||
document.documentElement.style.overflow = openLayerCount > 0 ? "hidden" : "";
|
||||
}), waitTime);
|
||||
}();
|
||||
return result;
|
||||
};
|
||||
|
||||
const originalLayerOpen = layer.open;
|
||||
|
||||
layer.open = function(options) {
|
||||
const originalSuccess = (options = options || {}).success;
|
||||
options.success = function(layero, index) {
|
||||
"function" == typeof originalSuccess && originalSuccess.call(this, layero, index);
|
||||
utils.setupEscClose(index);
|
||||
layer.close = function (index) {
|
||||
const result = originalLayerClose.call(this, index);
|
||||
!function (waitTime = 10) {
|
||||
setTimeout((() => {
|
||||
const openLayerCount = document.querySelectorAll(".layui-layer-shade").length;
|
||||
document.documentElement.style.overflow = openLayerCount > 0 ? "hidden" : "";
|
||||
}), waitTime);
|
||||
}();
|
||||
return result;
|
||||
};
|
||||
return originalLayerOpen.call(this, options);
|
||||
};
|
||||
|
||||
const originalLayerOpen = layer.open;
|
||||
|
||||
layer.open = function (options) {
|
||||
const originalSuccess = (options = options || {}).success;
|
||||
options.success = function (layero, index) {
|
||||
"function" == typeof originalSuccess && originalSuccess.call(this, layero, index);
|
||||
utils.setupEscClose(index);
|
||||
};
|
||||
return originalLayerOpen.call(this, options);
|
||||
};
|
||||
}
|
||||
|
||||
utils.importResource("https://cdn.jsdelivr.net/npm/layui-layer@1.0.9/layer.min.css");
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
+1051
-138
File diff suppressed because it is too large
Load Diff
+12
-1
File diff suppressed because one or more lines are too long
@@ -6,8 +6,9 @@ const getDownPathList = async () => {
|
||||
return "object" == typeof res ? res.data : null;
|
||||
};
|
||||
|
||||
const searchFiles = async (search_value, offset = 0, limit = 30) => {
|
||||
const url = `https://webapi.115.com/files/search?search_value=${encodeURIComponent(search_value)}&offset=${offset}&limit=${limit}`;
|
||||
const searchFiles = async (search_value, offset = 0, limit = 30, params = {}) => {
|
||||
const queryParams = new URLSearchParams({search_value, offset, limit, ...params});
|
||||
const url = `https://webapi.115.com/files/search?${queryParams}`;
|
||||
return await gmHttp.get(url);
|
||||
};
|
||||
|
||||
|
||||
+100
-18
@@ -275,7 +275,13 @@ const _WangPan115MatchPlugin = class _WangPan115MatchPlugin extends BasePlugin {
|
||||
const $detail = $('\n <div class="jhs-match-detail jhs-115-match-detail" id="115-match-table">\n <table>\n <thead>\n <tr style="text-align: center">\n <th colspan="4">115匹配</th>\n </tr>\n <tr>\n <th>名称</th>\n <th>大小</th>\n <th>时间</th>\n <th>播放</th>\n </tr>\n </thead>\n <tbody>\n </tbody>\n </table>\n </div>\n '), $tbody = $detail.find("tbody");
|
||||
try {
|
||||
const carNum2 = this.getPageInfo().carNum;
|
||||
matchList || (matchList = await this.searchFiles(carNum2));
|
||||
if (!matchList) {
|
||||
const {results, usedPhase2} = await this._searchFilesWithPhase(carNum2);
|
||||
matchList = results;
|
||||
if (usedPhase2 && matchList.length > 0) {
|
||||
await this.autoRenameFiles(carNum2, matchList);
|
||||
}
|
||||
}
|
||||
await this.checkLoginStatus();
|
||||
if (this.loginStatus === _WangPan115MatchPlugin.LoginStatus.LOGGED_OUT) $tbody.append(`<tr><td colspan="4">\n <a class='jhs-match-no-login-btn a-info'\n data-keyword="${carNum2}"\n title="未登录115网盘">未登录</a>\n </td></tr>`); else if (matchList.length > 0) {
|
||||
const rowsHtml = matchList.map((match => `\n <tr>\n <td>${match.name}</td>\n <td>${this.formatSize(match.size)}</td>\n <td>${match.createTime}</td>\n <td>\n <a href="https://115vod.com/?pickcode=${match.videoId}&share_id=0"\n target="_blank"\n class="a-success"\n title="播放">播放</a>\n </td>\n </tr>\n `)).join("");
|
||||
@@ -406,8 +412,8 @@ const _WangPan115MatchPlugin = class _WangPan115MatchPlugin extends BasePlugin {
|
||||
onProgress && onProgress(i + 1, selectedItems.length, item, "未匹配到115文件");
|
||||
continue;
|
||||
}
|
||||
const upperCarNum = item.carNum.toUpperCase();
|
||||
const safeMatchList = matchList.filter(m => m.name.toUpperCase().includes(upperCarNum));
|
||||
const {regex: safeRegex} = codeParse(item.carNum);
|
||||
const safeMatchList = matchList.filter(m => safeRegex.test(m.name));
|
||||
if (safeMatchList.length === 0) {
|
||||
failedCount++;
|
||||
onProgress && onProgress(i + 1, selectedItems.length, item, "无安全可删除目录");
|
||||
@@ -507,8 +513,8 @@ const _WangPan115MatchPlugin = class _WangPan115MatchPlugin extends BasePlugin {
|
||||
}
|
||||
|
||||
showDeleteDialog(carNum2, matchList, afterDelete) {
|
||||
const upperCarNum = carNum2.toUpperCase();
|
||||
const safeMatchList = matchList.filter(m => m.name.toUpperCase().includes(upperCarNum));
|
||||
const {regex: safeRegex} = codeParse(carNum2);
|
||||
const safeMatchList = matchList.filter(m => safeRegex.test(m.name));
|
||||
const unsafeCount = matchList.length - safeMatchList.length;
|
||||
if (safeMatchList.length === 0) {
|
||||
show.error(`作品 "${carNum2}" 匹配到的 ${matchList.length} 个项目均不含番号,无法安全删除。请手动在115中删除。`);
|
||||
@@ -616,20 +622,76 @@ const _WangPan115MatchPlugin = class _WangPan115MatchPlugin extends BasePlugin {
|
||||
window.open("https://115.com");
|
||||
}
|
||||
async searchFiles(carNum2) {
|
||||
return (await this._searchFilesWithPhase(carNum2)).results;
|
||||
}
|
||||
|
||||
async _searchFilesWithPhase(carNum2) {
|
||||
const {regex} = codeParse(carNum2);
|
||||
const searchKeyword = carNum2.toLowerCase().replace("fc2-", "");
|
||||
|
||||
const mapAndFilter = (rawData) => {
|
||||
return rawData.map((data => ({
|
||||
folderId: data.fid,
|
||||
dirId: data.cid,
|
||||
videoId: data.pc,
|
||||
name: data.n,
|
||||
createTime: utils.formatDate(new Date(1e3 * data.te)),
|
||||
size: data.s,
|
||||
isVideo: true
|
||||
}))).filter((x => x.folderId && regex.test(x.name)));
|
||||
};
|
||||
|
||||
var _a2;
|
||||
let searchKeyword = carNum2.toLowerCase().replace("fc2-", "");
|
||||
return (null == (_a2 = (await searchFiles(searchKeyword)).data) ? void 0 : _a2.map((data => ({
|
||||
folderId: data.fid,
|
||||
dirId: data.cid,
|
||||
videoId: data.pc,
|
||||
name: data.n,
|
||||
createTime: utils.formatDate(new Date(1e3 * data.te)),
|
||||
size: data.s,
|
||||
isVideo: [ ".mp4", ".avi", ".mov", ".mkv", ".flv", ".wmv" ].some((ext => {
|
||||
var _a3;
|
||||
return null == (_a3 = data.n) ? void 0 : _a3.toLowerCase().endsWith(ext);
|
||||
}))
|
||||
}))).filter((x => x.folderId && x.isVideo && x.name.toLowerCase().includes(searchKeyword)))) || [];
|
||||
const preciseData = (null == (_a2 = (await searchFiles(searchKeyword, 0, 30, {type: 4})).data) ? void 0 : _a2) || [];
|
||||
const preciseResults = mapAndFilter(preciseData);
|
||||
if (preciseResults.length > 0) return {results: preciseResults, usedPhase2: false};
|
||||
|
||||
const numberPart = extractNumberPart(carNum2);
|
||||
if (numberPart === searchKeyword) return {results: preciseResults, usedPhase2: false};
|
||||
|
||||
const fuzzyData = (null == (_a2 = (await searchFiles(numberPart, 0, 30, {type: 4})).data) ? void 0 : _a2) || [];
|
||||
return {results: mapAndFilter(fuzzyData), usedPhase2: true};
|
||||
}
|
||||
|
||||
buildRenameTarget(carNum, originalName) {
|
||||
const {regex} = codeParse(carNum);
|
||||
const match = regex.exec(originalName);
|
||||
if (!match) return null;
|
||||
const before = originalName.slice(0, match.index);
|
||||
const after = originalName.slice(match.index + match[0].length);
|
||||
return before + carNum + after;
|
||||
}
|
||||
|
||||
async autoRenameFiles(carNum, matchList) {
|
||||
try {
|
||||
const enableAutoRename = await storageManager.getSetting("enable115AutoRename", NO);
|
||||
if (enableAutoRename !== YES) return;
|
||||
const scope = await storageManager.getSetting("autoRenameScope", "vr_only");
|
||||
if (scope === "vr_only" && !carNum.toUpperCase().includes("VR")) return;
|
||||
const renameObj = {};
|
||||
matchList.forEach(match => {
|
||||
const newName = this.buildRenameTarget(carNum, match.name);
|
||||
if (newName && newName !== match.name) {
|
||||
renameObj[match.folderId] = newName;
|
||||
}
|
||||
});
|
||||
if (Object.keys(renameObj).length === 0) return;
|
||||
const formData = {};
|
||||
Object.entries(renameObj).forEach(([fid, newName]) => {
|
||||
formData[`files_new_name[${fid}]`] = newName;
|
||||
});
|
||||
const result = await gmHttp.postForm("https://webapi.115.com/files/batch_rename", formData);
|
||||
if (result && result.state) {
|
||||
Object.entries(renameObj).forEach(([fid, newName]) => {
|
||||
const match = matchList.find(m => m.folderId === fid);
|
||||
console.log(`[115重命名] ${match.name} → ${newName}`);
|
||||
});
|
||||
} else {
|
||||
console.warn("[115重命名] 重命名失败:", (result && result.error) || "未知错误");
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("[115重命名] 重命名失败,跳过:", e.message);
|
||||
}
|
||||
}
|
||||
showMatchError($box2, carNum2, error) {
|
||||
$box2.find(".jhs-match-btn").replaceWith(`<a class='jhs-match-error-btn' data-keyword="${carNum2}" \n title="匹配失败,点击重试">匹配失败</a>`);
|
||||
@@ -694,5 +756,25 @@ __publicField(_WangPan115MatchPlugin, "LoginStatus", {
|
||||
|
||||
let WangPan115MatchPlugin = _WangPan115MatchPlugin;
|
||||
|
||||
const extractNumberPart = (carNum) => {
|
||||
let cleaned = carNum.replace(/^fc2[-_]?(ppv[-_])?/i, "");
|
||||
const match = cleaned.match(/(\d+)$/);
|
||||
return match ? match[1] : cleaned;
|
||||
};
|
||||
|
||||
const codeParse = (code) => {
|
||||
const codes = code.split(/-|_/);
|
||||
const sep = "\\s?(0|-|_){0,2}\\s?";
|
||||
|
||||
let pattern = codes.join(sep);
|
||||
if (/^fc2/i.test(code)) pattern = `${codes[0]}${sep}(ppv)?${sep}${codes.at(-1)}`;
|
||||
|
||||
return {
|
||||
code,
|
||||
codes,
|
||||
prefix: codes[0],
|
||||
regex: new RegExp(`(?<![a-z])${pattern}(?!\\d)`, "i"),
|
||||
};
|
||||
};
|
||||
|
||||
export { WangPan115Plugin, WangPan115MatchPlugin };
|
||||
+3
-18
@@ -8,8 +8,8 @@ export default defineConfig({
|
||||
userscript: {
|
||||
name: 'JHS-enhance',
|
||||
namespace: 'JHS-enhance',
|
||||
version: '3.3.7',
|
||||
author: 'xie bro,fireinrain',
|
||||
version: '3.3.10',
|
||||
author: 'xiebro,fireinrain',
|
||||
description: 'Jav-鉴黄师 增强脚本。列表页:作品状态标签、一键筛选、新作品检测、演员黑名单过滤;详情页:磁力链接高亮、DMM 多画质预览视频、标题翻译、整合字幕搜索(迅雷+SubTitleCat)并支持 115 直传、多源预览图(javfree/projectjav/javstore)含来源切换;数据:115 网盘目录匹配与多目录选择、云盘备份/恢复、跨 Tab 同步;其他:自动翻页、分类折叠、Top250、以图识图、热门榜单、评论查看、相关清单。支持 JavDB / JavBus / JavSee / SeeJav / FC2 / JavTrailers',
|
||||
license: 'MIT',
|
||||
icon: 'https://www.google.com/s2/favicons?sz=64&domain=javdb.com',
|
||||
@@ -92,30 +92,15 @@ export default defineConfig({
|
||||
build: {
|
||||
fileName: 'jhs-enhance.user.js',
|
||||
externalGlobals: {
|
||||
'jquery': '$',
|
||||
'jquery': 'jQuery',
|
||||
'localforage': 'localforage',
|
||||
'toastify-js': 'Toastify',
|
||||
'blueimp-md5': 'md5',
|
||||
'tabulator-tables': 'Tabulator',
|
||||
'viewerjs': 'Viewer',
|
||||
'qrcodejs': 'QRCode',
|
||||
'layui-layer': 'layer',
|
||||
},
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: 'layui-layer-dev-shim',
|
||||
apply: 'serve',
|
||||
resolveId(id) {
|
||||
if (id === 'layui-layer') {
|
||||
return '\0layui-layer-shim';
|
||||
}
|
||||
},
|
||||
load(id) {
|
||||
if (id === '\0layui-layer-shim') {
|
||||
return 'export default window.layer;';
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
Reference in New Issue
Block a user