图片下载 | 页面所有图片打包下载 | 单张下载 | 图片预览放大,旋转,信息展示 | 简单有效,想要哪张点哪张

简单纯洁的网页图片下载工具,侵入性小不影响原网页显示,可集中展示页面所有图片,可点击预览放大,可旋转,可查看图片信息(尺寸,格式,图片大小) | (Ctrl+鼠标右键)下载单个图片

  1. // ==UserScript==
  2. // @name 图片下载 | 页面所有图片打包下载 | 单张下载 | 图片预览放大,旋转,信息展示 | 简单有效,想要哪张点哪张
  3. // @namespace http://tampermonkey.net/
  4. // @description 简单纯洁的网页图片下载工具,侵入性小不影响原网页显示,可集中展示页面所有图片,可点击预览放大,可旋转,可查看图片信息(尺寸,格式,图片大小) | (Ctrl+鼠标右键)下载单个图片
  5. // @description:zh-CN 一个帮你快速捕获网页图片并打包下载、也可单张下载的小工具🔧
  6. // @author <shing0727@foxmail.com>
  7. // @version v4.1.0
  8. // @license GPLv3
  9. // @icon https://s21.ax1x.com/2024/05/14/pkmNM0s.png
  10. // @require https://code.jquery.com/jquery-3.6.0.min.js
  11. // @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.6.0/jszip.min.js
  12. // @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js
  13. // @require https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.6/viewer.min.js
  14. // @grant GM_xmlhttpRequest
  15. // @grant GM_addStyle
  16. // @grant GM_download
  17. // @grant GM_registerMenuCommand
  18. // @match *://*/*
  19. // @connect *
  20. // @grant GM_getValue
  21. // @grant GM_setValue
  22.  
  23. // ==/UserScript==
  24.  
  25.  
  26. var isPackLoad = false
  27. // 多图片打包下载
  28. const downloadPackZipImgs = (all_imgs = []) => {
  29. if (!all_imgs.length || isPackLoad) return;
  30. isPackLoad = true
  31. isTopLoading(true, all_imgs.length)
  32. const zip = new JSZip();
  33. var currNum = 0;
  34. let total = all_imgs.length
  35.  
  36. Promise.all(
  37. all_imgs.map((item, index) => {
  38. if (item.blob) {
  39. zip.file(item.imgName, item.blob, { binary: true });
  40. realTimeSchedule(++currNum, total)
  41. return Promise.resolve()
  42. }
  43. return new Promise((resolve, reject) => {
  44. GM_xmlhttpRequest({
  45. method: "GET",
  46. url: item.src,
  47. responseType: "blob",
  48. onload: function (response) {
  49. if (response.status === 200) {
  50. let blob = response.response;
  51. item.blob = blob
  52. if (blob.size > (1024 * 1024)) {
  53. item.size = (blob.size / (1024 * 1024)).toFixed(1) + 'MB'
  54. } else if (blob.size < (1024 * 1024) && blob.size > 1024) {
  55. item.size = (blob.size / 1024).toFixed(1) + 'KB'
  56. } else {
  57. item.size = blob.size + '字节'
  58. }
  59. setItemImgsName(item)
  60. updateNodeItem(item)
  61. const filename = item.imgName;
  62. zip.file(filename, blob, { binary: true });
  63.  
  64. } else {
  65. console.error("请求报错,状态码: " + response.status);
  66. }
  67. realTimeSchedule(++currNum, total)
  68. resolve();
  69. },
  70. onerror: function (e) {
  71. console.error("请求失败: " + e.message);
  72. realTimeSchedule(++currNum, total)
  73. resolve();
  74. },
  75. });
  76. });
  77. })
  78. )
  79. .then(() => {
  80. // let domain = window.location.href.replace(/^https?:\/\//i, "");
  81. zip.generateAsync({ type: "blob" }).then((blob) => {
  82. // saveAs(blob, `【${document.title}】【${domain}】.zip`);
  83. let str = $('#ccc_all_page_rename_val').val()
  84. str = str.length > 245 ? str.substring(0, 245) : str;
  85. saveAs(blob, `${str}.zip`);
  86. });
  87. }).finally(() => {
  88. isPackLoad = false
  89. isTopLoading(false)
  90. })
  91.  
  92. }
  93. // 指定数组元素对象属性去重、去除宽高小于1的
  94. function removeDuplicatesByProperty(arr = [], property) {
  95. const seenIds = new Set();
  96. return arr.filter(item => {
  97. const isUnique = !seenIds.has(item[property]);
  98. if (isUnique) {
  99. seenIds.add(item[property]);
  100. }
  101. return isUnique;
  102. });
  103. }
  104.  
  105. // 根据blob设置图片后缀名
  106. function setItemImgsName(item) {
  107. try {
  108. let { src = "", blob = {} } = item
  109. let name = src.match(/\/([^\/?#]+)(?:[?#]|$)/)[1].split('.')[0]
  110. if (blob?.type && blob?.type.includes('image')) {
  111. item.lastName = blob.type.match(/^image\/([a-zA-Z0-9]+)/)[1]
  112. item.isImg = true
  113. } else {
  114. item.isImg = false
  115. }
  116. item.imgName = decodeURIComponent(name + '.' + item.lastName)
  117. } catch (e) {
  118. console.log('e = ', e)
  119. }
  120. }
  121. // 更新节点显示信息
  122. function updateNodeItem(item) {
  123. try {
  124. $('.ccc_image_item').each(function () {
  125. if ($(this).attr('data-imgsrc') == item.src) {
  126. let info = ''
  127. let imgDom = $(this).children('img')[0]
  128. if (imgDom.naturalWidth || imgDom.naturalHeight) {
  129. info = imgDom.naturalWidth + ' x ' + imgDom.naturalHeight
  130. item.width = imgDom.naturalWidth
  131. item.height = imgDom.naturalHeight
  132. }
  133. if (item.lastName) {
  134. info += (' | ' + item.lastName.toUpperCase())
  135. }
  136. if (item.size) {
  137. info += (' | ' + item.size)
  138. }
  139. $(this).find('.ccc_imgItem_info').text(info)
  140. item.isFullInfo = true
  141. }
  142. })
  143. } catch (e) {
  144. console.log(e)
  145. }
  146. }
  147.  
  148. // 获取单张图片blob
  149. const getSingleBlob = (item) => {
  150. return new Promise((resolve, reject) => {
  151. GM_xmlhttpRequest({
  152. method: "GET",
  153. url: item.src,
  154. responseType: "blob",
  155. onload: function (response) {
  156. if (response.status === 200) {
  157. let blob = response.response;
  158. item.blob = blob
  159. if (blob.size > (1024 * 1024)) {
  160. item.size = (blob.size / (1024 * 1024)).toFixed(1) + 'MB'
  161. } else if (blob.size < (1024 * 1024) && blob.size > 1024) {
  162. item.size = (blob.size / 1024).toFixed(1) + 'KB'
  163. } else {
  164. item.size = blob.size + '字节'
  165. }
  166. setItemImgsName(item)
  167. updateNodeItem(item)
  168. resolve(item);
  169. } else {
  170. console.error("请求报错,状态码: " + response.status);
  171. }
  172. },
  173. onerror: function (e) {
  174. console.error("请求失败: " + e.message);
  175. reject();
  176. },
  177. });
  178. })
  179. }
  180.  
  181. // 根据svg元素返回{src,blob}
  182. const getSvgAsFile = (svgElement) => {
  183. // 将 SVG 元素序列化为字符串
  184. const svgString = new XMLSerializer().serializeToString(svgElement);
  185. // 创建一个包含 SVG 数据的 Blob 对象
  186. const blob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });
  187. // 创建一个 URL 对象
  188. const src = URL.createObjectURL(blob);
  189. return {
  190. src,
  191. blob,
  192. }
  193. }
  194.  
  195.  
  196. // 获取页面所有图片
  197. const loadAllImgUrls = async () => {
  198. all_imgs = []
  199. document.querySelectorAll("img").forEach((item) => {
  200. let src = item?.src || item.getAttribute("srcset");
  201. if (!src) return;
  202. if (origin_all_imageUrls.some(n => {
  203. if (n.src === src) {
  204. all_imgs.push(n)
  205. return true
  206. } else {
  207. false
  208. }
  209. })) return;
  210.  
  211. let imgName = getImageFileNameFromUrl(src)
  212. let lastName = ''
  213. if (imgName.includes('.')) {
  214. let last = imgName.split('.').pop()
  215. if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg', 'tiff', 'tif', 'avif'].includes(last)) {
  216. lastName = last
  217. }
  218. }
  219. all_imgs.push({
  220. src,
  221. imgName,
  222. lastName,
  223. width: item.naturalWidth,
  224. height: item.naturalHeight,
  225. });
  226. });
  227. // 获取SVG标签图片
  228. // document.querySelectorAll("svg").forEach((svgDom, index) => {
  229. // let {src, blob} = getSvgAsFile(svgDom)
  230. // const { width, height } = svgDom.getBoundingClientRect();
  231. // all_imgs.push({
  232. // src,
  233. // blob,
  234. // imgName: `svg_${index}.svg`,
  235. // lastName: 'svg',
  236. // width,
  237. // height
  238. // });
  239. // })
  240. resetImgsObj(all_imgs)
  241. }
  242.  
  243. const reFetchImgs = () => {
  244. loadAllImgUrls()
  245. let w_min = parseInt($('#ccc_w_min').val()) || 0
  246. let w_max = parseInt($('#ccc_w_max').val()) || 99999
  247. let h_min = parseInt($('#ccc_h_min').val()) || 0
  248. let h_max = parseInt($('#ccc_h_max').val()) || 99999
  249. all_imageUrls = valid_all_imageUrls.filter(item => {
  250. if (item.width < w_min || item.width > w_max) return false
  251. if (item.height < h_min || item.height > h_max) return false
  252. return true
  253. })
  254. reRender()
  255. showNotify('已刷新')
  256. }
  257.  
  258. // 显示通知
  259. var notifyTimer = null;
  260. function showNotify(msg) {
  261. if (notifyTimer) {
  262. clearTimeout(notifyTimer)
  263. $('#ccc_notify').remove()
  264. }
  265. $('#ccc_popUps_container').append(`<div id="ccc_notify">${msg}</div>`)
  266. setTimeout(() => {
  267. $('#ccc_notify').addClass('active')
  268. }, 16);
  269. notifyTimer = setTimeout(() => {
  270. $('#ccc_notify').remove()
  271. }, 1000);
  272. }
  273.  
  274.  
  275.  
  276. // 获取图片名称
  277. function getImageFileNameFromUrl(url) {
  278. // 正则表达式匹配最后一个'/'和第一个'?'之间的内容(如果存在)
  279. // 或者最后一个'/'和字符串结尾之间的内容(如果不存在查询参数)
  280. const regex = /\/([^?\/]+?)(?:\?|$|@)/;
  281. const match = url.match(regex);
  282. if (match && match[1]) {
  283. // match[1] 是文件名(不包括查询参数及其后面的部分)
  284. return match[1];
  285. }
  286. return "default.jpg";
  287. }
  288.  
  289. // 获取图片扩展名
  290. function getImageExtension(url) {
  291. var extension = url.match(/\.(jpg|jpeg|png|gif|bmp|webp|svg|tiff|tif|avif)$/i);
  292. if (extension) {
  293. return '';
  294. }
  295. if (url.includes("data:image/png")) {
  296. return '.png'
  297. }
  298. if (url.includes("data:image/gif")) {
  299. return '.gif'
  300. }
  301.  
  302. return '.jpg'
  303. }
  304.  
  305. function deepClone(source) {
  306. if (!source && typeof source !== 'object') {
  307. throw new Error('error arguments', 'deepClone')
  308. }
  309. const targetObj = source.constructor === Array ? [] : {}
  310. Object.keys(source).forEach(keys => {
  311. if (source[keys] && typeof source[keys] === 'object') {
  312. targetObj[keys] = deepClone(source[keys])
  313. } else {
  314. targetObj[keys] = source[keys]
  315. }
  316. })
  317. return targetObj
  318. }
  319.  
  320. var origin_all_imageUrls = []; // 所有图片
  321. var valid_all_imageUrls = []; // 有效图片 = 所有图片 - 移除图片
  322. var all_imageUrls = []; // 筛选后的图片
  323. // 初始化加载图片数据
  324. const resetImgsObj = (imgsObj = []) => {
  325. imgsObj = removeDuplicatesByProperty(imgsObj, 'src')
  326. if (imgsObj.length) {
  327. origin_all_imageUrls = deepClone(imgsObj)
  328. valid_all_imageUrls = deepClone(imgsObj)
  329. all_imageUrls = deepClone(imgsObj)
  330. $('.pop_title_num').text(all_imageUrls.length)
  331. $('#load_mask').css('display', 'none')
  332. $('#open_popUps_icon>.pop_title_num').css('display', 'block')
  333. reRender()
  334. } else {
  335. }
  336. }
  337.  
  338.  
  339. // blob图片下载
  340. const blobDownload = (item = {}) => {
  341. let { blob, imgName } = item
  342. // 创建一个Blob UFRL
  343. const url = window.URL.createObjectURL(blob);
  344. // 创建一个<a>标签用于下载
  345. const a = document.createElement("a");
  346. a.href = url;
  347. a.download = imgName; // 设置下载的文件名
  348. a.style.display = "none";
  349. // 触发点击事件
  350. document.body.appendChild(a);
  351. a.click();
  352. // 释放URL对象
  353. window.URL.revokeObjectURL(url);
  354. // 清理<a>标签
  355. document.body.removeChild(a);
  356. }
  357.  
  358. // 渲染图片列表
  359. var viewer = null;
  360. const reRender = () => {
  361. // // 去除宽高小于1
  362. // all_imageUrls = all_imageUrls.filter(item => {
  363. // return item.width > 1 && item.height > 1
  364. // })
  365. $('.pop_title_num').text(all_imageUrls.length)
  366. var $newElements = $();
  367. all_imageUrls.forEach(item => {
  368. let addCss = item.isFullInfo === true ? 'hide_more' : ''
  369. var $el = $('<div>', { class: 'ccc_image_item ' + addCss, "data-imgsrc": item.src });
  370. var $img = $('<img>', { src: item.src, alt: item.imgName, title: '预览' });
  371.  
  372. let info = '';
  373. if (item.width || item.height) {
  374. info = item.width + ' x ' + item.height
  375. }
  376. if (item.lastName) {
  377. let s = (item.width || item.height) ? ' | ' : ''
  378. info += (s + item.lastName.toUpperCase())
  379. }
  380. if (item.size) {
  381. info += (' | ' + item.size)
  382. }
  383.  
  384. var $infoBox = $('<div>', { text: info, class: 'ccc_imgItem_info' });
  385.  
  386. $img.appendTo($el);
  387. $infoBox.appendTo($el);
  388.  
  389. $newElements = $.merge($newElements, $el);
  390. });
  391. $('#ccc_image_container').empty().append($newElements);
  392. $('.ccc_image_item').each(function () {
  393. $(this).append(`
  394. <div class="ccc_imgItem_ctrl">
  395. <div class="click_style" title="下载"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" t="1723013152119" class="icon" viewBox="0 0 1024 1024" version="1.1" p-id="6158" width="200" height="200"><path d="M862.39 161.61A222.53 222.53 0 0 0 704 96H320A224 224 0 0 0 96 320v384a224 224 0 0 0 224 224h384a224 224 0 0 0 224-224V320a222.53 222.53 0 0 0-65.61-158.39zM704 736a32 32 0 0 1-32 32H352a32 32 0 0 1-32-32 32 32 0 0 1 32-32h320a32 32 0 0 1 32 32z m-8.88-211.62L529.75 634.63a32 32 0 0 1-35.5 0L328.88 524.38A32 32 0 0 1 320 480a32 32 0 0 1 44.38-8.88l103.18 68.8a8 8 0 0 0 12.44-6.66V288a32 32 0 0 1 32-32 32 32 0 0 1 32 32v245.26a8 8 0 0 0 12.44 6.66l103.18-68.8A32 32 0 0 1 704 480a32 32 0 0 1-8.88 44.38z" fill="#ffffff" p-id="6159"/></svg></div>
  396. </div>
  397. <div class="ccc_imgItem_delete click_style" title="移除"><span></span></div>
  398. `)
  399. $(this).find('.ccc_imgItem_info').append(`
  400. <span class="ccc_more"> ···</span>
  401. `)
  402. })
  403.  
  404. viewer && viewer.destroy();
  405. viewer = new Viewer(document.getElementById('ccc_image_container'));
  406. }
  407.  
  408. const setLoading = (target, isLoading = true) => {
  409. if (isLoading) {
  410. $(target).append(
  411. `
  412. <div id="ccc_itemImgLoading">
  413. <div class="loader"></div>
  414. </div>
  415. `
  416. )
  417. } else {
  418. $(target).find('#ccc_itemImgLoading').remove();
  419. }
  420. }
  421.  
  422. var ccc_currentVersion = 'v4.1.0';
  423. var hasUpdate = false;
  424. var onlineVersion = null; // 线上版本号
  425. var online_homeUrl = 'https://greasyfork.org/zh-CN/scripts/492706-%E5%9B%BE%E7%89%87%E4%B8%8B%E8%BD%BD-%E9%A1%B5%E9%9D%A2%E6%89%80%E6%9C%89%E5%9B%BE%E7%89%87%E6%89%93%E5%8C%85%E4%B8%8B%E8%BD%BD-%E5%8D%95%E5%BC%A0%E4%B8%8B%E8%BD%BD-%E5%9B%BE%E7%89%87%E9%A2%84%E8%A7%88%E6%94%BE%E5%A4%A7-%E6%97%8B%E8%BD%AC-%E4%BF%A1%E6%81%AF%E5%B1%95%E7%A4%BA-%E7%AE%80%E5%8D%95%E6%9C%89%E6%95%88-%E6%83%B3%E8%A6%81%E5%93%AA%E5%BC%A0%E7%82%B9%E5%93%AA%E5%BC%A0'; // 脚本首页地址
  426. var online_update_url = 'https://update.greasyfork.org/scripts/492706/%E5%9B%BE%E7%89%87%E4%B8%8B%E8%BD%BD%20%7C%20%E9%A1%B5%E9%9D%A2%E6%89%80%E6%9C%89%E5%9B%BE%E7%89%87%E6%89%93%E5%8C%85%E4%B8%8B%E8%BD%BD%20%7C%20%E5%8D%95%E5%BC%A0%E4%B8%8B%E8%BD%BD%20%7C%20%E5%9B%BE%E7%89%87%E9%A2%84%E8%A7%88%E6%94%BE%E5%A4%A7,%E6%97%8B%E8%BD%AC,%E4%BF%A1%E6%81%AF%E5%B1%95%E7%A4%BA%20%7C%20%E7%AE%80%E5%8D%95%E6%9C%89%E6%95%88%EF%BC%8C%E6%83%B3%E8%A6%81%E5%93%AA%E5%BC%A0%E7%82%B9%E5%93%AA%E5%BC%A0.user.js'; // 脚本首页地址
  427. const loadUpdateTamp = () => {
  428. const extractVersion = (htmlString) => {
  429. // 使用正则表达式匹配 data-script-version 属性的值
  430. const versionMatch = htmlString.match(/data-script-version="([^"]+)"/);
  431. // 如果匹配成功,返回版本号;否则返回 null
  432. return versionMatch ? versionMatch[1] : null;
  433. }
  434.  
  435. const isUpdateAvailable = (ccc_currentVersion, onlineVersion) => {
  436. const current = ccc_currentVersion.replace('v', '').split('.').map(Number);
  437. const online = onlineVersion.replace('v', '').split('.').map(Number);
  438. for (let i = 0; i < Math.max(current.length, online.length); i++) {
  439. const currentPart = current[i] || 0; // 如果当前版本号部分不存在,则默认为 0
  440. const onlinePart = online[i] || 0; // 如果线上版本号部分不存在,则默认为 0
  441. if (onlinePart > currentPart) {
  442. return true; // 如果线上版本号更高,则需要更新
  443. } else if (onlinePart < currentPart) {
  444. return false; // 如果线上版本号更低,则不需要更新
  445. }
  446. // 如果当前部分的版本号相等,继续比较下一部分
  447. }
  448. // 如果所有部分的版本号都相等,则不需要更新
  449. return false;
  450. }
  451.  
  452. GM_xmlhttpRequest({
  453. method: "GET",
  454. url: online_homeUrl,
  455. onload: function (res) {
  456. if (res.status === 200) {
  457. onlineVersion = extractVersion(res.response)
  458. hasUpdate = isUpdateAvailable(ccc_currentVersion, onlineVersion)
  459.  
  460. if (hasUpdate) {
  461. GM_registerMenuCommand("有新版本啦~(♥ω", function () {
  462. window.open(online_update_url, '_blank');
  463. });
  464. $('#ccc_gotoUpdate').append(`
  465. <a href="${online_update_url}" target="_blank">有新版本啦,快去体验下吧~(♥ω</a>
  466. `)
  467. }
  468. }
  469. },
  470. onerror: function (e) {
  471. console.error(e);
  472. },
  473. });
  474.  
  475. }
  476.  
  477. // 渲染展示筛选条件
  478. function renderViewFilter() {
  479. let w_min = $('#ccc_w_min').val()
  480. let w_max = $('#ccc_w_max').val() || '∞'
  481. let h_min = $('#ccc_h_min').val()
  482. let h_max = $('#ccc_h_max').val() || '∞'
  483.  
  484. let isView = false
  485. $('#ccc_view_filter_itembox').empty();
  486. if (w_min || $('#ccc_w_max').val()) {
  487. $('#ccc_view_filter_itembox').append(`
  488. <span>宽 ${w_min || 0} - ${w_max}</span>
  489. `)
  490. isView = true
  491. }
  492. if (h_min || $('#ccc_h_max').val()) {
  493. $('#ccc_view_filter_itembox').append(`
  494. <span>高 ${h_min || 0} - ${h_max}</span>
  495. `)
  496. isView = true
  497. }
  498. if (isView) {
  499. $('.ccc_view_filter').css({ display: 'flex' })
  500. } else {
  501. $('.ccc_view_filter').css({ display: 'none' })
  502. }
  503. }
  504.  
  505. // 主要交互操作逻辑
  506. const loadMainOperations = () => {
  507.  
  508. GM_registerMenuCommand("打开图片列表(ALT + Q)", function () {
  509. handleOpenPopPus()
  510. });
  511.  
  512. var isOpenPop = false;
  513. // 处理打开弹窗
  514. const handleOpenPopPus = () => {
  515. isOpenPop = true;
  516. document.querySelector('#ccc_popUps_out').style.display = 'block';
  517. setLayout();
  518. }
  519. // 处理关闭弹窗
  520. const handleClosePop = () => {
  521. isOpenPop = false
  522. document.querySelector('#ccc_popUps_out').style.display = 'none';
  523. }
  524. // 关闭弹窗
  525. document.querySelector('#ccc_close_popUps').onclick = function () {
  526. handleClosePop()
  527. }
  528. // 快捷键事件
  529. document.addEventListener('keydown', function (event) {
  530. // 按alt + ` 显隐弹窗
  531. if (event.altKey && (event.key === 'Q' || event.key === 'q')) {
  532. isOpenPop ? handleClosePop() : handleOpenPopPus()
  533. }
  534. // Esc键-关闭弹窗
  535. if (event.key === 'Escape' || event.key === 'Esc') {
  536. handleClosePop()
  537. }
  538. });
  539.  
  540. const setLayout = () => {
  541. reRender() //渲染图片
  542. let container_h = ccc_popUps_container.offsetHeight - 30;
  543. ccc_image_container.style.height = (container_h - ccc_popUps_top.offsetHeight - 30) + 'px';
  544. }
  545. var isShowFilter = false;
  546. // 显示筛选
  547. const showHideFilter = (is, key) => {
  548. isShowFilter = is
  549. let speed = 300
  550. key === 'leave' && (speed = 500)
  551. if (key === 'enter') {
  552. $('#ccc_filter_container').stop();
  553. $('#ccc_filter_container').css('opacity', 1)
  554. return;
  555. }
  556.  
  557. if (isShowFilter) {
  558. $('#ccc_filter_container').fadeIn(speed);
  559. } else {
  560. $('#ccc_filter_container').fadeOut(speed);
  561. }
  562. }
  563.  
  564.  
  565. $('#ccc_filter_btn').click(function (e) {
  566. e.stopPropagation(); // 阻止事件冒泡
  567. isShowFilter = !isShowFilter
  568. showHideFilter(isShowFilter)
  569. })
  570. $('#ccc_filter_container').click(function (e) {
  571. e.stopPropagation(); // 阻止事件冒泡
  572. })
  573. $(document).click(function (e) {
  574. showHideFilter(false)
  575. })
  576.  
  577. $('#ccc_filter_container').mouseleave(function () {
  578. showHideFilter(false, 'leave')
  579. });
  580.  
  581. $('#ccc_filter_container').mouseenter(function () {
  582. showHideFilter(true, 'enter')
  583. });
  584.  
  585. // 筛选input触发
  586. $('.ccc_filter_input').on('input', function () {
  587. let w_min = parseInt($('#ccc_w_min').val()) || 0
  588. let w_max = parseInt($('#ccc_w_max').val()) || 99999
  589. let h_min = parseInt($('#ccc_h_min').val()) || 0
  590. let h_max = parseInt($('#ccc_h_max').val()) || 99999
  591. all_imageUrls = valid_all_imageUrls.filter(item => {
  592. if (item.width < w_min || item.width > w_max) return false
  593. if (item.height < h_min || item.height > h_max) return false
  594. return true
  595. })
  596. reRender()
  597. renderViewFilter()
  598. });
  599. // 重置筛选触发
  600. $("#refilter_btn").click(function () {
  601. $('#ccc_w_min').val('')
  602. $('#ccc_w_max').val('')
  603. $('#ccc_h_min').val('')
  604. $('#ccc_h_max').val('')
  605. all_imageUrls = valid_all_imageUrls
  606. reRender()
  607. renderViewFilter()
  608. })
  609.  
  610.  
  611. // 点击按钮下载单张图片
  612. $('#ccc_image_container').on('click', '.ccc_imgItem_ctrl svg', function () {
  613. let url = $(this).closest('.ccc_image_item').attr('data-imgsrc')
  614. let item = all_imageUrls.filter(item => item.src === url)[0]
  615. if (item.lock) return;
  616. item.lock = true
  617. let target = $(this).closest('.ccc_image_item')
  618. setLoading(target, true)
  619. if (item.lastName && item.blob) {
  620. blobDownload(item)
  621. item.lock = false
  622. setLoading(target, false)
  623. } else {
  624. getSingleBlob(item).then(res => {
  625. blobDownload(res)
  626. item.lock = false
  627. setLoading(target, false)
  628. })
  629. }
  630.  
  631. })
  632. // 移除图片
  633. $('#ccc_image_container').on('click', '.ccc_imgItem_delete', function () {
  634. let url = $(this).closest('.ccc_image_item').attr('data-imgsrc')
  635. valid_all_imageUrls = valid_all_imageUrls.filter(item => item.src !== url)
  636. all_imageUrls = all_imageUrls.filter(item => item.src !== url)
  637. reRender()
  638. })
  639. // 显示更多
  640. $('#ccc_image_container').on('click', '.ccc_imgItem_info', function () {
  641. let url = $(this).closest('.ccc_image_item').attr('data-imgsrc')
  642. let item = all_imageUrls.filter(item => item.src === url)[0]
  643. if (item.lock) return;
  644. item.lock = true
  645. $(this).find('.ccc_more').empty().append(`<div class="loader"></div>`);
  646.  
  647. $(this).closest('.ccc_image_item').find('.ccc_imgItem_ctrl>div').css('cursor', 'no-drop').removeClass('click_style')
  648. getSingleBlob(item).then(res => {
  649. }).finally(() => {
  650. $(this).find('.ccc_more').remove();
  651. $(this).css('cursor', 'initial')
  652. $(this).closest('.ccc_image_item').find('.ccc_imgItem_ctrl>div').css('cursor', 'pointer').addClass('click_style')
  653. item.lock = false
  654. })
  655. })
  656.  
  657.  
  658. // 显隐主体icon
  659. var isShowMainIcon = GM_getValue('ccc_main_icon_isshow', true);
  660. $(document).on('click', '#showhide_main_btn', function () {
  661. isShowMainIcon = !isShowMainIcon
  662. handleShowHide()
  663. })
  664.  
  665. const handleShowHide = () => {
  666. let speed = 600
  667. $('#ccc_main_icon_container').css({
  668. transition: `all ${speed}ms`
  669. })
  670. GM_setValue('ccc_main_icon_isshow', isShowMainIcon);
  671. if (isShowMainIcon) {
  672. $('#ccc_main_icon_container').css({
  673. 'right': '20px',
  674. })
  675. $('#showhide_main_btn').css({
  676. left: 'auto',
  677. right: '0',
  678. opacity: '0',
  679. }).text('»')
  680. } else {
  681. $('#ccc_main_icon_container').css({
  682. 'right': '-30px',
  683. })
  684. $('#showhide_main_btn').css({
  685. right: 'auto',
  686. left: '-40px',
  687. opacity: '1',
  688. }).text('«')
  689. }
  690. setTimeout(() => {
  691. $('#ccc_main_icon_container').css({
  692. transition: 'none'
  693. })
  694. }, speed);
  695. }
  696. handleShowHide()
  697.  
  698.  
  699. $('#ccc_popUps_container').click(function (e) {
  700. e.stopPropagation()
  701. })
  702.  
  703. document.getElementById('ccc_popUps_out').addEventListener("mousedown", function (event) {
  704. if (event.target.id === 'ccc_popUps_out') {
  705. let flag = document.querySelector('.ccc_all_pack_down_container').classList.contains('ccc_focus_rename');
  706. if (flag) return;
  707. handleClosePop()
  708. }
  709. });
  710.  
  711.  
  712.  
  713. // 声明拖动事件
  714. function bindHandleDrag() {
  715. let isMove = false
  716. let mouseToEleY;
  717. let mainContainerDom = document.querySelector('#ccc_main_icon_container')
  718. let iconDom = document.querySelector('#open_popUps_icon')
  719. let isOpen = true;
  720. // 拖动处理
  721. mainContainerDom.addEventListener("mousedown", function (e) {
  722. isMove = true
  723. // 获取鼠标相对于元素的位置
  724. mouseToEleY = e.clientY - mainContainerDom.getBoundingClientRect().top;
  725. });
  726. // 当鼠标移动时
  727. window.addEventListener('mousemove', (e) => {
  728. if (!isMove) return
  729. document.body.style.userSelect = 'none';
  730. iconDom.style.cursor = 'grabbing'
  731. // 防止默认的拖动选择文本行为
  732. e.preventDefault();
  733. let newTop = e.clientY - mouseToEleY;
  734. // 防止元素超出视口下方
  735. let maxTop = window.innerHeight - mainContainerDom.offsetHeight;
  736. if (newTop < 0) {
  737. newTop = 0;
  738. } else if (newTop > maxTop) {
  739. newTop = maxTop;
  740. }
  741. mainContainerDom.style.top = `${newTop}px`;
  742. mainContainerDom.style.bottom = 'auto';
  743. isOpen = false;
  744. })
  745. // 当鼠标松开时
  746.  
  747. document.querySelector('#open_popUps_icon').addEventListener('mouseup', () => {
  748. isOpen && handleOpenPopPus() // 打开弹窗
  749. });
  750. window.addEventListener('mouseup', () => {
  751. isMove = false;
  752. iconDom.style.cursor = 'pointer'
  753. isOpen = true
  754. document.body.style.userSelect = 'auto';
  755. });
  756. }
  757. bindHandleDrag();
  758. // 刷新抓取
  759. document.querySelector('#ccc_fetch_btn').onclick = () => {
  760. reFetchImgs()
  761. }
  762.  
  763. // 检测是否移除icon
  764. var isRemoveIcon = GM_getValue('ccc_main_icon_isRemoveIcon', true);
  765. handleRemoveIcon(isRemoveIcon)
  766. GM_registerMenuCommand('(显示/移除)右下角图标', function () {
  767. isRemoveIcon = !isRemoveIcon
  768. GM_setValue('ccc_main_icon_isRemoveIcon', isRemoveIcon);
  769. handleRemoveIcon(isRemoveIcon)
  770. });
  771.  
  772. // 处理是否显示右下角图片及注册油猴Menu
  773. function handleRemoveIcon(flag){
  774. if(flag === true){
  775. $('#ccc_main_icon_container').show()
  776. }else{
  777. $('#ccc_main_icon_container').hide()
  778. }
  779. }
  780.  
  781. }
  782. // 初始声明事件
  783. const initEvents = () => {
  784. // ctrl+右键 下载图片
  785. document.addEventListener("mousedown", function (event) {
  786. if (event.ctrlKey && event.button === 2) {
  787. event.preventDefault();
  788. var targetElement = event.target;
  789. const getUrl = (dom) => {
  790. return dom.getAttribute("src") || dom.getAttribute("srcset") || "";
  791. };
  792. if (targetElement) {
  793. let url = getUrl(targetElement);
  794. let srcArr = [];
  795. if (url) {
  796. srcArr = [url];
  797. } else {
  798. let arrDom = targetElement.querySelectorAll("img");
  799. arrDom.forEach((item) => {
  800. srcArr.push(getUrl(item));
  801. });
  802. }
  803. srcArr.forEach((url) => {
  804. let item = {
  805. src: url
  806. }
  807. getSingleBlob(item).then(res => {
  808. blobDownload(res)
  809. })
  810. });
  811. }
  812. }
  813. });
  814. document.querySelector('#ccc_all_pack_down_btn').onclick = function () {
  815. downloadPackZipImgs(all_imageUrls)
  816. }
  817.  
  818. // 获取textarea元素
  819. var textareaDom = document.getElementById('ccc_all_page_rename_val')
  820. // 监听focus事件
  821. textareaDom.addEventListener('focus', function () {
  822. document.querySelector('.ccc_all_pack_down_container').classList.add('ccc_focus_rename');
  823. });
  824. // 监听blur事件
  825. textareaDom.addEventListener('blur', function () {
  826. setTimeout(() => {
  827. document.querySelector('.ccc_all_pack_down_container').classList.remove('ccc_focus_rename');
  828. }, 100);
  829. });
  830. var ccc_domain = window.location.href.replace(/^https?:\/\//i, "");
  831. var ccc_zipFileName = `【${document.title}】【${ccc_domain}】`
  832. $(textareaDom).val(ccc_zipFileName)
  833. }
  834. // 打包下载loading
  835. function isTopLoading(flag, total) {
  836. if (flag) {
  837. if ($('#ccc_load_tip_style').length) {
  838. $('#ccc_load_tip_style').remove();
  839. }
  840. $('body').append(`
  841. <div id="ccc_load_tip_style">
  842. <div>稍等片刻,正在打包下载...</div>
  843. <div class="ccc_schedule_container">
  844. <div class="ccc_schedule_bg"><div class="ccc_schedule_curr"></div></div>
  845. <div class="ccc_schedule_text"><span id="curr_ing">0</span>/${total}</div>
  846. </div>
  847. </div>
  848. `)
  849. $('#ccc_all_pack_down_btn').css('cursor', 'no-drop').removeClass('click_style')
  850. } else {
  851. $('#ccc_load_tip_style').length && $('#ccc_load_tip_style').css('right', '-280px')
  852. $('#ccc_all_pack_down_btn').css('cursor', 'pointer').addClass('click_style')
  853. setTimeout(() => {
  854. $('#ccc_load_tip_style').remove();
  855. }, 800);
  856. }
  857. }
  858.  
  859. // 实时计算进度条
  860. const realTimeSchedule = (curr, total) => {
  861. try {
  862. if ($('#curr_ing').length) {
  863. $('#curr_ing').text(curr)
  864. let w = ((curr / total) * 100).toFixed(1) + '%'
  865. $('.ccc_schedule_curr').css('width', w)
  866. }
  867. } catch (e) {
  868. console.log(e)
  869. }
  870. }
  871.  
  872.  
  873. // 初始化加载页面
  874. const init = () => {
  875. window.addEventListener("load", function () {
  876. if (window.self !== window.top) return;
  877. setTimeout(() => {
  878. loadCss()
  879. loadElementDOM()
  880. loadAllImgUrls();
  881. loadMainOperations();
  882. initEvents();
  883. // loadUpdateTamp()
  884. }, 300);
  885. });
  886. };
  887. (function () {
  888. init();
  889. })();
  890.  
  891. const loadElementDOM = () => {
  892. $("body").append(`
  893. <!-- 主体Icom -->
  894. <div id="ccc_main_icon_container">
  895. <div id="showhide_main_btn" class="none_select">»</div>
  896. <div id="open_popUps_icon" title="ALT + Q">
  897. <span class="pop_title_num none_select">0</span>
  898. <svg t="1719977292759" class="icon" viewBox="0 0 1248 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
  899. p-id="9887" width="256" height="256">
  900. <path
  901. d="M0 159.430165V865.420028c0 65.985105 13.006679 78.509585 76.517343 78.509585h867.120413c62.977707 0 76.504653-12.029592 76.504653-78.458827v-706.040621c0-64.322788-11.991524-78.446138-76.504653-78.446138H76.504653C13.247779 80.984027 0 92.214184 0 159.430165z m900.02414 601.479609H120.638537c85.184232-127.389321 236.670806-339.721774 275.157887-339.721774 37.268895 0 163.693818 171.561272 220.796312 231.950332 0 0 73.484566-100.665353 111.984336-100.665353 39.261137 0 170.114676 207.358192 171.38362 208.398726zM671.017758 316.33513c0-53.295662 42.065504-96.439769 94.092221-96.439768s94.092222 43.144107 94.092222 96.439768-42.065504 96.439769-94.092222 96.439769-94.092222-43.144107-94.092221-96.439769zM478.39201 33.652403L329.265673 4.631647c-49.488829-9.631287-69.132087-6.167069-81.212437 29.020756z m702.792123 136.741441l-116.742877-22.714104c0 2.905882 0.076137 5.799076 0.076136 8.654201v710.050485c0 32.992552-2.131826 70.236068-27.536092 95.767228-24.706346 24.820551-60.503265 26.90162-92.099979 26.901619h-70.439099l149.824256 29.18572c61.873725 12.042282 77.405604 2.804367 89.435196-62.44475l128.379097-693.693793c11.699667-63.206117 2.537889-79.372467-60.909327-91.706606z"
  902. p-id="9888" fill="#333333"></path>
  903. </svg>
  904. </div>
  905. </div>
  906.  
  907. <!-- 弹窗 -->
  908. <div id="ccc_popUps_out">
  909. <div id="ccc_popUps_container">
  910. <div id="ccc_popUps_top">
  911. <div id="ccc_title_ctrl">
  912. <div class="ccc_title_text">网页图片列表 (共 <span class="pop_title_num">0</span> 张)</div>
  913. <div id="ccc_filter_out">
  914. <svg id="ccc_filter_btn" class="click_style" t="1719976985515" class="icon"
  915. viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6880"
  916. width="256" height="256">
  917. <path
  918. d="M577.499296 1023.99875a99.999878 99.999878 0 0 1-47.999942-11.999985l-131.999839-72.999911a99.999878 99.999878 0 0 1-51.999936-87.999893V431.999473a19.999976 19.999976 0 0 0-7.99999-15.999981L32.499961 171.99979l-3.999995-3.999995C0.5 138.99983-6.499991 96.999882 9.499989 59.999927S60.499927 0 100.499878 0h821.998997c39.999951 0 75.999907 22.999972 91.999887 59.999927s8.999989 77.999905-17.999978 107.999868l-3.999995 3.999995-307.999624 246.999699a19.999976 19.999976 0 0 0-6.999991 15.99998v488.999403a99.999878 99.999878 0 0 1-99.999878 99.999878zM84.499897 111.999863l302.999631 241.999705a98.999879 98.999879 0 0 1 37.999953 77.999905v418.999488a19.999976 19.999976 0 0 0 9.999988 17.999978l131.999839 71.999912a19.999976 19.999976 0 0 0 29.999963-17.999978V434.999469a99.999878 99.999878 0 0 1 36.999955-77.999905l303.999629-244.999701a19.999976 19.999976 0 0 0-15.99998-31.999961H100.499878a19.999976 19.999976 0 0 0-15.999981 31.999961z m881.998924 28.999965z"
  919. fill="#333333" p-id="6881"></path>
  920. <path
  921. d="M983.4988 520.999364H757.499076a39.999951 39.999951 0 0 1 0-79.999902h225.999724a39.999951 39.999951 0 0 1 0 79.999902zM983.4988 670.999181H757.499076a39.999951 39.999951 0 0 1 0-79.999902h225.999724a39.999951 39.999951 0 0 1 0 79.999902zM983.4988 819.998999H757.499076a39.999951 39.999951 0 0 1 0-79.999902h225.999724a39.999951 39.999951 0 0 1 0 79.999902z"
  922. fill="#333333" p-id="6882"></path>
  923. </svg>
  924. <div id="ccc_filter_container">
  925. <div>宽:<input id="ccc_w_min" class="ccc_filter_input" type="text"
  926. placeholder="0"><span>-</span><input id="ccc_w_max" class="ccc_filter_input"
  927. type="text" placeholder="∞">
  928. </div>
  929. <div>高:<input id="ccc_h_min" class="ccc_filter_input" type="text"
  930. placeholder="0"><span>-</span><input id="ccc_h_max" class="ccc_filter_input"
  931. type="text" placeholder="∞">
  932. </div>
  933. <div>
  934. <div id="refilter_btn" class="click_style">重置</div>
  935. </div>
  936. </div>
  937. </div>
  938. <div class="ccc_view_filter">
  939. <span style="font-weight: bold;">筛选条件:</span>
  940. <div id="ccc_view_filter_itembox">
  941. </div>
  942. </div>
  943. </div>
  944. <div class="ccc_popUps_top_right">
  945. <div id="ccc_gotoUpdate"></div>
  946. <div id="ccc_fetch_pageImgs_text">
  947. <div id="ccc_fetch_btn" class="click_style none_select">刷新抓取</div>
  948. <div class="ccc_fetch_tips none_select">(非首屏载入网页的图片,需刷新抓取)</div>
  949. </div>
  950. <div class="ccc_all_pack_down_container">
  951. <div id="ccc_all_pack_down_btn" class="none_select click_style"><span
  952. class="pop_title_num">0</span>打包下载
  953. </div>
  954. <!-- 🖊✍ -->
  955. <div id="ccc_all_page_rename"><span class="ccc_all_page_rename_icon">✍</span>
  956. <div class="ccc_all_page_rename_out">
  957. <div class="ccc_all_page_rename_container">
  958. <div class="ccc_all_page_rename_container_tips_font">重命名压缩包文件名称:</div>
  959. <textarea id="ccc_all_page_rename_val" maxlength="255"></textarea>
  960. </div>
  961. </div>
  962. </div>
  963. </div>
  964. <div id="ccc_close_popUps" class="none_select" title="Esc">❌</div>
  965. </div>
  966. </div>
  967. <div id="load_mask">图片加载中...</div>
  968.  
  969. <div id="ccc_image_container">
  970. <!-- <div class="ccc_image_item"></div> -->
  971. </div>
  972. </div>
  973. </div>
  974.  
  975. `)
  976. }
  977. const loadCss = () => {
  978. GM.addStyle(
  979. `
  980. /*!
  981. * Viewer.js v1.10.5
  982. * https://fengyuanchen.github.io/viewerjs
  983. *
  984. * Copyright 2015-present Chen Fengyuan
  985. * Released under the MIT license
  986. *
  987. * Date: 2022-04-05T08:21:00.150Z
  988. */
  989.  
  990. .viewer-zoom-in::before, .viewer-zoom-out::before, .viewer-one-to-one::before, .viewer-reset::before, .viewer-prev::before, .viewer-play::before, .viewer-next::before, .viewer-rotate-left::before, .viewer-rotate-right::before, .viewer-flip-horizontal::before, .viewer-flip-vertical::before, .viewer-fullscreen::before, .viewer-fullscreen-exit::before, .viewer-close::before {
  991. background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARgAAAAUCAYAAABWOyJDAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAQPSURBVHic7Zs/iFxVFMa/0U2UaJGksUgnIVhYxVhpjDbZCBmLdAYECxsRFBTUamcXUiSNncgKQbSxsxH8gzAP3FU2jY0kKKJNiiiIghFlccnP4p3nPCdv3p9778vsLOcHB2bfveeb7955c3jvvNkBIMdxnD64a94GHMfZu3iBcRynN7zAOI7TG15gHCeeNUkr8zaxG2lbYDYsdgMbktBsP03jdQwljSXdtBhLOmtjowC9Mg9L+knSlcD8TNKpSA9lBpK2JF2VdDSR5n5J64m0qli399hNFMUlpshQii5jbXTbHGviB0nLNeNDSd9VO4A2UdB2fp+x0eCnaXxWXGA2X0au/3HgN9P4LFCjIANOJdrLr0zzZ+BEpNYDwKbpnQMeAw4m8HjQtM6Z9qa917zPQwFr3M5KgA6J5rTJCdFZJj9/lyvGhsDvwFNVuV2MhhjrK6b9bFiE+j1r87eBl4HDwCF7/U/k+ofAX5b/EXBv5JoLMuILzf3Ap6Z3EzgdqHMCuF7hcQf4HDgeoHnccncqdK/TvSDWffFXI/exICY/xZyqc6XLWF1UFZna4gJ7q8BsRvgd2/xXpo6P+D9dfT7PpECtA3cnWPM0GXGFZh/wgWltA+cDNC7X+AP4GzjZQe+k5dRxuYPeiuXU7e1qwLpDz7dFjXKRaSwuMLvAlG8zZlG+YmiK1HoFqT7wP2z+4Q45TfEGcMt01xLoNZEBTwRqD4BLpnMLeC1A41UmVxsXgXeBayV/Wx20rpTyrpnWRft7p6O/FdqzGrDukPNtkaMoMo3FBdBSQMOnYBCReyf05s126fU9ytfX98+mY54Kxnp7S9K3kj6U9KYdG0h6UdLbkh7poFXMfUnSOyVvL0h6VtIXHbS6nOP+s/Zm9mvyXW1uuC9ohZ72E9uDmXWLJOB1GxsH+DxPftsB8B6wlGDN02TAkxG6+4D3TWsbeC5CS8CDFce+AW500LhhOW2020TRjK3b21HEmgti9m0RonxbdMZeVzV+/4tF3cBpP7E9mKHNL5q8h5g0eYsCMQz0epq8gQrwMXAgcs0FGXGFRcB9wCemF9PkbYqM/Bas7fxLwNeJPdTdpo4itQti8lPMqTpXuozVRVXPpbHI3KkNTB1NfkL81j2mvhDp91HgV9MKuRIqrykj3WPq4rHyL+axj8/qGPmTqi6F9YDlHOvJU6oYcTsh/TYSzWmTE6JT19CtLTJt32D6CmHe0eQn1O8z5AXgT4sx4Vcu0/EQecMydB8z0hUWkTd2t4CrwNEePqMBcAR4mrBbwyXLPWJa8zrXmmLEhNBmfpkuY2102xxrih+pb+ieAb6vGhuA97UcJ5KR8gZ77K+99xxeYBzH6Q3/Z0fHcXrDC4zjOL3hBcZxnN74F+zlvXFWXF9PAAAAAElFTkSuQmCC");
  992. background-repeat: no-repeat;
  993. background-size: 280px;
  994. color: transparent;
  995. display: block;
  996. font-size: 0;
  997. height: 20px;
  998. line-height: 0;
  999. width: 20px;
  1000. }
  1001.  
  1002. .viewer-zoom-in::before {
  1003. background-position: 0 0;
  1004. content: "Zoom In";
  1005. }
  1006.  
  1007. .viewer-zoom-out::before {
  1008. background-position: -20px 0;
  1009. content: "Zoom Out";
  1010. }
  1011.  
  1012. .viewer-one-to-one::before {
  1013. background-position: -40px 0;
  1014. content: "One to One";
  1015. }
  1016.  
  1017. .viewer-reset::before {
  1018. background-position: -60px 0;
  1019. content: "Reset";
  1020. }
  1021.  
  1022. .viewer-prev::before {
  1023. background-position: -80px 0;
  1024. content: "Previous";
  1025. }
  1026.  
  1027. .viewer-play::before {
  1028. background-position: -100px 0;
  1029. content: "Play";
  1030. }
  1031.  
  1032. .viewer-next::before {
  1033. background-position: -120px 0;
  1034. content: "Next";
  1035. }
  1036.  
  1037. .viewer-rotate-left::before {
  1038. background-position: -140px 0;
  1039. content: "Rotate Left";
  1040. }
  1041.  
  1042. .viewer-rotate-right::before {
  1043. background-position: -160px 0;
  1044. content: "Rotate Right";
  1045. }
  1046.  
  1047. .viewer-flip-horizontal::before {
  1048. background-position: -180px 0;
  1049. content: "Flip Horizontal";
  1050. }
  1051.  
  1052. .viewer-flip-vertical::before {
  1053. background-position: -200px 0;
  1054. content: "Flip Vertical";
  1055. }
  1056.  
  1057. .viewer-fullscreen::before {
  1058. background-position: -220px 0;
  1059. content: "Enter Full Screen";
  1060. }
  1061.  
  1062. .viewer-fullscreen-exit::before {
  1063. background-position: -240px 0;
  1064. content: "Exit Full Screen";
  1065. }
  1066.  
  1067. .viewer-close::before {
  1068. background-position: -260px 0;
  1069. content: "Close";
  1070. }
  1071.  
  1072. .viewer-container {
  1073. bottom: 0;
  1074. direction: ltr;
  1075. font-size: 0;
  1076. left: 0;
  1077. line-height: 0;
  1078. overflow: hidden;
  1079. position: absolute;
  1080. right: 0;
  1081. -webkit-tap-highlight-color: transparent;
  1082. top: 0;
  1083. -ms-touch-action: none;
  1084. touch-action: none;
  1085. -webkit-touch-callout: none;
  1086. -webkit-user-select: none;
  1087. -moz-user-select: none;
  1088. -ms-user-select: none;
  1089. user-select: none
  1090. }
  1091.  
  1092. .viewer-container::-moz-selection, .viewer-container *::-moz-selection {
  1093. background-color: transparent;
  1094. }
  1095.  
  1096. .viewer-container::selection,
  1097. .viewer-container *::selection {
  1098. background-color: transparent;
  1099. }
  1100.  
  1101. .viewer-container:focus {
  1102. outline: 0;
  1103. }
  1104.  
  1105. .viewer-container img {
  1106. display: block;
  1107. height: auto;
  1108. max-height: none !important;
  1109. max-width: none !important;
  1110. min-height: 0 !important;
  1111. min-width: 0 !important;
  1112. width: 100%;
  1113. }
  1114.  
  1115. .viewer-canvas {
  1116. bottom: 0;
  1117. left: 0;
  1118. overflow: hidden;
  1119. position: absolute;
  1120. right: 0;
  1121. top: 0
  1122. }
  1123.  
  1124. .viewer-canvas > img {
  1125. height: auto;
  1126. margin: 15px auto;
  1127. max-width: 90% !important;
  1128. width: auto;
  1129. }
  1130.  
  1131. .viewer-footer {
  1132. bottom: 0;
  1133. left: 0;
  1134. overflow: hidden;
  1135. position: absolute;
  1136. right: 0;
  1137. text-align: center;
  1138. }
  1139.  
  1140. .viewer-navbar {
  1141. background-color: rgba(0, 0, 0, 50%);
  1142. overflow: hidden;
  1143. }
  1144.  
  1145. .viewer-list {
  1146. box-sizing: content-box;
  1147. height: 50px;
  1148. margin: 0;
  1149. overflow: hidden;
  1150. padding: 1px 0
  1151. }
  1152.  
  1153. .viewer-list > li {
  1154. color: transparent;
  1155. cursor: pointer;
  1156. float: left;
  1157. font-size: 0;
  1158. height: 50px;
  1159. line-height: 0;
  1160. opacity: 0.5;
  1161. overflow: hidden;
  1162. transition: opacity 0.15s;
  1163. width: 30px
  1164. }
  1165.  
  1166. .viewer-list > li:focus,
  1167. .viewer-list > li:hover {
  1168. opacity: 0.75;
  1169. }
  1170.  
  1171. .viewer-list > li:focus {
  1172. outline: 0;
  1173. }
  1174.  
  1175. .viewer-list > li + li {
  1176. margin-left: 1px;
  1177. }
  1178.  
  1179. .viewer-list > .viewer-loading {
  1180. position: relative
  1181. }
  1182.  
  1183. .viewer-list > .viewer-loading::after {
  1184. border-width: 2px;
  1185. height: 20px;
  1186. margin-left: -10px;
  1187. margin-top: -10px;
  1188. width: 20px;
  1189. }
  1190.  
  1191. .viewer-list > .viewer-active,
  1192. .viewer-list > .viewer-active:focus,
  1193. .viewer-list > .viewer-active:hover {
  1194. opacity: 1;
  1195. }
  1196.  
  1197. .viewer-player {
  1198. background-color: #000;
  1199. bottom: 0;
  1200. cursor: none;
  1201. display: none;
  1202. left: 0;
  1203. position: absolute;
  1204. right: 0;
  1205. top: 0;
  1206. z-index: 1
  1207. }
  1208.  
  1209. .viewer-player > img {
  1210. left: 0;
  1211. position: absolute;
  1212. top: 0;
  1213. }
  1214.  
  1215. .viewer-toolbar > ul {
  1216. display: inline-block;
  1217. margin: 0 auto 5px;
  1218. overflow: hidden;
  1219. padding: 6px 3px
  1220. }
  1221.  
  1222. .viewer-toolbar > ul > li {
  1223. background-color: rgba(0, 0, 0, 50%);
  1224. border-radius: 50%;
  1225. cursor: pointer;
  1226. float: left;
  1227. height: 24px;
  1228. overflow: hidden;
  1229. transition: background-color 0.15s;
  1230. width: 24px
  1231. }
  1232.  
  1233. .viewer-toolbar > ul > li:focus,
  1234. .viewer-toolbar > ul > li:hover {
  1235. background-color: rgba(0, 0, 0, 80%);
  1236. }
  1237.  
  1238. .viewer-toolbar > ul > li:focus {
  1239. box-shadow: 0 0 3px #fff;
  1240. outline: 0;
  1241. position: relative;
  1242. z-index: 1;
  1243. }
  1244.  
  1245. .viewer-toolbar > ul > li::before {
  1246. margin: 2px;
  1247. }
  1248.  
  1249. .viewer-toolbar > ul > li + li {
  1250. margin-left: 1px;
  1251. }
  1252.  
  1253. .viewer-toolbar > ul > .viewer-small {
  1254. height: 18px;
  1255. margin-bottom: 3px;
  1256. margin-top: 3px;
  1257. width: 18px
  1258. }
  1259.  
  1260. .viewer-toolbar > ul > .viewer-small::before {
  1261. margin: -1px;
  1262. }
  1263.  
  1264. .viewer-toolbar > ul > .viewer-large {
  1265. height: 30px;
  1266. margin-bottom: -3px;
  1267. margin-top: -3px;
  1268. width: 30px
  1269. }
  1270.  
  1271. .viewer-toolbar > ul > .viewer-large::before {
  1272. margin: 5px;
  1273. }
  1274.  
  1275. .viewer-tooltip {
  1276. background-color: rgba(0, 0, 0, 80%);
  1277. border-radius: 10px;
  1278. color: #fff;
  1279. display: none;
  1280. font-size: 12px;
  1281. height: 20px;
  1282. left: 50%;
  1283. line-height: 20px;
  1284. margin-left: -25px;
  1285. margin-top: -10px;
  1286. position: absolute;
  1287. text-align: center;
  1288. top: 50%;
  1289. width: 50px;
  1290. }
  1291.  
  1292. .viewer-title {
  1293. color: #ccc;
  1294. display: inline-block;
  1295. font-size: 12px;
  1296. line-height: 1.2;
  1297. margin: 0 5% 5px;
  1298. max-width: 90%;
  1299. opacity: 0.8;
  1300. overflow: hidden;
  1301. text-overflow: ellipsis;
  1302. transition: opacity 0.15s;
  1303. white-space: nowrap
  1304. }
  1305.  
  1306. .viewer-title:hover {
  1307. opacity: 1;
  1308. }
  1309.  
  1310. .viewer-button {
  1311. -webkit-app-region: no-drag;
  1312. background-color: rgba(0, 0, 0, 50%);
  1313. border-radius: 50%;
  1314. cursor: pointer;
  1315. height: 80px;
  1316. overflow: hidden;
  1317. position: absolute;
  1318. right: -40px;
  1319. top: -40px;
  1320. transition: background-color 0.15s;
  1321. width: 80px
  1322. }
  1323.  
  1324. .viewer-button:focus,
  1325. .viewer-button:hover {
  1326. background-color: rgba(0, 0, 0, 80%);
  1327. }
  1328.  
  1329. .viewer-button:focus {
  1330. box-shadow: 0 0 3px #fff;
  1331. outline: 0;
  1332. }
  1333.  
  1334. .viewer-button::before {
  1335. bottom: 15px;
  1336. left: 15px;
  1337. position: absolute;
  1338. }
  1339.  
  1340. .viewer-fixed {
  1341. position: fixed;
  1342. }
  1343.  
  1344. .viewer-open {
  1345. overflow: hidden;
  1346. }
  1347.  
  1348. .viewer-show {
  1349. display: block;
  1350. }
  1351.  
  1352. .viewer-hide {
  1353. display: none;
  1354. }
  1355.  
  1356. .viewer-backdrop {
  1357. background-color: rgba(0, 0, 0, 50%);
  1358. }
  1359.  
  1360. .viewer-invisible {
  1361. visibility: hidden;
  1362. }
  1363.  
  1364. .viewer-move {
  1365. cursor: move;
  1366. cursor: -webkit-grab;
  1367. cursor: grab;
  1368. }
  1369.  
  1370. .viewer-fade {
  1371. opacity: 0;
  1372. }
  1373.  
  1374. .viewer-in {
  1375. opacity: 1;
  1376. }
  1377.  
  1378. .viewer-transition {
  1379. transition: all 0.3s;
  1380. }
  1381.  
  1382. @-webkit-keyframes viewer-spinner {
  1383. 0% {
  1384. transform: rotate(0deg);
  1385. }
  1386.  
  1387. 100% {
  1388. transform: rotate(360deg);
  1389. }
  1390. }
  1391.  
  1392. @keyframes viewer-spinner {
  1393. 0% {
  1394. transform: rotate(0deg);
  1395. }
  1396.  
  1397. 100% {
  1398. transform: rotate(360deg);
  1399. }
  1400. }
  1401.  
  1402. .viewer-loading::after {
  1403. -webkit-animation: viewer-spinner 1s linear infinite;
  1404. animation: viewer-spinner 1s linear infinite;
  1405. border: 4px solid rgba(255, 255, 255, 10%);
  1406. border-left-color: rgba(255, 255, 255, 50%);
  1407. border-radius: 50%;
  1408. content: "";
  1409. display: inline-block;
  1410. height: 40px;
  1411. left: 50%;
  1412. margin-left: -20px;
  1413. margin-top: -20px;
  1414. position: absolute;
  1415. top: 50%;
  1416. width: 40px;
  1417. z-index: 1;
  1418. }
  1419.  
  1420. @media (max-width: 767px) {
  1421. .viewer-hide-xs-down {
  1422. display: none;
  1423. }
  1424. }
  1425.  
  1426. @media (max-width: 991px) {
  1427. .viewer-hide-sm-down {
  1428. display: none;
  1429. }
  1430. }
  1431.  
  1432. @media (max-width: 1199px) {
  1433. .viewer-hide-md-down {
  1434. display: none;
  1435. }
  1436. }
  1437.  
  1438.  
  1439.  
  1440. // -------------- my-style ------------
  1441.  
  1442. .viewer-backdrop {
  1443. background-color: rgba(0, 0, 0, 0.75) !important;
  1444. }
  1445. #ccc_main_icon_container {
  1446. position: fixed;
  1447. bottom: 50px;
  1448. right: 20px;
  1449. opacity: 0.3;
  1450. z-index: 88888;
  1451. display: none;
  1452. }
  1453. #open_popUps_icon {
  1454. position: relative;
  1455. width: 30px;
  1456. height: 30px;
  1457. cursor: pointer;
  1458. }
  1459. #open_popUps_icon>svg {
  1460. width: 100%;
  1461. height: 100%;
  1462. }
  1463. #open_popUps_icon>.pop_title_num {
  1464. position: absolute;
  1465. top: 0;
  1466. right: 0;
  1467. transform: translate(50%, -50%);
  1468. padding: 2px 4px;
  1469. background-color: red;
  1470. color: #ffffff;
  1471. font-size: 10px;
  1472. border-radius: 30px;
  1473. }
  1474. #showhide_main_btn {
  1475. position: absolute;
  1476. display: flex;
  1477. align-items: center;
  1478. justify-content: center;
  1479. height: 30px;
  1480. width: 20px;
  1481. font-size: 26px;
  1482. line-height: 30px;
  1483. top: 0;
  1484. right: 0;
  1485. transform: translate(100%, 0%);
  1486. cursor: pointer;
  1487. transition: all 0.3s;
  1488. font-weight: bold;
  1489. background-image: linear-gradient(to right, #ffffff, #333333);
  1490. -webkit-background-clip: text;
  1491. color: transparent;
  1492. opacity: 0;
  1493. }
  1494. #ccc_main_icon_container:hover {
  1495. opacity: 1;
  1496. }
  1497. #ccc_main_icon_container:hover #showhide_main_btn {
  1498. opacity: 1 !important;
  1499. }
  1500. #showhide_main_btn:hover {
  1501. text-shadow:
  1502. -0 -0 0 #333,
  1503. 0 -0 0 #333,
  1504. -0 0 0 #333,
  1505. 0 0 0 #333;
  1506. }
  1507. /* 滚动条整体样式 */
  1508. #ccc_image_container::-webkit-scrollbar {
  1509. width: 6px;
  1510. /* 宽度 */
  1511. height: 6px;
  1512. /* 高度(对于垂直滚动条) */
  1513. }
  1514. /* 滚动条滑块 */
  1515. #ccc_image_container::-webkit-scrollbar-thumb {
  1516. background: #aaa;
  1517. border-radius: 6px;
  1518. }
  1519. /* 滚动条滑块:hover状态样式 */
  1520. #ccc_image_container::-webkit-scrollbar-thumb:hover {
  1521. background: #888;
  1522. }
  1523. /* 滚动条轨道 */
  1524. #ccc_image_container::-webkit-scrollbar-track {
  1525. background: #f1f1f1;
  1526. border-radius: 6px;
  1527. }
  1528. /* 滚动条轨道:hover状态样式 */
  1529. #ccc_image_container::-webkit-scrollbar-track:hover {
  1530. background: #ddd;
  1531. }
  1532. /* 滚动条轨道:active状态样式 */
  1533. #ccc_image_container::-webkit-scrollbar-track-piece:active {
  1534. background: #eee;
  1535. }
  1536. /* 滚动条:角落样式(即两个滚动条交汇处) */
  1537. #ccc_image_container::-webkit-scrollbar-corner {
  1538. background: #535353;
  1539. }
  1540. .none_select {
  1541. user-select: none;
  1542. /* 禁止选中 */
  1543. -webkit-user-select: none;
  1544. /* 对 Safari 和旧版 Chrome 的支持 */
  1545. -moz-user-select: none;
  1546. /* 对 Firefox 的支持 */
  1547. -ms-user-select: none;
  1548. /* 对 Internet Explorer 的支持 */
  1549. }
  1550. #ccc_popUps_out {
  1551. position: fixed;
  1552. background-color: rgba(0, 0, 0, 0.6);
  1553. width: 100vw;
  1554. height: 100vh;
  1555. top: 0;
  1556. left: 0;
  1557. z-index: 88888;
  1558. display: none;
  1559. }
  1560. #ccc_popUps_container {
  1561. position: absolute;
  1562. width: 75vw;
  1563. height: 75vh;
  1564. top: 50%;
  1565. left: 50%;
  1566. transform: translate(-50%, -50%);
  1567. background-color: #ffffff;
  1568. border-radius: 8px;
  1569. box-shadow: 0px 1px 4px 0 rgba(0, 0, 0, 0.2);
  1570. padding: 15px;
  1571. }
  1572. #ccc_popUps_top {
  1573. position: relative;
  1574. display: flex;
  1575. align-items: center;
  1576. justify-content: space-between;
  1577. padding-bottom: 10px;
  1578. margin-bottom: 10px;
  1579. z-index: 10;
  1580. }
  1581. .pop_title_num {
  1582. color: red;
  1583. }
  1584. .ccc_popUps_top_right {
  1585. display: flex;
  1586. align-items: center;
  1587. justify-content: flex-end;
  1588. }
  1589. #ccc_all_pack_down_btn, #ccc_all_page_screenShot {
  1590. position: relative;
  1591. cursor: pointer;
  1592. background-color: #666666;
  1593. color: #fff;
  1594. padding: 6px 10px;
  1595. font-size: 12px;
  1596. display: flex;
  1597. align-items: center;
  1598. justify-content: center;
  1599. border-radius: 4px;
  1600. margin-right: 30px;
  1601. transition: all 0.3s;
  1602. }
  1603. #ccc_all_page_screenShot{
  1604. margin-right: 20px;
  1605. background-color: #666666;
  1606. }
  1607. #ccc_all_page_screenShot:hover {
  1608. background-color: #333333;
  1609. box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.3);
  1610. }
  1611. #ccc_all_pack_down_btn>.pop_title_num {
  1612. /* position: absolute;
  1613. top: 0;
  1614. right: 0;
  1615. transform: translate(50%, -50%); */
  1616. padding: 2px 4px;
  1617. background-color: red;
  1618. color: #ffffff;
  1619. font-size: 10px;
  1620. line-height: 10px;
  1621. border-radius: 30px;
  1622. margin-right: 2px;
  1623. }
  1624. #ccc_close_popUps {
  1625. cursor: pointer;
  1626. filter: grayscale(100%);
  1627. font-size: 12px;
  1628. margin-left: 30px;
  1629. }
  1630. #ccc_close_popUps:hover {
  1631. filter: grayscale(0%);
  1632. }
  1633. #ccc_image_container {
  1634. display: grid;
  1635. grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  1636. gap: 10px;
  1637. box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.1);
  1638. padding: 10px;
  1639. overflow: auto;
  1640. align-content: start;
  1641. }
  1642. .ccc_image_item {
  1643. position: relative;
  1644. height: 120px;
  1645. background-color: #f5f5f5;
  1646. display: flex;
  1647. align-items: center;
  1648. justify-content: center;
  1649. border-radius: 3px;
  1650. padding: 1px;
  1651. box-sizing: border-box;
  1652. box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.1);
  1653. }
  1654. .ccc_image_item:hover {
  1655. box-shadow: 0 0 6px 1px rgba(0, 0, 0, 0.3);
  1656. }
  1657. .ccc_image_item img {
  1658. max-width: 100%;
  1659. max-height: 100%;
  1660. object-fit: contain;
  1661. cursor: zoom-in;
  1662. }
  1663. .ccc_imgItem_info,
  1664. .ccc_imgItem_ctrl,
  1665. .ccc_imgItem_delete {
  1666. position: absolute;
  1667. background-color: rgba(0, 0, 0, 0.6);
  1668. color: #fff;
  1669. box-sizing: border-box;
  1670. font-size: 10px;
  1671. display: flex;
  1672. align-items: center;
  1673. opacity: 0;
  1674. transition: all 0.3s;
  1675. }
  1676. .ccc_imgItem_info {
  1677. left: 0;
  1678. top: 0;
  1679. padding: 3px 5px;
  1680. border-bottom-right-radius: 5px;
  1681. flex-wrap: wrap;
  1682. max-width: 80%;
  1683. line-height: 14px;
  1684. }
  1685. .ccc_imgItem_ctrl {
  1686. right: 0;
  1687. bottom: 0;
  1688. color: #fff;
  1689. padding: 3px 6px;
  1690. border-top-left-radius: 5px;
  1691. }
  1692. .ccc_imgItem_delete {
  1693. right: 0;
  1694. top: 0;
  1695. padding: 8px;
  1696. background-color: transparent;
  1697. cursor: pointer;
  1698. transition: all 0.3s;
  1699. }
  1700. .ccc_imgItem_delete>span {
  1701. width: 14px;
  1702. height: 3px;
  1703. border-radius: 6px;
  1704. background-color: rgba(255, 0, 0, 1);
  1705. }
  1706. .ccc_imgItem_ctrl>div {
  1707. width: 17px;
  1708. height: 17px;
  1709. cursor: pointer;
  1710. transition: all 0.3s;
  1711. }
  1712. .ccc_imgItem_ctrl svg {
  1713. width: 100%;
  1714. height: 100%;
  1715. }
  1716. .ccc_image_item:hover .ccc_imgItem_info,
  1717. .ccc_image_item:hover .ccc_imgItem_ctrl,
  1718. .ccc_image_item:hover .ccc_imgItem_delete {
  1719. opacity: 1;
  1720. }
  1721. .viewer-container {
  1722. z-index: 99999 !important;
  1723. }
  1724. #ccc_title_ctrl {
  1725. display: flex;
  1726. align-items: center;
  1727. }
  1728. #ccc_title_ctrl>.ccc_title_text {
  1729. font-size: 14px;
  1730. }
  1731. #ccc_filter_out {
  1732. position: relative;
  1733. top: 1px;
  1734. display: flex;
  1735. width: 18px;
  1736. height: 18px;
  1737. margin-left: 20px;
  1738. }
  1739. #ccc_filter_out svg {
  1740. width: 100%;
  1741. height: 100%;
  1742. cursor: pointer;
  1743. transition: all 0.3s;
  1744. }
  1745. .ccc_view_filter {
  1746. /* display: flex; */
  1747. align-items: center;
  1748. font-size: 12px;
  1749. /* background-color: #fafafa; */
  1750. /* padding: 10px 14px; */
  1751. border-radius: 4px;
  1752. margin-left: 14px;
  1753. display: none;
  1754. }
  1755. #ccc_view_filter_itembox {
  1756. display: flex;
  1757. flex-wrap: wrap;
  1758. align-items: center;
  1759. max-width: 400px;
  1760. }
  1761. #ccc_view_filter_itembox>span {
  1762. display: inline-flex;
  1763. align-items: center;
  1764. justify-content: center;
  1765. padding: 3px 8px;
  1766. font-size: 11px;
  1767. border-radius: 4px;
  1768. box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.3);
  1769. background-color: #f5f5f5;
  1770. margin-left: 8px;
  1771. }
  1772. #ccc_view_filter_itembox>span:first-of-type {
  1773. margin-left: 0;
  1774. }
  1775. #ccc_filter_container {
  1776. position: absolute;
  1777. top: 50%;
  1778. left: 40px;
  1779. transform: translate(0, -50%);
  1780. padding: 10px 15px;
  1781. background: #fff;
  1782. border: 1px solid #555;
  1783. box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.6);
  1784. border-radius: 6px;
  1785. z-index: 9;
  1786. display: none;
  1787. width: 160px;
  1788. font-size: 14px;
  1789. /* opacity: 0; */
  1790. }
  1791. #ccc_filter_container::before,
  1792. #ccc_filter_container::after {
  1793. position: absolute;
  1794. content: '';
  1795. top: 50%;
  1796. }
  1797. #ccc_filter_container::before {
  1798. left: -23px;
  1799. margin-top: -13px;
  1800. border: 13px solid transparent;
  1801. border-right: 12px solid #fff;
  1802. z-index: 2;
  1803. }
  1804. #ccc_filter_container::after {
  1805. left: -26px;
  1806. margin-top: -13px;
  1807. border: 13px solid transparent;
  1808. border-right: 13px solid #555;
  1809. z-index: 1;
  1810. }
  1811. #ccc_filter_container>div {
  1812. width: 100%;
  1813. display: flex;
  1814. align-items: center;
  1815. margin: 6px auto;
  1816. align-items: center;
  1817. justify-content: center;
  1818. }
  1819. #ccc_filter_container>div>span {
  1820. width: 10%;
  1821. text-align: center;
  1822. display: block;
  1823. }
  1824. #ccc_filter_container>div input {
  1825. width: 35%;
  1826. height: 18px;
  1827. font-size: 13px;
  1828. text-align: center;
  1829. }
  1830. #ccc_filter_container>div input::placeholder {
  1831. text-align: center;
  1832. line-height: 18px;
  1833. }
  1834. #refilter_btn {
  1835. width: 40px;
  1836. height: 20px;
  1837. font-size: 10px;
  1838. display: flex;
  1839. align-items: center;
  1840. justify-content: center;
  1841. border-radius: 2px;
  1842. box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.2);
  1843. color: #ffffff;
  1844. background-color: #666666;
  1845. letter-spacing: 1px;
  1846. cursor: pointer;
  1847. transition: all 0.3s;
  1848. }
  1849. #refilter_btn:hover {
  1850. background-color: #333333;
  1851. box-shadow: 0 0 4px 1px rgba(0, 0, 0, 0.2);
  1852. }
  1853. #ccc_w_max::placeholder,
  1854. #ccc_h_max::placeholder {
  1855. position: relative;
  1856. top: 5px;
  1857. font-size: 26px;
  1858. }
  1859. #load_mask {
  1860. position: absolute;
  1861. top: 50%;
  1862. left: 50%;
  1863. transform: translate(-50%, -50%);
  1864. font-size: 18px;
  1865. letter-spacing: 1px;
  1866. padding: 10px 20px;
  1867. border-radius: 4px;
  1868. color: #fff;
  1869. background-color: rgba(0, 0, 0, 0.6);
  1870. z-index: 100;
  1871. }
  1872. .loader {
  1873. width: 30px;
  1874. height: 30px;
  1875. border: 3px solid #f3f3f3;
  1876. /* 边框的颜色 */
  1877. border-top: 3px solid #3498db;
  1878. /* 上边框颜色,旋转时的主要颜色 */
  1879. border-radius: 50%;
  1880. animation: spin 1s linear infinite;
  1881. }
  1882. @keyframes spin {
  1883. 0% {
  1884. transform: rotate(0deg);
  1885. }
  1886. 100% {
  1887. transform: rotate(360deg);
  1888. }
  1889. }
  1890. .ccc_more {
  1891. cursor: pointer;
  1892. display: inline-block;
  1893. margin-left: 4px;
  1894. }
  1895. .ccc_imgItem_info:hover .ccc_more {
  1896. color: rgb(24, 144, 255)
  1897. }
  1898. .ccc_imgItem_info:hover {
  1899. cursor: pointer;
  1900. }
  1901. .ccc_more>.loader {
  1902. width: 12px;
  1903. height: 12px;
  1904. border: 2px solid #f3f3f3;
  1905. border-top: 2px solid #3498db;
  1906. }
  1907. #ccc_load_tip_style {
  1908. position: fixed;
  1909. width: 210px;
  1910. padding: 12px 24px;
  1911. top: 20px;
  1912. right: 20px;
  1913. color: #333;
  1914. background-color: #fff;
  1915. box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 10px 5px;
  1916. border-radius: 5px;
  1917. transition: all 0.5s ease-in-out 0s, transform 0.5s ease-in-out 0s;
  1918. font-family: 'Damion', cursive;
  1919. font-weight: 600;
  1920. text-align: center;
  1921. z-index: 999999;
  1922. }
  1923. #ccc_gotoUpdate {
  1924. position: relative;
  1925. margin-right: 20px;
  1926. line-height: 24px;
  1927. }
  1928. #ccc_gotoUpdate>a {
  1929. text-decoration: none;
  1930. cursor: pointer;
  1931. color: #909090;
  1932. font-size: 12px;
  1933. transition: all 0.3s ease;
  1934. }
  1935. #ccc_gotoUpdate:hover>a {
  1936. color: #007fff;
  1937. }
  1938. #ccc_gotoUpdate::before {
  1939. content: '';
  1940. position: absolute;
  1941. left: 0;
  1942. bottom: 0;
  1943. height: 1px;
  1944. width: 0;
  1945. background-color: #007fff;
  1946. transition: all 0.3s ease;
  1947. }
  1948. #ccc_gotoUpdate:hover::before {
  1949. width: 100%;
  1950. }
  1951. .ccc_schedule_container {
  1952. margin-top: 5px;
  1953. display: flex;
  1954. align-items: center;
  1955. }
  1956. .ccc_schedule_text {
  1957. text-align: center;
  1958. font-size: 14px;
  1959. white-space: nowrap;
  1960. padding-left: 10px;
  1961. }
  1962. .ccc_schedule_bg {
  1963. position: relative;
  1964. flex-grow: 1;
  1965. height: 4px;
  1966. border-radius: 2px;
  1967. background-color: #ddd;
  1968. margin: 2px auto;
  1969. overflow: hidden;
  1970. }
  1971. .ccc_schedule_curr {
  1972. height: 100%;
  1973. background-color: #67C23A;
  1974. width: 20%;
  1975. transition: all 0.3s ease;
  1976. }
  1977. #curr_ing {
  1978. color: #67C23A;
  1979. }
  1980. #ccc_fetch_pageImgs {
  1981. display: flex;
  1982. width: 20px;
  1983. height: 20px;
  1984. margin: auto 20px;
  1985. }
  1986. #ccc_fetch_pageImgs>svg {
  1987. width: 100%;
  1988. height: 100%;
  1989. }
  1990. #ccc_fetch_pageImgs_text{
  1991. position: relative;
  1992. font-size: 14px;
  1993. margin-right: 20px;
  1994. }
  1995. #ccc_fetch_btn{
  1996. cursor: pointer;
  1997. padding: 3px 0;
  1998. transition: all 0.1s ease;
  1999. }
  2000. #ccc_fetch_pageImgs_text>.ccc_fetch_tips{
  2001. position: absolute;
  2002. /* color: #F56C6C; */
  2003. color: #999999;
  2004. font-size: 11px;
  2005. top: 100%;
  2006. right: 0;
  2007. width: 0%;
  2008. text-align: right;
  2009. letter-spacing: 1px;
  2010. opacity: 0;
  2011. white-space: nowrap; /* 确保文本不会换行 */
  2012. overflow: hidden; /* 隐藏超出div的文本 */
  2013. text-overflow: ellipsis; /* 超出部分显示省略号 */
  2014. transition: all 0.4s ease;
  2015. }
  2016. #ccc_fetch_btn:hover{
  2017. color: #007fff;
  2018. }
  2019. #ccc_fetch_btn:hover + .ccc_fetch_tips{
  2020. width: 400%;
  2021. opacity: 1;
  2022. }
  2023. #ccc_fetch_btn:active{
  2024. transform: translate3d(0, 1px, 0);
  2025. }
  2026. .click_style:active {
  2027. transform: scale(0.9);
  2028. }
  2029. #ccc_notify{
  2030. position: absolute;
  2031. top: 30px;
  2032. left: 50%;
  2033. transform: translate(-50%, 0);
  2034. background-color: rgb(226, 244, 219);
  2035. color: #67C23A;
  2036. padding: 8px 20px;
  2037. border-radius: 4px;
  2038. font-size: 14px;
  2039. letter-spacing: 1px;
  2040. z-index: 8;
  2041. opacity: 0;
  2042. transition: all 0.3s ease;
  2043. }
  2044. #ccc_notify.active{
  2045. top: 70px;
  2046. opacity: 1;
  2047. }
  2048. .ccc_all_pack_down_container{
  2049. display: flex;
  2050. background-color: #666666;
  2051. border-radius: 4px;
  2052. transition: all 0.3s;
  2053. cursor: pointer;
  2054. }
  2055. .ccc_all_pack_down_container:hover {
  2056. box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.3);
  2057. }
  2058. .ccc_all_pack_down_container> #ccc_all_pack_down_btn{
  2059. margin-right: 0;
  2060. border-top-right-radius: 0;
  2061. border-bottom-right-radius: 0;
  2062. background-color: initial;
  2063. }
  2064. .ccc_all_pack_down_container>#ccc_all_pack_down_btn:hover{
  2065. background-color: #333333;
  2066. }
  2067. #ccc_all_page_rename{
  2068. position: relative;
  2069. width: 20px;
  2070. display: flex;
  2071. align-items: center;
  2072. justify-content: center;
  2073. border-top-right-radius: 4px;
  2074. border-bottom-right-radius: 4px;
  2075. border-left: 1px solid #555;
  2076. color: #eee;
  2077. }
  2078. #ccc_all_page_rename>.ccc_all_page_rename_icon{
  2079. position: absolute;
  2080. top: 45%;
  2081. left: 50%;
  2082. transform: translate(-50%, -50%);
  2083. box-sizing: border-box;
  2084. font-size: 12px;
  2085. transition: all 0.3s;
  2086. }
  2087. .ccc_all_pack_down_container>#ccc_all_page_rename:hover .ccc_all_page_rename_icon, .ccc_focus_rename .ccc_all_page_rename_icon{
  2088. font-size: 55px !important;
  2089. z-index: 999 !important;
  2090. }
  2091. .ccc_all_pack_down_container>#ccc_all_page_rename:hover, .ccc_focus_rename #ccc_all_page_rename{
  2092. background-color: #eee;
  2093. color: red;
  2094. }
  2095. .ccc_all_page_rename_out{
  2096. /* display: none; */
  2097. visibility:hidden;
  2098. position: absolute;
  2099. top: 100%;
  2100. padding: 10px 50px 50px 50px;
  2101. cursor: initial;
  2102. }
  2103. .ccc_all_page_rename_container{
  2104. opacity: 0;
  2105. width: 0;
  2106. /* width: 340px; */
  2107. padding: 10px;
  2108. border-radius: 10px;
  2109. color: #333;
  2110. /* background-color: #f5f5f5; */
  2111. cursor: initial;
  2112. box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.3);
  2113. background-color: rgba(255, 255, 255, 0.6); /* 设置半透明背景 */
  2114. backdrop-filter: blur(10px); /* 应用背景模糊效果 */
  2115. -webkit-backdrop-filter: blur(10px); /* 兼容老版本Safari */
  2116. transition: all 0.3s;
  2117. }
  2118. .ccc_all_pack_down_container>#ccc_all_page_rename:hover .ccc_all_page_rename_out, .ccc_focus_rename .ccc_all_page_rename_out{
  2119. display: block;
  2120. visibility: visible;
  2121. }
  2122. .ccc_all_pack_down_container>#ccc_all_page_rename:hover .ccc_all_page_rename_container, .ccc_focus_rename .ccc_all_page_rename_container{
  2123. width: 340px;
  2124. opacity: 1;
  2125. }
  2126. .ccc_all_page_rename_container_tips_font{
  2127. font-size: 13px;
  2128. font-weight: 550;
  2129. letter-spacing: 0.5px;
  2130. margin-bottom: 5px;
  2131. white-space: nowrap;
  2132. }
  2133. #ccc_all_page_rename_val{
  2134. max-width: 100%;
  2135. min-width: 100%;
  2136. min-height: 100px;
  2137. box-sizing: border-box;
  2138. border: none;
  2139. outline: none; /* 可选:移除聚焦时的轮廓 */
  2140. padding: 4px 6px;
  2141. border-radius: 6px;
  2142. box-shadow: 0 0 10px 1px rgba(0, 0, 0, 0.1);
  2143. background-color: rgba(255, 255, 255, 0.7); /* 设置半透明背景 */
  2144. }
  2145. `
  2146. );
  2147. }