mirror of
https://github.com/JoeanAmier/XHS-Downloader.git
synced 2026-03-22 06:57:16 +08:00
refactor(script): 优化部分弹窗提示的交互界面样式
This commit is contained in:
@@ -24,4 +24,5 @@
|
|||||||
2. 添加未登录状态下无法提取作品链接的提示
|
2. 添加未登录状态下无法提取作品链接的提示
|
||||||
3. 脚本设置新增 `菜单始终显示` 配置项
|
3. 脚本设置新增 `菜单始终显示` 配置项
|
||||||
4. 修复用户脚本 CSS 样式冲突问题
|
4. 修复用户脚本 CSS 样式冲突问题
|
||||||
5. 优化提取作品 ID 的正则表达式
|
5. 优化部分弹窗提示的交互界面样式
|
||||||
|
6. 优化提取作品 ID 的正则表达式
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name XHS-Downloader
|
// @name XHS-Downloader
|
||||||
// @namespace https://github.com/JoeanAmier/XHS-Downloader
|
// @namespace https://github.com/JoeanAmier/XHS-Downloader
|
||||||
// @version 2.1.2
|
// @version 2.1.3
|
||||||
// @description 提取小红书作品/用户链接,下载小红书无水印图文/视频作品文件
|
// @description 提取小红书作品/用户链接,下载小红书无水印图文/视频作品文件
|
||||||
// @author JoeanAmier
|
// @author JoeanAmier
|
||||||
// @match http*://xhslink.com/*
|
// @match http*://xhslink.com/*
|
||||||
@@ -45,17 +45,17 @@
|
|||||||
},
|
},
|
||||||
}, // 位置配置
|
}, // 位置配置
|
||||||
position: {
|
position: {
|
||||||
bottom: '8rem', left: '2rem'
|
bottom: '6rem', left: '1rem'
|
||||||
}, // 动画配置
|
}, // 动画配置
|
||||||
animation: {
|
animation: {
|
||||||
duration: 0.35, // 动画时长(s)
|
duration: 0.25, // 动画时长(s)
|
||||||
easing: 'cubic-bezier(0.4, 0, 0.2, 1)'
|
easing: 'cubic-bezier(0.4, 0, 0.2, 1)'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const readme = () => {
|
const readme = async () => {
|
||||||
const instructions = `
|
const instructions = `
|
||||||
XHS-Downloader 用户脚本 功能清单:
|
功能清单:
|
||||||
1. 下载小红书无水印作品文件
|
1. 下载小红书无水印作品文件
|
||||||
2. 提取推荐页面作品链接
|
2. 提取推荐页面作品链接
|
||||||
3. 提取账号发布作品链接
|
3. 提取账号发布作品链接
|
||||||
@@ -65,7 +65,7 @@ XHS-Downloader 用户脚本 功能清单:
|
|||||||
7. 提取搜索结果作品链接
|
7. 提取搜索结果作品链接
|
||||||
8. 提取搜索结果用户链接
|
8. 提取搜索结果用户链接
|
||||||
|
|
||||||
XHS-Downloader 用户脚本 详细说明:
|
注意事项:
|
||||||
1. 下载小红书无水印作品文件时,脚本需要花费时间处理文件,请等待片刻,请勿多次点击下载按钮
|
1. 下载小红书无水印作品文件时,脚本需要花费时间处理文件,请等待片刻,请勿多次点击下载按钮
|
||||||
2. 无水印作品文件较大,可能需要较长的时间处理,页面跳转可能会导致下载失败
|
2. 无水印作品文件较大,可能需要较长的时间处理,页面跳转可能会导致下载失败
|
||||||
3. 提取账号发布、收藏、点赞、专辑作品链接时,脚本可以自动滚动页面直至加载全部作品
|
3. 提取账号发布、收藏、点赞、专辑作品链接时,脚本可以自动滚动页面直至加载全部作品
|
||||||
@@ -77,30 +77,35 @@ XHS-Downloader 用户脚本 详细说明:
|
|||||||
项目开源地址:https://github.com/JoeanAmier/XHS-Downloader
|
项目开源地址:https://github.com/JoeanAmier/XHS-Downloader
|
||||||
`
|
`
|
||||||
const disclaimer_content = `
|
const disclaimer_content = `
|
||||||
关于 XHS-Downloader 的 免责声明:
|
|
||||||
|
|
||||||
1. 使用者对本项目的使用由使用者自行决定,并自行承担风险。作者对使用者使用本项目所产生的任何损失、责任、或风险概不负责。
|
1. 使用者对本项目的使用由使用者自行决定,并自行承担风险。作者对使用者使用本项目所产生的任何损失、责任、或风险概不负责。
|
||||||
2. 本项目的作者提供的代码和功能是基于现有知识和技术的开发成果。作者尽力确保代码的正确性和安全性,但不保证代码完全没有错误或缺陷。
|
2. 本项目的作者提供的代码和功能是基于现有知识和技术的开发成果。作者按现有技术水平努力确保代码的正确性和安全性,但不保证代码完全没有错误或缺陷。
|
||||||
3. 使用者在使用本项目时必须严格遵守 GNU General Public License v3.0 的要求,并在适当的地方注明使用了 GNU General Public License v3.0 的代码。
|
3. 本项目依赖的所有第三方库、插件或服务各自遵循其原始开源或商业许可,使用者需自行查阅并遵守相应协议,作者不对第三方组件的稳定性、安全性及合规性承担任何责任。
|
||||||
4. 使用者在任何情况下均不得将本项目的作者、贡献者或其他相关方与使用者的使用行为联系起来,或要求其对使用者使用本项目所产生的任何损失或损害负责。
|
4. 使用者在使用本项目时必须严格遵守 GNU General Public License v3.0 的要求,并在适当的地方注明使用了 GNU General Public License v3.0 的代码。
|
||||||
5. 使用者在使用本项目的代码和功能时,必须自行研究相关法律法规,并确保其使用行为合法合规。任何因违反法律法规而导致的法律责任和风险,均由使用者自行承担。
|
5. 使用者在使用本项目的代码和功能时,必须自行研究相关法律法规,并确保其使用行为合法合规。任何因违反法律法规而导致的法律责任和风险,均由使用者自行承担。
|
||||||
6. 本项目的作者不会提供 XHS-Downloader 项目的付费版本,也不会提供与 XHS-Downloader 项目相关的任何商业服务。
|
6. 使用者不得使用本工具从事任何侵犯知识产权的行为,包括但不限于未经授权下载、传播受版权保护的内容,开发者不参与、不支持、不认可任何非法内容的获取或分发。
|
||||||
7. 基于本项目进行的任何二次开发、修改或编译的程序与原创作者无关,原创作者不承担与二次开发行为或其结果相关的任何责任,使用者应自行对因二次开发可能带来的各种情况负全部责任。
|
7. 本项目不对使用者涉及的数据收集、存储、传输等处理活动的合规性承担责任。使用者应自行遵守相关法律法规,确保处理行为合法正当;因违规操作导致的法律责任由使用者自行承担。
|
||||||
|
8. 使用者在任何情况下均不得将本项目的作者、贡献者或其他相关方与使用者的使用行为联系起来,或要求其对使用者使用本项目所产生的任何损失或损害负责。
|
||||||
|
9. 本项目的作者不会提供 XHS-Downloader 项目的付费版本,也不会提供与 XHS-Downloader 项目相关的任何商业服务。
|
||||||
|
10. 基于本项目进行的任何二次开发、修改或编译的程序与原创作者无关,原创作者不承担与二次开发行为或其结果相关的任何责任,使用者应自行对因二次开发可能带来的各种情况负全部责任。
|
||||||
|
11. 本项目不授予使用者任何专利许可;若使用本项目导致专利纠纷或侵权,使用者自行承担全部风险和责任。未经作者或权利人书面授权,不得使用本项目进行任何商业宣传、推广或再授权。
|
||||||
|
12. 作者保留随时终止向任何违反本声明的使用者提供服务的权利,并可能要求其销毁已获取的代码及衍生作品。
|
||||||
|
13. 作者保留在不另行通知的情况下更新本声明的权利,使用者持续使用即视为接受修订后的条款。
|
||||||
|
|
||||||
在使用本项目的代码和功能之前,请您认真考虑并接受以上免责声明。如果您对上述声明有任何疑问或不同意,请不要使用本项目的代码和功能。如果您使用了本项目的代码和功能,则视为您已完全理解并接受上述免责声明,并自愿承担使用本项目的一切风险和后果。
|
在使用本项目的代码和功能之前,请您认真考虑并接受以上免责声明。如果您对上述声明有任何疑问或不同意,请不要使用本项目的代码和功能。如果您使用了本项目的代码和功能,则视为您已完全理解并接受上述免责声明,并自愿承担使用本项目的一切风险和后果。
|
||||||
|
|
||||||
是否已阅读 XHS-Downloader 功能说明与免责声明(YES/NO)
|
|
||||||
`
|
`
|
||||||
alert(instructions);
|
|
||||||
|
await showTextModal({
|
||||||
|
title: 'XHS-Downloader 脚本说明', text: instructions, mode: 'info', // info: 仅关闭
|
||||||
|
closeText: '关闭'
|
||||||
|
});
|
||||||
if (!config.disclaimer) {
|
if (!config.disclaimer) {
|
||||||
const answer = prompt(disclaimer_content, "");
|
showTextModal({
|
||||||
if (!answer) {
|
title: 'XHS-Downloader 免责声明', text: disclaimer_content, mode: 'confirm', // confirm: 确认+关闭
|
||||||
GM_setValue("disclaimer", false);
|
confirmText: '我已知晓', closeText: '关闭'
|
||||||
config.disclaimer = false;
|
}).then(answer => {
|
||||||
} else {
|
GM_setValue("disclaimer", answer);
|
||||||
GM_setValue("disclaimer", answer.toUpperCase() === "YES" || answer.toUpperCase() === "Y");
|
config.disclaimer = answer;
|
||||||
config.disclaimer = GM_getValue("disclaimer");
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -149,9 +154,21 @@ XHS-Downloader 用户脚本 详细说明:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const abnormal = (text) => {
|
const abnormal = (text) => {
|
||||||
alert(`${text}请向作者反馈!\n项目开源地址:https://github.com/JoeanAmier/XHS-Downloader`);
|
showTextModal({
|
||||||
|
title: '发生异常',
|
||||||
|
text: `${text}请向作者反馈!\n项目开源地址:https://github.com/JoeanAmier/XHS-Downloader`,
|
||||||
|
mode: 'info', // info: 仅关闭
|
||||||
|
closeText: '关闭'
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const runTips = (text) => {
|
||||||
|
showTextModal({
|
||||||
|
title: '脚本提示', text: text, mode: 'info', // info: 仅关闭
|
||||||
|
closeText: '关闭'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const generateVideoUrl = note => {
|
const generateVideoUrl = note => {
|
||||||
try {
|
try {
|
||||||
return [`https://sns-video-bd.xhscdn.com/${note.video.consumer.originVideoKey}`];
|
return [`https://sns-video-bd.xhscdn.com/${note.video.consumer.originVideoKey}`];
|
||||||
@@ -518,7 +535,7 @@ XHS-Downloader 用户脚本 详细说明:
|
|||||||
if (order >= 0 && order <= 2) {
|
if (order >= 0 && order <= 2) {
|
||||||
data = extractNotesInfo(order);
|
data = extractNotesInfo(order);
|
||||||
if (!invalidDetection(data)) {
|
if (!invalidDetection(data)) {
|
||||||
alert("提取作品链接失败!受平台限制,未登录状态下无法通过账号主页浏览作品!");
|
runTips("提取作品链接失败!受平台限制,未登录状态下无法通过账号主页浏览作品详情!请登录后重试!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (order === 3) {
|
} else if (order === 3) {
|
||||||
@@ -550,217 +567,282 @@ XHS-Downloader 用户脚本 详细说明:
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (typeof JSZip === 'undefined') {
|
if (typeof JSZip === 'undefined') {
|
||||||
alert("XHS-Downloader 用户脚本依赖库 JSZip 加载失败,作品文件打包下载功能无法使用,请尝试刷新网页或者向作者反馈!");
|
runTips("XHS-Downloader 用户脚本依赖库 JSZip 加载失败,作品文件打包下载功能无法使用,请尝试刷新网页或者向作者反馈!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ==================== 样式定义 ==================== */
|
|
||||||
let style = document.createElement('style');
|
let style = document.createElement('style');
|
||||||
style.textContent = `
|
style.textContent = `
|
||||||
/* 弹窗基础样式 */
|
/* 通用 Overlay(三个弹窗共用) */
|
||||||
#SettingsOverlay {
|
#SettingsOverlay,
|
||||||
position: fixed;
|
#imageSelectionOverlay,
|
||||||
top: 0;
|
#textGenericOverlay {
|
||||||
left: 0;
|
position: fixed;
|
||||||
width: 100%;
|
top: 0;
|
||||||
height: 100%;
|
left: 0;
|
||||||
background: rgba(0,0,0,0.32);
|
width: 100%;
|
||||||
backdrop-filter: blur(4px);
|
height: 100%;
|
||||||
display: flex;
|
background: rgba(0,0,0,0.32);
|
||||||
justify-content: center;
|
backdrop-filter: blur(4px);
|
||||||
align-items: center;
|
display: flex;
|
||||||
z-index: 10000;
|
justify-content: center;
|
||||||
animation: fadeIn 0.3s;
|
align-items: center;
|
||||||
}
|
z-index: 10000;
|
||||||
|
animation: fadeIn 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
.optimized-scroll-modal {
|
/* Settings 容器,仅本块特有尺寸 */
|
||||||
background: white;
|
.optimized-scroll-modal {
|
||||||
border-radius: 16px;
|
background: white;
|
||||||
width: 380px; /* 缩小窗口宽度 */
|
border-radius: 16px;
|
||||||
max-width: 95vw;
|
width: 380px; /* 缩小窗口宽度 */
|
||||||
box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
|
max-width: 95vw;
|
||||||
overflow: hidden;
|
box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
|
||||||
animation: scaleUp 0.3s;
|
overflow: hidden;
|
||||||
}
|
animation: scaleUp 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
/* 头部样式 */
|
/* 通用头部/内容/底部/按钮(三个弹窗共用) */
|
||||||
.modal-header {
|
.modal-header {
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-bottom: 1px solid #eee;
|
border-bottom: 1px solid #eee;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
.modal-header span {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #212121;
|
||||||
|
}
|
||||||
|
.modal-body {
|
||||||
|
flex: 1;
|
||||||
|
padding: 1rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
.modal-footer {
|
||||||
|
padding: 1rem;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
.primary-btn {
|
||||||
|
background: #2196F3;
|
||||||
|
color: white;
|
||||||
|
padding: 8px 24px;
|
||||||
|
border-radius: 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
.secondary-btn {
|
||||||
|
background: #f0f0f0;
|
||||||
|
color: #666;
|
||||||
|
padding: 8px 24px;
|
||||||
|
border-radius: 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
.modal-header span {
|
/* Settings 专用的设置项样式(保持不变) */
|
||||||
font-size: 1.25rem;
|
.setting-item {
|
||||||
font-weight: 500;
|
margin: 0.5rem 0;
|
||||||
color: #212121;
|
padding: 10px;
|
||||||
}
|
border-radius: 8px;
|
||||||
|
transition: background 0.2s;
|
||||||
|
}
|
||||||
|
.setting-item:hover { background: #f0f0f0; }
|
||||||
|
.setting-item label {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.setting-item label span {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
/* 内容区域 */
|
.toggle-switch {
|
||||||
.modal-body {
|
position: relative;
|
||||||
padding: 1rem; /* 减小内边距 */
|
width: 40px;
|
||||||
}
|
height: 20px;
|
||||||
|
}
|
||||||
|
.toggle-switch input { opacity: 0; width: 0; height: 0; }
|
||||||
|
.slider {
|
||||||
|
position: absolute;
|
||||||
|
cursor: pointer;
|
||||||
|
top: 0; left: 0; right: 0; bottom: 0;
|
||||||
|
background: #ccc;
|
||||||
|
transition: 0.4s;
|
||||||
|
border-radius: 34px;
|
||||||
|
}
|
||||||
|
.slider:before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
height: 16px; width: 16px;
|
||||||
|
left: 2px; bottom: 2px;
|
||||||
|
background: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
transition: 0.4s;
|
||||||
|
}
|
||||||
|
input:checked + .slider { background: #2196F3; }
|
||||||
|
input:checked + .slider:before { transform: translateX(20px); }
|
||||||
|
|
||||||
/* 设置项样式 */
|
.number-input {
|
||||||
.setting-item {
|
display: flex;
|
||||||
margin: 0.5rem 0; /* 减少设置项间距 */
|
align-items: center;
|
||||||
padding: 10px;
|
border: 1px solid #ddd;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
transition: background 0.2s;
|
overflow: hidden;
|
||||||
}
|
margin: 6px 0;
|
||||||
|
}
|
||||||
|
.number-input input {
|
||||||
|
width: 60px;
|
||||||
|
text-align: center;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
.number-button {
|
||||||
|
padding: 4px 8px;
|
||||||
|
background: #f0f0f0;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
.text-input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
margin-top: 8px;
|
||||||
|
transition: border-color 0.2s;
|
||||||
|
}
|
||||||
|
.text-input:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #2196F3;
|
||||||
|
box-shadow: 0 0 4px rgba(33, 150, 243, 0.3);
|
||||||
|
}
|
||||||
|
.setting-description {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: #757575;
|
||||||
|
margin-top: 4px;
|
||||||
|
line-height: 1.4;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
.setting-item:hover {
|
/* 通用动画:统一定义一次 */
|
||||||
background: #f0f0f0;
|
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
||||||
}
|
@keyframes scaleUp { from { transform: scale(0.98); } to { transform: scale(1); } }
|
||||||
|
@keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }
|
||||||
.setting-item label {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 设置项标题 */
|
|
||||||
.setting-item label span {
|
|
||||||
font-size: 1rem; /* 增大标题文字 */
|
|
||||||
font-weight: 500;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 开关样式 */
|
|
||||||
.toggle-switch {
|
|
||||||
position: relative;
|
|
||||||
width: 40px;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle-switch input {
|
|
||||||
opacity: 0;
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slider {
|
|
||||||
position: absolute;
|
|
||||||
cursor: pointer;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background: #ccc;
|
|
||||||
transition: 0.4s;
|
|
||||||
border-radius: 34px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slider:before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
height: 16px;
|
|
||||||
width: 16px;
|
|
||||||
left: 2px;
|
|
||||||
bottom: 2px;
|
|
||||||
background: white;
|
|
||||||
border-radius: 50%;
|
|
||||||
transition: 0.4s;
|
|
||||||
}
|
|
||||||
|
|
||||||
input:checked + .slider {
|
|
||||||
background: #2196F3;
|
|
||||||
}
|
|
||||||
|
|
||||||
input:checked + .slider:before {
|
|
||||||
transform: translateX(20px);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 数值输入 */
|
|
||||||
.number-input {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
margin: 6px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.number-input input {
|
|
||||||
width: 60px;
|
|
||||||
text-align: center;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.number-button {
|
|
||||||
padding: 4px 8px;
|
|
||||||
background: #f0f0f0;
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 文本输入框 */
|
|
||||||
.text-input {
|
|
||||||
width: 100%;
|
|
||||||
padding: 8px;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
margin-top: 8px; /* 增加与标题的距离 */
|
|
||||||
transition: border-color 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-input:focus {
|
|
||||||
outline: none;
|
|
||||||
border-color: #2196F3;
|
|
||||||
box-shadow: 0 0 4px rgba(33, 150, 243, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 设置项说明 */
|
|
||||||
.setting-description {
|
|
||||||
font-size: 0.875rem;
|
|
||||||
color: #757575;
|
|
||||||
margin-top: 4px;
|
|
||||||
line-height: 1.4;
|
|
||||||
text-align: left; /* 左对齐 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 底部按钮 */
|
|
||||||
.modal-footer {
|
|
||||||
padding: 1rem;
|
|
||||||
border-top: 1px solid #eee;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.primary-btn {
|
|
||||||
background: #2196F3;
|
|
||||||
color: white;
|
|
||||||
padding: 8px 24px;
|
|
||||||
border-radius: 24px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.secondary-btn {
|
|
||||||
background: #f0f0f0;
|
|
||||||
color: #666;
|
|
||||||
padding: 8px 24px;
|
|
||||||
border-radius: 24px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 动画 */
|
|
||||||
@keyframes fadeIn {
|
|
||||||
from { opacity: 0; }
|
|
||||||
to { opacity: 1; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes scaleUp {
|
|
||||||
from { transform: scale(0.98); }
|
|
||||||
to { transform: scale(1); }
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
document.head.appendChild(style);
|
document.head.appendChild(style);
|
||||||
|
|
||||||
|
// 覆盖修改:文本弹窗样式
|
||||||
|
(() => {
|
||||||
|
if (!document.getElementById('textModalStyle')) {
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.id = 'textModalStyle';
|
||||||
|
style.textContent = `
|
||||||
|
/* 仅文本弹窗容器特有的尺寸与外观 */
|
||||||
|
.text-generic-modal {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16px;
|
||||||
|
width: 80%;
|
||||||
|
max-width: 700px;
|
||||||
|
max-height: 80vh;
|
||||||
|
box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
|
||||||
|
overflow: hidden;
|
||||||
|
animation: scaleUp 0.3s;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
/* 仅该弹窗使用的文本内容样式 */
|
||||||
|
.text-content {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-word;
|
||||||
|
color: #1e272e;
|
||||||
|
line-height: 1.6;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
user-select: text;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
document.head.appendChild(style);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示文本弹窗(手动调用)
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {string} opts.title 标题
|
||||||
|
* @param {string} opts.text 文本内容
|
||||||
|
* @param {'confirm'|'info'} opts.mode 模式:confirm=确认+关闭;info=仅关闭
|
||||||
|
* @param {string} [opts.confirmText='确认'] 确认按钮文案(仅 confirm 模式生效)
|
||||||
|
* @param {string} [opts.closeText='关闭'] 关闭按钮文案
|
||||||
|
* @returns {Promise<boolean>} confirm 返回 true;关闭/点遮罩返回 false
|
||||||
|
*/
|
||||||
|
function showTextModal(opts) {
|
||||||
|
const {
|
||||||
|
title = '提示', text = '', mode = 'info', confirmText = '确认', closeText = '关闭',
|
||||||
|
} = opts || {};
|
||||||
|
|
||||||
|
if (document.getElementById('textGenericOverlay')) {
|
||||||
|
return Promise.resolve(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const overlay = document.createElement('div');
|
||||||
|
overlay.id = 'textGenericOverlay';
|
||||||
|
|
||||||
|
const modal = document.createElement('div');
|
||||||
|
modal.className = 'text-generic-modal';
|
||||||
|
|
||||||
|
const header = document.createElement('div');
|
||||||
|
header.className = 'modal-header';
|
||||||
|
header.innerHTML = `<span>${title}</span>`;
|
||||||
|
|
||||||
|
const body = document.createElement('div');
|
||||||
|
body.className = 'modal-body';
|
||||||
|
const content = document.createElement('div');
|
||||||
|
content.className = 'text-content';
|
||||||
|
content.textContent = text ?? '';
|
||||||
|
body.appendChild(content);
|
||||||
|
|
||||||
|
const footer = document.createElement('div');
|
||||||
|
footer.className = 'modal-footer';
|
||||||
|
|
||||||
|
if (mode === 'confirm') {
|
||||||
|
const okBtn = document.createElement('button');
|
||||||
|
okBtn.className = 'primary-btn';
|
||||||
|
okBtn.textContent = confirmText;
|
||||||
|
okBtn.addEventListener('click', () => close(true));
|
||||||
|
footer.appendChild(okBtn);
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeBtn = document.createElement('button');
|
||||||
|
closeBtn.className = 'secondary-btn';
|
||||||
|
closeBtn.textContent = closeText;
|
||||||
|
closeBtn.addEventListener('click', () => close(false));
|
||||||
|
footer.appendChild(closeBtn);
|
||||||
|
|
||||||
|
modal.appendChild(header);
|
||||||
|
modal.appendChild(body);
|
||||||
|
modal.appendChild(footer);
|
||||||
|
overlay.appendChild(modal);
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
|
||||||
|
function close(result) {
|
||||||
|
overlay.style.animation = 'fadeOut 0.2s';
|
||||||
|
setTimeout(() => {
|
||||||
|
overlay.remove();
|
||||||
|
resolve(result);
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
overlay.addEventListener('click', (e) => {
|
||||||
|
if (e.target === overlay) close(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 创建开关项
|
// 创建开关项
|
||||||
const createSettingItem = ({label, description, checked}) => {
|
const createSettingItem = ({label, description, checked}) => {
|
||||||
const item = document.createElement('div');
|
const item = document.createElement('div');
|
||||||
@@ -962,155 +1044,74 @@ XHS-Downloader 用户脚本 详细说明:
|
|||||||
/* ==================== 样式定义 ==================== */
|
/* ==================== 样式定义 ==================== */
|
||||||
style = document.createElement('style');
|
style = document.createElement('style');
|
||||||
style.textContent = `
|
style.textContent = `
|
||||||
/* 弹窗基础样式 */
|
/* 图片选择弹窗:仅容器尺寸与自身网格等特有样式 */
|
||||||
#imageSelectionOverlay {
|
.image-selection-modal {
|
||||||
position: fixed;
|
background: white;
|
||||||
top: 0;
|
border-radius: 16px;
|
||||||
left: 0;
|
width: 80%;
|
||||||
width: 100%;
|
max-width: 900px;
|
||||||
height: 100%;
|
max-height: 90vh;
|
||||||
background: rgba(0,0,0,0.32);
|
box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
|
||||||
backdrop-filter: blur(4px);
|
overflow: hidden;
|
||||||
display: flex;
|
animation: scaleUp 0.3s;
|
||||||
justify-content: center;
|
display: flex;
|
||||||
align-items: center;
|
flex-direction: column;
|
||||||
z-index: 10000;
|
}
|
||||||
animation: fadeIn 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-selection-modal {
|
/* 图片网格等仅此弹窗拥有的样式 */
|
||||||
background: white;
|
.image-grid {
|
||||||
border-radius: 16px;
|
display: grid;
|
||||||
width: 80%;
|
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
|
||||||
max-width: 900px;
|
gap: 12px;
|
||||||
max-height: 90vh;
|
}
|
||||||
box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
|
.image-item {
|
||||||
overflow: hidden;
|
position: relative;
|
||||||
animation: scaleUp 0.3s;
|
border-radius: 8px;
|
||||||
display: flex;
|
overflow: hidden;
|
||||||
flex-direction: column;
|
cursor: pointer;
|
||||||
}
|
transition: all 0.2s;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
}
|
||||||
|
.image-item img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100px;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
.image-item.selected { border-color: #2196F3; }
|
||||||
|
|
||||||
/* 头部样式 */
|
.image-checkbox {
|
||||||
.modal-header {
|
position: absolute;
|
||||||
padding: 1rem;
|
top: 8px;
|
||||||
border-bottom: 1px solid #eee;
|
right: 8px;
|
||||||
text-align: center;
|
width: 20px;
|
||||||
}
|
height: 20px;
|
||||||
|
opacity: 0;
|
||||||
.modal-header span {
|
}
|
||||||
font-size: 1.25rem;
|
.image-checkbox + label {
|
||||||
font-weight: 500;
|
position: absolute;
|
||||||
color: #212121;
|
top: 8px;
|
||||||
}
|
right: 8px;
|
||||||
|
width: 20px;
|
||||||
/* 内容区域 */
|
height: 20px;
|
||||||
.modal-body {
|
background: white;
|
||||||
flex: 1;
|
border: 1px solid #ccc;
|
||||||
padding: 1rem;
|
border-radius: 50%;
|
||||||
overflow-y: auto;
|
cursor: pointer;
|
||||||
}
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
/* 图片网格 */
|
align-items: center;
|
||||||
.image-grid {
|
transition: all 0.2s;
|
||||||
display: grid;
|
}
|
||||||
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
|
.image-checkbox:checked + label {
|
||||||
gap: 12px;
|
background: #2196F3;
|
||||||
}
|
border-color: #2196F3;
|
||||||
|
}
|
||||||
.image-item {
|
.image-checkbox:checked + label::after {
|
||||||
position: relative;
|
content: "✓";
|
||||||
border-radius: 8px;
|
color: white;
|
||||||
overflow: hidden;
|
font-size: 12px;
|
||||||
cursor: pointer;
|
}
|
||||||
transition: all 0.2s;
|
|
||||||
border: 2px solid transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-item img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100px;
|
|
||||||
object-fit: cover;
|
|
||||||
border-radius: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-item.selected {
|
|
||||||
border-color: #2196F3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-checkbox {
|
|
||||||
position: absolute;
|
|
||||||
top: 8px;
|
|
||||||
right: 8px;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-checkbox + label {
|
|
||||||
position: absolute;
|
|
||||||
top: 8px;
|
|
||||||
right: 8px;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
background: white;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 50%;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
transition: all 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-checkbox:checked + label {
|
|
||||||
background: #2196F3;
|
|
||||||
border-color: #2196F3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-checkbox:checked + label::after {
|
|
||||||
content: "✓";
|
|
||||||
color: white;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 底部按钮 */
|
|
||||||
.modal-footer {
|
|
||||||
padding: 1rem;
|
|
||||||
border-top: 1px solid #eee;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.primary-btn {
|
|
||||||
background: #2196F3;
|
|
||||||
color: white;
|
|
||||||
padding: 8px 24px;
|
|
||||||
border-radius: 24px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.secondary-btn {
|
|
||||||
background: #f0f0f0;
|
|
||||||
color: #666;
|
|
||||||
padding: 8px 24px;
|
|
||||||
border-radius: 24px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 动画 */
|
|
||||||
@keyframes fadeIn {
|
|
||||||
from { opacity: 0; }
|
|
||||||
to { opacity: 1; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes scaleUp {
|
|
||||||
from { transform: scale(0.98); }
|
|
||||||
to { transform: scale(1); }
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
document.head.appendChild(style);
|
document.head.appendChild(style);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user