阅读器版本

This commit is contained in:
2025-10-11 11:08:42 +08:00
parent a10ef743dc
commit e76b22180d
63 changed files with 14774 additions and 2515 deletions

View File

@@ -1,31 +1,30 @@
<template>
<div id="app">
<div id="app" ref="app" :style="{ height: windowHeightApp + 'px' }">
<!-- <img alt="Vue logo" src="./assets/logo.png"> -->
<!-- <HelloWorld2 msg="Welcome to Your Vue.js App"/> -->
<HelloWorld style="display:none" msg="Welcome to Your Vue.js App"/>
<!-- <HelloWorld style="display:none" msg="Welcome to Your Vue.js App"/> -->
<router-view/>
</div>
</template>
<script>
// import HelloWorld from './components/vditor2Bd.vue'
// import HelloWorld from './components/homePage3.vue'
// import HelloWorld from './components/quill.vue'
// import HelloWorld from './components/tinyMCE.vue'
// import HelloWorld from './components/vditor.vue'
import HelloWorld from './components/wang.vue'
// import HelloWorld2 from './components/wangTest.vue'
// import HelloWorld from './components/wangG.vue'
// import HelloWorld2 from './components/wangITEM.vue'
// import HelloWorld from './components/XMLwangS1000D.vue'
// import HelloWorld from './components/XMLwang.vue'
// import HelloWorld from './components/vditor2.vue'
// import HelloWorld from './components/ueditor.vue'
// import HelloWorld from './components/wang.vue'
export default {
name: 'App',
components: {
HelloWorld,
// HelloWorld,
},
data() {
return {
screenHeightApp: 0, // 屏幕总高度
windowHeightApp: 0 // 可视窗口高度
};
},
mounted() {
this.screenHeightApp = window.screen.height;
// 可视窗口高度(浏览器窗口高度)
this.windowHeightApp = window.innerHeight;
}
}
</script>
@@ -39,4 +38,5 @@ export default {
color: #2c3e50;
/* margin-top: 60px; */
}
body{margin:0 !important;}
</style>

5522
src/assets/brex.xsd Normal file

File diff suppressed because it is too large Load Diff

1142
src/assets/css/style.css Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
src/assets/img/Music.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
src/assets/img/addIcon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
src/assets/img/bianji.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
src/assets/img/bianji1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
src/assets/img/br.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
src/assets/img/br2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
src/assets/img/danwei.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
src/assets/img/delIcon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 823 B

BIN
src/assets/img/dinggao.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
src/assets/img/duoyuyan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

BIN
src/assets/img/editIcon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
src/assets/img/fenlei.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
src/assets/img/file.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
src/assets/img/history.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
src/assets/img/jgIcon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

BIN
src/assets/img/jinggao.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

BIN
src/assets/img/jingshi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
src/assets/img/jsIcon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
src/assets/img/leixing.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
src/assets/img/miji.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
src/assets/img/mp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
src/assets/img/mp1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
src/assets/img/quanxian.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
src/assets/img/saveIcon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
src/assets/img/shanchu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
src/assets/img/shanchu1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
src/assets/img/shanchu2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
src/assets/img/video.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
src/assets/img/wenjian.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
src/assets/img/xinjian.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
src/assets/img/xinjian1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
src/assets/img/xinxi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
src/assets/img/xml.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
src/assets/img/yongtu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
src/assets/img/yulan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
src/assets/img/zhuti.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@@ -1,95 +0,0 @@
<template>
<div>
<div ref="editor" style="text-align:left"></div>
<button @click="exportToXml">导出为XML</button>
<input type="file" accept=".xml" @change="handleXmlUpload">
</div>
</template>
<script>
import E from 'wangeditor';
import { js2xml, xml2js } from 'xml-js';
export default {
data() {
return {
editor: null
};
},
mounted() {
this.editor = new E(this.$refs.editor);
this.editor.create();
},
methods: {
convertHtmlToXml(htmlContent) {
const xmlObject = {
declaration: {
attributes: {
version: '1.0',
encoding: 'UTF-8'
}
},
elements: [{
type: 'element',
name: 'richText',
elements: [{
type: 'text',
text: htmlContent
}]
}]
};
return js2xml(xmlObject, { compact: false, spaces: 4 });
},
downloadXml(content, fileName = 'content.xml') {
const blob = new Blob([content], { type: 'application/xml' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = fileName;
link.click();
URL.revokeObjectURL(link.href);
},
exportToXml() {
const html = this.editor.txt.html();
const xml = this.convertHtmlToXml(html);
this.downloadXml(xml);
},
parseXmlToHtml(xmlString) {
try {
const result = xml2js(xmlString, { compact: false });
const richTextElement = result.elements.find(el => el.name === 'richText');
if (richTextElement && richTextElement.elements && richTextElement.elements.length > 0) {
return richTextElement.elements[0].text;
}
return '';
} catch (e) {
console.error('XML解析错误:', e);
return '';
}
},
handleXmlUpload(event) {
const file = event.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (e) => {
const xmlString = e.target.result;
const html = this.parseXmlToHtml(xmlString);
if (html) {
this.editor.txt.html(html);
}
};
reader.readAsText(file);
}
},
beforeDestroy() {
if (this.editor) {
this.editor.destroy();
}
}
};
</script>

View File

@@ -1,425 +0,0 @@
<template>
<div class="editor-container">
<div class="toolbar">
<button @click="insertImage">上传图片</button>
<button @click="insertVideo">上传视频</button>
<button @click="loadAllContent">加载所有内容</button>
<button @click="generateTOC">生成目录</button>
<button @click="deleteAllVideos">删除所有视频</button>
<button @click="loadFwb">模拟加载</button>
</div>
<div id="main" class="content-preview"></div>
<div id="nav" class="toc-container"></div>
<div id="editor" ref="editor"></div>
<!-- <div id="editor2" ref="editor2"></div> -->
<!-- <button @click="callWpfMethod">调用WPF方法</button> -->
<input type="text" v-model="val1">
<input type="text" v-model="val2">
<button @click="sendMessageToHost('李四','张三')">传递</button>
</div>
</template>
<script>
import WangEditor from 'wangeditor'
// import axios from 'axios';
// window.handleMessageFromDotNet = function(msg) {
// alert("Received message from C#: " + msg);
// }
export default {
name: 'RichTextEditor',
data() {
return {
val1:'',
val2:'',
wpfData: '',
message: '',
editor: null,
editor2:null,
editorContent: '',
editorContent2:'',
hasVideoSelected: false,
}
},
mounted() {
this.initEditor()
// this.initEditor2();
// window.receiveMessageFromWpf = this.receiveMessageFromWpf;
console.log('chrome对象是否存在:', !!window.chrome);
console.log('webview对象是否存在:', !!window.chrome?.webview);
},
beforeDestroy() {
// 销毁编辑器
if (this.editor) {
this.editor.destroy()
}
},
methods: {
sendMessageToHost() {
this.$sendToDotNet(this.val1,this.val2);
},
loadFwb() {
this.editor2.txt.html(this.editorContent)
// 创建编辑器
},
initEditor() {
this.editor = new WangEditor(this.$refs.editor)
// 配置编辑器
this.editor.config.uploadImgShowBase64 = true // 使用 base64 保存图片
this.editor.config.onchange = (html) => {
this.editorContent = html
}
let dm = this.editor.config.menus;
console.log("默认菜单",dm)
// 完全自定义菜单
this.editor.config.menus = [
'head', // 标题
'bold', // 粗体
// 'fontSize',//字号
// 'fontName',//字体
'italic', // 斜体
'underline', // 下划线
'strikeThrough', // 删除线
// 'line',//行高
'lineHeight',//
// 'foreColor', // 文字颜色
// 'backColor', // 背景颜色
// 'link', // 链接
'list', // 列表
// 'todo',//
'justify', // 对齐方式
// 'quote', // 引用
// 'emoticon',//表情
'image', // 图片
'video', // 视频
'table', // 表格
// 'code', // 代码
'splitLine',//分割线
'undo', // 撤销
'redo' // 重做
]
// 创建编辑器
this.editor.create();
// this.editor2 = new WangEditor(this.$refs.editor2)
// // 配置编辑器
// this.editor2.config.uploadImgShowBase64 = true // 使用 base64 保存图片
// this.editor2.config.onchange = (html) => {
// console.log("22222",html)
// // this.editorContent2 = html
// }
// this.editor2.create()
},
// 上传图片
insertImage() {
const imgUrl = 'http://youneed.top:10017/uploads/1.jpg'
this.editor.cmd.do('insertHTML', `<img src="${imgUrl}" style="max-width: 100%;" alt="图片">`)
},
// 插入视频(可靠版本)
insertVideo() {
const videoUrl = 'http://youneed.top:10017/uploads/video.mp4'
const videoId = `video-${Date.now()}`
// 创建视频HTML
const videoHtml = `
<div class="video-wrapper" data-video-id="${videoId}">
<video controls width="50%" style='margin:auto' data-video-id="${videoId}">
<source src="${videoUrl}" type="video/mp4">
</video>
<div class="video-controls">
<span class="video-delete" data-video-id="${videoId}">× 删除</span>
</div>
</div>
<p><br></p>
`
// 使用编辑器命令插入
this.editor.cmd.do('insertHTML', videoHtml)
// 添加删除事件监听
this.bindDel();
},
// 根据ID删除视频修正版
deleteVideoById(videoId) {
console.log("ID",videoId)
const videoWrapper = document.querySelector(`[data-video-id="${videoId}"]`)
if (videoWrapper) {
// 获取视频所在段落
let parent = videoWrapper.parentElement
while (parent && parent !== this.$refs.editor) {
if (parent.tagName === 'P') {
// 如果是空段落,一并删除
if (parent.textContent.trim() === '') {
parent.remove()
}
break
}
parent = parent.parentElement
}
videoWrapper.remove()
// 修正:使用正确的方式通知内容变更
if (this.editor.txt) {
this.editor.txt.html(this.editor.txt.html()) // 强制更新编辑器内容
}
}
},
bindDel(){
this.$nextTick(() => {
const deleteButtons = document.querySelectorAll('.video-delete')
console.log("所有绑定:",deleteButtons)
deleteButtons.forEach(btn => {
btn.onclick = (e) => {
e.preventDefault()
e.stopPropagation()
const videoId = btn.getAttribute('data-video-id')
this.deleteVideoById(videoId)
}
})
})
},
deleteAllVideos() {
const videoWrappers = document.querySelectorAll('.video-wrapper')
if (videoWrappers.length === 0) {
alert('没有找到可删除的视频')
return
}
videoWrappers.forEach(wrapper => {
wrapper.remove()
})
// 删除可能残留的空段落
const editor = this.$refs.editor
const paragraphs = editor.querySelectorAll('p')
paragraphs.forEach(p => {
if (p.textContent.trim() === '' && p.children.length === 0) {
p.remove()
}
})
// 修正:使用正确的方式通知内容变更
if (this.editor.txt) {
this.editor.txt.html(this.editor.txt.html()) // 强制更新编辑器内容
}
console.log(`已删除 ${videoWrappers.length} 个视频`)
},
// 加载所有内容到 main 容器
loadAllContent() {
const mainContainer = document.getElementById('main')
mainContainer.innerHTML = this.editorContent;
console.log("this.editorContent",this.editorContent)
// 为main容器中的标题添加ID
this.addHeadingIds(mainContainer)
},
// 为标题元素添加ID
addHeadingIds(container) {
const headings = container.querySelectorAll('h1, h2, h3, h4, h5, h6')
headings.forEach((heading, index) => {
if (!heading.id) {
heading.id = `heading-${index}-${Date.now()}`
}
})
},
// 生成带锚点的目录
generateTOC() {
const navContainer = document.getElementById('nav')
navContainer.innerHTML = '' // 清空原有目录
// 确保main容器已加载内容
if (!document.getElementById('main').innerHTML) {
this.loadAllContent()
}
const mainContainer = document.getElementById('main')
const headings = mainContainer.querySelectorAll('h1, h2, h3, h4, h5, h6')
if (headings.length === 0) {
navContainer.innerHTML = '<p>没有找到标题元素,无法生成目录。</p>'
return
}
const tocList = document.createElement('ul')
tocList.style.listStyleType = 'none'
tocList.style.paddingLeft = '0'
headings.forEach(heading => {
const level = parseInt(heading.tagName.substring(1))
const listItem = document.createElement('li')
listItem.style.marginLeft = `${(level - 1) * 15}px`
listItem.style.marginBottom = '5px'
const link = document.createElement('a')
link.href = `#${heading.id}`
link.textContent = heading.textContent
link.style.textDecoration = 'none'
link.style.color = '#333'
// 添加平滑滚动效果
link.addEventListener('click', (e) => {
e.preventDefault()
document.getElementById(heading.id).scrollIntoView({
behavior: 'smooth'
})
})
listItem.appendChild(link)
tocList.appendChild(listItem)
})
const tocContainer = document.createElement('div')
tocContainer.style.border = '1px solid #ddd'
tocContainer.style.padding = '15px'
tocContainer.style.marginBottom = '20px'
tocContainer.style.background = '#f9f9f9'
tocContainer.style.borderRadius = '4px'
const tocTitle = document.createElement('h2')
tocTitle.textContent = '目录'
tocTitle.style.marginTop = '0'
tocContainer.appendChild(tocTitle)
tocContainer.appendChild(tocList)
navContainer.appendChild(tocContainer)
}
},
created() {
// 方式1直接访问全局变量
this.$watch(
() => this.$dotNetMessage,
(newMsg) => {
console.log('收到消息:', newMsg)
}
)
// 方式2监听全局事件
window.addEventListener('dotnet-message', (e) => {
console.log('通过事件收到:', e.detail)
})
}
}
</script>
<style>
.editor-container {
width: 80%;
margin: 0 auto;
padding: 20px;
}
.toolbar {
margin-bottom: 10px;
}
.toolbar button {
margin-right: 10px;
padding: 5px 10px;
background: #409eff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.toolbar button:hover {
background: #66b1ff;
}
#editor,#editor2 {
border: 1px solid #ddd;
min-height: 300px;
padding: 10px;
text-align: left;
}
.content-preview {
margin-top: 20px;
border: 1px solid #eee;
padding: 15px;
background: #fafafa;
}
#main th,
#main td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
#main th {
background-color: #f2f2f2;
}
/* 视频容器样式 */
.video-wrapper {
position: relative;
margin: 15px 0;
/* border: 1px solid #ddd; */
border-radius: 4px;
overflow: hidden;
}
.video-controls {
position: absolute;
top: 5px;
right: 5px;
z-index: 10;
}
.video-delete {
display: inline-block;
padding: 2px 8px;
background: rgba(255, 0, 0, 0.7);
color: white;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
user-select: none;
}
.video-delete:hover {
background: rgba(255, 0, 0, 0.9);
}
/* 确保视频响应式 */
video {
max-width: 100%;
display: block;
background: #000;
}
</style>

File diff suppressed because it is too large Load Diff

657
src/components/wangG2.vue Normal file
View File

@@ -0,0 +1,657 @@
<template>
<div>
<!-- <el-button @click='getNet'>获取</el-button>
<input type="text"> -->
<el-descriptions class="margin-top" v-if='viewXml' title="章节信息" :column="3" border>
<template slot="extra">
<el-button @click='dmcTable' type="primary" size="small">{{dmcHint?"收起":"展开"}}</el-button>
</template>
<el-descriptions-item v-if='dmcHint'>
<template slot="label">
章节名称
</template>
{{rdfDescriptions[0].children[0].text}}
</el-descriptions-item>
<el-descriptions-item v-if='dmcHint'>
<template slot="label">
创作单位
</template>
{{rdfDescriptions[0].children[1].text}}
</el-descriptions-item>
<el-descriptions-item v-if='dmcHint'>
<template slot="label">
权限
</template>
{{formatOther('permission',rdfDescriptions[0].children[2].text).label}}
</el-descriptions-item>
<el-descriptions-item v-if='dmcHint'>
<template slot="label">
合作单位
</template>
{{rdfDescriptions[0].children[5].text}}
</el-descriptions-item>
<el-descriptions-item v-if='dmcHint'>
<template slot="label">
版本号
</template>
{{rdfDescriptions[0].children[6].text}}
</el-descriptions-item>
<el-descriptions-item v-if='dmcHint'>
<template slot="label">
密级
</template>
<!-- {{rdfDescriptions[0].children[7].text}} -->
{{formatOther('level',rdfDescriptions[0].children[7].text).label}}
</el-descriptions-item>
<el-descriptions-item v-if='dmcHint'>
<template slot="label">
发布日期
</template>
{{formatDate(rdfDescriptions[0].children[8].text)}}
</el-descriptions-item>
<el-descriptions-item v-if='dmcHint'>
<template slot="label">
适用性信息
</template>
{{rdfDescriptions[0].children[9].text}}
</el-descriptions-item>
<el-descriptions-item v-if='dmcHint'>
<template slot="label">
质量验证
</template>
{{rdfDescriptions[0].children[10].text}}
</el-descriptions-item>
<el-descriptions-item v-if='dmcHint'>
<template slot="label">
语言
</template>
{{rdfDescriptions[0].children[14].text}}
</el-descriptions-item>
</el-descriptions>
<div class="loadContent" style="width:100%;" v-html="neirong">
</div>
</div>
</template>
<script>
export default {
data() {
return {
optionsPermission:[
{label:'一级',value:'1'},
{label:'二级',value:'2'},
{label:'三级',value:'3'},
{label:'四级',value:'4'},
{label:'五级',value:'5'},
{label:'六级',value:'6'},
{label:'七级',value:'7'},
{label:'八级',value:'8'},
{label:'九级',value:'9'},
{label:'十级',value:'10'},
],
optionsLevel: [
{value: '1',label: '公开'},
{value: '2',label: '秘密'},
{value: '3',label: '机密'},
{value: '4',label: '绝密'}
],
dmcHint:false,
rdfDescriptions:[],
pmTitleContent:{},
viewLis:'',
viewXml:'',
neirong:'',
oldSelector:[//基础标签模块
'div','code','hr','br','h1,h2,h3,h4','p','img','table','a','ul','ol','blockquote','pre',
],
newSelector:[//替换后的标签模块
'pDiv','pCode','pHr','pBr','pTitle','pDiv','pImg','pTable','pA','pUl','pOl','pBlockquote','pPre',
],
};
},
mounted() {
console.log('G2页面2222 chrome对象是否存在:', !!window.chrome);
console.log('G2页面2222 webview对象是否存在:', !!window.chrome?.webview);
this.neirong = '';
this.getNet()
},
methods: {
dmcTable() {
if(this.dmcHint){
this.dmcHint = false;
}else{
this.dmcHint = true;
}
},
formatOther(type,data){
let textStr = null;
console.log("内容",type,data)
switch(type){
case "level":
textStr = this.optionsLevel.find(item => {
return item.value === data;
});
break;
case "permission":
textStr = this.optionsPermission.find(item => {
return item.value === data;
});
break;
}
console.log('内容',data,textStr)
return textStr;
},
formatDate(dateStr) {
if (!dateStr) return "";
try {
// 将字符串转换为Date对象
const date = new Date(dateStr);
// 获取年、月、日
const year = date.getFullYear();
// 月份从0开始需要+1并用padStart补零确保两位数
const month = String(date.getMonth() + 1).padStart(2, "0");
// 日期补零确保两位数
const day = String(date.getDate()).padStart(2, "0");
// 返回格式化后的字符串格式YYYY-MM-DD
return `${year}-${month}-${day}`;
} catch (error) {
console.error("日期格式化失败:", error);
return "无效日期";
}
},
getNet() {
console.log("发送请求",this.rdfDescriptions)
this.$sendToDotNet('DMPreview','HistoryDMPreview')
this.$sendToDotNet('DMPreview','UserLocalDMPreview')
},
parseRdfDescriptions() {
try {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(this.viewXml, 'text/xml');
// 定义RDF命名空间关键必须与XML中的命名空间一致
const nsResolver = (prefix) => {
const ns = {
'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
// 可以添加其他需要的命名空间
};
return ns[prefix] || null;
};
// 使用XPath查询所有rdf:Description元素
const xpathResult = xmlDoc.evaluate(
'//rdf:Description',
xmlDoc,
nsResolver,
XPathResult.ORDERED_NODE_ITERATOR_TYPE,
null
);
this.rdfDescriptions = [];
let currentNode;
// 遍历所有找到的rdf:Description节点
while ((currentNode = xpathResult.iterateNext())) {
// 获取节点内的所有内容(包括子节点和文本)
const content = {
attributes: {},
children: [],
innerXML: currentNode.innerHTML // 完整的内部XML
};
// 获取所有属性
if (currentNode.attributes) {
for (let i = 0; i < currentNode.attributes.length; i++) {
const attr = currentNode.attributes[i];
content.attributes[attr.name] = attr.value;
}
}
// 获取所有子节点文本内容
if (currentNode.children && currentNode.children.length > 0) {
for (let i = 0; i < currentNode.children.length; i++) {
const child = currentNode.children[i];
content.children.push({
tag: child.tagName,
text: child.textContent,
attributes: Array.from(child.attributes).reduce((attrs, attr) => {
attrs[attr.name] = attr.value;
return attrs;
}, {})
});
}
} else {
// 如果没有子节点,直接获取文本内容
content.text = currentNode.textContent;
}
this.rdfDescriptions.push(content);
}
console.log('所有rdf:Description内容', this.rdfDescriptions);
} catch (error) {
console.error('解析XML出错', error);
}
},
//解析新建目录时候的DMC文件
parseXmlDmc_loadFile() {
try {
// 解析XML字符串
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(this.viewXml, "text/xml");
console.log("得到的1",xmlDoc)
// 检查解析错误
const errorNode = xmlDoc.querySelector("parsererror");
console.log("得到的2",errorNode)
// if (errorNode) {
// throw new Error("XML解析错误: " + errorNode.textContent);
// }
// 提取content标签内容
this.extractContent2(xmlDoc);
} catch (error) {
console.error("解析失败:", error);
// alert("解析XML失败: " + error.message);
}
},
// 提取新建目录时候的DMC文件中content标签内的内容
extractContent2(xmlDoc) {
const contentNodes = xmlDoc.getElementsByTagName("content");
if (contentNodes.length === 0) {
this.contentResult = "未找到content标签";
return;
}
const contentNode = contentNodes[0];
let contentHtml = "";
// 序列化content节点的所有子节点
for (let i = 0; i < contentNode.childNodes.length; i++) {
const child = contentNode.childNodes[i];
// 忽略空文本节点
if (child.nodeType === 1 || (child.nodeType === 3 && child.textContent.trim())) {
contentHtml += new XMLSerializer().serializeToString(child);
}
}
// this.viewXmlContent = contentHtml.trim();
console.log("加载解析出来DMC内容",contentHtml)
console.log("加载解析出来DMC内容",contentHtml.trim())
this.restoreContentXh2(contentHtml.trim())
// this.contentResult = contentHtml.trim();
},
// XML文件标签剔除
restoreContentXh2(html) {
console.log("XML初始内容",html)
if (html) {
this.tempDivData1 = document.createElement('div')
this.tempDivData1.innerHTML = html
let times = this.oldSelector.length;
for(let i =0;i<times;i++){
// 处理所有dmTitle标签
const dmTitles = this.tempDivData1.querySelectorAll(this.newSelector[i])
dmTitles.forEach(dmTitle => {
// 获取dmTitle的子节点
const children = Array.from(dmTitle.childNodes)
console.log("剔除标签:",dmTitles,children)
// 在dmTitle之前插入所有子节点
children.forEach(child => {
dmTitle.parentNode.insertBefore(child.cloneNode(true), dmTitle)
})
// 移除dmTitle
dmTitle.parentNode.removeChild(dmTitle)
console.log("剔除标签移除:",dmTitle,'替换成',dmTitle)
})
}
console.log('内容还原完成dmTitle标签已被移除')
console.log("tempDiv.innerHTML",this.tempDivData1.innerHTML)
const reg2 = /(<(model3d|img|audio|video)[^>]+src=")(?!http:\/\/)([^"]+)("[^>]*>)/gi;
let jc = this.viewLis;
// 检查并去除开头的双引号
if (jc.startsWith('"')) {
jc = jc.substring(1);
}
// 检查并去除结尾的双引号
if (jc.endsWith('"')) {
jc = jc.substring(0, jc.length - 1);
}
// if(!this.dialogVisibleNav){
// jc = jc+this.historyVsPath+'/';
// }
// console.log("jc")
// 替换为src="基础URL+文件名"
// 这里假设原路径可能包含DM_Material目录如果不需要可以去掉
let html_2 = this.tempDivData1.innerHTML.replace(reg2, `$1${jc}$3$4`);
// html_2 = this.modelToImg(html_2);
console.log("大豪科技等哈时间",this.viewLis)
console.log('加载还原地址:',html_2)
let processedL = this.hintFun(html_2)
this.neirong = this.modelToImg(processedL);
}else{
console.log("空白文档")
}
},
hintFun(html_2) {
let html = html_2;
// 定义需要替换的class映射关系
const classMappings = {
'teshu': 'testBo',
'teshu2': 'testBo2'
};
// 使用正则表达式匹配class属性并替换相应的值
// 这个正则表达式会匹配class属性中的各个class名称
html = html.replace(/class="([^"]*)"/g, (match, classValues) => {
let newClassValues = classValues;
// 遍历替换映射替换每个需要替换的class
Object.keys(classMappings).forEach(oldClass => {
const newClass = classMappings[oldClass];
// 使用单词边界确保只替换完整的class名称
const regex = new RegExp(`\\b${oldClass}\\b`, 'g');
newClassValues = newClassValues.replace(regex, newClass);
});
return `class="${newClassValues}"`;
});
const regex = /(<div\s+[^>]*class="[^"]*(testBo2|testBo)[^"]*"[^>]*>)(.*?)(<\/div>)/gis;
html = html.replace(regex, (match, startTag, className, content, endTag) => {
// 验证捕获的className
console.log('捕获的class名称:', className);
// 定义不同class对应的边框样式
let borderStyle;
if (className === 'testBo2') {
borderStyle = '3px solid #ffcc00'; // testBo的边框样式(深黄色)
} else if (className === 'testBo') {
borderStyle = '3px solid red'; // testBo2的边框样式(红色)
}
// 包裹div的完整样式
const wrapperStyle = `background:#fff;padding: 10px;border: ${borderStyle};border-radius: 8px;`;
// 包裹内容
const wrappedContent = `<div style='${wrapperStyle}'>${content}</div>`;
// 返回处理后的标签
return `${startTag}${wrappedContent}${endTag}`;
});
return html;
},
//解析3d资源标识
modelToImg(htmlString) {
// 匹配<model3d>标签且class中包含model3d
const regex = /<model3d([^>]*?)class="([^"]*?)model3d([^"]*?)"([^>]*?)>/gi;
// 替换标签名,保留所有属性
return htmlString.replace(regex, '<img$1class="$2model3d$3"$4>');
},
/**
* 自动修复XML中的常见语法错误重点处理属性构造问题
* @param {string} xmlString - 包含错误的XML字符串
* @returns {Object} { fixedXml: 修复后的XML, errors: 修复过程中发现的错误 }
*/
fixXml(xmlString) {
if (typeof xmlString !== 'string') {
this.$emit('xml-error', '输入必须是字符串类型');
return { fixedXml: '', errors: ['输入必须是字符串类型'] };
}
let fixedXml = xmlString;
const errors = [];
try {
// 1. 修复属性构造错误 - 处理未闭合的引号和非法字符
fixedXml = this.fixAttributeIssues(fixedXml, errors);
// 2. 修复自闭合标签 - 将空的成对标签转换为自闭合标签
const emptyTagRegex = /<(\w+:[^\s>]+|\w+)(\s+[^>]*?)?>\s*<\/\1\s*>/g;
const emptyTagMatches = fixedXml.match(emptyTagRegex);
if (emptyTagMatches && emptyTagMatches.length) {
errors.push(`发现并修复了 ${emptyTagMatches.length} 个空成对标签`);
fixedXml = fixedXml.replace(emptyTagRegex, '<$1$2/>');
}
// 3. 修复常见的单标签错误
const selfClosingTags = ['br', 'img', 'input', 'audio', 'video', 'pbr'];
selfClosingTags.forEach(tag => {
const regex = new RegExp(`<(${tag})(\\s+[^>]*?)?>(\\s*</\\1\\s*>)?`, 'g');
const tagMatches = fixedXml.match(regex);
if (tagMatches && tagMatches.length) {
errors.push(`发现并修复了 ${tagMatches.length}${tag}标签`);
fixedXml = fixedXml.replace(regex, '<$1$2/>');
}
});
// 4. 修复dc命名空间的空标签
const dcTagsRegex = /<(dc:[^\s>]+)(\s+[^>]*?)?>\s*<\/\1\s*>/g;
const dcTagMatches = fixedXml.match(dcTagsRegex);
if (dcTagMatches && dcTagMatches.length) {
errors.push(`发现并修复了 ${dcTagMatches.length} 个dc命名空间标签`);
fixedXml = fixedXml.replace(dcTagsRegex, '<$1$2/>');
}
// 5. 修复表格相关的空标签
const tableTags = ['th', 'td'];
tableTags.forEach(tag => {
const regex = new RegExp(`<(${tag})(\\s+[^>]*?)?>(\\s*</\\1\\s*>)?`, 'g');
fixedXml = fixedXml.replace(regex, (match, tagName, attrs) => {
// 检查标签内是否有实际内容
const contentStart = match.indexOf(`<${tagName}`) + tagName.length + 1;
const contentEnd = match.indexOf(`</${tagName}>`);
const hasContent = contentEnd > contentStart &&
match.substring(contentStart, contentEnd).trim().length > 0;
if (!hasContent) {
errors.push(`修复了空的${tagName}标签`);
return `<${tagName}${attrs || ''}/>`;
}
return match;
});
});
// 6. 去除多余的闭合标签
const redundantClosingRegex = /<(\w+:[^\s>]+|\w+)(\s+[^>]*?)?\/>\s*<\/\1\s*>/g;
fixedXml = fixedXml.replace(redundantClosingRegex, '<$1$2/>');
// 验证修复结果
const validation = this.validateXml(fixedXml);
if (!validation.valid) {
errors.push(...validation.errors);
// 尝试定位错误位置
const lineNumber = validation.errors[0].match(/line (\d+)/);
if (lineNumber && lineNumber[1]) {
errors.push(`错误大致位置:第 ${lineNumber[1]}`);
// 提取错误行附近的内容帮助调试
const lines = fixedXml.split('\n');
const errorLineNum = parseInt(lineNumber[1]) - 1; // 转换为0基索引
if (lines[errorLineNum]) {
errors.push(`错误行内容:${lines[errorLineNum].substring(0, 100)}...`);
}
}
} else {
errors.push('XML修复成功格式验证通过');
}
return { fixedXml, errors };
} catch (err) {
this.$emit('xml-error', `修复过程出错: ${err.message}`);
return { fixedXml: xmlString, errors: [`修复过程出错: ${err.message}`] };
}
},
/**
* 专门修复属性构造错误
* @param {string} xmlString - XML字符串
* @param {Array} errors - 错误信息数组
* @returns {string} 修复后的XML字符串
*/
fixAttributeIssues(xmlString, errors) {
let fixed = xmlString;
// 1. 修复未闭合的属性引号
// 匹配模式:属性名="值但没有闭合引号
fixed = fixed.replace(/(\s\w+)=("|')([^"']*)(?=\s|>)/g, (match, attrName, quote, value) => {
errors.push(`修复了未闭合的${attrName}属性引号`);
return `${attrName}=${quote}${value}${quote}`;
});
// 2. 修复属性值中的非法字符
fixed = fixed.replace(/(\s\w+)=("|')([^"']*)(?=\s|>)/g, (match, attrName, quote, value) => {
// 替换属性值中的非法字符
const sanitizedValue = value
.replace(/&/g, '&amp;') // & 必须转义
.replace(/</g, '&lt;') // < 必须转义
.replace(/>/g, '&gt;') // > 必须转义
.replace(/"/g, '&quot;') // " 必须转义
.replace(/'/g, '&#39;'); // ' 必须转义
if (sanitizedValue !== value) {
errors.push(`修复了${attrName}属性中的非法字符`);
return `${attrName}=${quote}${sanitizedValue}${quote}`;
}
return match;
});
// 3. 修复重复的属性
fixed = fixed.replace(/<(\w+)(\s+[^>]+?)>/g, (match, tagName, attrsStr) => {
const attrs = {};
const attrRegex = /(\w+)=("|')([^"']*)\2/g;
let cleanedAttrs = '';
attrsStr.replace(attrRegex, (attrMatch, name, quote, value) => {
if (!attrs[name]) {
attrs[name] = true;
cleanedAttrs += ` ${name}=${quote}${value}${quote}`;
} else {
errors.push(`移除了${tagName}标签中重复的${name}属性`);
}
});
return `<${tagName}${cleanedAttrs}>`;
});
return fixed;
},
/**
* 验证XML是否合法
* @param {string} xmlString - 要验证的XML字符串
* @returns {Object} { valid: 是否有效, errors: 错误信息数组 }
*/
validateXml(xmlString) {
try {
const parser = new DOMParser();
const doc = parser.parseFromString(xmlString, 'text/xml');
const errorNode = doc.querySelector('parsererror');
if (errorNode) {
const errorText = errorNode.textContent || 'XML格式错误';
return { valid: false, errors: [errorText] };
}
return { valid: true, errors: [] };
} catch (err) {
return { valid: false, errors: [`验证出错: ${err.message}`] };
}
},
/**
* 定位并显示错误行内容,帮助调试
* @param {string} xmlString - XML字符串
* @param {number} lineNumber - 错误行号
* @returns {string} 错误行附近的内容
*/
showErrorLine(xmlString, lineNumber) {
const lines = xmlString.split('\n');
const start = Math.max(0, lineNumber - 2);
const end = Math.min(lines.length, lineNumber + 2);
let errorContext = `错误位置:第 ${lineNumber}\n`;
for (let i = start; i < end; i++) {
errorContext += `${i + 1}: ${lines[i] || ''}\n`;
}
return errorContext;
}
},
beforeDestroy() {
},
created() {
window.addEventListener('handreContent', (e) => {
if(e){
this.viewXml = e.detail;
if (this.viewLis.startsWith('"')) {
this.viewXml = this.viewXml.substring(1);
}
// 检查并去除结尾的双引号
if (this.viewXml.endsWith('"')) {
this.viewXml = this.viewXml.substring(0, this.viewXml.length - 1);
}
console.log("得到的0",this.viewXml)
this.parseRdfDescriptions(this.viewXml)
this.parseXmlDmc_loadFile();
}
})
window.addEventListener('handPrePath', (e) => {
console.log("返回handPrePath",e.detail)
if(e){
this.viewLis = e.detail;
}
})
window.addEventListener('handleMessageNotice', () => {
this.getNet();
})
}
};
</script>
<style>
/* 为表格添加边框 */
table {
border-collapse: collapse; /* 合并边框 */
width: 100%; /* 可选:设置表格宽度 */
}
/* 为表格单元格添加边框 */
table, th, td {
border: 1px solid #ddd; /* 灰色边框 */
}
/* 为表头添加背景色 */
th {
background-color: #f2f2f2;
padding: 8px; /* 单元格内边距 */
text-align: left; /* 文本左对齐 */
}
/* 为单元格添加内边距 */
td {
padding: 8px;
}
</style>

430
src/components/wangG3.vue Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,207 +0,0 @@
<template>
<div class="s1000d-container">
<button @click="exportToS1000D">导出为S1000D XML</button>
<div ref="editor"></div>
</div>
</template>
<script>
import E from 'wangeditor'
export default {
data() {
return {
editor: null,
content: '<p>这是初始内容</p>'
}
},
mounted() {
this.initEditor()
},
methods: {
initEditor() {
this.editor = new E(this.$refs.editor)
this.editor.config.onchange = (html) => {
this.content = html
}
this.editor.create()
this.editor.txt.html(this.content)
},
exportToS1000D() {
// 1. 获取富文本内容
const htmlContent = this.content || this.editor.txt.html()
// 2. 转换为S1000D XML结构
const s1000dXml = this.convertToS1000D(htmlContent)
// 3. 下载XML文件
this.downloadXML(s1000dXml, 's1000d-data-module.xml')
},
convertToS1000D(html) {
// 基本S1000D XML结构
return `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dmodule [
<!ENTITY % ISOEntities PUBLIC "ISO 8879-1986//ENTITIES ISO Character Entities 20030531//EN" "ISOEntities">
%ISOEntities;
]>
<dmodule xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.s1000d.org/S1000D_4-1/xml_schema_flat/descript.xsd">
<!-- 标识和状态部分 -->
<idstatus>
<dmaddress>
<dmc>
<avee>AVE</avee>
<modelic>MODEL</modelic>
<sdc>A</sdc>
<chapnum>00</chapnum>
<section>0</section>
<subsect>0</subsect>
<subject>SUB</subject>
<discode>DISC</discode>
<discodev>001</discodev>
<incode>INC</incode>
<incodev>001</incodev>
<itemloc>ITEM</itemloc>
</dmc>
<issue inwork="01" issno="001" type="new"/>
<language language-iso="zh-CN"/>
<dmtitle>
<techname>技术文档标题</techname>
<infoname>信息名称</infoname>
</dmtitle>
</dmaddress>
</idstatus>
<!-- 内容部分 -->
<content>
<description>
${this.htmlToS1000D(html)}
</description>
</content>
</dmodule>`
},
// 将HTML转换为S1000D兼容的XML
htmlToS1000D(html) {
// 创建临时div来解析HTML
const tempDiv = document.createElement('div')
tempDiv.innerHTML = html
// 递归处理DOM节点
const processNode = (node) => {
if (node.nodeType === Node.TEXT_NODE) {
return this.escapeXml(node.textContent)
}
if (node.nodeType !== Node.ELEMENT_NODE) return ''
const tag = node.tagName.toLowerCase()
const children = Array.from(node.childNodes).map(processNode).join('')
const attrs = Array.from(node.attributes)
.map(attr => ` ${attr.name}="${this.escapeXml(attr.value)}"`)
.join('')
// 将HTML标签映射到S1000D元素
switch(tag) {
case 'p':
return `<para${attrs}>${children}</para>`
case 'b':
case 'strong':
return `<emphasis role="bold">${children}</emphasis>`
case 'i':
case 'em':
return `<emphasis role="italic">${children}</emphasis>`
case 'u':
return `<emphasis role="underline">${children}</emphasis>`
case 'ol':
return `<orderedlist${attrs}>${children}</orderedlist>`
case 'ul':
return `<itemizedlist${attrs}>${children}</itemizedlist>`
case 'li':
return `<listitem>${children}</listitem>`
case 'img': {
const figureId = `FIG_${Date.now()}`
return `<figure><graphic infoentityid="${figureId}"${attrs}/></figure>`
}
case 'table':
return `<table${attrs}>${children}</table>`
case 'tr':
return `<row>${children}</row>`
case 'td':
return `<entry>${children}</entry>`
case 'th':
return `<entry thead="yes">${children}</entry>`
case 'h1':
case 'h2':
case 'h3':
case 'h4':
case 'h5':
case 'h6': {
const level = parseInt(tag.substring(1))
return `<title level="${level}">${children}</title>`
}
case 'a':
return `<xref xrefid="${node.getAttribute('href') || ''}">${children}</xref>`
default:
return children // 忽略不支持的标签但保留内容
}
}
return Array.from(tempDiv.childNodes).map(processNode).join('')
},
// XML特殊字符转义
escapeXml(text) {
return text
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&apos;')
},
// 下载XML文件
downloadXML(xmlString, fileName) {
const blob = new Blob([xmlString], { type: 'application/xml' })
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = fileName
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
URL.revokeObjectURL(link.href)
}
},
beforeDestroy() {
if (this.editor) {
this.editor.destroy()
}
}
}
</script>
<style>
.s1000d-container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
button {
padding: 8px 16px;
background: #0066cc;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin-bottom: 20px;
}
button:hover {
background: #0052a3;
}
</style>

View File

@@ -0,0 +1,88 @@
export default {
bind(el) {
// 获取对话框头部和主体元素
const dialogHeaderEl = el.querySelector('.el-dialog__header');
const dragDom = el.querySelector('.el-dialog');
if (!dialogHeaderEl || !dragDom) {
console.warn('未找到对话框头部或主体元素,拖拽功能无法启用');
return;
}
// 设置头部元素可拖动样式
dialogHeaderEl.style.cursor = 'move';
// 初始化对话框位置关键消除默认margin居中的影响
const initPosition = () => {
// 如果是首次加载且未设置过left/top强制计算初始位置
if (!dragDom.style.left || !dragDom.style.top) {
// 获取视口和对话框尺寸
const viewWidth = window.innerWidth;
const viewHeight = window.innerHeight;
const dialogWidth = dragDom.offsetWidth;
const dialogHeight = dragDom.offsetHeight;
// 计算居中位置替代默认的margin居中
const initLeft = (viewWidth - dialogWidth) / 2;
const initTop = Math.max(50, (viewHeight - dialogHeight) / 3); // 稍微靠上一点
// 应用初始位置同时清除默认margin
dragDom.style.left = `${initLeft}px`;
dragDom.style.top = `${initTop}px`;
dragDom.style.margin = '0'; // 关键移除默认margin
}
};
// 初始化位置
initPosition();
// 鼠标按下事件
dialogHeaderEl.onmousedown = (e) => {
// 防止拖动时选中文本
e.preventDefault();
// 获取鼠标在对话框头部的相对位置关键使用getBoundingClientRect计算绝对位置
const dialogRect = dragDom.getBoundingClientRect();
const disX = e.clientX - dialogRect.left;
const disY = e.clientY - dialogRect.top;
// 鼠标移动事件
const handleMouseMove = (moveE) => {
moveE.preventDefault();
// 计算新位置(基于视口的绝对位置)
const newLeft = moveE.clientX - disX;
const newTop = moveE.clientY - disY;
// 限制在视口内
const maxLeft = window.innerWidth - dragDom.offsetWidth;
const maxTop = window.innerHeight - dragDom.offsetHeight;
// 应用新位置
dragDom.style.left = `${Math.max(0, Math.min(newLeft, maxLeft))}px`;
dragDom.style.top = `${Math.max(0, Math.min(newTop, maxTop))}px`;
};
// 鼠标释放事件
const handleMouseUp = () => {
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
};
// 绑定事件
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
};
// 窗口大小改变时重新居中
window.addEventListener('resize', () => {
// 只有在未被拖拽过的情况下才重新居中
if (!dragDom.dataset.dragged) {
initPosition();
}
});
// 标记是否被拖拽过
dragDom.dataset.dragged = 'false';
}
};

213
src/main - 副本.js Normal file
View File

@@ -0,0 +1,213 @@
import Vue from 'vue'
import App from './App.vue'
import axios from 'axios';
import router from './router' // 引入路由配置
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
// 导入拖拽指令
import draggable from './directives/draggable';
// 全局注册指令
Vue.directive('draggable', draggable);
Vue.use(ElementUI);
Vue.prototype.$axios = axios;
Vue.config.productionTip = false
// axios.defaults.baseURL = 'http://localhost:3000';
axios.defaults.baseURL = 'http://192.168.31.181:3000';
// axios.defaults.baseURL = 'https://api.example.com';
// 可以在此处配置请求头、超时等
axios.defaults.headers.common['Authorization'] = 'Bearer token';
axios.defaults.timeout = 10000;
window.handleMessageFromDotNet = function(msg) {//窗口界面测试传递
Vue.prototype.$dotNetMessage = msg
// 可以触发全局事件
const event = new CustomEvent('dotnet-message', { detail: msg })
window.dispatchEvent(event)
}
window.SelectFilePathSend = function(msg) {//接收后端返回路径
Vue.prototype.$dotNetMessage = msg
// 可以触发全局事件
// console.log("MAIN SelectFilePathSend",msg)
const event = new CustomEvent('SelectFilePathSend', { detail: msg })
window.dispatchEvent(event)
}
// window.frontLoadProject = function(msg) {//接收后端返回路径
// Vue.prototype.$dotNetMessage = msg
// // 可以触发全局事件
// console.log("MAIN FrontLoadProject 2222",msg)
// const event = new CustomEvent('frontLoadProject', { detail: msg })
// window.dispatchEvent(event)
// }
// window.FrontLoadProject = function(msg) {//接收后端返回路径
// Vue.prototype.$dotNetMessage = msg
// // 可以触发全局事件
// // console.log("MAIN FrontLoadProject 2222",msg)
// const event = new CustomEvent('FrontLoadProject', { detail: msg })
// window.dispatchEvent(event)
// }
let funAll = ['FrontLoadProject'];
for(let i =0;i<funAll.length;i++){
window[funAll[i]] = function(msg) {//接收后端返回路径
Vue.prototype.$dotNetMessage = msg
// 可以触发全局事件
// console.log("MAIN FrontLoadProject 2222",msg)
const event = new CustomEvent(funAll[i], { detail: msg })
window.dispatchEvent(event)
}
}
window.aaa = function(msg) {//接收后端返回路径
Vue.prototype.$dotNetMessage = msg
// 可以触发全局事件
// console.log("MAIN FrontLoadProject 2222",msg)
const event = new CustomEvent('aaa', { detail: msg })
window.dispatchEvent(event)
}
window.FrontLoadDM = function(msg) {//接收后端返回路径
Vue.prototype.$dotNetMessage = msg
// 可以触发全局事件
// console.log("MAIN FrontLoadDM",msg)
const event = new CustomEvent('FrontLoadDM', { detail: msg })
window.dispatchEvent(event)
}
window.GetDMDta = function(msg) {//接收后端返回路径
Vue.prototype.$dotNetMessage = msg
// 可以触发全局事件
// console.log("MAIN GetDMDta",msg)
const event = new CustomEvent('GetDMDta', { detail: msg })
window.dispatchEvent(event)
}
window.SendResourcePath = function(msg) {//接收后端返回路径
Vue.prototype.$dotNetMessage = msg
// 可以触发全局事件
// console.log("MAIN SendResourcePath",msg)
const event = new CustomEvent('SendResourcePath', { detail: msg })
window.dispatchEvent(event)
}
window.SendLisentPath = function(msg) {//接收后端返回路径
Vue.prototype.$dotNetMessage = msg
console.log("监听")
const event = new CustomEvent('SendLisentPath', { detail: msg })
window.dispatchEvent(event)
}
window.SendProjectName = function(msg) {//接收后端返回路径
Vue.prototype.$dotNetMessage = msg
// 可以触发全局事件
// console.log("MAIN SendProjectName",msg)
const event = new CustomEvent('SendProjectName', { detail: msg })
window.dispatchEvent(event)
}
window.SendNewVersionDMFileName = function(msg) {//接收后端返回路径
Vue.prototype.$dotNetMessage = msg
// 可以触发全局事件
// console.log("MAIN SendNewVersionDMFileName",msg)
const event = new CustomEvent('SendNewVersionDMFileName', { detail: msg })
window.dispatchEvent(event)
}
window.GetHistoryVesions = function(msg) {//接收后端返回路径
Vue.prototype.$dotNetMessage = msg
// 可以触发全局事件
// console.log("MAIN GetHistoryVesions",msg)
const event = new CustomEvent('GetHistoryVesions', { detail: msg })
window.dispatchEvent(event)
}
window.GetDMHistoryContent = function(msg) {//接收后端返回路径
Vue.prototype.$dotNetMessage = msg
// 可以触发全局事件
// console.log("MAIN GetDMHistoryContent",msg)
const event = new CustomEvent('GetDMHistoryContent', { detail: msg })
window.dispatchEvent(event)
}
window.GetHistoryDMContent = function(msg) {//接收后端返回路径
Vue.prototype.$dotNetMessage = msg
// 可以触发全局事件
// console.log("MAIN GetHistoryDMContent",msg)
const event = new CustomEvent('GetHistoryDMContent', { detail: msg })
window.dispatchEvent(event)
}
window.GetExistenceDMContent = function(msg) {
Vue.prototype.$dotNetMessage = msg
const event = new CustomEvent('GetExistenceDMContent', { detail: msg })
window.dispatchEvent(event)
}
window.handPrePath = function(msg) {
Vue.prototype.$dotNetMessage = msg
const event = new CustomEvent('handPrePath1', { detail: msg })
window.dispatchEvent(event)
}
window.handreContent = function(msg) {//接收后端返回路径
Vue.prototype.$dotNetMessage = msg
// 可以触发全局事件
// console.log("MAIN handreContent",msg)
const event = new CustomEvent('handreContent1', { detail: msg })
window.dispatchEvent(event)
}
export const sendToDotNet = (type, payload,id,content,lagreVersion) => {//和后端进行通讯
if (!window.chrome?.webview?.postMessage) {
console.error('WebView2 环境未就绪!当前环境:', window.chrome ? '有chrome对象' : '无chrome对象');
return;
}
// const message = JSON.stringify(type, payload)
// console.log("开始给C#发送的信息",message)
console.log('接收到的参数:', { type, payload, id, content,lagreVersion });
let message = {
// GetFilePath、SaveFile 取,存。
// LoadDM 加载DM 富文本。
// DragMaterial 拖拽时候告诉后端
// 当Type为SaveFile时
// Data1为类型PMC或者DMC 目录PMC,富文本DMC
// Data2为文件编号、
// Data3为文件内容
'Type':type||'',// AddSource
'Data1':payload||'',
'Data2':id||'',
'Data3':content||'',
'Data4':lagreVersion||'',
'Data5':'',
'Data6':'',
}
console.log("传参",message,JSON.stringify(message))
window.chrome.webview.postMessage(message)
}
Vue.prototype.$sendToDotNet = sendToDotNet
new Vue({
router, // 注册路由
render: h => h(App),
}).$mount('#app')

60
src/main copy.js Normal file
View File

@@ -0,0 +1,60 @@
import Vue from 'vue'
import App from './App.vue'
import axios from 'axios';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
Vue.prototype.$axios = axios;
Vue.config.productionTip = false
// axios.defaults.baseURL = 'http://localhost:3000';
axios.defaults.baseURL = 'http://192.168.31.181:3000';
// axios.defaults.baseURL = 'https://api.example.com';
// 可以在此处配置请求头、超时等
axios.defaults.headers.common['Authorization'] = 'Bearer token';
axios.defaults.timeout = 10000;
window.handleMessageFromDotNet = function(msg) {
Vue.prototype.$dotNetMessage = msg
// 可以触发全局事件
console.log("MAIN收到信息",msg)
const event = new CustomEvent('dotnet-message', { detail: msg })
window.dispatchEvent(event)
}
export const sendToDotNet = (type, payload) => {
if (!window.chrome?.webview?.postMessage) {
console.error('WebView2 环境未就绪!当前环境:', window.chrome ? '有chrome对象' : '无chrome对象');
return;
}
// const message = JSON.stringify(type, payload)
// console.log("开始给C#发送的信息",message)
let message = {
// 'Type':'',
'Payload':payload
}
console.log("传参",message,JSON.stringify(message))
window.chrome.webview.postMessage(message)
// if (window.chrome?.webview?.postMessage) {
// const message = JSON.stringify({ type, payload })
// console.log("开始给C#发送的信息",message)
// window.chrome.webview.postMessage(message)
// } else {
// console.warn('WebView2环境未就绪')
// // 可选:开发环境模拟
// if (process.env.NODE_ENV === 'development') {
// console.log('[模拟发送]', { type, payload })
// }
// }
}
Vue.prototype.$sendToDotNet = sendToDotNet
new Vue({
render: h => h(App),
}).$mount('#app')

View File

@@ -42,7 +42,8 @@ let funAll = [
'handPrePath',
'handreContent',
'SelectFilePathSend',
'handleMessageFromDotNet'
'handleMessageFromDotNet',
'handleMessageNotice',
];
for(let i =0;i<funAll.length;i++){
window[funAll[i]] = function(msg) {//接收后端返回路径
@@ -57,7 +58,7 @@ for(let i =0;i<funAll.length;i++){
window.FrontLoadProject = function(msg) {//接收后端返回路径
Vue.prototype.$dotNetMessage = msg
// 可以触发全局事件
console.log("MAIN FrontLoadProject 2222",msg)
// console.log("MAIN FrontLoadProject 2222",msg)
const event = new CustomEvent('FrontLoadProjectNew', { detail: msg })
window.dispatchEvent(event)
}
@@ -69,7 +70,7 @@ export const sendToDotNet = (type, payload,id,content,lagreVersion) => {//和后
}
// const message = JSON.stringify(type, payload)
// console.log("开始给C#发送的信息",message)
console.log('接收到的参数:', { type, payload, id, content,lagreVersion });
// console.log('接收到的参数:', { type, payload, id, content,lagreVersion });
let message = {
// GetFilePath、SaveFile 取,存。
// LoadDM 加载DM 富文本。

60
src/router/index.js Normal file
View File

@@ -0,0 +1,60 @@
// 引入依赖
import Vue from 'vue'
import VueRouter from 'vue-router'
// 确保组件路径和文件名正确
import Wang from '@/components/wang.vue'
import WangG2 from '@/components/wangG2.vue' // 注意组件文件名是否正确
// import WangG3 from '@/components/wangYZ3.vue' // 注意组件文件名是否正确
import WangG3 from '@/components/wangG3.vue' // 注意组件文件名是否正确
import WangG4 from '@/components/wangG4.vue' // 注意组件文件名是否正确
// import WangG3 from '@/components/wangYZ2.vue' // 注意组件文件名是否正确
// 注册路由
Vue.use(VueRouter)
// 路由规则
const routes = [
{
path: '/',
redirect: '/wang'
},
{
path: '/wang',
name: 'Wang',
component: Wang
},
{
path: '/wangG2', // 路径必须与router-link的to属性完全一致
name: 'WangG2',
component: WangG2 // 确保组件正确引入
},
{
path: '/WangG3',
name: 'WangG3',
component: WangG3
},
{
path: '/WangG4',
name: 'WangG4',
component: WangG4
},
{
path: '*',
redirect: '/wang' // 未匹配的路径重定向到首页
}
]
const router = new VueRouter({
// mode: 'history',
base: process.env.BASE_URL,
routes
})
// 调试用:路由跳转时打印信息
router.afterEach((to, from) => {
console.log('路由跳转:', from.path, '->', to.path)
console.log('对应的组件:', to.matched[0]?.components.default?.name)
})
export default router