5.0版本 发布 新增 cadviewer转换方法

This commit is contained in:
高雄
2026-01-22 11:28:25 +08:00
parent 7dc0469b30
commit e43f10138f
1022 changed files with 293112 additions and 3187 deletions

View File

@@ -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);

View 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>

View File

@@ -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(/&amp;/gi,"&");
s = s.replace(/&lt;/gi,"<");
s = s.replace(/&gt;/gi,">");
s = s.replace(/&nbsp;/gi," ");
s = s.replace(/&#39;/gi,"\'");
s = s.replace(/&quot;/gi,"\"");
s = s.replace(/javascript/g,"javascript ");
if (txt === 2){
s = s.replace(/<script/gi, "&lt;script ");
s = s.replace(/javascript/g,"javascript ");
s = s.replace(/<\/script/gi, "&lt;/script ");
s = s.replace(/<iframe/gi, "&lt;iframe ");
s = s.replace(/<\/iframe/gi, "&lt;/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>

View File

@@ -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); //文件所在地址

View File

@@ -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";

View File

@@ -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;

View File

@@ -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;

View File

@@ -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) {

View 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>

View File

@@ -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));
}

View File

@@ -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>
&lt;script src="${baseUrl}js/crypto-js.js"></script><br>
&lt;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>

View File

@@ -35,29 +35,47 @@
</div>
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">2025年12月25v5.0版本</h3>
<h3 class="panel-title">2026年01月20v5.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>

View File

@@ -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(/&amp;/g,"&");
s = str.replace(/&amp;amp;/g,"&");
s = s.replace(/&lt;/g,"<");
s = s.replace(/&gt;/g,">");
s = s.replace(/&nbsp;/g," ");
s = s.replace(/&#39;/g,"\'");
s = s.replace(/&quot;/g,"\"");
s = s.replace(/<script.*?>.*?<\/script>/ig, '');
s = s.replace(/<script/gi, "&lt;script ");
s = s.replace(/<iframe/gi, "&lt;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, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#39;")
.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>

View 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>

View File

@@ -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}";

View File

@@ -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>

View File

@@ -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>

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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>

View File

@@ -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)';
}

View File

@@ -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>";

View File

@@ -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(/&amp;/gi,"&");
s = s.replace(/&lt;/gi,"<");
s = s.replace(/&gt;/gi,">");
s = s.replace(/&nbsp;/gi," ");
s = s.replace(/&#39;/gi,"\'");
s = s.replace(/&quot;/gi,"\"");
s = s.replace(/javascript/g,"javascript ");
if (txt === 2){
s = s.replace(/<script/gi, "&lt;script ");
s = s.replace(/javascript/g,"javascript ");
s = s.replace(/<\/script/gi, "&lt;/script ");
s = s.replace(/<iframe/gi, "&lt;iframe ");
s = s.replace(/<\/iframe/gi, "&lt;/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>

View File

@@ -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

View File

@@ -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;

View File

@@ -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(/&lt;!--[\s\S]*?--&gt;/g, '<span class="xml-comment">$&</span>')
// 处理标签
.replace(/&lt;(\/?)([a-zA-Z][a-zA-Z0-9:_-]*)/g, '&lt;<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(/&lt;!\[CDATA\[[\s\S]*?\]\]&gt;/g, '<span class="xml-highlight">$&</span>');
}
// HTML转义函数
function htmlEscape(str){
var s = "";
if(str.length == 0) return "";
s = str.replace(/&amp;/g,"&");
@@ -65,29 +172,129 @@
s = s.replace(/<iframe/gi, "&lt;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>