mirror of
https://gitee.com/kekingcn/file-online-preview.git
synced 2026-04-09 09:47:35 +00:00
5.0版本 发布 新增 cadviewer转换方法
This commit is contained in:
@@ -45,7 +45,7 @@
|
||||
var kkagent = '${kkagent}';
|
||||
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';
|
||||
if (kkagent === 'true' || !url.startsWith(baseUrl)) {
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url));
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url))+ "&key=${kkkey}";
|
||||
}
|
||||
async function showDiagram(diagramXML) {
|
||||
await viewer.importXML(diagramXML);
|
||||
|
||||
182
server/src/main/resources/web/cadviewer.ftl
Normal file
182
server/src/main/resources/web/cadviewer.ftl
Normal file
@@ -0,0 +1,182 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CADViewer - 中文界面</title>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<!-- 核心样式 - 精简版本 -->
|
||||
<link href="cadviewer/app/css/cadviewer-core-styles.css" media="screen" rel="stylesheet" type="text/css" />
|
||||
<link href="cadviewer/app/css/font-awesome.min.css" media="screen" rel="stylesheet" type="text/css" />
|
||||
<link href="cadviewer/app/css/cadviewer-bootstrap.css" media="screen" rel="stylesheet" type="text/css" />
|
||||
<link href="cadviewer/app/css/jquery-ui-1.13.2.min.css" media="screen" rel="stylesheet" type="text/css" />
|
||||
|
||||
<!-- 核心脚本 - 最小化依赖 -->
|
||||
<script src="js/jquery-3.6.1.min.js" type="text/javascript"></script>
|
||||
<script src="cadviewer/app/js/jquery-ui-1.13.2.min.js" type="text/javascript"></script>
|
||||
<script src="cadviewer/app/js/eve.js" type="text/javascript"></script>
|
||||
<script src="cadviewer/app/js/xml2json.min.js" type="text/javascript"></script>
|
||||
<script src="cadviewer/app/js/list.js" type="text/javascript"></script>
|
||||
|
||||
<!-- CADViewer 核心库 -->
|
||||
<script src="cadviewer/app/cv/cv-pro/cadviewer.min.js" type="text/javascript"></script>
|
||||
<#if currentUrl?contains("http://") || currentUrl?contains("https://") || currentUrl?contains("file://")|| currentUrl?contains("ftp://")>
|
||||
<#assign finalUrl="${currentUrl}">
|
||||
<#else>
|
||||
<#assign finalUrl="${baseUrl}${currentUrl}">
|
||||
</#if>
|
||||
<!-- 必需的第三方库 -->
|
||||
<script src="cadviewer/app/js/jscolor.js" type="text/javascript"></script>
|
||||
<script src="cadviewer/app/js/snap.svg-min.js" type="text/javascript"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
// 基本配置
|
||||
var ServerUrl = '${baseUrl}' + "cadviewer/";
|
||||
|
||||
// 图纸文件路径
|
||||
var FileName = '${finalUrl}'+"?Type=svgz";
|
||||
|
||||
$(document).ready(function() {
|
||||
console.log("正在初始化CADViewer...");
|
||||
|
||||
try {
|
||||
// 启用CADViewer专业版
|
||||
if (typeof cvjs_CADViewerPro === 'function') {
|
||||
cvjs_CADViewerPro(true);
|
||||
}
|
||||
|
||||
// 设置调试模式
|
||||
if (typeof cvjs_debugMode === 'function') {
|
||||
cvjs_debugMode(true);
|
||||
}
|
||||
|
||||
// 设置服务器路径和处理程序 - 简化版本
|
||||
if (typeof cvjs_setAllServerPaths_and_Handlers === 'function') {
|
||||
cvjs_setAllServerPaths_and_Handlers(ServerUrl, ServerUrl, "", "PHP", "JavaScript", "floorPlan");
|
||||
}
|
||||
|
||||
// 设置语言为简体中文 - 使用正确的方法名
|
||||
if (typeof cvjs_loadCADViewerLanguage === 'function') {
|
||||
cvjs_loadCADViewerLanguage("Chinese-Simplified");
|
||||
}
|
||||
|
||||
// 设置皮肤 - 暂时不设置,避免错误
|
||||
// if (typeof cvjs_setCADViewerSkin === 'function') {
|
||||
// cvjs_setCADViewerSkin("light-skin");
|
||||
// }
|
||||
|
||||
// 初始化CADViewer - 使用最简化的版本
|
||||
if (typeof cvjs_InitCADViewer === 'function') {
|
||||
cvjs_InitCADViewer("floorPlan", ServerUrl + "app/images/", ServerUrl + "app/");
|
||||
}
|
||||
|
||||
// 设置许可证路径
|
||||
if (typeof cvjs_setLicenseKeyPath === 'function') {
|
||||
cvjs_setLicenseKeyPath(ServerUrl + "/app/cv/");
|
||||
}
|
||||
|
||||
// 清空转换参数并设置新参数
|
||||
if (typeof cvjs_conversion_clearAXconversionParameters === 'function') {
|
||||
cvjs_conversion_clearAXconversionParameters();
|
||||
cvjs_conversion_addAXconversionParameter("last", "");
|
||||
cvjs_conversion_addAXconversionParameter("extents", "");
|
||||
}
|
||||
|
||||
// 加载图纸
|
||||
if (typeof cvjs_LoadDrawing === 'function') {
|
||||
cvjs_LoadDrawing("floorPlan", FileName);
|
||||
}
|
||||
|
||||
// 调整画布大小为全屏
|
||||
if (typeof cvjs_resizeWindow_position === 'function') {
|
||||
cvjs_resizeWindow_position("floorPlan");
|
||||
}
|
||||
|
||||
console.log("CADViewer初始化完成");
|
||||
} catch (error) {
|
||||
console.error("初始化CADViewer时出错:", error);
|
||||
// 尝试基本初始化
|
||||
try {
|
||||
if (typeof cvjs_InitCADViewer === 'function') {
|
||||
cvjs_InitCADViewer("floorPlan", ServerUrl + "app/images/", ServerUrl + "app/");
|
||||
cvjs_LoadDrawing("floorPlan", FileName);
|
||||
}
|
||||
} catch (e2) {
|
||||
console.error("基本初始化也失败:", e2);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$(window).resize(function() {
|
||||
if (typeof cvjs_resizeWindow_position === 'function') {
|
||||
cvjs_resizeWindow_position("floorPlan");
|
||||
}
|
||||
});
|
||||
|
||||
// 图纸加载完成回调
|
||||
function cvjs_OnLoadEnd() {
|
||||
console.log("图纸加载完成");
|
||||
try {
|
||||
if (typeof cvjs_resetZoomPan === 'function') {
|
||||
cvjs_resetZoomPan("floorPlan");
|
||||
}
|
||||
|
||||
|
||||
|
||||
console.log("OnLoadEnd完成");
|
||||
} catch (error) {
|
||||
console.error("OnLoadEnd中出错:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// 批注加载完成回调
|
||||
function cvjs_OnLoadEndRedlines() {
|
||||
console.log("批注加载完成");
|
||||
// 空实现
|
||||
}
|
||||
|
||||
// 必须的其他回调函数
|
||||
function cvjs_change_space() {}
|
||||
function cvjs_ObjectSelected(rmid) {}
|
||||
function cvjs_graphicalObjectCreated(graphicalObject) {}
|
||||
function cvjs_popupTitleClick(graphicalObject) {}
|
||||
function cvjs_graphicalObjectOnChange(type, graphicalObject, spaceID, evt) {}
|
||||
function cvjs_mousedown(id, handle, entity) {}
|
||||
function cvjs_click(id, handle, entity) {}
|
||||
function cvjs_dblclick(id, handle, entity) {}
|
||||
function cvjs_mouseout(id, handle, entity) {}
|
||||
function cvjs_mouseover(id, handle, entity) {}
|
||||
function cvjs_mouseleave(id, handle, entity) {}
|
||||
function cvjs_mouseenter(id, handle, entity) {}
|
||||
|
||||
// 保存批注函数
|
||||
function cvjs_saveStickyNotesRedlinesUser() {
|
||||
try {
|
||||
if (typeof cvjs_openRedlineSaveModal === 'function') {
|
||||
cvjs_openRedlineSaveModal("floorPlan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("保存批注时出错:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// 加载批注函数
|
||||
function cvjs_loadStickyNotesRedlinesUser() {
|
||||
try {
|
||||
if (typeof cvjs_openRedlineLoadModal === 'function') {
|
||||
cvjs_openRedlineLoadModal("floorPlan");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("加载批注时出错:", error);
|
||||
}
|
||||
}
|
||||
/*初始化水印*/
|
||||
window.onload = function () {
|
||||
initWaterMark();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body style="margin:0; height:100vh; overflow:hidden;">
|
||||
<!-- CADViewer 显示容器 -->
|
||||
<div id="floorPlan" class="cadviewer-bootstrap cadviewer-core-styles" style="width:100%; height:100%;"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -14,11 +14,95 @@
|
||||
<script src="js/fenye.js" type="text/javascript"></script>
|
||||
<#if "${file.suffix?lower_case}" == "js" >
|
||||
<script src="js/jsformat.js" type="text/javascript"></script>
|
||||
</#if>
|
||||
</#if>
|
||||
<script src="js/base64.min.js" type="text/javascript"></script>
|
||||
</head>
|
||||
<body>
|
||||
<input hidden id="textData" value="${textData}"/>
|
||||
<#if isHtmlFile>
|
||||
<!-- HTML文件预览模式 -->
|
||||
<div class="container">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<strong><font color="red"><input class="GLOkBtn" type="button" value="运行html" onclick="loadXmlData();" /></font></strong>
|
||||
<a data-toggle="collapse" data-parent="#accordion" onclick="loadText();">
|
||||
${file.name}
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div id="text"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
// 将Freemarker的布尔值传递给JavaScript
|
||||
var scriptjs = ${scriptjs?c}; // ?c 将布尔值转换为字符串true/false
|
||||
|
||||
/**
|
||||
*加载普通文本
|
||||
*/
|
||||
function loadText() {
|
||||
var base64data = $("#textData").val()
|
||||
var div = document.getElementById("text");
|
||||
div.innerHTML = ""; //
|
||||
var textData = Base64.decode(base64data);
|
||||
textData = htmlttt(textData,1);
|
||||
var textPreData = "<xmp style='background-color: #FFFFFF;overflow-y: scroll;border:none'>" + textData + "</xmp>";
|
||||
$("#text").append(textPreData);
|
||||
}
|
||||
|
||||
function htmlttt (str,txt){
|
||||
var s = "";
|
||||
if(str.length == 0) return "";
|
||||
s = str.replace(/&/gi,"&");
|
||||
s = s.replace(/</gi,"<");
|
||||
s = s.replace(/>/gi,">");
|
||||
s = s.replace(/ /gi," ");
|
||||
s = s.replace(/'/gi,"\'");
|
||||
s = s.replace(/"/gi,"\"");
|
||||
s = s.replace(/javascript/g,"javascript ");
|
||||
if (txt === 2){
|
||||
s = s.replace(/<script/gi, "<script ");
|
||||
s = s.replace(/javascript/g,"javascript ");
|
||||
s = s.replace(/<\/script/gi, "</script ");
|
||||
s = s.replace(/<iframe/gi, "<iframe ");
|
||||
s = s.replace(/<\/iframe/gi, "</iframe ");
|
||||
s = s.replace(/confirm/gi, "c&onfirm");
|
||||
s = s.replace(/alert/gi, "a&lert");
|
||||
s = s.replace(/eval/gi, "e&val");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
*加载运行
|
||||
*/
|
||||
function loadXmlData() {
|
||||
var base64data = $("#textData").val();
|
||||
var textData = Base64.decode(base64data);
|
||||
|
||||
// 直接使用JavaScript变量进行判断
|
||||
if (scriptjs) {
|
||||
textData = htmlttt(textData, 1);
|
||||
} else {
|
||||
textData = htmlttt(textData, 2);
|
||||
}
|
||||
|
||||
$('#text').html(textData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
window.onload = function () {
|
||||
initWaterMark();
|
||||
loadText();
|
||||
}
|
||||
</script>
|
||||
<#else>
|
||||
<!-- 其他代码文件预览模式 -->
|
||||
<div class="container">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
@@ -28,30 +112,33 @@
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="divPagenation" class="black" >
|
||||
</div>
|
||||
<div id="divPagenation" class="black" >
|
||||
</div>
|
||||
<div id="divContent" class="panel-body">
|
||||
</div>
|
||||
<div id="divPagenationx" class="black" >
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var base64data = $("#textData").val()
|
||||
var s = Base64.decode(base64data);
|
||||
var kkkeyword = '${highlightall}';
|
||||
var Length= 20000;
|
||||
var page= '${page}';
|
||||
<#if "${file.suffix?lower_case}" == "js" > var txt = "js";<#else>var txt = "code";</#if>
|
||||
DHTMLpagenation(s,kkkeyword,Length,page,txt);
|
||||
/**
|
||||
<script type="text/javascript">
|
||||
var base64data = $("#textData").val()
|
||||
var s = Base64.decode(base64data);
|
||||
var kkkeyword = '${highlightall}';
|
||||
var Length = 20000;
|
||||
var page = '${page}';
|
||||
<#if "${file.suffix?lower_case}" == "js" >
|
||||
var txt = "js";
|
||||
<#else>
|
||||
var txt = "code";
|
||||
</#if>
|
||||
DHTMLpagenation(s, kkkeyword, Length, page, txt);
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
window.onload = function () {
|
||||
initWaterMark();
|
||||
}
|
||||
</script>
|
||||
</#if>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
@@ -36,9 +36,10 @@ var process_wb = (function() {
|
||||
};
|
||||
})();
|
||||
var url = '${finalUrl}';
|
||||
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';
|
||||
if (!url.startsWith(baseUrl)) {
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url));
|
||||
var kkagent = '${kkagent}';
|
||||
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';
|
||||
if (kkagent === 'true' || !url.startsWith(baseUrl)) {
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url))+ "&key=${kkkey}";
|
||||
}
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open('GET',url); //文件所在地址
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
var kkagent = '${kkagent}';
|
||||
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';
|
||||
if (kkagent === 'true' || !url.startsWith(baseUrl)) {
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url));
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url))+ "&key=${kkkey}";
|
||||
}
|
||||
"use strict";
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
var kkagent = '${kkagent}';
|
||||
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';
|
||||
if (kkagent === 'true' || !url.startsWith(baseUrl)) {
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url));
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url))+ "&key=${kkkey}";
|
||||
}
|
||||
document.getElementsByTagName('iframe')[0].src = "${baseUrl}drawio/index.html?lightbox=1&gapi=0&db=0&od=0&tr=0&gh=0&gl=0&edit=_blank&lang=zh#U"+ encodeURIComponent(url)+"";
|
||||
document.getElementsByTagName('iframe')[0].height = document.documentElement.clientHeight - 10;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
var kkagent = '${kkagent}';
|
||||
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';
|
||||
if (kkagent === 'true' || !url.startsWith(baseUrl)) {
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url));
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url))+ "&key=${kkkey}";
|
||||
}
|
||||
document.getElementsByTagName('iframe')[0].src = "${baseUrl}eml/index.html?file="+encodeURIComponent(url);
|
||||
document.getElementsByTagName('iframe')[0].height = document.documentElement.clientHeight - 10;
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
var kkagent = '${kkagent}';
|
||||
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';
|
||||
if (kkagent === 'true' || !url.startsWith(baseUrl)) {
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url));
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url))+ "&key=${kkkey}";
|
||||
}
|
||||
|
||||
function blobToArrayBuffer(blob) {
|
||||
|
||||
103
server/src/main/resources/web/heic.ftl
Normal file
103
server/src/main/resources/web/heic.ftl
Normal file
@@ -0,0 +1,103 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>${file.name}文件预览</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0">
|
||||
<#include "*/commonHeader.ftl">
|
||||
<script src="js/base64.min.js" type="text/javascript"></script>
|
||||
<script src="/heic/src/index.js" type="text/javascript"></script>
|
||||
</head>
|
||||
<style>
|
||||
body {
|
||||
background-color: #404040;
|
||||
}
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.my-photo {
|
||||
max-width: 98%;
|
||||
margin:0 auto;
|
||||
border-radius:3px;
|
||||
box-shadow:rgba(0,0,0,0.15) 0 0 8px;
|
||||
background:#FBFBFB;
|
||||
border:1px solid #ddd;
|
||||
margin:1px auto;
|
||||
margin-left: 15px;
|
||||
padding:5px;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div class="container">
|
||||
<#-- 获取反代配置 -->
|
||||
<#assign kkagentValue = kkagent>
|
||||
<#assign baseUrlValue = baseUrl.endsWith('/')?then(baseUrl, baseUrl + '/')>
|
||||
|
||||
<#list imgUrls as img>
|
||||
<#-- 处理每个图片URL -->
|
||||
<#if img?contains("http://") || img?contains("https://")|| img?contains("ftp://")|| img?contains("file://")>
|
||||
<#assign originalUrl = img>
|
||||
<#else>
|
||||
<#assign originalUrl = baseUrl + img>
|
||||
</#if>
|
||||
|
||||
<#-- 应用反代逻辑 -->
|
||||
<#assign finalUrl = originalUrl>
|
||||
<#if kkagentValue == "true">
|
||||
<#assign finalUrl = baseUrlValue + "getCorsFile?urlPath=" + originalUrl?url + "&key=${kkkey}">
|
||||
</#if>
|
||||
|
||||
<img class="my-photo" src="${finalUrl}" data-original="${originalUrl}">
|
||||
</#list>
|
||||
</div>
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
// 定义跨域处理方法
|
||||
function processImageUrls() {
|
||||
var kkagent = '${kkagent}';
|
||||
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';
|
||||
var kkkey = '${kkkey}';
|
||||
|
||||
// 获取所有图片
|
||||
var images = document.querySelectorAll('.my-photo');
|
||||
|
||||
images.forEach(function(img) {
|
||||
var originalUrl = img.getAttribute('data-original');
|
||||
var currentSrc = img.src;
|
||||
|
||||
// 检查是否需要反代
|
||||
if (kkagent === 'true') {
|
||||
// 构建反代URL
|
||||
var proxyUrl = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(originalUrl)) + "&key=" + kkkey;
|
||||
|
||||
// 如果当前src不是反代URL,则更新
|
||||
if (currentSrc !== proxyUrl) {
|
||||
img.src = proxyUrl;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 页面加载时处理图片URL
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// 先处理跨域图片
|
||||
processImageUrls();
|
||||
|
||||
// 然后设置HEIC转换监听器
|
||||
document.querySelectorAll('img').forEach(async x => {
|
||||
x.addEventListener('error', async function() {
|
||||
x.title = x.alt;
|
||||
x.src = await document.ConvertHeicToPng(x.src, stat => x.alt = stat);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/*初始化水印*/
|
||||
if (!!window.ActiveXObject || "ActiveXObject" in window) {
|
||||
// IE浏览器不添加水印
|
||||
} else {
|
||||
initWaterMark();
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
@@ -151,19 +151,19 @@
|
||||
<li>支持 vsd, vsdx 等 Visio 流程图文件</li>
|
||||
<li>支持 wmf, emf 等 Windows 系统图像文件</li>
|
||||
<li>支持 psd, eps 等 Photoshop 软件模型文件</li>
|
||||
<li>支持 pdf ,ofd, rtf 等文档</li>
|
||||
<li>支持 pdf, ofd, rtf 等文档</li>
|
||||
<li>支持 xmind 软件模型文件</li>
|
||||
<li>支持 bpmn 工作流文件</li>
|
||||
<li>支持 eml 邮件文件</li>
|
||||
<li>支持 eml, msg邮件文件</li>
|
||||
<li>支持 epub 图书文档</li>
|
||||
<li>支持 obj, 3ds, stl, ply, gltf, glb, off, 3dm, fbx, dae, wrl, 3mf, ifc, brep, step, iges, fcstd, bim 等 3D 模型文件</li>
|
||||
<li>支持 dwg, dxf, dwf, iges , igs, dwt, dng, ifc, dwfx, stl, cf2, plt 等 CAD 模型文件</li>
|
||||
<li>支持 txt, xml(渲染), md(渲染), java, php, py, js, css 等所有纯文本</li>
|
||||
<li>支持 zip, rar, jar, tar, gzip, 7z 等压缩包</li>
|
||||
<li>支持 jpg, jpeg, png, gif, bmp, ico, jfif, webp 等图片预览(翻转,缩放,镜像)</li>
|
||||
<li>支持 tif, tiff 图信息模型文件</li>
|
||||
<li>支持 jpg, jpeg, png, gif, bmp, ico, jfif, webp, heic 等图片预览(翻转,缩放,镜像)</li>
|
||||
<li>支持 tif, tiff 图信息模型文件(翻转,缩放)</li>
|
||||
<li>支持 tga 图像格式文件</li>
|
||||
<li>支持 svg 矢量图像格式文件</li>
|
||||
<li>支持 svg 矢量图像格式文件 (翻转,缩放)</li>
|
||||
<li>支持 mp3,wav,mp4,flv 等音视频格式文件</li>
|
||||
<li>支持 avi,mov,rm,webm,ts,rm,mkv,mpeg,ogg,mpg,rmvb,wmv,3gp,ts,swf 等视频格式转码预览</li>
|
||||
<li>支持 dcm 等医疗数位影像预览</li>
|
||||
@@ -197,7 +197,7 @@
|
||||
<input type="text" id="highlightall" name="highlightall" placeholder="高亮显示" style="width:50px;">
|
||||
<input type="text" id="watermarkTxt" name="watermarkTxt" placeholder="插入水印" style="width:50px;">
|
||||
<#if isshowkey>
|
||||
<input type="text" id="aeskey" name="key" placeholder="KK秘钥" style="width:60px;">
|
||||
<input type="text" id="kkkey" name="key" placeholder="KK秘钥" style="width:60px;">
|
||||
</#if>
|
||||
|
||||
<input type="submit" value="预览" class="btn btn-success">
|
||||
@@ -241,15 +241,6 @@
|
||||
</form>
|
||||
<#else>
|
||||
<div class="disabled-upload">
|
||||
<form enctype="multipart/form-data" id="fileUpload" class="form-inline">
|
||||
<div class="input-group" style="width: 100%;">
|
||||
<input type="file" id="file" name="file" class="form-control" style="flex: 1;" disabled/>
|
||||
<span class="input-group-btn">
|
||||
<input type="button" id="fileUploadBtn" class="btn btn-success" value="上传文件" disabled/>
|
||||
<input type="button" id="newFolderBtn" class="btn btn-primary" style="margin-left:5px;" value="新建文件夹" disabled/>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
<div class="alert alert-warning" style="margin-top: 10px; padding: 8px; font-size: 13px;">
|
||||
<span class="glyphicon glyphicon-info-sign"></span>
|
||||
文件上传功能已禁用。如需开启,请修改配置文件或联系管理员。
|
||||
@@ -389,8 +380,8 @@
|
||||
function checkUrl(url) {
|
||||
<#if "${kkkey}" != "false" >
|
||||
var kkkey = document.getElementById("kkkey");
|
||||
if (kkkey.value == "") {
|
||||
alert("程序需要秘钥接入,请输入秘钥<#if isshowkey><#if "${kkkey}" != "false" >:${kkkey}</#if><#else>,联系系统管理员获取</#if>");
|
||||
if (!kkkey || kkkey.value == "") {
|
||||
alert("程序需要秘钥接入,请输入秘钥:<#if isshowkey><#if "${kkkey}" != "false" >${kkkey}</#if><#else>,联系系统管理员获取</#if>");
|
||||
return false;
|
||||
}
|
||||
</#if>
|
||||
@@ -460,6 +451,7 @@
|
||||
sidePagination: 'server',
|
||||
pagination: true,
|
||||
pageSize: ${homePageSize},
|
||||
pageNumber: ${homePageNumber},//初始化加载页
|
||||
pageList: [5, 10, 20, 30, 50, 100],
|
||||
search: false,
|
||||
searchOnEnterKey: false,
|
||||
@@ -785,7 +777,7 @@
|
||||
}
|
||||
|
||||
// 添加KK秘钥参数
|
||||
var key = $('#aeskey').val();
|
||||
var key = $('#kkkey').val();
|
||||
if (key) {
|
||||
params.push('key=' + encodeURIComponent(key));
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
【http/https 资源文件预览】如果你的项目需要接入文件预览项目,达到对docx、excel、ppt、jpg等文件的预览效果,那么通过在你的项目中加入下面的代码就可以成功实现:
|
||||
<p style="background-color: #2f332a;color: #cccccc;font-size: 14px;padding:10px;margin-top:10px;">
|
||||
var url = 'http://127.0.0.1:8080/file/test.txt'; //要预览文件的访问地址 <br>
|
||||
window.open('http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent(base64Encode(url)));
|
||||
window.open('${baseUrl}onlinePreview?url='+encodeURIComponent(base64Encode(url)));
|
||||
</p>
|
||||
</div>
|
||||
<br>
|
||||
@@ -49,15 +49,15 @@
|
||||
<p style="background-color: #2f332a;color: #cccccc;font-size: 14px;padding:10px;margin-top:10px;">
|
||||
var originUrl = 'http://127.0.0.1:8080/filedownload?fileId=1'; //要预览文件的访问地址<br>
|
||||
var previewUrl = originUrl + '&fullfilename=test.txt'<br>
|
||||
window.open('http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent(Base64.encode(previewUrl)));
|
||||
window.open('${baseUrl}onlinePreview?url='+encodeURIComponent(Base64.encode(previewUrl)));
|
||||
</p>
|
||||
</div>
|
||||
<br>
|
||||
<div style="font-size: 16px;">
|
||||
<div style="font-size: 16px;">
|
||||
【ftp 资源文件预览】如果要预览的FTP url是可以匿名访问的(不需要用户名密码),则可以直接通过下载url预览,示例如下
|
||||
<p style="background-color: #2f332a;color: #cccccc;font-size: 14px;padding:10px;margin-top:10px;">
|
||||
var url = 'ftp://127.0.0.1/file/test.txt'; //要预览文件的访问地址<br>
|
||||
window.open('http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent(Base64.encode(url)));
|
||||
window.open('${baseUrl}onlinePreview?url='+encodeURIComponent(Base64.encode(url)));
|
||||
</p>
|
||||
</div>
|
||||
<br>
|
||||
@@ -65,8 +65,50 @@
|
||||
【ftp 加密资源文件预览】如果 FTP 需要认证访问服,可以通过在 url 中加入用户名密码等参数预览,示例如下
|
||||
<p style="background-color: #2f332a;color: #cccccc;font-size: 14px;padding:10px;margin-top:10px;">
|
||||
var originUrl = 'ftp://127.0.0.1/file/test.txt'; //要预览文件的访问地址<br>
|
||||
var previewUrl = originUrl + '?ftp.username=xx&ftp.password=xx&ftp.control.encoding=xx';<br>
|
||||
window.open('http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent(Base64.encode(previewUrl)));
|
||||
var previewUrl = originUrl + '?ftp.control.port=xx&ftp.username=xx&ftp.password=xx&ftp.control.encoding=(gbk,utf8等)'; //(为了安全强烈建议在配置中设置相关信息)<br>
|
||||
window.open('${baseUrl}onlinePreview?url='+encodeURIComponent(Base64.encode(previewUrl)));
|
||||
</p>
|
||||
</div>
|
||||
<div style="font-size: 16px;">
|
||||
【Basic 鉴权资源文件预览】如果需要认证访问服,可以通过在url中加入用户名密码等参数预览,示例如下
|
||||
<p style="background-color: #2f332a;color: #cccccc;font-size: 14px;padding:10px;margin-top:10px;">
|
||||
var originUrl = 'http://127.0.0.1/file/test.txt'; //要预览文件的访问地址<br>
|
||||
var previewUrl = originUrl + '?basic.name=admin&basic.pass=123456'; //(为了安全强烈建议在配置中设置相关信息)<br>
|
||||
window.open('${baseUrl}onlinePreview?url='+encodeURIComponent(Base64.encode(previewUrl)));
|
||||
</p>
|
||||
</div>
|
||||
<div style="font-size: 16px;">
|
||||
AES加密接入方法,示例如下
|
||||
<p style="background-color: #2f332a;color: #cccccc;font-size: 14px;padding:10px;margin-top:10px;">
|
||||
主要事项:首先引入下面js 在把url转换成AES,注意前后端key必须相同(注意:JS下载到你接入服务器的网址)<br>
|
||||
<script src="${baseUrl}js/crypto-js.js"></script><br>
|
||||
<script src="${baseUrl}js/aes.js"></script><br>
|
||||
function aesEncrypt(encryptString, key) { <br>
|
||||
var key = CryptoJS.enc.Utf8.parse(key); <br>
|
||||
var srcs = CryptoJS.enc.Utf8.parse(encryptString); <br>
|
||||
var encrypted = CryptoJS.AES.encrypt(srcs, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }); <br>
|
||||
return encrypted.toString(); <br>
|
||||
}<br>
|
||||
var key = "1234567890123456"; // AES秘钥16位数字<br>
|
||||
var url = "http://127.0.0.1/file/test.txt";<br>
|
||||
window.open('${baseUrl}onlinePreview?url='+encodeURIComponent(aesEncrypt(url, key))+'&encryption=aes');
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div style="font-size: 16px;">
|
||||
其他参数,示例如下
|
||||
<p style="background-color: #2f332a;color: #cccccc;font-size: 14px;padding:10px;margin-top:10px;">
|
||||
密码参数:&filePassword=加密文件的密码<br>
|
||||
页码参数:&page=选择第几页预览<br>
|
||||
高亮参数:&highlightall=关键字 突出显示 <br>
|
||||
水印参数:&watermarkTxt=你的水印<br>
|
||||
重生参数:&forceUpdatedCache=true <br>
|
||||
跨域参数:&kkagent=true <br>
|
||||
加密缓存:&usePasswordCache=true <br>
|
||||
秘钥参数:&key= 访问秘钥 <br>
|
||||
主要事项:以上参数是把url转换成base64后面在添加<br>
|
||||
var url = 'http://127.0.0.1:8080/file/test.txt'<br>
|
||||
window.open('${baseUrl}onlinePreview?url='+encodeURIComponent(base64Encode(url))+'&filePassword=123&page=1&highlightall=kkfileview&watermarkTxt=kkfileview&kkagent=false&key=123');
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -35,29 +35,47 @@
|
||||
</div>
|
||||
<div class="panel panel-success">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">2025年12月25日,v5.0版本</h3>
|
||||
<h3 class="panel-title">2026年01月20日,v5.0版本</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div>
|
||||
<h4>优化</h4>
|
||||
1. 优化 OFD 移动端预览 页面不自适应 <br>
|
||||
2. 更新 xlsx 前端解析组件,加速解析速度 <br>
|
||||
3. 升级 CAD 组件 <br>
|
||||
4. office 功能调整,支持批注、转换页码限制、生成水印等功能 <br>
|
||||
5. 升级 markdown 组件 <br>
|
||||
6. 升级 dcm 解析组件 <br>
|
||||
7. 升级 PDF.JS 解析组件 <br>
|
||||
8. 更换视频播放插件为 ckplayer <br>
|
||||
9. tif 解析更加智能化,支持被修改的图片格式 <br>
|
||||
10. 针对大小文本文件检测字符编码的正确率,处理并发隐患 <br>
|
||||
11. 重构下载文件的代码,新增通用的文件服务器认证访问的设计 <br>
|
||||
12. 更新 bootstrap 组件,并精简掉不需要的文件 <br>
|
||||
13. 更新 epub 版本,优化 epub 显示效果 <br>
|
||||
14. 解决定时清除缓存时,对于多媒体类型文件,只删除了磁盘缓存文件 <br>
|
||||
15. 自动检测已安装 Office 组件,增加 LibreOffice 7.5 & 7.6 版本默认路径 <br>
|
||||
16. 修改 drawio 默认为预览模式 <br>
|
||||
17. 新增 PDF 线程管理、超时管理、内存缓存管理,更新 PDF 解析组件版本 <br>
|
||||
18. 优化 Dockerfile,支持真正的跨平台构建镜像 <br>
|
||||
1. 优化 xlsx 前端解析 <br>
|
||||
2. 优化 图片 解析 <br>
|
||||
3. 优化 tif 解析 <br>
|
||||
4. 优化 svg 解析 <br>
|
||||
5. 优化 json 解析 <br>
|
||||
6. 优化 ftp多客户端接入 <br>
|
||||
7. 优化 首页支持目录访问 采用post 服务端分页 <br>
|
||||
8. 优化 marked 解析 <br>
|
||||
<h4>新增</h4>
|
||||
1. 新增 msg 邮件 解析 <br>
|
||||
2. 新增 heic 图片 解析 <br>
|
||||
3. 新增 跨域方法 <br>
|
||||
4. 新增 高亮方法 <br>
|
||||
5. 新增 页码方法 <br>
|
||||
6. 新增 AES加密方法 <br>
|
||||
7. 新增 Basic 鉴权方法 <br>
|
||||
8. 新增 秘钥方法 <br>
|
||||
9. 新增 防重复转换 <br>
|
||||
10. 新增 异步等待 <br>
|
||||
11. 新增 上传限制不支持的文件禁止上传 <br>
|
||||
12. 新增 异步等待 <br>
|
||||
13. 新增 cadviewer转换方法<br>
|
||||
<h4>修复</h4>
|
||||
1. 压缩包路径问题 <br>
|
||||
2. 安全问题 <br>
|
||||
3. 图片水印不全问题 <br>
|
||||
4. 修复SSL自签证书接入问题 <br>
|
||||
<h4>更新</h4>
|
||||
1. jdk强制现在21版本以上 <br>
|
||||
2. pdf 前端解析<br>
|
||||
3. odf 前端解析<br>
|
||||
4. 3D 模型前端解析<br>
|
||||
5. pdf后端异步转换 多线程等等<br>
|
||||
6. tif后端异步转换 多线程等等<br>
|
||||
7. 视频后端异步转换 多线程等等<br>
|
||||
8. CAD后端异步转换 多线程等等<br>
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,91 +3,227 @@
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0">
|
||||
<title>markdown文本预览</title>
|
||||
<title>${file.name}文本预览</title>
|
||||
<#include "*/commonHeader.ftl">
|
||||
<script src="js/jquery-3.6.1.min.js" type="text/javascript"></script>
|
||||
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"/>
|
||||
<link rel="stylesheet" href="css/index.css"/>
|
||||
<script src="bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
|
||||
<script src="js/marked.min.js" type="text/javascript"></script>
|
||||
<script src="js/base64.min.js" type="text/javascript"></script>
|
||||
<script src="js/codemirror.js" type="text/javascript"></script>
|
||||
<link rel="stylesheet" href="js/codemirror.css"/>
|
||||
<style>
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<input hidden id="textData" value="${textData}"/>
|
||||
|
||||
<!-- 目录区域 - 左侧 -->
|
||||
<div id="directory">
|
||||
<div>文档目录</div>
|
||||
<div id="content">
|
||||
<ul></ul>
|
||||
<div class="empty-toc" style="display:none;">暂无目录</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 主内容区域 -->
|
||||
<div class="container">
|
||||
<div class="panel panel-default">
|
||||
<div id="markdown_btn" class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<div class="panel-heading">
|
||||
<h6 class="panel-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
|
||||
${file.name}
|
||||
</a>
|
||||
</h4>
|
||||
</h6>
|
||||
</div>
|
||||
<div id="text_btn" class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
|
||||
${file.name}
|
||||
</a>
|
||||
</h4>
|
||||
|
||||
<!-- 视图切换按钮 -->
|
||||
<div class="view-toggle">
|
||||
<button id="preview_btn" class="view-btn active">预览模式</button>
|
||||
<button id="source_btn" class="view-btn">源代码</button>
|
||||
</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<div id="markdown"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<textarea id="textarea" style="display:none;"></textarea>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
window.onload = function () {
|
||||
$("#markdown_btn").hide()
|
||||
initWaterMark();
|
||||
loadMarkdown();
|
||||
}
|
||||
function htmlEscape(str){
|
||||
var s = "";
|
||||
if(str.length == 0) return "";
|
||||
s = str.replace(/&/g,"&");
|
||||
s = str.replace(/&amp;/g,"&");
|
||||
s = s.replace(/</g,"<");
|
||||
s = s.replace(/>/g,">");
|
||||
s = s.replace(/ /g," ");
|
||||
s = s.replace(/'/g,"\'");
|
||||
s = s.replace(/"/g,"\"");
|
||||
s = s.replace(/<script.*?>.*?<\/script>/ig, '');
|
||||
s = s.replace(/<script/gi, "<script ");
|
||||
s = s.replace(/<iframe/gi, "<iframe ");
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载markdown
|
||||
*/
|
||||
function loadMarkdown() {
|
||||
var textData = Base64.decode($("#textData").val())
|
||||
textData = htmlEscape(textData);
|
||||
window.textPreData = "<pre style='background-color: #FFFFFF;border:none'>" + textData + "</pre>";
|
||||
window.textMarkdownData = marked.parse(textData);
|
||||
$("#markdown").html(window.textMarkdownData);
|
||||
}
|
||||
|
||||
|
||||
$(function () {
|
||||
$("#markdown_btn").click(function () {
|
||||
$("#markdown").html(window.textMarkdownData);
|
||||
$("#text_btn").show()
|
||||
$("#markdown_btn").hide()
|
||||
// 初始化编辑器
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById('textarea'), {
|
||||
mode: "text/html",
|
||||
lineNumbers: true,
|
||||
tabMode: "indent",
|
||||
lineWrapping: false,
|
||||
theme: "default",
|
||||
viewportMargin: Infinity
|
||||
});
|
||||
|
||||
// 初始化目录
|
||||
function initTOC() {
|
||||
let html = "";
|
||||
let index = 0;
|
||||
|
||||
// 从预览内容中提取标题
|
||||
$("#markdown h1, #markdown h2, #markdown h3, #markdown h4, #markdown h5").each(function() {
|
||||
let id = "heading-" + index++;
|
||||
$(this).attr('id', id);
|
||||
let level = this.tagName.toLowerCase().replace('h', '');
|
||||
let text = $(this).text().substring(0, 50);
|
||||
html += '<li class="li-h' + level + '"><a href="#' + id + '">' + text + '</a></li>';
|
||||
});
|
||||
|
||||
$("#text_btn").click(function () {
|
||||
$("#markdown_btn").show()
|
||||
$("#text_btn").hide();
|
||||
|
||||
$("#directory ul").html(html);
|
||||
|
||||
// 显示/隐藏空目录提示
|
||||
if (html === "") {
|
||||
$("#directory .empty-toc").show();
|
||||
$("#directory ul").hide();
|
||||
} else {
|
||||
$("#directory .empty-toc").hide();
|
||||
$("#directory ul").show();
|
||||
}
|
||||
|
||||
// 更新目录高度
|
||||
updateTOCHeight();
|
||||
}
|
||||
|
||||
// 更新目录高度
|
||||
function updateTOCHeight() {
|
||||
const windowHeight = window.innerHeight;
|
||||
const tocTop = document.getElementById('directory').getBoundingClientRect().top;
|
||||
const availableHeight = windowHeight - tocTop - 20;
|
||||
document.getElementById('directory').style.maxHeight = availableHeight + 'px';
|
||||
}
|
||||
|
||||
// 安全HTML转义函数
|
||||
function htmlEscape(str) {
|
||||
if (!str) return "";
|
||||
return str
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'")
|
||||
.replace(/javascript/gi, "javascript ");
|
||||
}
|
||||
|
||||
// 加载markdown内容
|
||||
function loadMarkdown() {
|
||||
try {
|
||||
var textData = Base64.decode($("#textData").val());
|
||||
textData = htmlEscape(textData);
|
||||
|
||||
window.textPreData = "<pre style='background-color: #f8f9fa;border:1px solid #e9ecef;border-radius:8px;padding:18px;overflow-x:auto;'>" + textData + "</pre>";
|
||||
window.textMarkdownData = marked.parse(textData);
|
||||
|
||||
$("#markdown").html(window.textMarkdownData);
|
||||
editor.setValue(textData);
|
||||
|
||||
// 初始化目录
|
||||
initTOC();
|
||||
|
||||
} catch (e) {
|
||||
console.error("加载内容失败:", e);
|
||||
$("#markdown").html("<div class='alert alert-danger' style='padding:15px;border-radius:8px;'>加载内容失败: " + e.message + "</div>");
|
||||
}
|
||||
}
|
||||
|
||||
// 切换视图
|
||||
function switchView(mode) {
|
||||
if (mode === 'preview') {
|
||||
$("#preview_btn").addClass('active');
|
||||
$("#source_btn").removeClass('active');
|
||||
$("#markdown").html(window.textMarkdownData);
|
||||
initTOC();
|
||||
} else {
|
||||
$("#source_btn").addClass('active');
|
||||
$("#preview_btn").removeClass('active');
|
||||
$("#markdown").html(window.textPreData);
|
||||
$("#directory .empty-toc").show();
|
||||
$("#directory ul").hide();
|
||||
}
|
||||
}
|
||||
|
||||
// 页面加载完成
|
||||
$(document).ready(function() {
|
||||
// 初始化水印
|
||||
if (typeof initWaterMark === 'function') {
|
||||
initWaterMark();
|
||||
}
|
||||
|
||||
// 加载markdown内容
|
||||
loadMarkdown();
|
||||
|
||||
// 监听编辑器变化
|
||||
editor.on('change', function(cm) {
|
||||
// 更新预览
|
||||
var content = cm.getValue();
|
||||
window.textPreData = "<pre style='background-color: #f8f9fa;border:1px solid #e9ecef;border-radius:8px;padding:18px;overflow-x:auto;'>" + content + "</pre>";
|
||||
window.textMarkdownData = marked.parse(content);
|
||||
|
||||
// 如果当前是预览模式,更新预览内容
|
||||
if ($("#preview_btn").hasClass('active')) {
|
||||
$("#markdown").html(window.textMarkdownData);
|
||||
initTOC();
|
||||
}
|
||||
});
|
||||
|
||||
// 绑定视图切换事件
|
||||
$("#preview_btn").click(function() {
|
||||
switchView('preview');
|
||||
});
|
||||
|
||||
$("#source_btn").click(function() {
|
||||
switchView('source');
|
||||
});
|
||||
|
||||
// 为目录链接添加平滑滚动
|
||||
$(document).on('click', '#directory a', function(e) {
|
||||
e.preventDefault();
|
||||
var target = $(this.getAttribute('href'));
|
||||
if (target.length) {
|
||||
$('html, body').animate({
|
||||
scrollTop: target.offset().top - 100
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
|
||||
// 窗口调整大小时更新目录高度
|
||||
$(window).resize(function() {
|
||||
updateTOCHeight();
|
||||
});
|
||||
|
||||
// 初始化目录高度
|
||||
setTimeout(updateTOCHeight, 100);
|
||||
|
||||
// 添加键盘快捷键
|
||||
$(document).keydown(function(e) {
|
||||
// Ctrl+1 切换到预览模式
|
||||
if (e.ctrlKey && e.key === '1') {
|
||||
e.preventDefault();
|
||||
switchView('preview');
|
||||
}
|
||||
// Ctrl+2 切换到源代码模式
|
||||
else if (e.ctrlKey && e.key === '2') {
|
||||
e.preventDefault();
|
||||
switchView('source');
|
||||
}
|
||||
});
|
||||
|
||||
// 添加目录项悬停效果
|
||||
$(document).on('mouseenter', '#directory li a', function() {
|
||||
$(this).parent().addClass('hover');
|
||||
}).on('mouseleave', '#directory li a', function() {
|
||||
$(this).parent().removeClass('hover');
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
40
server/src/main/resources/web/msg.ftl
Normal file
40
server/src/main/resources/web/msg.ftl
Normal file
@@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0">
|
||||
<title>${file.name}</title>
|
||||
<#include "*/commonHeader.ftl">
|
||||
<script src="js/base64.min.js" type="text/javascript"></script>
|
||||
</head>
|
||||
<body>
|
||||
<#if currentUrl?contains("http://") || currentUrl?contains("https://")|| currentUrl?contains("ftp://")|| currentUrl?contains("file://")>
|
||||
<#assign finalUrl="${currentUrl}">
|
||||
<#else>
|
||||
<#assign finalUrl="${baseUrl}${currentUrl}">
|
||||
</#if>
|
||||
<iframe src="" width="100%" frameborder="0"></iframe>
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
var url = '${finalUrl}';
|
||||
var kkagent = '${kkagent}';
|
||||
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';
|
||||
if (kkagent === 'true' || !url.startsWith(baseUrl)) {
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url))+ "&key=${kkkey}";
|
||||
}
|
||||
document.getElementsByTagName('iframe')[0].src = "${baseUrl}msg/index.html?file="+ encodeURIComponent(url);
|
||||
document.getElementsByTagName('iframe')[0].height = document.documentElement.clientHeight - 10;
|
||||
/**
|
||||
* 页面变化调整高度
|
||||
*/
|
||||
window.onresize = function () {
|
||||
var fm = document.getElementsByTagName("iframe")[0];
|
||||
fm.height = window.document.documentElement.clientHeight - 10;
|
||||
}
|
||||
/*初始化水印*/
|
||||
window.onload = function () {
|
||||
initWaterMark();
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
@@ -22,7 +22,7 @@
|
||||
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';
|
||||
|
||||
if (kkagent === 'true' || !url.startsWith(baseUrl)) {
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url));
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url))+ "&key=${kkkey}";
|
||||
}
|
||||
if(IsPhone()){
|
||||
document.getElementsByTagName('iframe')[0].src = "${baseUrl}ofd/index.html?file=" + encodeURIComponent(url)+"&scale=width"+"&page=${page}";
|
||||
|
||||
@@ -53,9 +53,6 @@
|
||||
setTimeout(function() {
|
||||
// 滚动到指定页码
|
||||
scrollToPage(targetPage);
|
||||
|
||||
// 显示当前页码指示器
|
||||
showPageIndicator(targetPage);
|
||||
}, 100);
|
||||
|
||||
// 初始化懒加载
|
||||
@@ -68,7 +65,6 @@
|
||||
var imgAreas = document.querySelectorAll('.img-area');
|
||||
imgAreas.forEach(function(area, index) {
|
||||
area.onclick = function() {
|
||||
showPageIndicator(index + 1);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -113,26 +109,10 @@
|
||||
// 滚动到目标位置
|
||||
targetElement.scrollIntoView({behavior: 'smooth', block: 'start'});
|
||||
|
||||
// 显示页码指示器
|
||||
showPageIndicator(pageNum);
|
||||
}
|
||||
}
|
||||
|
||||
// 显示页码指示器
|
||||
function showPageIndicator(pageNum) {
|
||||
var indicator = document.getElementById('pageIndicator');
|
||||
var currentPageSpan = document.getElementById('currentPageNum');
|
||||
|
||||
currentPageSpan.textContent = pageNum;
|
||||
indicator.style.display = 'block';
|
||||
|
||||
// 3秒后自动隐藏
|
||||
clearTimeout(window.indicatorTimeout);
|
||||
window.indicatorTimeout = setTimeout(function() {
|
||||
indicator.style.display = 'none';
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
|
||||
// 获取当前可见的页码
|
||||
function getCurrentPage() {
|
||||
var imgAreas = document.querySelectorAll('.img-area');
|
||||
@@ -310,7 +290,6 @@
|
||||
// 滚动监听更新页码指示器
|
||||
window.addEventListener('scroll', function() {
|
||||
var currentPage = getCurrentPage();
|
||||
showPageIndicator(currentPage);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
|
||||
// 添加加载状态管理
|
||||
let isLoading = false;
|
||||
let loadingTask = null;
|
||||
|
||||
</script>
|
||||
<style>
|
||||
@@ -159,9 +158,10 @@
|
||||
}
|
||||
|
||||
var url = '${finalUrl}';
|
||||
var kkagent = '${kkagent}';
|
||||
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';
|
||||
if (!url.startsWith(baseUrl)) {
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url));
|
||||
if (kkagent === 'true' || !url.startsWith(baseUrl)) {
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url))+ "&key=${kkkey}";
|
||||
}
|
||||
|
||||
let mask = document.getElementById("lucky-mask-demo");
|
||||
@@ -223,9 +223,7 @@
|
||||
updateProgress(30);
|
||||
|
||||
// 使用异步方式加载
|
||||
await new Promise(resolve => setTimeout(resolve, 100)); // 给UI更新一点时间
|
||||
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 100)); // 给UI更新一点时间
|
||||
|
||||
// 或者使用现有的同步方法,但放在setTimeout中避免阻塞
|
||||
await transformWithTimeout(value, name);
|
||||
@@ -273,21 +271,22 @@
|
||||
print: true,
|
||||
exportXlsx: true,
|
||||
},
|
||||
allowCopy: true,
|
||||
showtoolbar: true,
|
||||
showinfobar: false,
|
||||
showsheetbar: true,
|
||||
showstatisticBar: true,
|
||||
sheetBottomConfig: true,
|
||||
allowEdit: true,
|
||||
enableAddRow: false,
|
||||
enableAddCol: false,
|
||||
userInfo: false,
|
||||
showRowBar: true,
|
||||
showColumnBar: false,
|
||||
sheetFormulaBar: false,
|
||||
enableAddBackTop: true,
|
||||
forceCalculation: false,
|
||||
allowCopy: true, // 是否允许拷贝
|
||||
showtoolbar: ${xlsxshowtoolbar?string('true','false')}, // 是否显示工具栏
|
||||
showinfobar: true, // 是否显示顶部信息栏
|
||||
// myFolderUrl: "/",//作用:左上角<返回按钮的链接
|
||||
showsheetbar: true, // 是否显示底部sheet页按钮
|
||||
showstatisticBar: true, // 是否显示底部计数栏
|
||||
sheetBottomConfig: true, // sheet页下方的添加行按钮和回到顶部按钮配置
|
||||
allowEdit: ${(xlsxallowEdit!false)?string('true','false')},// 是否允许前台编辑
|
||||
enableAddRow: false, // 允许增加行
|
||||
enableAddCol: false, // 允许增加列
|
||||
userInfo: false, // 右上角的用户信息展示样式
|
||||
showRowBar: true, // 是否显示行号区域
|
||||
showColumnBar: false, // 是否显示列号区域
|
||||
sheetFormulaBar: false, // 是否显示公式栏
|
||||
enableAddBackTop: true,//返回头部按钮
|
||||
forceCalculation: false, //下面是导出插件 默认关闭
|
||||
data: exportJson.sheets,
|
||||
title: exportJson.info.name,
|
||||
userInfo: exportJson.info.name.creator,
|
||||
@@ -305,7 +304,7 @@
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
@@ -314,44 +313,6 @@
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 初始化Luckysheet
|
||||
function initializeLuckysheet(exportJson) {
|
||||
if (!exportJson.sheets || exportJson.sheets.length === 0) {
|
||||
throw new Error("读取excel文件内容失败!");
|
||||
}
|
||||
|
||||
window.luckysheet.destroy();
|
||||
window.luckysheet.create({
|
||||
container: 'luckysheet',
|
||||
lang: "zh",
|
||||
showtoolbarConfig:{
|
||||
image: true,
|
||||
print: true,
|
||||
exportXlsx: true,
|
||||
},
|
||||
allowCopy: true,
|
||||
showtoolbar: true,
|
||||
showinfobar: false,
|
||||
showsheetbar: true,
|
||||
showstatisticBar: true,
|
||||
sheetBottomConfig: true,
|
||||
allowEdit: true,
|
||||
enableAddRow: false,
|
||||
enableAddCol: false,
|
||||
userInfo: false,
|
||||
showRowBar: true,
|
||||
showColumnBar: false,
|
||||
sheetFormulaBar: false,
|
||||
enableAddBackTop: true,
|
||||
forceCalculation: false,
|
||||
data: exportJson.sheets,
|
||||
title: exportJson.info.name,
|
||||
userInfo: exportJson.info.name.creator,
|
||||
});
|
||||
}
|
||||
|
||||
// 页面加载完成后开始异步加载
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// 延迟一点时间开始加载,确保DOM完全加载
|
||||
@@ -367,14 +328,6 @@
|
||||
console.log('用户取消了加载');
|
||||
}
|
||||
});
|
||||
|
||||
// 打印时,获取luckysheet指定区域html内容
|
||||
function to_print() {
|
||||
const html = luckysheet.getRangeHtml();
|
||||
document.querySelector('#print-html').innerHTML = html;
|
||||
document.querySelector('#print-area').style.display = 'block';
|
||||
document.querySelector('#button-area').style.display = 'none';
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -21,9 +21,10 @@
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
var url = '${finalUrl}';
|
||||
var kkagent = '${kkagent}';
|
||||
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';
|
||||
if (!url.startsWith(baseUrl)) {
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url));
|
||||
if (kkagent === 'true' || !url.startsWith(baseUrl)) {
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url))+ "&key=${kkkey}";
|
||||
document.getElementsByTagName('iframe')[0].src = "${baseUrl}website/index.html#model="+ url + "&fullfilename=/${file.name}";
|
||||
}else{
|
||||
document.getElementsByTagName('iframe')[0].src = "${baseUrl}website/index.html#model="+ url;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
var kkagent = '${kkagent}';
|
||||
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';
|
||||
if (kkagent === 'true' || !url.startsWith(baseUrl)) {
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url));
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url))+ "&key=${kkkey}";
|
||||
}
|
||||
document.getElementsByTagName('iframe')[0].src = "${baseUrl}pdfjs/web/viewer.html?file=" + encodeURIComponent(url) + "&disablepresentationmode=${pdfPresentationModeDisable}&disableopenfile=${pdfOpenFileDisable}&disableprint=${pdfPrintDisable}&disabledownload=${pdfDownloadDisable}&disablebookmark=${pdfBookmarkDisable}&disableediting=${pdfDisableEditing}";
|
||||
document.getElementsByTagName('iframe')[0].height = document.documentElement.clientHeight - 10;
|
||||
@@ -39,13 +39,6 @@
|
||||
|
||||
function goForImage() {
|
||||
var url = window.location.href
|
||||
|
||||
if (url.indexOf("tifPreviewType=pdf") != -1) {
|
||||
url = url.replace("tifPreviewType=pdf", "tifPreviewType=jpg");
|
||||
} else {
|
||||
url = url + "&tifPreviewType=jpg";
|
||||
}
|
||||
|
||||
if (url.indexOf("officePreviewType=pdf") != -1) {
|
||||
url = url.replace("officePreviewType=pdf", "officePreviewType=image");
|
||||
} else {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<#include "*/commonHeader.ftl">
|
||||
<link rel="stylesheet" href="css/viewer.min.css">
|
||||
<script src="js/viewer.min.js"></script>
|
||||
<script src="js/base64.min.js"></script>
|
||||
<style>
|
||||
body {
|
||||
background-color: #404040;
|
||||
@@ -19,30 +20,61 @@
|
||||
|
||||
<ul id="image">
|
||||
<#list imgUrls as img>
|
||||
<#if img?contains("http://") || img?contains("https://")|| img?contains("ftp://")|| img?contains("file://")>
|
||||
<#if img?contains("http://") || img?contains("https://")|| img?contains("ftp://")|| img?contains("file://")>
|
||||
<#assign finalUrl="${img}">
|
||||
<#else>
|
||||
<#else>
|
||||
<#assign finalUrl="${baseUrl}${img}">
|
||||
</#if>
|
||||
<li><div src="${finalUrl}" style="display: none"></li>
|
||||
</#if>
|
||||
<li><div src="${finalUrl}" data-original-url="${finalUrl}" style="display: none"></li>
|
||||
</#list>
|
||||
</ul>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var viewer = new Viewer(document.getElementById('image'), {
|
||||
url: 'src',
|
||||
navbar: false,
|
||||
button: false,
|
||||
backdrop: false,
|
||||
loop : true,
|
||||
});
|
||||
viewer.view(0); // 0 是图片的索引,如果你想点击第一张图片,索引为 0
|
||||
// 获取反代配置
|
||||
var kkagent = '${kkagent}';
|
||||
// 处理图片URL,如果需要反代则替换URL
|
||||
function processImageUrls() {
|
||||
var imageElements = document.querySelectorAll('#image li div');
|
||||
|
||||
imageElements.forEach(function(imgDiv) {
|
||||
var originalUrl = imgDiv.getAttribute('data-original-url');
|
||||
var finalUrl = originalUrl;
|
||||
|
||||
// 检查是否需要反代
|
||||
if (kkagent === 'true') {
|
||||
finalUrl = '${baseUrl}' + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(originalUrl));
|
||||
}
|
||||
|
||||
// 更新src属性
|
||||
imgDiv.setAttribute('src', finalUrl);
|
||||
});
|
||||
}
|
||||
|
||||
// 初始化图片查看器
|
||||
function initImageViewer() {
|
||||
var viewer = new Viewer(document.getElementById('image'), {
|
||||
url: 'src',
|
||||
navbar: false,
|
||||
button: false,
|
||||
backdrop: false,
|
||||
loop: true,
|
||||
});
|
||||
viewer.view(0); // 0 是图片的索引,如果你想点击第一张图片,索引为 0
|
||||
}
|
||||
|
||||
// 页面加载完成后初始化
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// 先处理图片URL
|
||||
processImageUrls();
|
||||
|
||||
// 然后初始化图片查看器
|
||||
initImageViewer();
|
||||
});
|
||||
|
||||
/*初始化水印*/
|
||||
window.onload = function() {
|
||||
initWaterMark();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
@@ -18,9 +18,8 @@
|
||||
|
||||
#svg-container {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
top: 0;
|
||||
left: 0;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
@@ -121,19 +120,20 @@
|
||||
// 初始化变量
|
||||
let svgElement = null;
|
||||
let svgContainer = document.getElementById('svg-container');
|
||||
let container = document.getElementById('container');
|
||||
let zoomLevel = 1;
|
||||
let rotationAngle = 0;
|
||||
let minZoom = 0.1;
|
||||
let maxZoom = 10;
|
||||
let zoomStep = 0.2;
|
||||
let isDragging = false;
|
||||
let startX, startY, startLeft, startTop;
|
||||
let startX, startY, startTranslateX, startTranslateY;
|
||||
let panStartX, panStartY;
|
||||
var url = '${finalUrl}';
|
||||
var kkagent = '${kkagent}';
|
||||
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';
|
||||
if (kkagent === 'true' || !url.startsWith(baseUrl)) {
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url));
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url))+ "&key=${kkkey}";
|
||||
}
|
||||
|
||||
// 加载并显示SVG
|
||||
@@ -161,6 +161,9 @@
|
||||
svgElement.style.width = '100%';
|
||||
svgElement.style.height = '100%';
|
||||
|
||||
// 重置视图
|
||||
resetView();
|
||||
|
||||
// 添加拖拽功能
|
||||
setupDragAndDrop();
|
||||
|
||||
@@ -211,11 +214,20 @@
|
||||
isDragging = true;
|
||||
panStartX = e.touches[0].clientX;
|
||||
panStartY = e.touches[0].clientY;
|
||||
startLeft = parseInt(svgContainer.style.left) || 0;
|
||||
startTop = parseInt(svgContainer.style.top) || 0;
|
||||
|
||||
const transform = svgContainer.style.transform;
|
||||
const match = transform.match(/translate\(([^)]+)\)/);
|
||||
if (match) {
|
||||
const parts = match[1].split(',');
|
||||
startTranslateX = parseFloat(parts[0]) || 0;
|
||||
startTranslateY = parseFloat(parts[1]) || 0;
|
||||
} else {
|
||||
startTranslateX = 0;
|
||||
startTranslateY = 0;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
} else if (e.touches.length === 2) {
|
||||
// 双指缩放处理
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
@@ -227,8 +239,7 @@
|
||||
const dx = e.touches[0].clientX - panStartX;
|
||||
const dy = e.touches[0].clientY - panStartY;
|
||||
|
||||
svgContainer.style.left = (startLeft + dx) + 'px';
|
||||
svgContainer.style.top = (startTop + dy) + 'px';
|
||||
updateTransform(startTranslateX + dx, startTranslateY + dy);
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
@@ -242,8 +253,18 @@
|
||||
isDragging = true;
|
||||
startX = e.clientX;
|
||||
startY = e.clientY;
|
||||
startLeft = parseInt(svgContainer.style.left) || 0;
|
||||
startTop = parseInt(svgContainer.style.top) || 0;
|
||||
|
||||
const transform = svgContainer.style.transform;
|
||||
const match = transform.match(/translate\(([^)]+)\)/);
|
||||
if (match) {
|
||||
const parts = match[1].split(',');
|
||||
startTranslateX = parseFloat(parts[0]) || 0;
|
||||
startTranslateY = parseFloat(parts[1]) || 0;
|
||||
} else {
|
||||
startTranslateX = 0;
|
||||
startTranslateY = 0;
|
||||
}
|
||||
|
||||
svgContainer.style.cursor = 'grabbing';
|
||||
}
|
||||
|
||||
@@ -254,8 +275,7 @@
|
||||
const dx = e.clientX - startX;
|
||||
const dy = e.clientY - startY;
|
||||
|
||||
svgContainer.style.left = (startLeft + dx) + 'px';
|
||||
svgContainer.style.top = (startTop + dy) + 'px';
|
||||
updateTransform(startTranslateX + dx, startTranslateY + dy);
|
||||
}
|
||||
|
||||
// 停止拖拽
|
||||
@@ -276,22 +296,31 @@
|
||||
const delta = e.deltaY > 0 ? -zoomStep : zoomStep;
|
||||
const newZoom = Math.min(maxZoom, Math.max(minZoom, zoomLevel + delta));
|
||||
|
||||
// 计算缩放中心点相对于容器的位置
|
||||
const containerX = mouseX - rect.width / 2;
|
||||
const containerY = mouseY - rect.height / 2;
|
||||
// 获取当前变换
|
||||
const transform = svgContainer.style.transform;
|
||||
let translateX = 0, translateY = 0;
|
||||
const match = transform.match(/translate\(([^)]+)\)/);
|
||||
if (match) {
|
||||
const parts = match[1].split(',');
|
||||
translateX = parseFloat(parts[0]) || 0;
|
||||
translateY = parseFloat(parts[1]) || 0;
|
||||
}
|
||||
|
||||
// 计算缩放中心点相对于容器中心的位置
|
||||
const centerX = rect.width / 2;
|
||||
const centerY = rect.height / 2;
|
||||
const offsetX = mouseX - centerX;
|
||||
const offsetY = mouseY - centerY;
|
||||
|
||||
// 更新缩放级别
|
||||
const zoomChange = newZoom / zoomLevel;
|
||||
zoomLevel = newZoom;
|
||||
|
||||
// 调整位置以保持鼠标点位置不变
|
||||
const currentLeft = parseInt(svgContainer.style.left) || 0;
|
||||
const currentTop = parseInt(svgContainer.style.top) || 0;
|
||||
translateX = translateX - offsetX * (zoomChange - 1);
|
||||
translateY = translateY - offsetY * (zoomChange - 1);
|
||||
|
||||
svgContainer.style.left = (currentLeft - containerX * (zoomChange - 1)) + 'px';
|
||||
svgContainer.style.top = (currentTop - containerY * (zoomChange - 1)) + 'px';
|
||||
|
||||
updateTransform();
|
||||
updateTransform(translateX, translateY);
|
||||
updateDisplay();
|
||||
});
|
||||
}
|
||||
@@ -369,22 +398,45 @@
|
||||
function resetView() {
|
||||
zoomLevel = 1;
|
||||
rotationAngle = 0;
|
||||
svgContainer.style.left = '50%';
|
||||
svgContainer.style.top = '50%';
|
||||
updateTransform();
|
||||
|
||||
// 计算居中位置
|
||||
const containerRect = container.getBoundingClientRect();
|
||||
if (svgElement) {
|
||||
const svgRect = svgContainer.getBoundingClientRect();
|
||||
const translateX = (containerRect.width - svgRect.width) / 2;
|
||||
const translateY = (containerRect.height - svgRect.height) / 2;
|
||||
updateTransform(translateX, translateY);
|
||||
} else {
|
||||
updateTransform(0, 0);
|
||||
}
|
||||
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
// 更新变换
|
||||
function updateTransform() {
|
||||
let transform = 'translate(-50%, -50%)';
|
||||
function updateTransform(translateX, translateY) {
|
||||
let transform = '';
|
||||
|
||||
// 先应用缩放
|
||||
// 如果有传入的平移值,使用它
|
||||
if (translateX !== undefined && translateY !== undefined) {
|
||||
transform += 'translate(' + translateX + 'px, ' + translateY + 'px)';
|
||||
} else {
|
||||
// 否则保持当前的平移
|
||||
const currentTransform = svgContainer.style.transform;
|
||||
const match = currentTransform.match(/translate\(([^)]+)\)/);
|
||||
if (match) {
|
||||
transform += match[0];
|
||||
} else {
|
||||
transform += 'translate(0px, 0px)';
|
||||
}
|
||||
}
|
||||
|
||||
// 应用缩放
|
||||
if (zoomLevel !== 1) {
|
||||
transform += ' scale(' + zoomLevel + ')';
|
||||
}
|
||||
|
||||
// 再应用旋转
|
||||
// 应用旋转
|
||||
if (rotationAngle !== 0) {
|
||||
transform += ' rotate(' + rotationAngle + 'deg)';
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
var kkagent = '${kkagent}';
|
||||
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';
|
||||
if (kkagent === 'true' || !url.startsWith(baseUrl)) {
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url));
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url))+ "&key=${kkkey}";
|
||||
}
|
||||
var myp = document.getElementById('tiff');
|
||||
let pages;
|
||||
@@ -128,13 +128,11 @@ return;
|
||||
|
||||
var html = "";
|
||||
html += "<div class=\"img-area\">";
|
||||
html += "<div class=\"image-container\">";
|
||||
html += "<div class=\"image-container\" style=\"position:relative;\">";
|
||||
html += '<img class="my-photo" id="page'+p+'" src="'+canvas.toDataURL('image/png')+'">';
|
||||
html += " <div class=\"button-container\">";
|
||||
html += "<button class=\"nszImg\">"+p+"/"+pages.length+"页</button>";
|
||||
html += "<button class=\"nszImg\" onclick=\"rotateImg('page"+p+"', false)\">逆时针</button>";
|
||||
html += "<button class=\"sszImg\" onclick=\"rotateImg('page"+p+"', true)\">顺时针</button>";
|
||||
html += "<button class=\"sszImg\" onclick=\"recoveryImg('page"+p+"', true)\">恢复</button>";
|
||||
html += "<div class=\"button-container\" style=\"position:absolute; bottom:5px; right:5px; opacity:0.1; transition:opacity 0.2s;\" onmouseover=\"this.style.opacity='0.9'\" onmouseout=\"this.style.opacity='0.1'\">";
|
||||
html += "<button class=\"nszImg\" style=\"margin-right:3px; font-size:11px; padding:2px 6px; background:rgba(255,255,255,0.9); border:1px solid #999; border-radius:2px; min-width:50px;\">"+p+"/"+pages.length+"页</button>";
|
||||
html += "<button class=\"sszImg\" onclick=\"rotateImg('page"+p+"', true)\" style=\"font-size:11px; padding:2px 6px; background:rgba(255,255,255,0.9); border:1px solid #999; border-radius:2px;\">↻</button>";
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
|
||||
@@ -12,89 +12,10 @@
|
||||
</head>
|
||||
<body>
|
||||
<input hidden id="textData" value="${textData}"/>
|
||||
<#if "${file.suffix?html}" == "htm" || "${file.suffix?html}" == "html" || "${file.suffix?html}" == "shtml" >
|
||||
<div class="container">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"> <strong><font color="red"><input class="GLOkBtn" type="button" value="运行html" onclick="loadXmlData();" /></font></strong>
|
||||
<a data-toggle="collapse" data-parent="#accordion" onclick="loadText();">
|
||||
${file.name}
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div id="text"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
// 将Freemarker的布尔值传递给JavaScript
|
||||
var scriptjs = ${scriptjs?c}; // ?c 将布尔值转换为字符串true/false
|
||||
|
||||
/**
|
||||
*加载普通文本
|
||||
*/
|
||||
function loadText() {
|
||||
var base64data = $("#textData").val()
|
||||
var div = document.getElementById("text");
|
||||
div.innerHTML = ""; //
|
||||
var textData = Base64.decode(base64data);
|
||||
textData = htmlttt(textData,1);
|
||||
var textPreData = "<xmp style='background-color: #FFFFFF;overflow-y: scroll;border:none'>" + textData + "</xmp>";
|
||||
$("#text").append(textPreData);
|
||||
}
|
||||
|
||||
function htmlttt (str,txt){
|
||||
var s = "";
|
||||
if(str.length == 0) return "";
|
||||
s = str.replace(/&/gi,"&");
|
||||
s = s.replace(/</gi,"<");
|
||||
s = s.replace(/>/gi,">");
|
||||
s = s.replace(/ /gi," ");
|
||||
s = s.replace(/'/gi,"\'");
|
||||
s = s.replace(/"/gi,"\"");
|
||||
s = s.replace(/javascript/g,"javascript ");
|
||||
if (txt === 2){
|
||||
s = s.replace(/<script/gi, "<script ");
|
||||
s = s.replace(/javascript/g,"javascript ");
|
||||
s = s.replace(/<\/script/gi, "</script ");
|
||||
s = s.replace(/<iframe/gi, "<iframe ");
|
||||
s = s.replace(/<\/iframe/gi, "</iframe ");
|
||||
s = s.replace(/confirm/gi, "c&onfirm");
|
||||
s = s.replace(/alert/gi, "a&lert");
|
||||
s = s.replace(/eval/gi, "e&val");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
*加载运行
|
||||
*/
|
||||
function loadXmlData() {
|
||||
var base64data = $("#textData").val();
|
||||
var textData = Base64.decode(base64data);
|
||||
|
||||
// 直接使用JavaScript变量进行判断
|
||||
if (scriptjs) {
|
||||
textData = htmlttt(textData, 1);
|
||||
} else {
|
||||
textData = htmlttt(textData, 2);
|
||||
}
|
||||
|
||||
$('#text').html(textData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
window.onload = function () {
|
||||
initWaterMark();
|
||||
loadText();
|
||||
}
|
||||
</script>
|
||||
<#else/>
|
||||
<link rel="stylesheet" href="highlight/highlight.css">
|
||||
<!-- 先加载fenye.js -->
|
||||
<script src="js/fenye.js" type="text/javascript"></script>
|
||||
<!-- 改为普通的container,而不是container-fluid -->
|
||||
<div class="container">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
@@ -107,27 +28,60 @@
|
||||
<div id="divPagenation" class="black" >
|
||||
</div>
|
||||
<div id="divContent" class="panel-body">
|
||||
</div>
|
||||
<div id="divPagenationx" class="black" >
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
var base64data = $("#textData").val()
|
||||
var s = Base64.decode(base64data);
|
||||
var kkkeyword = '${highlightall}';
|
||||
var Length = 20000;
|
||||
var page = '${page}';
|
||||
var txt = "txt";
|
||||
DHTMLpagenation(s, kkkeyword, Length, page, txt);
|
||||
// 确保DOM加载完成
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// 解码Base64数据
|
||||
var base64data = document.getElementById("textData").value;
|
||||
var s;
|
||||
try {
|
||||
s = Base64.decode(base64data);
|
||||
} catch(e) {
|
||||
console.error("Base64解码失败:", e);
|
||||
s = "内容解码失败";
|
||||
}
|
||||
|
||||
// 获取参数
|
||||
var kkkeyword = '${highlightall}';
|
||||
var Length = 20000;
|
||||
var page = '${page}' || 1;
|
||||
var txt = "txt";
|
||||
|
||||
console.log("初始化分页,参数:", {
|
||||
contentLength: s.length,
|
||||
kkkeyword: kkkeyword,
|
||||
Length: Length,
|
||||
page: page,
|
||||
txt: txt
|
||||
});
|
||||
|
||||
// 初始化分页
|
||||
if (typeof DHTMLpagenation === 'function') {
|
||||
try {
|
||||
DHTMLpagenation(s, kkkeyword, Length, page, txt);
|
||||
console.log("分页初始化成功");
|
||||
} catch(e) {
|
||||
console.error("分页初始化失败:", e);
|
||||
document.getElementById("divContent").innerHTML = "分页初始化失败: " + e.message;
|
||||
}
|
||||
} else {
|
||||
console.error("DHTMLpagenation函数未定义");
|
||||
document.getElementById("divContent").innerHTML = "分页功能加载失败,请刷新页面重试";
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
window.onload = function () {
|
||||
initWaterMark();
|
||||
if (typeof initWaterMark === 'function') {
|
||||
initWaterMark();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</#if>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -35,7 +35,7 @@
|
||||
</div>
|
||||
|
||||
<div class="countdown-section">
|
||||
<p class="countdown-text">页面将在<span id="countdown">5</span>秒后自动刷新</p>
|
||||
<p class="countdown-text">页面将在<span id="countdown">${time}</span>秒后自动刷新</p>
|
||||
</div>
|
||||
|
||||
<div class="controls">
|
||||
@@ -60,7 +60,7 @@
|
||||
<p style="margin-top: 5px;">如有问题,请联系技术支持</p>
|
||||
</div>
|
||||
</div><script>
|
||||
let countdown = 5;
|
||||
let countdown = ${time};
|
||||
let countdownInterval;
|
||||
|
||||
// 删除forceUpdatedCache参数并更新URL
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
var kkagent = '${kkagent}';
|
||||
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';
|
||||
if (kkagent === 'true' || !url.startsWith(baseUrl)) {
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url));
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(Base64.encode(url))+ "&key=${kkkey}";
|
||||
}
|
||||
const init = async () => {
|
||||
var windowWidth = document.documentElement.clientWidth || document.body.clientWidth;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0">
|
||||
<title>xml文本预览</title>
|
||||
<title>XML预览器</title>
|
||||
<#include "*/commonHeader.ftl">
|
||||
<script src="js/jquery-3.6.1.min.js" type="text/javascript"></script>
|
||||
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"/>
|
||||
@@ -11,46 +11,153 @@
|
||||
<link rel="stylesheet" href="css/xmlTreeViewer.css"/>
|
||||
<script src="js/xmlTreeViewer.js" type="text/javascript"></script>
|
||||
<script src="js/base64.min.js" type="text/javascript"></script>
|
||||
<style>
|
||||
.view-switcher {
|
||||
margin-bottom: 15px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.view-switcher .btn-group {
|
||||
float: right;
|
||||
}
|
||||
.xml-text-view {
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
background-color: #f8f9fa;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #dee2e6;
|
||||
overflow-x: auto;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.xml-tree-view {
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
.active-view {
|
||||
font-weight: bold;
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
.xml-tag {
|
||||
color: #007bff;
|
||||
font-weight: bold;
|
||||
}
|
||||
.xml-attr-name {
|
||||
color: #28a745;
|
||||
font-weight: bold;
|
||||
}
|
||||
.xml-attr-value {
|
||||
color: #dc3545;
|
||||
}
|
||||
.xml-comment {
|
||||
color: #6c757d;
|
||||
font-style: italic;
|
||||
}
|
||||
.xml-text {
|
||||
color: #212529;
|
||||
}
|
||||
.xml-highlight {
|
||||
background-color: #fff3cd;
|
||||
padding: 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.toggle-btn {
|
||||
cursor: pointer;
|
||||
color: #007bff;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.toggle-btn:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<input hidden id="textData" value="${textData}"/>
|
||||
<div class="container">
|
||||
<div class="panel panel-default">
|
||||
<div id="xml_btn" class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
|
||||
<div class="panel-heading">
|
||||
<div class="view-switcher">
|
||||
<h4 class="panel-title" style="display: inline-block;">
|
||||
${file.name}
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="text_btn" class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
|
||||
${file.name}
|
||||
</a>
|
||||
</h4>
|
||||
</h4>
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" id="treeViewBtn" class="btn btn-primary active">
|
||||
<span class="glyphicon glyphicon-tree-conifer"></span> 树状视图
|
||||
</button>
|
||||
<button type="button" id="textViewBtn" class="btn btn-default">
|
||||
<span class="glyphicon glyphicon-align-left"></span> 文本视图
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div id="xml"></div>
|
||||
<div id="treeView" class="xml-tree-view"></div>
|
||||
<div id="textView" class="xml-text-view" style="display: none;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
window.onload = function () {
|
||||
$("#xml_btn").hide()
|
||||
initWaterMark();
|
||||
loadXmlData()
|
||||
// XML格式化函数
|
||||
function formatXml(xml, indentChars = ' ') {
|
||||
let formatted = '';
|
||||
let indent = 0;
|
||||
const tab = indentChars;
|
||||
xml = xml.replace(/(>)(<)(\/*)/g, "$1\n$2$3");
|
||||
|
||||
const lines = xml.split('\n');
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
let line = lines[i].trim();
|
||||
|
||||
if (!line) continue;
|
||||
|
||||
// 减少缩进级别
|
||||
if (line.match(/^<\//) || line.match(/^\/>/)) {
|
||||
indent--;
|
||||
}
|
||||
|
||||
// 添加当前行的缩进
|
||||
if (indent > 0) {
|
||||
formatted += tab.repeat(indent);
|
||||
}
|
||||
|
||||
formatted += line + '\n';
|
||||
|
||||
// 增加缩进级别(如果不是自闭合标签且不是结束标签)
|
||||
if (line.match(/<.*>.*<\/.*>/) || line.match(/\/>/) ||
|
||||
line.match(/<!/) || line.match(/\?>/)) {
|
||||
// 自闭合标签、注释、处理指令等不增加缩进
|
||||
} else if (line.match(/<[^\/?]/) && !line.match(/<\//)) {
|
||||
indent++;
|
||||
}
|
||||
}
|
||||
|
||||
return formatted;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载xml数据
|
||||
*/
|
||||
function htmlEscape(str){
|
||||
// XML语法高亮函数
|
||||
function highlightXml(xml) {
|
||||
return xml
|
||||
// 处理注释
|
||||
.replace(/<!--[\s\S]*?-->/g, '<span class="xml-comment">$&</span>')
|
||||
// 处理标签
|
||||
.replace(/<(\/?)([a-zA-Z][a-zA-Z0-9:_-]*)/g, '<<span class="xml-tag">$1$2</span>')
|
||||
// 处理属性名
|
||||
.replace(/\s([a-zA-Z][a-zA-Z0-9:_-]*)="/g, ' <span class="xml-attr-name">$1</span>="')
|
||||
// 处理属性值
|
||||
.replace(/="([^"]*)"/g, '="<span class="xml-attr-value">$1</span>"')
|
||||
// 处理CDATA
|
||||
.replace(/<!\[CDATA\[[\s\S]*?\]\]>/g, '<span class="xml-highlight">$&</span>');
|
||||
}
|
||||
|
||||
// HTML转义函数
|
||||
|
||||
|
||||
function htmlEscape(str){
|
||||
var s = "";
|
||||
if(str.length == 0) return "";
|
||||
s = str.replace(/&/g,"&");
|
||||
@@ -65,29 +172,129 @@
|
||||
s = s.replace(/<iframe/gi, "<iframe ");
|
||||
return s;
|
||||
}
|
||||
function loadXmlData() {
|
||||
var textData = Base64.decode($("#textData").val())
|
||||
textData = htmlEscape(textData);
|
||||
window.textPreData = "<xmp style='background-color: #FFFFFF;overflow-y: scroll;border:none'>" + textData + "</xmp>";
|
||||
var xmlNode = xmlTreeViewer.parseXML(textData);
|
||||
window.retNode = xmlTreeViewer.getXMLViewerNode(xmlNode.xml);
|
||||
$("#xml").html(window.retNode);
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
window.onload = function () {
|
||||
initWaterMark();
|
||||
loadXmlData();
|
||||
|
||||
// 视图切换按钮事件
|
||||
$("#treeViewBtn").click(function() {
|
||||
$("#treeView").show();
|
||||
$("#textView").hide();
|
||||
$(this).removeClass('btn-default').addClass('btn-primary active');
|
||||
$("#textViewBtn").removeClass('btn-primary active').addClass('btn-default');
|
||||
});
|
||||
|
||||
$("#textViewBtn").click(function() {
|
||||
$("#textView").show();
|
||||
$("#treeView").hide();
|
||||
$(this).removeClass('btn-default').addClass('btn-primary active');
|
||||
$("#treeViewBtn").removeClass('btn-primary active').addClass('btn-default');
|
||||
});
|
||||
}
|
||||
|
||||
$(function () {
|
||||
$("#xml_btn").click(function () {
|
||||
$("#xml").html(window.retNode);
|
||||
$("#text_btn").show()
|
||||
$("#xml_btn").hide()
|
||||
});
|
||||
/**
|
||||
* 加载XML数据
|
||||
*/
|
||||
function loadXmlData() {
|
||||
try {
|
||||
// 解码Base64数据
|
||||
var textData = Base64.decode($("#textData").val());
|
||||
|
||||
// 转义HTML特殊字符
|
||||
textData =htmlEscape(textData);
|
||||
|
||||
|
||||
// 格式化XML
|
||||
var formattedXml = formatXml(textData);
|
||||
|
||||
// 应用语法高亮
|
||||
var highlightedXml = highlightXml(formattedXml);
|
||||
|
||||
// 设置文本视图内容
|
||||
$("#textView").html(highlightedXml);
|
||||
|
||||
// 解析并显示树状视图
|
||||
try {
|
||||
|
||||
var xmlNode = xmlTreeViewer.parseXML(textData);
|
||||
window.retNode = xmlTreeViewer.getXMLViewerNode(xmlNode.xml);
|
||||
$("#treeView").html(window.retNode);
|
||||
|
||||
// 为树状视图添加交互功能
|
||||
enhanceTreeView();
|
||||
} catch (treeError) {
|
||||
console.error("树状视图解析错误:", treeError);
|
||||
$("#treeView").html(
|
||||
'<div class="alert alert-warning">' +
|
||||
'<strong>警告:</strong>无法生成树状视图,XML格式可能不正确。<br>' +
|
||||
'错误信息:' + treeError.message +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error("XML处理错误:", error);
|
||||
$("#textView").html(
|
||||
'<div class="alert alert-danger">' +
|
||||
'<strong>错误:</strong>无法解析XML数据。<br>' +
|
||||
'请检查XML格式是否正确。<br>' +
|
||||
'错误信息:' + error.message +
|
||||
'</div>'
|
||||
);
|
||||
$("#treeView").html(
|
||||
'<div class="alert alert-danger">' +
|
||||
'<strong>错误:</strong>无法解析XML数据。<br>' +
|
||||
'请检查XML格式是否正确。<br>' +
|
||||
'错误信息:' + error.message +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$("#text_btn").click(function () {
|
||||
$("#xml_btn").show()
|
||||
$("#text_btn").hide();
|
||||
$("#xml").html(window.textPreData);
|
||||
/**
|
||||
* 增强树状视图的交互功能
|
||||
*/
|
||||
function enhanceTreeView() {
|
||||
// 为所有可折叠节点添加点击事件
|
||||
$(".xml-tree-view .toggle-btn").off('click').on('click', function() {
|
||||
$(this).toggleClass('collapsed');
|
||||
var target = $(this).data('target');
|
||||
if (target) {
|
||||
$(target).toggle();
|
||||
}
|
||||
});
|
||||
|
||||
// 添加节点高亮功能
|
||||
$(".xml-tree-view .xml-node").hover(
|
||||
function() {
|
||||
$(this).addClass('xml-highlight');
|
||||
},
|
||||
function() {
|
||||
$(this).removeClass('xml-highlight');
|
||||
}
|
||||
);
|
||||
|
||||
// 双击节点展开/折叠所有子节点
|
||||
$(".xml-tree-view .xml-node").off('dblclick').on('dblclick', function() {
|
||||
var toggleBtn = $(this).find('.toggle-btn').first();
|
||||
if (toggleBtn.length) {
|
||||
toggleBtn.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 页面加载完成后重新绑定事件
|
||||
$(document).ready(function() {
|
||||
// 如果XML内容很大,显示加载提示
|
||||
var textData = $("#textData").val();
|
||||
if (textData && textData.length > 100000) { // 大约100KB
|
||||
$("#textView").html('<div class="alert alert-info">正在格式化XML内容,请稍候...</div>');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
Reference in New Issue
Block a user