baogutang/baogutang-admin/src/main/resources/templates/file-baogutang.html
2024-12-19 20:13:33 +08:00

336 lines
10 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<link rel="icon" type="image/png" href="/NIKO.png" th:href="@{/NIKO.png}">
<title>BAOGUTANG-FILE</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="HandheldFriendly" content="True"/>
<meta name="MobileOptimized" content="320"/>
<meta http-equiv="Cache-Control" content="max-age=7200"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="all"/>
<meta name="author" content="BAOGUTANG-FILE"/>
<link href="/css/bootstrap.min.css" rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
<link href="/css/font-awesome.min.css" rel="stylesheet" th:href="@{/css/font-awesome.min.css}">
<link href="/css/base.css" rel="stylesheet" th:href="@{/css/base.css}">
<style>
body {
font-family: "Microsoft YaHei", Arial, sans-serif;
background-color: #f7f8fa;
margin: 0;
padding: 0;
}
.container {
max-width: 1200px;
margin: 20px auto;
padding: 20px;
background: #fff;
border: 1px solid #ddd;
border-radius: 5px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
h3 {
color: #444;
margin-bottom: 10px;
}
.section {
margin-bottom: 30px;
}
label {
font-weight: bold;
margin-bottom: 5px;
display: block;
}
input[type="file"], textarea, button {
width: 100%;
margin-bottom: 10px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 3px;
font-size: 14px;
}
button {
background-color: rgb(98, 210, 161);
color: white;
cursor: pointer;
border: none;
}
button:hover {
background-color: rgba(98, 210, 161, 0.8);
}
textarea {
height: 150px;
resize: none;
}
.preview {
margin-top: 10px;
min-height: 200px;
transition: opacity 0.3s ease; /* 添加过渡 */
opacity: 1;
}
.preview.hide {
opacity: 0;
}
img, iframe {
max-width: 100%;
border: 1px solid #ddd;
border-radius: 3px;
}
iframe {
height: 80vh;
}
.download-link {
display: block;
margin-top: 10px;
color: rgb(98, 210, 161);
text-decoration: none;
font-weight: bold;
}
.download-link:hover {
text-decoration: underline;
}
.divider {
margin: 30px 0;
border-top: 1px solid #ddd;
}
.type-options {
display: flex;
gap: 10px;
margin-bottom: 10px;
flex-wrap: wrap;
}
.type-option {
flex: 0 0 auto;
padding: 10px;
border: 1px solid #ddd;
border-radius: 3px;
cursor: pointer;
background-color: #fff;
font-size: 14px;
color: #333;
text-align: center;
user-select: none;
transition: background-color 0.2s;
}
.type-option:hover {
background-color: #eee;
}
.type-option.active {
background-color: rgb(98, 210, 161);
color: #fff;
border-color: rgb(98, 210, 161);
}
</style>
</head>
<body style="over-flow:hidden;">
<header class="header">
<div class="row-fluid">
<div class="col-md-5" style="position:relative;">
<span class="logo">BAOGUTANG-FILE</span>
</div>
<nav class="col-md-7" style="padding:10px 0;" align="right">
</nav>
<br style="clear:both;"/>
</div>
</header>
<div class="container">
<!-- 文件转 Base64 -->
<div class="section">
<h3>文件转 Base64</h3>
<input type="file" id="fileInput" />
<button onclick="convertToBase64()">转换为 Base64</button>
<label for="base64Output">Base64 输出</label>
<textarea id="base64Output" readonly placeholder="Base64 输出"></textarea>
</div>
<div class="divider"></div>
<!-- Base64 转文件 -->
<div class="section">
<h3>Base64 转文件</h3>
<textarea id="base64Input" placeholder="粘贴 Base64 字符串"></textarea>
<div class="type-options" id="typeOptions">
<div class="type-option" data-type="auto">自动识别</div>
<div class="type-option" data-type="image/png">图片(PNG)</div>
<div class="type-option" data-type="image/jpeg">图片(JPEG)</div>
<div class="type-option" data-type="video/mp4">视频(MP4)</div>
<div class="type-option" data-type="application/pdf">PDF文件</div>
<div class="type-option" data-type="text/plain">文本文件</div>
<div class="type-option" data-type="application/octet-stream">通用文件</div>
</div>
<button onclick="convertToFile()">转换为文件并预览</button>
<div class="preview hide" id="previewArea"></div>
</div>
</div>
<script>
let selectedType = 'auto';
window.addEventListener('DOMContentLoaded', () => {
resetTypeSelection();
});
function resetTypeSelection() {
const typeOptions = document.querySelectorAll('.type-option');
typeOptions.forEach(option => {
option.classList.remove('active');
if(option.dataset.type === 'auto') {
option.classList.add('active');
selectedType = 'auto';
}
});
}
document.getElementById('typeOptions').addEventListener('click', (e) => {
if (e.target.classList.contains('type-option')) {
const typeOptions = document.querySelectorAll('.type-option');
typeOptions.forEach(option => option.classList.remove('active'));
e.target.classList.add('active');
selectedType = e.target.dataset.type;
}
});
function convertToBase64() {
const fileInput = document.getElementById('fileInput');
const base64Output = document.getElementById('base64Output');
if (!fileInput.files || fileInput.files.length === 0) {
alert('请选择一个文件!');
return;
}
const file = fileInput.files[0];
const reader = new FileReader();
reader.onload = function (e) {
base64Output.value = e.target.result;
};
reader.onerror = function () {
alert('文件读取失败!');
};
reader.readAsDataURL(file);
}
function convertToFile() {
const base64Input = document.getElementById('base64Input');
const previewArea = document.getElementById('previewArea');
let inputValue = base64Input.value.trim();
if (!inputValue) {
alert('请提供有效的 Base64 字符串!');
resetTypeSelection();
return;
}
// 隐藏预览区(淡出)
previewArea.classList.add('hide');
let finalBase64 = inputValue;
let mimeType = '';
if (selectedType === 'auto') {
let headerMatch = finalBase64.match(/^data:(.*);base64,/);
if (headerMatch) {
mimeType = headerMatch[1];
finalBase64 = finalBase64.substring(finalBase64.indexOf(',')+1);
} else {
mimeType = 'application/octet-stream';
}
} else {
finalBase64 = finalBase64.replace(/^data:.*;base64,/, '');
mimeType = selectedType;
}
const binary = atob(finalBase64);
const arrayBuffer = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
arrayBuffer[i] = binary.charCodeAt(i);
}
const blob = new Blob([arrayBuffer], { type: mimeType });
const fileUrl = URL.createObjectURL(blob);
const fragment = document.createDocumentFragment();
const downloadLink = document.createElement('a');
downloadLink.href = fileUrl;
downloadLink.download = 'converted_file';
downloadLink.textContent = '点击下载文件';
downloadLink.className = 'download-link';
fragment.appendChild(downloadLink);
if (mimeType.startsWith('image/')) {
const img = document.createElement('img');
img.src = fileUrl;
fragment.appendChild(img);
updatePreview(fragment);
} else if (mimeType === 'application/pdf') {
const iframe = document.createElement('iframe');
iframe.src = fileUrl;
fragment.appendChild(iframe);
updatePreview(fragment);
} else if (mimeType.startsWith('text/')) {
const reader = new FileReader();
reader.onload = function (e) {
const textArea = document.createElement('textarea');
textArea.value = e.target.result;
textArea.style.width = '100%';
textArea.style.height = '200px';
fragment.appendChild(textArea);
updatePreview(fragment);
};
reader.readAsText(blob);
} else if (mimeType.startsWith('video/')) {
const video = document.createElement('video');
video.controls = true;
video.src = fileUrl;
fragment.appendChild(video);
updatePreview(fragment);
} else {
// 其他类型,不预览,只提供下载
updatePreview(fragment);
}
function updatePreview(fragment) {
// 将新内容插入前先等待CSS过渡结束后再显示减少闪动感
// 这里可以直接替换内容然后在下一个事件循环中取消hide类以渐显
previewArea.innerHTML = '';
previewArea.appendChild(fragment);
// 使用requestAnimationFrame在下一帧再移除'hide'类保证CSS有机会渲染
requestAnimationFrame(() => {
previewArea.classList.remove('hide');
});
}
}
</script>
</body>
</html>