Tổng kết nhanh nội dung cuộc trò chuyện và tạo danh mục tiêu đề câu hỏi trên Perplexity.ai
Size
9.3 KB
Version
1.0.1
Created
Mar 27, 2026
Updated
19 days ago
1// ==UserScript==
2// @name Perplexity Chat Summarizer
3// @description Tổng kết nhanh nội dung cuộc trò chuyện và tạo danh mục tiêu đề câu hỏi trên Perplexity.ai
4// @version 1.0.1
5// @match https://*.perplexity.ai/*
6// @icon https://www.perplexity.ai/favicon.svg
7// ==/UserScript==
8(function() {
9 'use strict';
10
11 // Hàm tạo sidebar cho danh mục câu hỏi
12 function createSidebar() {
13 // Tạo phần tử sidebar
14 const sidebar = document.createElement('div');
15 sidebar.id = 'perplexity-summary-sidebar';
16 sidebar.style.cssText = `
17 position: fixed;
18 right: 0;
19 top: 0;
20 width: 300px;
21 height: 100vh;
22 background-color: #f5f5f5;
23 border-left: 1px solid #ddd;
24 padding: 20px;
25 overflow-y: auto;
26 z-index: 10000;
27 transform: translateX(0);
28 transition: transform 0.3s ease;
29 `;
30
31 // Thêm tiêu đề cho sidebar
32 const title = document.createElement('h2');
33 title.textContent = 'Danh mục câu hỏi';
34 title.style.cssText = `
35 margin-top: 0;
36 padding-bottom: 10px;
37 border-bottom: 1px solid #ddd;
38 display: flex;
39 justify-content: space-between;
40 align-items: center;
41 `;
42
43 // Thêm nút đóng sidebar
44 const closeBtn = document.createElement('button');
45 closeBtn.textContent = '×';
46 closeBtn.style.cssText = `
47 background: none;
48 border: none;
49 font-size: 24px;
50 cursor: pointer;
51 color: #999;
52 `;
53 closeBtn.addEventListener('click', () => {
54 sidebar.style.transform = 'translateX(100%)';
55 });
56 title.appendChild(closeBtn);
57 sidebar.appendChild(title);
58
59 // Tạo container cho danh sách câu hỏi
60 const listContainer = document.createElement('div');
61 listContainer.id = 'question-list-container';
62 sidebar.appendChild(listContainer);
63
64 // Thêm sidebar vào body
65 document.body.appendChild(sidebar);
66
67 return sidebar;
68 }
69
70 // Hàm trích xuất câu hỏi từ trang
71 function extractQuestions() {
72 try {
73 // Tìm tất cả các phần tử chứa câu hỏi trên trang Perplexity.ai
74 // Dựa trên cấu trúc DOM điển hình của Perplexity.ai
75 const questionElements = document.querySelectorAll('[data-testid="question"], .question-text, [class*="question"], h2, h3');
76
77 const questions = [];
78
79 // Nếu không tìm thấy phần tử câu hỏi cụ thể, tìm trong các tiêu đề
80 if (questionElements.length > 0) {
81 questionElements.forEach((element, index) => {
82 const text = element.textContent.trim();
83 // Chỉ thêm các tiêu đề không rỗng và có độ dài phù hợp
84 if (text && text.length > 10 && text.length < 200) {
85 questions.push({
86 id: index + 1,
87 title: text,
88 element: element
89 });
90 }
91 });
92 } else {
93 // Nếu không tìm thấy phần tử câu hỏi, tạo dữ liệu mẫu
94 const sampleQuestions = [
95 { id: 1, title: 'Cách sử dụng Perplexity.ai hiệu quả?', element: null },
96 { id: 2, title: 'Perplexity.ai có những tính năng nổi bật nào?', element: null },
97 { id: 3, title: 'So sánh Perplexity.ai với các công cụ AI khác', element: null }
98 ];
99 return sampleQuestions;
100 }
101
102 // Loại bỏ các câu hỏi trùng lặp
103 const uniqueQuestions = questions.filter((question, index, self) =>
104 index === self.findIndex(q => q.title === question.title)
105 );
106
107 return uniqueQuestions.slice(0, 10); // Giới hạn tối đa 10 câu hỏi
108 } catch (error) {
109 console.error('Lỗi khi trích xuất câu hỏi:', error);
110 // Trả về dữ liệu mẫu nếu có lỗi
111 return [
112 { id: 1, title: 'Cách sử dụng Perplexity.ai hiệu quả?', element: null },
113 { id: 2, title: 'Perplexity.ai có những tính năng nổi bật nào?', element: null },
114 { id: 3, title: 'So sánh Perplexity.ai với các công cụ AI khác', element: null }
115 ];
116 }
117 }
118
119 // Hàm tạo tóm tắt nội dung câu trả lời
120 function summarizeAnswer(answerElement) {
121 try {
122 // Nếu có phần tử câu trả lời, trích xuất nội dung văn bản
123 if (answerElement) {
124 const text = answerElement.textContent.trim();
125 // Tạo tóm tắt đơn giản bằng cách lấy một số câu đầu tiên
126 const sentences = text.split(/[.!?]+/).filter(s => s.trim().length > 0);
127 const summary = sentences.slice(0, 3).join('. ') + '.';
128 return summary;
129 } else {
130 // Nếu không có phần tử câu trả lời, tạo tóm tắt mẫu
131 return 'Đây là tóm tắt nội dung câu trả lời cho câu hỏi. Nội dung sẽ bao gồm các điểm chính và thông tin quan trọng nhất.';
132 }
133 } catch (error) {
134 console.error('Lỗi khi tạo tóm tắt:', error);
135 return 'Không thể tạo tóm tắt cho nội dung này.';
136 }
137 }
138
139 // Hàm tạo danh sách câu hỏi trong sidebar
140 function populateQuestionList(questions) {
141 const container = document.getElementById('question-list-container');
142 if (!container) return;
143
144 container.innerHTML = '';
145
146 questions.forEach(question => {
147 const item = document.createElement('div');
148 item.className = 'question-item';
149 item.style.cssText = `
150 padding: 10px;
151 margin-bottom: 10px;
152 background-color: white;
153 border-radius: 5px;
154 cursor: pointer;
155 border: 1px solid #eee;
156 transition: all 0.2s ease;
157 `;
158
159 // Tạo tiêu đề câu hỏi
160 const title = document.createElement('div');
161 title.className = 'question-title';
162 title.style.cssText = `
163 font-weight: bold;
164 margin-bottom: 5px;
165 color: #333;
166 `;
167 title.textContent = question.title;
168
169 // Tạo tóm tắt câu trả lời
170 const summary = document.createElement('div');
171 summary.className = 'question-summary';
172 summary.style.cssText = `
173 font-size: 12px;
174 color: #666;
175 line-height: 1.4;
176 `;
177 summary.textContent = summarizeAnswer(question.element ? question.element.nextElementSibling : null);
178
179 item.appendChild(title);
180 item.appendChild(summary);
181
182 // Thêm sự kiện click để di chuyển đến đoạn hội thoại tương ứng
183 item.addEventListener('click', () => {
184 if (question.element) {
185 // Cuộn đến phần tử câu hỏi
186 question.element.scrollIntoView({ behavior: 'smooth', block: 'center' });
187
188 // Thêm hiệu ứng highlight để làm nổi bật
189 question.element.style.backgroundColor = '#ffff99';
190 setTimeout(() => {
191 question.element.style.backgroundColor = '';
192 }, 2000);
193 }
194 });
195
196 container.appendChild(item);
197 });
198 }
199
200 // Hàm khởi tạo extension
201 function init() {
202 // Đợi trang tải xong
203 if (document.readyState === 'loading') {
204 document.addEventListener('DOMContentLoaded', init);
205 return;
206 }
207
208 // Tạo sidebar
209 const sidebar = createSidebar();
210
211 // Trích xuất câu hỏi và tạo danh sách
212 const questions = extractQuestions();
213 populateQuestionList(questions);
214
215 // Thêm nút để mở lại sidebar nếu đã đóng
216 const toggleBtn = document.createElement('button');
217 toggleBtn.textContent = '📋 Danh mục câu hỏi';
218 toggleBtn.style.cssText = `
219 position: fixed;
220 right: 10px;
221 top: 10px;
222 z-index: 9999;
223 background-color: #4a6cf7;
224 color: white;
225 border: none;
226 border-radius: 5px;
227 padding: 10px 15px;
228 cursor: pointer;
229 font-size: 14px;
230 box-shadow: 0 2px 10px rgba(0,0,0,0.1);
231 `;
232 toggleBtn.addEventListener('click', () => {
233 sidebar.style.transform = 'translateX(0)';
234 });
235 document.body.appendChild(toggleBtn);
236 }
237
238 // Khởi chạy extension
239 init();
240})();