🏠 Home 

语雀思维导图一键保存

语雀思维导图一键保存,保存html,自动询问要保存的文件名,自动添加时间戳


Install this script?
  1. // ==UserScript==
  2. // @name 语雀思维导图一键保存
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1
  5. // @description 语雀思维导图一键保存,保存html,自动询问要保存的文件名,自动添加时间戳
  6. // @author thunder-sword
  7. // @match https://www.yuque.com/yuluo-vdhow/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=yuque.com
  9. // @license MIT
  10. // @grant none
  11. // ==/UserScript==
  12. /* 作用:根据指定的html字符串下载html文件,可指定文件名,自动获取当前页面中的css,自动添加时间戳 */
  13. function downloadHtml(html, fileName='page.html', getCSS=true, addTim###ffix=true){
  14. var r###lt=`<head><meta charset="UTF-8"></head>`;
  15. if(getCSS){
  16. /* 获取当前页面 css */
  17. const css = Array.from(document.styleSheets)
  18. .map(styleSheet => Array.from(styleSheet.cssRules).map(rule => rule.cssText))
  19. .flat()
  20. .join("\n");
  21. r###lt=`<head><style>\n${css}\n</style></head>`;
  22. }
  23. r###lt+='<body>'+html+'</body>';
  24. const file = new File([r###lt], "page.html", { type: "text/html" });
  25. const a = document.createElement("a");
  26. a.href = URL.createObjectURL(file);
  27. fileName = fileName.endsWith(".html") ? fileName : fileName + ".html";
  28. if(addTim###ffix){
  29. var currentTime = new Date();
  30. fileName=fileName.slice(0,-5)+`-${currentTime.getFullYear()}${(currentTime.getMonth()+1).toString().padStart(2, "0")}${currentTime.getDate().toString().padStart(2, "0")}.html`;
  31. }
  32. a.download = fileName;
  33. document.body.appendChild(a);
  34. a.click();
  35. }
  36. /* 作用:保存语雀思维导图,可弹窗询问要保存的文件名,默认为false */
  37. function savaYuQueMindMap(fileName='page.html', askFileName=false){
  38. /* askFileName为true时弹窗询问文件名 */
  39. fileName=askFileName?prompt('输入要保存的文件名:'):fileName;
  40. downloadHtml(document.querySelector('div.lake-diagram-viewport-container svg').outerHTML, fileName, getCSS=false);
  41. }
  42. // 创建一个 div 元素
  43. var floatWindow = document.createElement('div');
  44. // 设置 div 的内容
  45. floatWindow.innerHTML = '一键保存思维导图';
  46. // 设置 div 的样式
  47. floatWindow.style.position = 'fixed';
  48. floatWindow.style.bottom = '10px';
  49. floatWindow.style.right = '10px';
  50. floatWindow.style.padding = '5px 10px';
  51. floatWindow.style.backgroundColor = '#333';
  52. floatWindow.style.color = '#fff';
  53. floatWindow.style.cursor = 'pointer';
  54. // 将悬浮窗的优先级提高
  55. floatWindow.style.zIndex = "99999";
  56. var isDragging = false;
  57. var currentX;
  58. var currentY;
  59. var initialX;
  60. var initialY;
  61. var xOffset = 0;
  62. var yOffset = 0;
  63. var cursorX;
  64. var vursorY;
  65. floatWindow.addEventListener("mousedown", function(e) {
  66. if (!isDragging) {
  67. cursorX = e.clientX;
  68. cursorY = e.clientY;
  69. initialX = cursorX - xOffset;
  70. initialY = cursorY - yOffset;
  71. isDragging = true;
  72. }
  73. });
  74. floatWindow.addEventListener("mousemove", function(e) {
  75. if (isDragging) {
  76. e.preventDefault();
  77. currentX = e.clientX - initialX;
  78. currentY = e.clientY - initialY;
  79. xOffset = currentX;
  80. yOffset = currentY;
  81. setTranslate(currentX, currentY, floatWindow);
  82. }
  83. });
  84. floatWindow.addEventListener("mouseup", function(e) {
  85. initialX = currentX;
  86. initialY = currentY;
  87. isDragging = false;
  88. // 如果点击时鼠标的位置没有改变,就认为是真正的点击
  89. if (cursorX === e.clientX && cursorY === e.clientY) {
  90. execCode();
  91. }
  92. });
  93. // 为悬浮窗添加事件处理程序,用来监听触摸开始和触摸移动事件
  94. // 这些事件处理程序的实现方式与上面的鼠标事件处理程序类似
  95. floatWindow.addEventListener('touchstart', (event) => {
  96. if (!isDragging) {
  97. cursorX = event.touches[0].clientX;
  98. cursorY = event.touches[0].clientY;
  99. initialX = cursorX - xOffset;
  100. initialY = cursorY - yOffset;
  101. isDragging = true;
  102. }
  103. });
  104. floatWindow.addEventListener('touchmove', (event) => {
  105. if (isDragging) {
  106. currentX = event.touches[0].clientX - initialX;
  107. currentY = event.touches[0].clientY - initialY;
  108. xOffset = currentX;
  109. yOffset = currentY;
  110. setTranslate(currentX, currentY, floatWindow);
  111. }
  112. });
  113. // 为悬浮窗添加事件处理程序,用来监听触摸结束事件
  114. // 这个事件处理程序的实现方式与上面的鼠标事件处理程序类似
  115. floatWindow.addEventListener('touchend', () => {
  116. initialX = currentX;
  117. initialY = currentY;
  118. isDragging = false;
  119. // 如果点击时鼠标的位置没有改变,就认为是真正的点击
  120. if (cursorX === event.touches[0].clientX && cursorY === event.touches[0].clientY) {
  121. execCode();
  122. }
  123. });
  124. function setTranslate(xPos, yPos, el) {
  125. el.style.transform = "translate3d(" + xPos + "px, " + yPos + "px, 0)";
  126. }
  127. // 想要执行的代码放到此函数中:
  128. function execCode() {
  129. // 执行你想要执行的代码
  130. //alert('执行代码');
  131. savaYuQueMindMap('',true);
  132. }
  133. // 将悬浮窗添加到 body 元素中
  134. document.body.appendChild(floatWindow);