mirror of
https://github.com/JoeanAmier/XHS-Downloader.git
synced 2025-12-25 20:36:47 +08:00
refactor(script): 优化部分弹窗提示的交互界面样式
This commit is contained in:
parent
9ad005c381
commit
120e5d65c3
@ -24,4 +24,5 @@
|
||||
2. 添加未登录状态下无法提取作品链接的提示
|
||||
3. 脚本设置新增 `菜单始终显示` 配置项
|
||||
4. 修复用户脚本 CSS 样式冲突问题
|
||||
5. 优化提取作品 ID 的正则表达式
|
||||
5. 优化部分弹窗提示的交互界面样式
|
||||
6. 优化提取作品 ID 的正则表达式
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// ==UserScript==
|
||||
// @name XHS-Downloader
|
||||
// @namespace https://github.com/JoeanAmier/XHS-Downloader
|
||||
// @version 2.1.2
|
||||
// @version 2.1.3
|
||||
// @description 提取小红书作品/用户链接,下载小红书无水印图文/视频作品文件
|
||||
// @author JoeanAmier
|
||||
// @match http*://xhslink.com/*
|
||||
@ -45,17 +45,17 @@
|
||||
},
|
||||
}, // 位置配置
|
||||
position: {
|
||||
bottom: '8rem', left: '2rem'
|
||||
bottom: '6rem', left: '1rem'
|
||||
}, // 动画配置
|
||||
animation: {
|
||||
duration: 0.35, // 动画时长(s)
|
||||
duration: 0.25, // 动画时长(s)
|
||||
easing: 'cubic-bezier(0.4, 0, 0.2, 1)'
|
||||
}
|
||||
};
|
||||
|
||||
const readme = () => {
|
||||
const readme = async () => {
|
||||
const instructions = `
|
||||
XHS-Downloader 用户脚本 功能清单:
|
||||
功能清单:
|
||||
1. 下载小红书无水印作品文件
|
||||
2. 提取推荐页面作品链接
|
||||
3. 提取账号发布作品链接
|
||||
@ -65,7 +65,7 @@ XHS-Downloader 用户脚本 功能清单:
|
||||
7. 提取搜索结果作品链接
|
||||
8. 提取搜索结果用户链接
|
||||
|
||||
XHS-Downloader 用户脚本 详细说明:
|
||||
注意事项:
|
||||
1. 下载小红书无水印作品文件时,脚本需要花费时间处理文件,请等待片刻,请勿多次点击下载按钮
|
||||
2. 无水印作品文件较大,可能需要较长的时间处理,页面跳转可能会导致下载失败
|
||||
3. 提取账号发布、收藏、点赞、专辑作品链接时,脚本可以自动滚动页面直至加载全部作品
|
||||
@ -77,30 +77,35 @@ XHS-Downloader 用户脚本 详细说明:
|
||||
项目开源地址:https://github.com/JoeanAmier/XHS-Downloader
|
||||
`
|
||||
const disclaimer_content = `
|
||||
关于 XHS-Downloader 的 免责声明:
|
||||
|
||||
1. 使用者对本项目的使用由使用者自行决定,并自行承担风险。作者对使用者使用本项目所产生的任何损失、责任、或风险概不负责。
|
||||
2. 本项目的作者提供的代码和功能是基于现有知识和技术的开发成果。作者尽力确保代码的正确性和安全性,但不保证代码完全没有错误或缺陷。
|
||||
3. 使用者在使用本项目时必须严格遵守 GNU General Public License v3.0 的要求,并在适当的地方注明使用了 GNU General Public License v3.0 的代码。
|
||||
4. 使用者在任何情况下均不得将本项目的作者、贡献者或其他相关方与使用者的使用行为联系起来,或要求其对使用者使用本项目所产生的任何损失或损害负责。
|
||||
2. 本项目的作者提供的代码和功能是基于现有知识和技术的开发成果。作者按现有技术水平努力确保代码的正确性和安全性,但不保证代码完全没有错误或缺陷。
|
||||
3. 本项目依赖的所有第三方库、插件或服务各自遵循其原始开源或商业许可,使用者需自行查阅并遵守相应协议,作者不对第三方组件的稳定性、安全性及合规性承担任何责任。
|
||||
4. 使用者在使用本项目时必须严格遵守 GNU General Public License v3.0 的要求,并在适当的地方注明使用了 GNU General Public License v3.0 的代码。
|
||||
5. 使用者在使用本项目的代码和功能时,必须自行研究相关法律法规,并确保其使用行为合法合规。任何因违反法律法规而导致的法律责任和风险,均由使用者自行承担。
|
||||
6. 本项目的作者不会提供 XHS-Downloader 项目的付费版本,也不会提供与 XHS-Downloader 项目相关的任何商业服务。
|
||||
7. 基于本项目进行的任何二次开发、修改或编译的程序与原创作者无关,原创作者不承担与二次开发行为或其结果相关的任何责任,使用者应自行对因二次开发可能带来的各种情况负全部责任。
|
||||
6. 使用者不得使用本工具从事任何侵犯知识产权的行为,包括但不限于未经授权下载、传播受版权保护的内容,开发者不参与、不支持、不认可任何非法内容的获取或分发。
|
||||
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) {
|
||||
const answer = prompt(disclaimer_content, "");
|
||||
if (!answer) {
|
||||
GM_setValue("disclaimer", false);
|
||||
config.disclaimer = false;
|
||||
} else {
|
||||
GM_setValue("disclaimer", answer.toUpperCase() === "YES" || answer.toUpperCase() === "Y");
|
||||
config.disclaimer = GM_getValue("disclaimer");
|
||||
}
|
||||
showTextModal({
|
||||
title: 'XHS-Downloader 免责声明', text: disclaimer_content, mode: 'confirm', // confirm: 确认+关闭
|
||||
confirmText: '我已知晓', closeText: '关闭'
|
||||
}).then(answer => {
|
||||
GM_setValue("disclaimer", answer);
|
||||
config.disclaimer = answer;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -149,9 +154,21 @@ XHS-Downloader 用户脚本 详细说明:
|
||||
}
|
||||
|
||||
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 => {
|
||||
try {
|
||||
return [`https://sns-video-bd.xhscdn.com/${note.video.consumer.originVideoKey}`];
|
||||
@ -518,7 +535,7 @@ XHS-Downloader 用户脚本 详细说明:
|
||||
if (order >= 0 && order <= 2) {
|
||||
data = extractNotesInfo(order);
|
||||
if (!invalidDetection(data)) {
|
||||
alert("提取作品链接失败!受平台限制,未登录状态下无法通过账号主页浏览作品!");
|
||||
runTips("提取作品链接失败!受平台限制,未登录状态下无法通过账号主页浏览作品详情!请登录后重试!");
|
||||
return;
|
||||
}
|
||||
} else if (order === 3) {
|
||||
@ -550,217 +567,282 @@ XHS-Downloader 用户脚本 详细说明:
|
||||
};
|
||||
|
||||
if (typeof JSZip === 'undefined') {
|
||||
alert("XHS-Downloader 用户脚本依赖库 JSZip 加载失败,作品文件打包下载功能无法使用,请尝试刷新网页或者向作者反馈!");
|
||||
runTips("XHS-Downloader 用户脚本依赖库 JSZip 加载失败,作品文件打包下载功能无法使用,请尝试刷新网页或者向作者反馈!");
|
||||
}
|
||||
|
||||
/* ==================== 样式定义 ==================== */
|
||||
let style = document.createElement('style');
|
||||
style.textContent = `
|
||||
/* 弹窗基础样式 */
|
||||
#SettingsOverlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.32);
|
||||
backdrop-filter: blur(4px);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 10000;
|
||||
animation: fadeIn 0.3s;
|
||||
}
|
||||
/* 通用 Overlay(三个弹窗共用) */
|
||||
#SettingsOverlay,
|
||||
#imageSelectionOverlay,
|
||||
#textGenericOverlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.32);
|
||||
backdrop-filter: blur(4px);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 10000;
|
||||
animation: fadeIn 0.3s;
|
||||
}
|
||||
|
||||
.optimized-scroll-modal {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
width: 380px; /* 缩小窗口宽度 */
|
||||
max-width: 95vw;
|
||||
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;
|
||||
}
|
||||
/* Settings 容器,仅本块特有尺寸 */
|
||||
.optimized-scroll-modal {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
width: 380px; /* 缩小窗口宽度 */
|
||||
max-width: 95vw;
|
||||
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;
|
||||
}
|
||||
|
||||
/* 头部样式 */
|
||||
.modal-header {
|
||||
padding: 1rem;
|
||||
border-bottom: 1px solid #eee;
|
||||
text-align: center;
|
||||
}
|
||||
/* 通用头部/内容/底部/按钮(三个弹窗共用) */
|
||||
.modal-header {
|
||||
padding: 1rem;
|
||||
border-bottom: 1px solid #eee;
|
||||
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 {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 500;
|
||||
color: #212121;
|
||||
}
|
||||
/* Settings 专用的设置项样式(保持不变) */
|
||||
.setting-item {
|
||||
margin: 0.5rem 0;
|
||||
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;
|
||||
}
|
||||
|
||||
/* 内容区域 */
|
||||
.modal-body {
|
||||
padding: 1rem; /* 减小内边距 */
|
||||
}
|
||||
.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); }
|
||||
|
||||
/* 设置项样式 */
|
||||
.setting-item {
|
||||
margin: 0.5rem 0; /* 减少设置项间距 */
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
.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;
|
||||
}
|
||||
|
||||
.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 {
|
||||
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); }
|
||||
}
|
||||
/* 通用动画:统一定义一次 */
|
||||
@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; } }
|
||||
`;
|
||||
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 item = document.createElement('div');
|
||||
@ -962,155 +1044,74 @@ XHS-Downloader 用户脚本 详细说明:
|
||||
/* ==================== 样式定义 ==================== */
|
||||
style = document.createElement('style');
|
||||
style.textContent = `
|
||||
/* 弹窗基础样式 */
|
||||
#imageSelectionOverlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.32);
|
||||
backdrop-filter: blur(4px);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 10000;
|
||||
animation: fadeIn 0.3s;
|
||||
}
|
||||
/* 图片选择弹窗:仅容器尺寸与自身网格等特有样式 */
|
||||
.image-selection-modal {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
width: 80%;
|
||||
max-width: 900px;
|
||||
max-height: 90vh;
|
||||
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;
|
||||
}
|
||||
|
||||
.image-selection-modal {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
width: 80%;
|
||||
max-width: 900px;
|
||||
max-height: 90vh;
|
||||
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;
|
||||
}
|
||||
/* 图片网格等仅此弹窗拥有的样式 */
|
||||
.image-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
.image-item {
|
||||
position: relative;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
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; }
|
||||
|
||||
/* 头部样式 */
|
||||
.modal-header {
|
||||
padding: 1rem;
|
||||
border-bottom: 1px solid #eee;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.modal-header span {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 500;
|
||||
color: #212121;
|
||||
}
|
||||
|
||||
/* 内容区域 */
|
||||
.modal-body {
|
||||
flex: 1;
|
||||
padding: 1rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* 图片网格 */
|
||||
.image-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.image-item {
|
||||
position: relative;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
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); }
|
||||
}
|
||||
.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;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user