ChatGPT Questions' Tree

进入问题页面后,点击按钮获取问题列表;点击问题某一项,直接跳转到对应位置。

  1. // ==UserScript==
  2. // @name ChatGPT Questions' Tree
  3. // @namespace https://github.com/DrNaki
  4. // @version 1.1.0
  5. // @description 进入问题页面后,点击按钮获取问题列表;点击问题某一项,直接跳转到对应位置。
  6. // @author zeanzai
  7. // @copyright 2024, zeanzai (https://github.com/zeanzai)
  8. // @license MIT
  9. // @match *://chatgpt.com/*
  10. // @compatible chrome
  11. // @compatible firefox
  12. // @grant none
  13. // @run-at document-start
  14. // ==/UserScript==
  15.  
  16. window.addEventListener('DOMContentLoaded', function () {
  17.  
  18. let btn = document.createElement("button");
  19. btn.style.position = 'fixed';
  20. btn.style.top = '20px';
  21. btn.style.right = '350px';
  22. btn.style.width = '100px';
  23. btn.style.backgroundColor = '#2e95d3';
  24. btn.innerHTML = "问题列表";//innerText也可以,区别是innerText不会解析html
  25. btn.onclick = function () {
  26. if(document.getElementById('mulu')){
  27. document.getElementById('mulu').remove();
  28. }
  29.  
  30. // 获取所有具有 data-message-id 属性的标签
  31. const messageElements = document.querySelectorAll('[data-message-id]');
  32. const messages = [];
  33.  
  34. // 遍历所有匹配的元素并提取信息
  35. messageElements.forEach(element => {
  36. const messageId = element.getAttribute('data-message-id');
  37. const messageContent = element.textContent.trim();
  38.  
  39. const authorRole = element.getAttribute('data-message-author-role');
  40. console.log(authorRole)
  41. if (authorRole === 'user') {
  42. const message = {};
  43. message.authorName = 'q';
  44. message.id = messageId;
  45. message.content = messageContent;
  46. messages.push(message);
  47.  
  48. } else if (authorRole === 'assistant') {
  49. const message = {};
  50. message.authorName = 'a';
  51. message.id = messageId;
  52. message.content = messageContent;
  53. messages.push(message);
  54. }
  55. });
  56.  
  57. // 创建一个新的 div 标签
  58. const messageContainer = document.createElement('div');
  59. messageContainer.setAttribute('id', 'mulu');
  60. messageContainer.classList.add('message-container');
  61. messageContainer.style.position = 'fixed';
  62. messageContainer.style.top = '50px';
  63. messageContainer.style.left = '250px';
  64. messageContainer.style.width = '400px';
  65. messageContainer.style.maxHeight = '90vh';
  66. messageContainer.style.overflowY = 'auto';
  67. messageContainer.style.border = '1px solid #ddd';
  68. messageContainer.style.padding = '10px';
  69. messageContainer.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.1)';
  70. messageContainer.style.cursor = 'move';
  71. messageContainer.style.zIndex = '1000';
  72.  
  73. // 创建一个用于渲染消息列表的 ul 元素
  74. const messageList = document.createElement('ul');
  75. messageList.classList.add('message-list');
  76.  
  77. // 创建列表项并添加到列表中
  78. let count=0;
  79. messages.forEach(message => {
  80. if (message.authorName == 'q') {
  81. count++;
  82. const listItem = document.createElement('li');
  83. listItem.style.border = '1px solid #ddd';
  84. listItem.style.padding = '5px';
  85. listItem.style.margin = '5px 0';
  86. if(count%2===1){
  87. listItem.style.backgroundColor='#e9950c';
  88. }else{
  89. listItem.style.backgroundColor='#2e95d3';
  90. }
  91. listItem.textContent = message.content.length > 50
  92. ? message.authorName + ': ' + message.content.substring(0, 50) + '...'
  93. : message.authorName + ': ' + message.content;
  94. listItem.title = message.content; // 显示完整内容的悬停文本
  95. listItem.addEventListener('click', () => {
  96. // 滚动到对应的消息元素
  97. document.querySelector(`[data-message-id="${message.id}"]`).parentElement.parentElement.scrollIntoView({ behavior: 'smooth' });
  98. listItem.style.backgroundColor = '#ececec';
  99. });
  100. messageList.appendChild(listItem);
  101. }
  102.  
  103. });
  104.  
  105. // 将消息列表添加到新的 div 标签中
  106. messageContainer.appendChild(messageList);
  107.  
  108. // 将新的 div 标签添加到 body 中
  109. document.body.appendChild(messageContainer);
  110.  
  111. // 添加拖动功能
  112. let isDragging = false;
  113. let offsetX, offsetY;
  114.  
  115. messageContainer.addEventListener('mousedown', (e) => {
  116. isDragging = true;
  117. offsetX = e.clientX - messageContainer.offsetLeft;
  118. offsetY = e.clientY - messageContainer.offsetTop;
  119. messageContainer.style.cursor = 'grabbing';
  120. });
  121.  
  122. document.addEventListener('mousemove', (e) => {
  123. if (isDragging) {
  124. messageContainer.style.left = `${e.clientX - offsetX}px`;
  125. messageContainer.style.top = `${e.clientY - offsetY}px`;
  126. }
  127. });
  128.  
  129. document.addEventListener('mouseup', () => {
  130. isDragging = false;
  131. messageContainer.style.cursor = 'move';
  132. });
  133.  
  134. // Prevent text selection while dragging
  135. messageContainer.addEventListener('dragstart', (e) => {
  136. e.preventDefault();
  137. });
  138. }
  139.  
  140. let btn2 = document.createElement("button");
  141. btn2.style.position = 'fixed';
  142. btn2.style.top = '20px';
  143. btn2.style.right = '200px';
  144. btn2.style.width = '100px';
  145. btn2.style.backgroundColor = '#2e95d3';
  146. btn2.innerHTML = "关闭列表";//innerText也可以,区别是innerText不会解析html
  147. btn2.onclick = function () {
  148. if(document.getElementById('mulu')){
  149. document.getElementById('mulu').remove();
  150. }
  151. };
  152. document.body.append(btn);
  153. document.body.append(btn2);
  154. });
  155.  
  156.  

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址