This commit is contained in:
scout 2024-11-12 19:31:42 +08:00
parent 6970d1b9c0
commit e7ca16821a
9 changed files with 469 additions and 0 deletions

BIN
icons/icon128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
icons/icon16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

BIN
icons/icon48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 945 B

18
mammoth.browser.min.js vendored Normal file

File diff suppressed because one or more lines are too long

23
manifest.json Normal file
View File

@ -0,0 +1,23 @@
{
"manifest_version": 3,
"name": "丰链工具箱",
"version": "1.0",
"description": "二维码生成、Word转HTML等实用工具集合。made by Scout",
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
},
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
},
"permissions": ["activeTab", "downloads"],
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'"
}
}

49
popup.html Normal file
View File

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="styles.css">
<script src="qrcode.min.js"></script>
<script src="mammoth.browser.min.js"></script>
</head>
<body>
<div class="container">
<h1>丰链工具箱</h1>
<div class="tab">
<button class="tablinks active" data-tab="qr">
<span class="icon">🔲</span>
二维码生成
</button>
<button class="tablinks" data-tab="word">
<span class="icon">📄</span>
Word转HTML
</button>
</div>
<div id="qr" class="tabcontent" style="display:block;">
<div class="input-group">
<input type="text" id="urlInput" placeholder="输入链接或文本">
<button id="generateBtn">生成二维码</button>
</div>
<div id="qrcode" class="result-container"></div>
</div>
<div id="word" class="tabcontent" style="display:none;">
<div class="file-upload">
<label for="wordFile" class="file-label">
<span class="icon">📎</span>
<span id="fileNameDisplay">选择Word文件</span>
</label>
<input type="file" id="wordFile" accept=".docx" hidden>
</div>
<div id="convertStatus" class="status-message"></div>
<div id="preview" class="preview-container"></div>
<button id="downloadBtn" class="download-btn" style="display:none;">
<span class="icon">💾</span>
下载HTML
</button>
</div>
</div>
<script src="popup.js"></script>
</body>
</html>

134
popup.js Normal file
View File

@ -0,0 +1,134 @@
document.addEventListener('DOMContentLoaded', function() {
const urlInput = document.getElementById('urlInput');
const generateBtn = document.getElementById('generateBtn');
const qrcodeDiv = document.getElementById('qrcode');
const wordFile = document.getElementById('wordFile');
const preview = document.getElementById('preview');
const downloadBtn = document.getElementById('downloadBtn');
let qr = null;
let convertedHtml = '';
const tabs = document.querySelectorAll('.tablinks');
const tabContents = document.querySelectorAll('.tabcontent');
tabs.forEach(tab => {
tab.addEventListener('click', (e) => {
const tabName = e.target.getAttribute('data-tab');
tabs.forEach(t => t.classList.remove('active'));
tab.classList.add('active');
tabContents.forEach(content => {
content.style.display = 'none';
});
const selectedContent = document.getElementById(tabName);
if (selectedContent) {
selectedContent.style.display = 'block';
}
});
});
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
if (tabs[0] && tabs[0].url) {
urlInput.value = tabs[0].url;
generateQRCode(tabs[0].url);
}
});
generateBtn.addEventListener('click', function() {
generateQRCode(urlInput.value);
});
function generateQRCode(text) {
if (!text) return;
qrcodeDiv.innerHTML = '';
qr = new QRCode(qrcodeDiv, {
text: text,
width: 256,
height: 256,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.H
});
}
// Word转HTML功能
const fileNameDisplay = document.getElementById('fileNameDisplay');
const convertStatus = document.getElementById('convertStatus');
let currentFileName = '';
wordFile.addEventListener('change', function(e) {
const file = e.target.files[0];
if (file) {
currentFileName = file.name.replace(/\.docx$/i, '');
fileNameDisplay.innerHTML = `
<span class="file-name" title="${file.name}">
📄 ${file.name}
</span>
`;
showStatus('loading', '正在转换中...');
const reader = new FileReader();
reader.onload = function(e) {
mammoth.convertToHtml({arrayBuffer: e.target.result})
.then(function(result) {
convertedHtml = result.value;
preview.innerHTML = convertedHtml;
downloadBtn.style.display = 'block';
showStatus('success', '转换成功!');
})
.catch(function(error) {
console.error(error);
showStatus('error', '转换失败:' + error.message);
});
};
reader.readAsArrayBuffer(file);
}
});
function showStatus(type, message) {
convertStatus.className = 'status-message ' + type;
convertStatus.textContent = message;
if (type === 'success') {
setTimeout(() => {
convertStatus.style.display = 'none';
}, 3000);
}
}
downloadBtn.addEventListener('click', function() {
if (!convertedHtml) return;
const fullHtml = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>${currentFileName}</title>
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; }
</style>
</head>
<body>
${convertedHtml}
</body>
</html>
`;
const blob = new Blob([fullHtml], {type: 'text/html'});
const url = URL.createObjectURL(blob);
chrome.downloads.download({
url: url,
filename: `${currentFileName}.html`,
saveAs: true
});
});
});

1
qrcode.min.js vendored Normal file

File diff suppressed because one or more lines are too long

244
styles.css Normal file
View File

@ -0,0 +1,244 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
background: #f5f5f5;
}
.container {
width: 380px;
padding: 20px;
background: white;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
font-size: 20px;
color: #333;
margin-bottom: 20px;
text-align: center;
font-weight: 600;
}
.tab {
display: flex;
gap: 10px;
margin-bottom: 20px;
background: #f5f5f5;
padding: 5px;
border-radius: 8px;
}
.tab button {
flex: 1;
padding: 12px;
border: none;
background: transparent;
color: #666;
cursor: pointer;
border-radius: 6px;
transition: all 0.3s ease;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.tab button:hover {
background: rgba(0,0,0,0.05);
}
.tab button.active {
background: #1a73e8;
color: white;
}
.input-group {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
input[type="text"] {
flex: 1;
padding: 12px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 14px;
transition: border-color 0.3s ease;
}
input[type="text"]:focus {
outline: none;
border-color: #1a73e8;
}
button {
padding: 12px 20px;
background: #1a73e8;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
transition: background 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
button:hover {
background: #1557b0;
}
.result-container {
background: #f8f9fa;
border-radius: 8px;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
}
.file-upload {
margin-bottom: 15px;
}
.file-label {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 12px;
background: #f8f9fa;
border: 2px dashed #ddd;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s ease;
}
.file-label:hover {
border-color: #1a73e8;
background: #f0f7ff;
}
.preview-container {
margin: 15px 0;
max-height: 300px;
overflow-y: auto;
padding: 15px;
background: #f8f9fa;
border-radius: 6px;
border: 1px solid #ddd;
}
.download-btn {
width: 100%;
background: #34a853;
}
.download-btn:hover {
background: #2d8a46;
}
.icon {
font-size: 18px;
}
/* 美化滚动条 */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 4px;
}
::-webkit-scrollbar-thumb {
background: #888;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #555;
}
/* 预览区域的样式 */
#preview {
font-size: 14px;
line-height: 1.6;
}
#preview h1, #preview h2, #preview h3 {
margin: 16px 0 8px 0;
color: #333;
}
#preview p {
margin-bottom: 8px;
}
#preview table {
border-collapse: collapse;
width: 100%;
margin: 10px 0;
}
#preview td, #preview th {
border: 1px solid #ddd;
padding: 8px;
}
#preview img {
max-width: 100%;
height: auto;
}
.status-message {
margin: 10px 0;
padding: 10px;
border-radius: 6px;
font-size: 14px;
display: none;
animation: fadeIn 0.3s ease;
}
.status-message.success {
display: block;
background-color: #e6f4ea;
color: #1e8e3e;
border: 1px solid #1e8e3e;
}
.status-message.loading {
display: block;
background-color: #e8f0fe;
color: #1a73e8;
border: 1px solid #1a73e8;
}
.status-message.error {
display: block;
background-color: #fce8e6;
color: #d93025;
border: 1px solid #d93025;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.file-name {
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}