From 805d3037e63517ac791f5dc1a4ddc6a9ac508d0a Mon Sep 17 00:00:00 2001 From: intelligrow <15511098+intelligrow@user.noreply.gitee.com> Date: Mon, 23 Jun 2025 16:41:24 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=BC=BA=E4=BA=BA=E7=BE=A4?= =?UTF-8?q?=E7=94=BB=E5=83=8F=E6=89=B9=E9=87=8F=E4=B8=8B=E8=BD=BD=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=8C=E6=94=AF=E6=8C=81=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在现有的人群画像批量下载功能中,新增了自定义文件名的选项,用户可以根据需求设置下载文件的名称。这一改进提升了用户的灵活性和体验,同时保持了原有功能的稳定性。 --- douyin/douyinVideoDownload.user.js | 430 +++++++++++++++++++++++++++++ 1 file changed, 430 insertions(+) create mode 100644 douyin/douyinVideoDownload.user.js diff --git a/douyin/douyinVideoDownload.user.js b/douyin/douyinVideoDownload.user.js new file mode 100644 index 0000000..6b38d08 --- /dev/null +++ b/douyin/douyinVideoDownload.user.js @@ -0,0 +1,430 @@ +// ==UserScript== +// @name 抖音视频下载助手 +// @namespace https://github.com/scriptCat/ +// @version 1.0.0 +// @description 抖音视频下载助手,监听视频详情API并提供下载功能 +// @author wangxi +// @match https://www.douyin.com/* +// @grant GM_addStyle +// @grant GM_download +// @connect douyin.com +// @connect * +// @require https://cdn.jsdelivr.net/npm/sweetalert2@11 +// @run-at document-start +// @license MIT +// ==/UserScript== + + + +(function() { + 'use strict'; + + // 配置 + const CONFIG = { + enabled: true + }; + + // 当前视频信息 + let currentVideoInfo = null; + + // 简化工具函数 + function showToast(message, type = 'info') { + const Toast = Swal.mixin({ + toast: true, + position: 'top-end', + showConfirmButton: false, + timer: 2000 + }); + Toast.fire({ icon: type, title: message }); + } + + + + // 下载视频 + function downloadVideo() { + if (!currentVideoInfo) { + showToast('没有可下载的视频', 'error'); + return; + } + + const filename = `${currentVideoInfo.videoId}.mp4`; + console.log('[抖音下载] 下载链接:', currentVideoInfo.downloadUrl); + console.log('[抖音下载] 文件名:', filename); + + updateFloatingButton('downloading'); + + // 使用fetch下载并创建blob链接 + fetch(currentVideoInfo.downloadUrl, { + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', + 'Referer': 'https://www.douyin.com/', + 'Accept': '*/*' + } + }) + .then(response => { + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return response.blob(); + }) + .then(blob => { + // 创建下载链接 + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = filename; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + + showToast('下载成功', 'success'); + updateFloatingButton('ready'); + }) + .catch(error => { + console.error('[抖音下载] 下载失败:', error); + showToast('下载失败', 'error'); + updateFloatingButton('ready'); + }); + } + + // 创建悬浮按钮 + function createFloatingButton() { + // 检查是否已存在 + if (document.querySelector('.douyin-download-float')) { + return; + } + + const floatingButton = document.createElement('div'); + floatingButton.className = 'douyin-download-float'; + floatingButton.innerHTML = ` +
+ `; + + // 添加样式 + GM_addStyle(` + .douyin-download-float { + position: fixed; + bottom: 100px; + right: 30px; + z-index: 9999; + user-select: none; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + opacity: 0.8; + } + + .douyin-download-float:hover { + opacity: 1; + transform: scale(1.05); + } + + .douyin-download-float.dragging { + transition: none !important; + opacity: 1; + transform: scale(1.05); + } + + .douyin-download-btn { + display: flex; + align-items: center; + gap: 8px; + padding: 12px 16px; + background: linear-gradient(135deg, #ff6b6b 0%, #ff8e8e 100%); + color: white; + border-radius: 25px; + cursor: pointer; + font-size: 14px; + font-weight: 500; + box-shadow: 0 4px 12px rgba(255, 107, 107, 0.3); + transition: all 0.2s ease; + min-width: 80px; + justify-content: center; + } + + .douyin-download-btn:hover { + background: linear-gradient(135deg, #ff5252 0%, #ff7979 100%); + box-shadow: 0 6px 16px rgba(255, 107, 107, 0.4); + } + + .douyin-download-btn:active { + transform: scale(0.95); + } + + .douyin-download-btn.disabled { + background: linear-gradient(135deg, #d1d5db 0%, #9ca3af 100%); + cursor: not-allowed; + opacity: 0.6; + } + + .douyin-download-btn.downloading { + background: linear-gradient(135deg, #f59e0b 0%, #fbbf24 100%); + box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3); + } + + .douyin-download-icon { + width: 16px; + height: 16px; + flex-shrink: 0; + } + + .douyin-download-icon.spinning { + animation: spin 1s linear infinite; + } + + @keyframes spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } + } + + .douyin-download-text { + font-size: 13px; + font-weight: 600; + } + + /* 吸附效果 */ + .douyin-download-float.snap-right { + right: 0; + border-radius: 25px 0 0 25px; + } + + .douyin-download-float.snap-left { + left: 0; + border-radius: 0 25px 25px 0; + } + `); + + // 添加到页面 + document.body.appendChild(floatingButton); + + // 设置拖拽功能 + setupDragAndSnap(floatingButton); + + // 设置点击事件 + const downloadBtn = floatingButton.querySelector('.douyin-download-btn'); + downloadBtn.addEventListener('click', () => { + if (downloadBtn.classList.contains('disabled')) return; + + // 点击反馈 + downloadBtn.style.transform = 'scale(0.9)'; + setTimeout(() => { + downloadBtn.style.transform = ''; + }, 150); + + downloadVideo(); + }); + + + } + + // 设置拖拽和吸附功能 + function setupDragAndSnap(floatingButton) { + let isDragging = false; + let startX, startY, startLeft, startTop; + + floatingButton.addEventListener('mousedown', (e) => { + isDragging = true; + startX = e.clientX; + startY = e.clientY; + + const rect = floatingButton.getBoundingClientRect(); + startLeft = rect.left; + startTop = rect.top; + + floatingButton.classList.add('dragging'); + e.preventDefault(); + }); + + document.addEventListener('mousemove', (e) => { + if (!isDragging) return; + + const deltaX = e.clientX - startX; + const deltaY = e.clientY - startY; + + let newLeft = startLeft + deltaX; + let newTop = startTop + deltaY; + + // 限制在视窗内 + const maxX = window.innerWidth - floatingButton.offsetWidth; + const maxY = window.innerHeight - floatingButton.offsetHeight; + + newLeft = Math.max(0, Math.min(newLeft, maxX)); + newTop = Math.max(0, Math.min(newTop, maxY)); + + // 设置位置 + floatingButton.style.left = newLeft + 'px'; + floatingButton.style.top = newTop + 'px'; + floatingButton.style.right = 'auto'; + floatingButton.style.bottom = 'auto'; + }); + + document.addEventListener('mouseup', () => { + if (!isDragging) return; + + isDragging = false; + floatingButton.classList.remove('dragging'); + + // 吸附效果 + const rect = floatingButton.getBoundingClientRect(); + const windowWidth = window.innerWidth; + const centerX = rect.left + rect.width / 2; + + // 移除吸附类 + floatingButton.classList.remove('snap-left', 'snap-right'); + + if (centerX < windowWidth / 2) { + // 吸附到左边 + floatingButton.style.left = '0px'; + floatingButton.style.right = 'auto'; + floatingButton.classList.add('snap-left'); + } else { + // 吸附到右边 + floatingButton.style.right = '0px'; + floatingButton.style.left = 'auto'; + floatingButton.classList.add('snap-right'); + } + }); + } + + // 更新悬浮按钮状态 + function updateFloatingButton(status = 'ready') { + const floatingButton = document.querySelector('.douyin-download-float'); + if (!floatingButton) return; + + const downloadBtn = floatingButton.querySelector('.douyin-download-btn'); + const icon = floatingButton.querySelector('.douyin-download-icon'); + const text = floatingButton.querySelector('.douyin-download-text'); + + if (!downloadBtn || !icon || !text) return; + + // 移除所有状态类 + downloadBtn.classList.remove('disabled', 'downloading'); + icon.classList.remove('spinning'); + + switch (status) { + case 'ready': + if (currentVideoInfo) { + downloadBtn.title = `下载视频: ${currentVideoInfo.title}`; + text.textContent = '下载'; + icon.innerHTML = '