Files
IETM-web/src/components/wang.vue

5298 lines
184 KiB
Vue
Raw Normal View History

2025-07-25 13:28:47 +08:00
<template>
2025-10-17 08:28:46 +08:00
<div style="height:100%;width:100%;">
<el-container style="height:100%;width:100%;">
<el-aside
:width="leftWidth + 'px'"
style="position: relative; overflow: hidden;"
>
<div class="drag-handle" @mousedown="startDrag"></div>
<div class="leftDiv" v-if='isLoadXml' style="width:100%;" >
2025-09-15 09:58:52 +08:00
<div id='navMain'>
<!-- 操作栏 -->
<div class="operation-buttons">
<!-- 节点搜索框 -->
2025-10-17 08:28:46 +08:00
<div style="margin:5px auto;width:100%;">
2025-09-15 09:58:52 +08:00
<el-input
placeholder="输入节点名称搜索"
v-model="searchText"
class="search-input"
clearable
@clear="handleSearchClear"
@keyup.enter="handleSearch">
<el-button slot="append" icon="el-icon-search" @click="handleSearch"></el-button>
</el-input>
</div>
<!-- 操作栏按钮 -->
2025-10-11 11:08:42 +08:00
<div style="display:flex;margin-bottom: 5px;">
<div style="width:25%;height:30px;" class="iconImgDiv" @click="showAddDialog('create')" title='新建' v-if='isLoadXml'><img class='iconImg' title='新建' src="../assets/img/addIcon.png" alt=""></div>
<div style="width:25%;height:30px;" class="iconImgDiv" @click="showAddDialog('edit')" title='编辑' v-if='currentNode'><img class='iconImg' title='编辑' src="../assets/img/editIcon.png" alt=""></div>
<div style="width:25%;height:30px;" class="iconImgDiv" @click="saveNowDmcClick" title='保存' v-if='currentNode' ><img class='iconImg' title='保存' src="../assets/img/saveIcon.png" alt=""></div>
<div style="width:25%;height:30px;" class="iconImgDiv" @click="deleteDialog" title='删除' v-if='currentNode'><img class='iconImg' title='删除' src="../assets/img/delIcon.png" alt=""></div>
</div>
2025-09-15 09:58:52 +08:00
</div>
2025-10-11 11:08:42 +08:00
<!-- 'maxHeight':leftHeight+'px', -->
<div class="tree-container" :style="{'minHeight':'100px'}">
<div class="navTitle" >
<p @click='clearNodeState' :title="getBookName">{{getBookName}}</p>
<img @click='editBookName' class='iconImgMulu' title='编辑书名' src="../assets/img/bianji.png" alt="">
</div>
2025-10-17 08:28:46 +08:00
<el-scrollbar style="">
<!-- 滚动内容区域 -->
<div class="scroll-content">
<!-- 目录结构树 -->
2025-10-11 11:08:42 +08:00
<el-tree
class="elTree elTreeMain gd"
2025-09-15 09:58:52 +08:00
ref="tree"
:data="treeData"
node-key="id"
icon-class="el-icon-arrow-right"
:default-expand-all="true"
:props="defaultProps"
2025-10-11 11:08:42 +08:00
:filter-node-method="filterNode"
@node-click="handleNodeClick"
@node-drag-end="handleDragEnd"
@node-contextmenu="handleNodeContextMenu"
:expand-on-click-node="false"
:highlight-current="true"
draggable
2025-09-15 09:58:52 +08:00
>
2025-10-11 11:08:42 +08:00
<!-- 节点自定义渲染插槽 -->
<span slot-scope="{ data }">
<!-- 1原有节点图标+名称渲染逻辑 -->
<template v-if="data.children && data.children.length > 0">
<!-- 父节点有子节点 -->
<div>
<i class="el-icon-folder" :style="'font-size: 14px; padding: 0 5px 0 5px'"/>
<i class="el-icon-warning changeState" @click.stop="handleModify(data)" v-if="showModifyBtn && hasMinorVersion01(data)" :style="'font-size: 14px; padding: 0 5px 0 5px'"/>
<span :title="data.id + '-' + data.name" :class="{ 'highlight': isHighlight(data) }">
{{ data.name }}
</span>
<!-- 关键条件显示修改检查状态开启 + 当前节点/子节点有minorVersion:01 -->
<!-- <span
class="modify-btn"
v-if="showModifyBtn && hasMinorVersion01(data)"
@click.stop="handleModify(data)"
>
修改
</span> -->
</div>
</template>
<template v-else>
<!-- 叶子节点无子节点 -->
<div style="margin-left: 0px;">
<i class="leaf-node-line"></i>
<i class="el-icon-document" :style="'padding: 0 5px 0 5px'"></i>
<!-- <svg viewBox="64 64 896 896" data-icon="deployment-unit" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">
<path d="M888.3 693.2c-42.5-24.6-94.3-18-129.2 12.8l-53-30.7V523.6c0-15.7-8.4-30.3-22-38.1l-136-78.3v-67.1c44.2-15 76-56.8 76-106.1 0-61.9-50.1-112-112-112s-112 50.1-112 112c0 49.3 31.8 91.1 76 106.1v67.1l-136 78.3c-13.6 7.8-22 22.4-22 38.1v151.6l-53 30.7c-34.9-30.8-86.8-37.4-129.2-12.8-53.5 31-71.7 99.4-41 152.9 30.8 53.5 98.9 71.9 152.2 41 42.5-24.6 62.7-73 53.6-118.8l48.7-28.3 140.6 81c6.8 3.9 14.4 5.9 22 5.9s15.2-2 22-5.9L674.5 740l48.7 28.3c-9.1 45.7 11.2 94.2 53.6 118.8 53.3 30.9 121.5 12.6 152.2-41 30.8-53.6 12.6-122-40.7-152.9zm-673 138.4a47.6 47.6 0 0 1-65.2-17.6c-13.2-22.9-5.4-52.3 17.5-65.5a47.6 47.6 0 0 1 65.2 17.6c13.2 22.9 5.4 52.3-17.5 65.5zM522 463.8zM464 234a48.01 48.01 0 0 1 96 0 48.01 48.01 0 0 1-96 0zm170 446.2l-122 70.3-122-70.3V539.8l122-70.3 122 70.3v140.4zm239.9 133.9c-13.2 22.9-42.4 30.8-65.2 17.6-22.8-13.2-30.7-42.6-17.5-65.5s42.4-30.8 65.2-17.6c22.9 13.2 30.7 42.5 17.5 65.5z"></path>
</svg> -->
<!-- <i :style="'font-size: 13px; padding: 0 5px 0 5px'">
</i> -->
<i class="el-icon-warning changeState" @click.stop="handleModify(data)" v-if="showModifyBtn && hasMinorVersion01(data)" :style="'font-size: 14px; padding: 0 5px 0 5px'"/>
<span :title="data.id + '-' + data.name" :class="{ 'highlight': isHighlight(data) }">
{{ data.name }}
2025-10-17 08:28:46 +08:00
</span>
2025-10-11 11:08:42 +08:00
</div>
</template>
2025-09-15 09:58:52 +08:00
</span>
2025-10-11 11:08:42 +08:00
</el-tree>
2025-10-17 08:28:46 +08:00
</div>
</el-scrollbar>
2025-09-15 09:58:52 +08:00
</div>
</div>
<!-- <div id='nav'>
<nav-temp />
</div> -->
</div>
2025-10-17 08:28:46 +08:00
</el-aside>
<el-main style="">
<div class="rightDiv">
2025-10-11 11:08:42 +08:00
<div class="bName" :title="getBookName">{{getBookName}}</div>
<!-- 编辑框 -->
<!-- :style="{height:editorHeight+'px'}" -->
2025-10-17 08:28:46 +08:00
<!-- <el-button
type="primary"
icon="el-icon-s-data"
@click="countDomNodes"
style="margin: 5px;"
>
统计DOM节点数量
</el-button> -->
2025-10-11 11:08:42 +08:00
<!-- :class="{ editor2Opacity: dialogVisibleNav||dialogVisibleNavDel|| dialogVisible||dialogVisibleImg||dialogVisibleRight||dialogVisibleTips||dialogVisibleBland||dialogVisibleHistory||dialogVisibleTips2||editBookNameDialog }" -->
<div id="editor" v-show='currentNode' :class="{ editor2Opacity: dialogVisibleNav||dialogVisibleNavDel|| dialogVisible||dialogVisibleImg||dialogVisibleRight||dialogVisibleTips||dialogVisibleBland||dialogVisibleHistory||dialogVisibleTips2||editBookNameDialog }" ref="editor" ></div>
<!-- 提示信息 -->
<!-- <div class="paAutoStyle" v-show="!currentNode && isLoadXml">请打开所要编辑的的章节目录</div>
<div class="paAutoStyle" v-show="!isLoadXml">请加载所要编辑的文档目录</div> -->
2025-09-15 09:58:52 +08:00
</div>
2025-10-17 08:28:46 +08:00
</el-main>
</el-container>
<div class="paAuto paAutoStyle" v-show="!isLoadMsg">请加载有需编辑的项目</div>
2025-10-11 11:08:42 +08:00
2025-09-15 09:58:52 +08:00
2025-10-17 08:28:46 +08:00
<!-- 统计结果弹窗 -->
<el-dialog
title="DOM节点统计结果"
:visible.sync="countDialogVisible"
width="40%"
>
<div class="statistics-result">
<p>目标容器: {{ countTarget }}</p>
<p>总DOM节点数量: <span class="count-number">{{ domCount }}</span></p>
<p>元素节点数量: <span class="count-number">{{ elementCount }}</span></p>
<p>文本节点数量: <span class="count-number">{{ textCount }}</span></p>
<p>注释节点数量: <span class="count-number">{{ commentCount }}</span></p>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="countDialogVisible = false">关闭</el-button>
</span>
</el-dialog>
2025-10-11 11:08:42 +08:00
<!-- 历史弹窗 -->
2025-09-15 09:58:52 +08:00
<el-dialog
title="历史版本"
:visible.sync="dialogVisibleHistory"
width='80%'
class="custom-dialog"
:before-close="handleClose">
<div class="attribute-selection" v-if='historyData'>
<div class='zyBox' style="text-align: left;" v-for="(item,index) in historyData" :key="index">
<p>版本名称{{item.Name}}</p>
<p>修改时间{{timeChange(item.CreationTime)}}</p>
<p>文件路径{{item.Path}}</p>
<el-button @click='lookHistoryFile(item.Path)'>查看历史版本</el-button>
2025-07-28 17:01:13 +08:00
</div>
2025-09-15 09:58:52 +08:00
</div>
<div class="attribute-selection" v-if='historyData.length == 0'>
暂无历史版本
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisibleHistory = false">关闭</el-button>
<!-- <el-button type="primary" @click="catalogueAnalysis(treeData)">选择绑定资源</el-button> -->
</span>
</el-dialog>
2025-10-11 11:08:42 +08:00
<!-- 绑定资源弹窗 -->
2025-09-15 09:58:52 +08:00
<el-dialog
title="绑定资源"
class="custom-dialog"
:visible.sync="dialogVisibleBland"
width="50%"
:before-close="handleClose">
<div class="attribute-selection" v-if="currentNode&&currentNode.attributes.length > 0">
<p>已绑资源</p>
<!-- 属性展示区域 -->
<div v-if='currentNode' class='bindMain'>
<div class="zyBox" v-for="(item,index) in currentNode.attributes" :key="index">
<p>{{item}}</p>
<el-button type="danger" size="mini" @click="deleteAttr(item,index)" :disabled="!currentNode">删除</el-button>
</div>
</div>
</div>
<div v-else>暂未绑定资源</div>
<span slot="footer" class="dialog-footer">
<el-button @click='saveAttributes'>选择绑定资源</el-button>
<el-button @click="dialogVisibleBland = false">关闭</el-button>
<!-- <el-button type="primary" @click="catalogueAnalysis(treeData)">选择绑定资源</el-button> -->
</span>
2025-10-11 11:08:42 +08:00
</el-dialog>
2025-09-15 09:58:52 +08:00
2025-10-11 11:08:42 +08:00
2025-09-15 09:58:52 +08:00
2025-10-11 11:08:42 +08:00
<!-- 新建编辑目录弹窗 -->
2025-09-15 09:58:52 +08:00
<el-dialog
2025-10-11 11:08:42 +08:00
:title="navIsAdd=='create'?'新建章节':'编辑章节'"
2025-09-15 09:58:52 +08:00
:visible.sync="dialogVisibleNav"
width="80%"
class="custom-dialog"
:before-close="handleClose"
>
2025-10-11 11:08:42 +08:00
<el-form label-position="left" label-width="120px" :model="form" :rules="rules" ref="form">
<!-- 按钮区域 -->
<div style="margin-bottom: 15px;">
<el-button type="info" icon="el-icon-folder-opened" v-if='navIsAdd == "create"' @click="loadFileBtn">加载文件</el-button>
<el-button type="info" icon="el-icon-data-analysis" v-if='showView' @click="viewLoadDMFile">预览文件</el-button>
</div>
<!-- 两列布局容器 -->
<el-row :gutter="20">
<!-- 第一列 -->
<el-col :span="24">
<div class="colStyle colStyle1">
<img title='章节名称' src="../assets/img/wenjian.png" >
<span>章节名称</span>
</div>
<el-input v-model="form.name" autocomplete="off"></el-input>
</el-col>
<!-- 第二列 -->
<el-col :span="12">
<div class="colStyle">
<img title='责任合作单位' src="../assets/img/danwei.png" >
<span>责任合作单位</span>
</div>
<el-input v-model="form.contributor" autocomplete="off"></el-input>
</el-col>
<!-- 第一列 -->
<el-col :span="12">
<div class="colStyle">
<img title='创作单位' src="../assets/img/hezuodanwei.png" >
<span>创作单位</span>
</div>
<el-input v-model="form.creator" autocomplete="off"></el-input>
</el-col>
<!-- 第二列 -->
<el-col :span="12">
<div class="colStyle">
<img title='适用性信息' src="../assets/img/xinxi.png" >
<span>适用性信息</span>
</div>
<el-input v-model="form.applicabilityInformation" autocomplete="off"></el-input>
</el-col>
<!-- 第一列 -->
<el-col :span="12">
<div class="colStyle">
<img title='质量验证' src="../assets/img/xinxi.png" >
<span>质量验证</span>
</div>
<el-input v-model="form.qualityVerification" autocomplete="off"></el-input>
</el-col>
<!-- 第二列 -->
<el-col :span="12">
<div class="colStyle">
<img title='权限' src="../assets/img/quanxian.png" >
<span>权限</span>
</div>
<!-- <el-input v-model="form.permission" autocomplete="off"></el-input> -->
<el-select v-model="form.permission" style="width:100%;" placeholder="请选择">
<el-option
v-for="item in optionsPermission"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-col>
<!-- 第一列 -->
<el-col :span="12">
<div class="colStyle">
<img title='版本信息' src="../assets/img/jurassic_version.png" >
<span>版本信息</span>
</div>
<el-input v-model="form.version" disabled autocomplete="off"></el-input>
</el-col>
<!-- 第二列 -->
<el-col :span="12">
<div class="colStyle">
<img title='发布时间' src="../assets/img/fabushijian.png" >
<span>发布时间</span>
</div>
<el-date-picker
style="width:100%;"
v-model="form.date"
type="date"
placeholder="选择日期">
</el-date-picker>
<!-- <el-input v-model="form.date" autocomplete="off"></el-input> -->
</el-col>
<!-- 第一列 -->
<el-col :span="12">
<div class="colStyle">
<img title='语言' src="../assets/img/duoyuyan.png" >
<span>语言</span>
</div>
<el-input v-model="form.language" autocomplete="off"></el-input>
</el-col>
<!-- 第二列 -->
<el-col :span="12">
<div class="colStyle">
<img title='密级' src="../assets/img/miji.png" >
<span>密级</span>
</div>
<el-select v-model="form.level" style="width:100%;" placeholder="请选择">
<el-option
v-for="item in optionsLevel"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<!-- <el-input v-model="form.level" autocomplete="off"></el-input> -->
</el-col>
<!-- 单独占满一行的表单项 -->
<el-col :span="12" v-if='showView'>
<div class="colStyle">
<img title='使用加载数据' src="../assets/img/xinxi.png" >
<span>使用加载数据</span>
</div>
<div>
<el-select v-model="isLoadOldDmc" style="width:100%;" placeholder="请选择">
<el-option
v-for="item in options2"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<!-- <el-radio v-model="isLoadOldDmc" label="1">使用</el-radio> -->
<!-- <el-radio v-model="isLoadOldDmc" label="2">不使用</el-radio> -->
</div>
</el-col>
</el-row>
</el-form>
<span slot="footer" class="dialog-footer">
2025-09-15 09:58:52 +08:00
<el-button @click="dialogVisibleNav = false"> </el-button>
2025-10-11 11:08:42 +08:00
<el-button type="primary" v-if='navIsAdd == "create"&&isLoadOldDmc == "1"' @click="confirmAdd(false)"> </el-button>
<el-button v-if='navIsAdd == "create"&&isLoadOldDmc == "2"' type="primary" @click="confirmAdd(true)"> </el-button>
<el-button v-if='navIsAdd == "edit"' type="primary" @click="confirmEdit()"> </el-button>
2025-09-15 09:58:52 +08:00
</span>
</el-dialog>
2025-10-11 11:08:42 +08:00
<!-- 删除目录确认弹窗 -->
2025-09-15 09:58:52 +08:00
<el-dialog
title="删除章节"
:visible.sync="dialogVisibleNavDel"
2025-10-11 11:08:42 +08:00
width="50%"
2025-09-15 09:58:52 +08:00
class="custom-dialog"
>
<div>
是否确定删除{{currentNode?currentNode.name:''}}?
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisibleNavDel = false"> </el-button>
<el-button type="primary" @click="deleteNode"> </el-button>
</span>
</el-dialog>
2025-10-11 11:08:42 +08:00
<!-- 删除资源确认弹窗 -->
2025-09-15 09:58:52 +08:00
<el-dialog
title="删除资源"
:visible.sync="dialogVisibleAttrDel"
2025-10-11 11:08:42 +08:00
width="50%"
2025-09-15 09:58:52 +08:00
class="custom-dialog"
>
<div>
是否确定删除{{nowAttr.name}}的绑定?
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisibleAttrDel = false"> </el-button>
<el-button type="primary" @click="deleteAttrSure"> </el-button>
</span>
</el-dialog>
2025-10-11 11:08:42 +08:00
<!--操作目录时候未保存提示 -->
2025-09-15 09:58:52 +08:00
<el-dialog
title="提示"
:visible.sync="dialogVisibleTips"
2025-10-11 11:08:42 +08:00
width="50%"
2025-09-15 09:58:52 +08:00
class="custom-dialog"
:before-close="handleClose2">
2025-10-11 11:08:42 +08:00
<span>是否保存当前编辑内容</span>
2025-09-15 09:58:52 +08:00
<span slot="footer" class="dialog-footer">
<el-button @click="saveNowDmc('noSave')">不保存</el-button>
<el-button type="primary" @click="saveNowDmc('save')">保存</el-button>
</span>
</el-dialog>
2025-10-11 11:08:42 +08:00
<!-- 切换目录时候未保存提示 -->
2025-09-15 09:58:52 +08:00
<el-dialog
2025-10-17 08:28:46 +08:00
title="提 示"
2025-09-15 09:58:52 +08:00
:visible.sync="dialogVisibleTips2"
2025-10-11 11:08:42 +08:00
width="50%"
2025-09-15 09:58:52 +08:00
class="custom-dialog"
:before-close="saveNowDmc2">
2025-10-11 11:08:42 +08:00
<span>是否保存当前编辑内容</span>
2025-09-15 09:58:52 +08:00
<span slot="footer" class="dialog-footer">
<el-button @click="saveNowDmc2('noSave')">不保存</el-button>
<el-button type="primary" @click="saveNowDmc2('save')">保存</el-button>
</span>
</el-dialog>
2025-10-11 11:08:42 +08:00
<!-- 邮件弹窗 -->
2025-09-15 09:58:52 +08:00
<div
v-if="contextMenuVisible"
class="custom-context-menu"
:style="{ left: contextMenuLeft + 'px', top: contextMenuTop + 'px' }"
2025-10-11 11:08:42 +08:00
>
<div class='nowRightHint' :title="nowRightHint">{{nowRightHint}}</div>
<div class="menu-item" @click="handleMenuClick('a')"><img title='编辑章节' src="../assets/img/bianji1.png" ><span>编辑章节</span></div>
<div class="menu-item" @click="handleMenuClick('b')"><img title='绑定资源' src="../assets/img/bangdingziyuanchi.png" ><span>绑定资源</span></div>
<div class="menu-item" @click="handleMenuClick('c')"><img title='版本定稿' src="../assets/img/dinggao.png" ><span>版本定稿</span></div>
<div class="menu-item" @click="handleMenuClick('d')"><img title='历史版本' src="../assets/img/gaojisousuo.png" ><span>历史版本</span></div>
<div class="menu-item" @click="handleMenuClick('e')"><img title='删除章节' src="../assets/img/shanchu-copy.png" ><span>删除章节</span></div>
<!-- <div class="menu-divider"></div> -->
<!-- <div class="menu-item" @click="contextMenuVisible = false">关闭</div> -->
2025-09-15 09:58:52 +08:00
</div>
2025-10-11 11:08:42 +08:00
<!-- 文件预览弹窗 -->
2025-09-15 09:58:52 +08:00
<el-dialog
title="文件预览"
:visible.sync="maskViewShow"
width="90%"
class="custom-dialog viewDialog"
:before-close="handleCloseMask"
>
2025-10-11 11:08:42 +08:00
<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>
{{formatOther('level',this.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>
2025-09-15 09:58:52 +08:00
<div class="loadContent" v-html="neirong">
</div>
2025-10-11 11:08:42 +08:00
</el-dialog>
2025-09-15 09:58:52 +08:00
2025-10-11 11:08:42 +08:00
<el-dialog
title="修改书名"
:visible.sync="editBookNameDialog"
width="60%"
class="custom-dialog viewDialog2"
:before-close="handleCloseEditBookName"
>
<el-input v-model="getBookName" autocomplete="off"></el-input>
<span slot="footer" class="dialog-footer">
<el-button @click="editBookFun(false)">取消</el-button>
<el-button type="primary" @click="editBookFun(true)">修改</el-button>
</span>
</el-dialog>
2025-07-25 13:28:47 +08:00
</div>
</template>
<script>
2025-09-15 09:58:52 +08:00
import WangEditor from 'wangeditor';
2025-10-11 11:08:42 +08:00
import brImg from '../assets/img/br.png';
import '../assets/css/style.css'
2025-07-25 13:28:47 +08:00
export default {
2025-10-17 08:28:46 +08:00
name: 'WangEditor',
2025-09-15 09:58:52 +08:00
components: {
},
2025-07-25 13:28:47 +08:00
data() {
return {
2025-10-17 08:28:46 +08:00
countDialogVisible: false,
domCount: 0,
elementCount: 0,
textCount: 0,
commentCount: 0,
countTarget: '',
leftWidth: 380,
isDragging: false,
isLoadMsg:false,
2025-10-11 11:08:42 +08:00
minLevel:'',
maxLevel:'',
maxPermission:'',
minPermission:'',
nowRightHint:'',
dmcHint:false,
rdfDescriptions:[],
editBookNameDialog:false,
getBookName:'',
getBookNameDf:'',
pickerOptions: {
disabledDate(time) {
return time.getTime() > Date.now();
},
shortcuts: [{
text: '今天',
onClick(picker) {
picker.$emit('pick', new Date());
}
}, {
text: '昨天',
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24);
picker.$emit('pick', date);
}
}, {
text: '一周前',
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit('pick', date);
}
}]
},
optionList:[
{
label:'使用',
value:"1"
},
{
label:'不使用',
value:"2"
}
],
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: '绝密'}
],
brImg:brImg,
imgUrlJg: require('../assets/img/jgIcon.png'),//警告Icon
imgUrlJs: require('../assets/img/jsIcon.png'),//警示Icon
editorHeight:'',//编辑器高度
historyVsPath:'',//查看历史文件路径
leftHeight:'0',//左边容器高度
2025-09-15 09:58:52 +08:00
isLoadXml:false,//是否加载DMC
neirong:'',//预览内容
isLoadOldDmc: "1", // 初始值需与 options 中的 value 类型一致
2025-10-11 11:08:42 +08:00
options2:[
{
value:"1",
label:"使用",
},
{
value:"2",
label:"不使用",
}
],
2025-09-15 09:58:52 +08:00
showView:false,//是否显加载原文档
2025-10-11 11:08:42 +08:00
tempDivData1:'',//模板文件容器
viewLis:'',//预览时候端口号
viewXml:'',//预览时候的XML内容
maskViewShow:false,//文件预览弹窗是否显示
2025-09-15 09:58:52 +08:00
// 屏幕整体尺寸(设备屏幕尺寸)
screenWidth: 0,
screenHeight: 0,
// 浏览器窗口尺寸
windowW: 0,
windowH: 0,
// 用于防抖的定时器
resizeTimer: null,
// 保存对新窗口的引用
wangG2Window: null,
// 用于检查窗口状态的定时器
2025-10-11 11:08:42 +08:00
checkWindowTimer: null,
2025-09-15 09:58:52 +08:00
showModifyBtn: false, // 控制是否显示【修改】的开关按钮点击后设为true
2025-10-11 11:08:42 +08:00
mId:'',//当前最大ID
2025-09-15 09:58:52 +08:00
loadFileDMC:'',//加载的DMC文件里面的content内容
loadFileXML:'',//加载的DMC文件内容
historyData:[],//历史版本列表信息
contextMenuVisible: false, // 右键菜单是否可见
contextMenuLeft: 0, // 右键菜单left位置
contextMenuTop: 0, // 右键菜单top位置
contextMenuNode: null, // 右键点击的节点数据
2025-10-11 11:08:42 +08:00
nowAttr:{//当前操作的资源
name:'',
index:''
},
2025-09-15 09:58:52 +08:00
dialogVisibleAttrDel:false,//删除弹窗
2025-10-11 11:08:42 +08:00
dialogVisibleTips2:false,//切换目录时候未保存提示弹窗是否显示
dialogVisibleTips:false,//操作目录时候未保存提示弹窗是否显示
2025-09-15 09:58:52 +08:00
contentXmlStr:'',//当前富文本字符串
getDmName:'',//当前DM文件名。
isNavEdit:false,//是否在目录编辑状态。
allImgType://暂定当前的图片类型
new Set([
"bmp", "jpg", "jpeg", "png", "tif", "gif", "pcx", "tga", "exif", "fpx", "svg", "psd", "cdr", "pcd", "dxf", "ufo", "eps", "ai", "raw", "WMF", "webp", "avif", "apng"
]),
allMusicType:new Set([//暂定当前的音频类型
"mp3", "aac", "wav", "flac", "alac", "wma"
]),
allVideoType:new Set([//暂定当前的视频类型
"mp4", "avi", "mkv", "mov", "flv", "wmv", "webm", "mpeg"
]),
otherType:new Set(['wrl','jltf']),
lisenPath:'',//当前内置服务器端口
//目录
domNameStr:[//拼接文档名
'DMC-','test2','-A-P4-20-00-00A-','A-A_000_00','_zh_cn'
],
lastClick:'',//上一次点击的目录id
nowClick:'',//当前点击的目录id
nowMaxId:'',//最大文档id
catalogueString:'',//目录字符串
navIsAdd:'',//判断当前目录操作类型
searchText:'',//搜索目录章节
dialogVisibleNav:false,//目录弹窗
dialogVisibleRight:false,//右键绑定弹窗
dialogVisibleBland:false,//绑定源弹窗
dialogVisibleHistory:false,//历史版本弹窗
dialogVisibleNavDel:false,//删除弹窗
selectedAttributes: [], // 当前选中的属性
treeData: [//基础目录数据
// { id: '00001', name: '根节点1根节点1根节点1根节点1根节点1根节点1', children: [
// {
// id: '00003', name: '根节点3根节点3根节点3根节点3根节点3', children: [{
// id: '00004', name: '根节点4根节点4根节点4根节点4根节点4', children: [],
// attributes: [] // 示例:已绑定的属性
// }]
// }
// ], attributes: [] // 示例:已绑定的属性
// },
// { id:'00002', name: '根节点2根节点2根节点2根节点2根节点2', children: [
// {id: '00005', name: '根节点5根节点5根节点5根节点5根节点5', children: [ { id:'00002', name: '根节点2根节点2根节点2根节点2根节点2', children: [
// {id: '00005', name: '根节点5根节点5根节点5根节点5根节点5', children: [ { id:'00002', name: '根节点2根节点2根节点2根节点2根节点2', children: [
// {id: '00005', name: '根节点5根节点5根节点5根节点5根节点5', children: [ { id:'00002', name: '根节点2根节点2根节点2根节点2根节点2', children: [
// {id: '00005', name: '根节点5根节点5根节点5根节点5根节点5', children: []}
// ] }]}
// ] }]}
// ] }]}
// ] }
],
treeData2:[
{
id: '00001',
name: '装备概况',
attributes: ['金', '木', '水'],
formMes: {},
lagreVersion: '001',
minorVersion: '01',
children: [
{
id: '00002',
name: '方舱概述',
attributes: [],
lagreVersion: '001',
minorVersion: '01',
children: [
{
id: '00003',
name: '功能介绍',
attributes: [],
formMes: {},
lagreVersion: '001',
minorVersion: '01',
children: []
},
{
id: '00004',
name: '规格介绍',
attributes: ['水'],
formMes: {},
lagreVersion: '001',
minorVersion: '01',
children: []
}
]
},
{
id: '00005',
name: '舱体',
attributes: ['火', '土'],
formMes: {},
lagreVersion: '001',
minorVersion: '01',
children: []
},
{
id: '00006',
name: '机身转运小车',
attributes: [],
formMes: {},
lagreVersion: '001',
minorVersion: '01',
children: []
},
{
id: '00007',
name: '无人机部件存储装置',
attributes: [],
formMes: {},
lagreVersion: '001',
minorVersion: '01',
children: []
},
{
id: '00008',
name: '机身转运小车',
attributes: [],
formMes: {},
lagreVersion: '001',
minorVersion: '01',
children: []
},
{
id: '00009',
name: '附件及工具',
attributes: [],
formMes: {},
lagreVersion: '001',
minorVersion: '01',
children: [
{
id: '00010',
name: '灭火器',
attributes: [],
formMes: {},
lagreVersion: '001',
minorVersion: '01',
children: []
},
{
id: '00011',
name: '应急灯',
attributes: [],
formMes: {},
lagreVersion: '001',
minorVersion: '01',
children: []
},
{
id: '00012',
name: '土木工具',
attributes: [],
formMes: {},
lagreVersion: '001',
minorVersion: '01',
children: []
},
{
id: '00013',
name: '机械工具',
attributes: [],
formMes: {},
lagreVersion: '001',
minorVersion: '01',
children: []
}
]
}
]
},
{
id: '00013',
name: '使用说明',
attributes: [],
formMes: {},
lagreVersion: '001',
minorVersion: '01',
children: [
{
id: '00014',
name: '无人机出舱',
attributes: [],
formMes: {},
lagreVersion: '001',
minorVersion: '01',
children: []
},
{
id: '00015',
name: '无人机入舱',
attributes: [],
formMes: {},
lagreVersion: '001',
minorVersion: '01',
children: []
},
{
id: '00016',
name: '灭火器使用',
attributes: [],
formMes: {},
lagreVersion: '001',
minorVersion: '01',
children: []
}
]
}
2025-10-11 11:08:42 +08:00
],
2025-09-15 09:58:52 +08:00
defaultProps: {//树结构
children: 'children',
label: 'name'
},
currentNode: null,//当前节点
form: {//默认目录信息
name: '',
version:'000',
date:'',
language:'',
2025-10-11 11:08:42 +08:00
level:'1',
2025-09-15 09:58:52 +08:00
contributor:'',
2025-10-11 11:08:42 +08:00
creator:'四威高科',
2025-09-15 09:58:52 +08:00
applicabilityInformation:'',
qualityVerification:'',
2025-10-11 11:08:42 +08:00
permission:'1'
2025-09-15 09:58:52 +08:00
// version:'001',
// date:'2046-12-12',
// language:'zn_cn',
// level:'公开',
// contributor:'责任合作单位',
// creator:'创作单位',
// applicabilityInformation:'适用性信息',
// qualityVerification:'质量验证',
// permission:'10'
},
2025-10-11 11:08:42 +08:00
rules: {//规则
2025-09-15 09:58:52 +08:00
name: [
{ required: true, message: '请输入节点名称', trigger: 'blur' },
{ min: 1, max: 40, message: '长度在 1 到 40 个字符', trigger: 'blur' }
]
},
//弹窗
dialogVisible:false,//自定义弹窗
idLength:10,//暂无用
contextMenu: {//暂无用
visible: false,
x: 0,
y: 0,
selectedElement: null,
selectedParam: ''
},
isContextMenuEnabled: false,//暂无用
itemParams: {}, //暂无用
// 存储元素的参数 {elementId: param}
// 模拟弹框参数
//查看图片begin
dialogVisibleImg:false,//暂无用
images: [//暂无用
'https://ww2.sinaimg.cn/mw690/007ut4Uhly1hx4v37mpxcj30u017cgrv.jpg',
'https://example.com/image2.jpg'
],
currentImage: '',//暂无用
scale: 1,//暂无用
rotation: 0,//暂无用
startX: 0,//暂无用
startY: 0,//暂无用
translateX: 0,//暂无用
translateY: 0,//暂无用
containerHeight: '90vh', //暂无用 动态控制高度
//查看图片end
2025-10-17 08:28:46 +08:00
// 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',
// ],
newSelector:[],
oldSelector:[],
2025-09-15 09:58:52 +08:00
tempDivData:{//当前富文本str
innerHTML:'五'
},
colors:'',//暂无用
val1:'',//暂无用
val2:'',//暂无用
message: '',//暂无用
2025-10-11 11:08:42 +08:00
editor: null, //编辑器
editorContent: '',//富文本内容
2025-07-28 17:01:13 +08:00
}
},
2025-10-11 11:08:42 +08:00
computed: {
2025-07-25 13:28:47 +08:00
},
mounted() {
2025-09-15 09:58:52 +08:00
// 初始化尺寸
this.getWindowSize()
// 绑定 resize 事件
window.addEventListener('resize', this.handleResize)
2025-10-11 11:08:42 +08:00
// // 确保DOM已加载
// this.$nextTick(() => {
// this.initEditor()
// })
2025-09-15 09:58:52 +08:00
this.$nextTick(() => {
2025-10-11 11:08:42 +08:00
// 初始时如果容器不可见,等待 currentNode 变化后再初始化
if (this.currentNode) {
this.initEditor();
}
});
2025-09-15 09:58:52 +08:00
2025-07-25 13:28:47 +08:00
console.log('chrome对象是否存在:', !!window.chrome);
2025-10-11 11:08:42 +08:00
console.log('webview对象是否存在:', !!window.chrome?.webview);
2025-07-25 13:28:47 +08:00
2025-09-15 09:58:52 +08:00
window.removeEventListener('SelectFilePathSend', this.handleFilePathSend);
// 再绑定新的监听器
window.addEventListener('SelectFilePathSend', this.handleFilePathSend);
window.addEventListener('SelectFilePathSend', this.SendLisentPathFun);
2025-07-25 13:28:47 +08:00
},
beforeDestroy() {
// 销毁编辑器
if (this.editor) {
this.editor.destroy()
}
2025-09-15 09:58:52 +08:00
// 清理定时器
if (this.checkWindowTimer) {
clearInterval(this.checkWindowTimer)
}
console.log('监听器开始移除:', Date.now()) // 打印移除时间戳
window.removeEventListener('resize', this.handleResize)
window.removeEventListener('FrontLoadDM', this.FrontLoadDM_g1)
window.removeEventListener('handleMessageFromDotNet', this.fun1)
window.removeEventListener('SelectFilePathSend', this.SendLisentPathFun)
2025-07-25 13:28:47 +08:00
},
2025-09-15 09:58:52 +08:00
methods: {
//清除节点选中
clearNodeState() {
2025-10-11 11:08:42 +08:00
this.currentNode = '';
2025-09-15 09:58:52 +08:00
// 通过ref获取el-tree实例
const tree = this.$refs.tree;
if (tree) {
// 取消当前选中状态
tree.setCurrentKey(null);
// 如果需要清除所有节点的选中状态(包括多选情况)
// 先获取所有选中的节点
const selectedNodes = tree.getCheckedNodes();
// 取消所有节点的选中状态
selectedNodes.forEach(node => {
tree.setChecked(node.id, false);
});
// 可选触发节点点击事件的回调传递null表示无选中节点
// this.handleNodeClick(null);
}
},
// 测试接收数据
fun1(e) {
console.log("方法1",e,e.detail)
},
// 获取服务端口地址
SendLisentPathFun(e) {
console.log('服务端口地址信息1:',e,e.detail)
this.lisenPath = e.detail;
},
2025-10-11 11:08:42 +08:00
FrontLoadDM_g2(e) {
// 加载目录
console.log('FrontLoadProjectNew111 参数接收:')
this.isLoadXml = true;
this.currentNode = '';
//获取目录字段拼接,暂不用
// this.extractDmCode(e.detail)
// 去除首尾的双引号
let processed = e.detail.trim();
// 检查并去除开头的双引号
if (processed.startsWith('"')) {
processed = processed.substring(1);
}
// 检查并去除结尾的双引号
if (processed.endsWith('"')) {
processed = processed.substring(0, processed.length - 1);
}
// this.outputXml = processed;
this.generateTreeData(processed);
// this.parseXml(processed);
// this.parseToTreeData(processed)
},
2025-09-15 09:58:52 +08:00
//接收富文本内容信息
FrontLoadDM_g1(e) {
console.log("加载文档数据 1111")
2025-10-17 08:28:46 +08:00
// console.log('FrontLoadDM 参数接收111:',e,e.detail)
2025-09-15 09:58:52 +08:00
// this.editorShow = true;
let xmlContent = e.detail.trim();
if (xmlContent.startsWith('"')) {
xmlContent = xmlContent.substring(1);
}
// 检查并去除结尾的双引号
if (xmlContent.endsWith('"')) {
xmlContent = xmlContent.substring(0, xmlContent.length - 1);
}
// console.log("xmlContent",xmlContent)
const parser = new DOMParser()
const xmlDoc = parser.parseFromString(xmlContent, "text/xml")
2025-10-17 08:28:46 +08:00
// console.log("xmlDoc",xmlDoc)
2025-09-15 09:58:52 +08:00
const contentNodes = xmlDoc.getElementsByTagName('content')[0];
2025-10-17 08:28:46 +08:00
// console.log("xmlDoc.getElementsByTagName('content')",xmlDoc.getElementsByTagName('content'))
// console.log("contentNodes",contentNodes)
2025-09-15 09:58:52 +08:00
const rdfDescription = xmlDoc.querySelector('rdf\\:Description, Description');
if (rdfDescription) {
// 填充表单数据 - 映射关系form字段 -> XML标签
this.form = {
name: this.getNodeValue(rdfDescription, 'dc\\:title, title'),
version: this.getNodeValue(rdfDescription, 'dc\\:version, version'),
date: this.getNodeValue(rdfDescription, 'dc\\:date, date'),
language: this.getNodeValue(rdfDescription, 'dc\\:language, language'),
level: this.getNodeValue(rdfDescription, 'dc\\:level, level'),
contributor: this.getNodeValue(rdfDescription, 'dc\\:contributor, contributor'),
creator: this.getNodeValue(rdfDescription, 'dc\\:creator, creator'),
applicabilityInformation: this.getNodeValue(rdfDescription, 'dc\\:applicabilityInformation, applicabilityInformation'),
qualityVerification: this.getNodeValue(rdfDescription, 'dc\\:qualityVerification, qualityVerification'),
permission: this.getNodeValue(rdfDescription, 'dc\\:permission, permission')
};
2025-10-17 08:28:46 +08:00
// console.log('XML解析成功', this.form);
2025-09-15 09:58:52 +08:00
}else{
this.form = {
name: '',
2025-10-11 11:08:42 +08:00
version:'000',
2025-09-15 09:58:52 +08:00
date:'',
language:'',
2025-10-11 11:08:42 +08:00
level:'1',
2025-09-15 09:58:52 +08:00
contributor:'',
2025-10-11 11:08:42 +08:00
creator:'四威高科',
2025-09-15 09:58:52 +08:00
applicabilityInformation:'',
qualityVerification:'',
};
console.log("目录解析不成功 置空",this.form)
}
if (contentNodes) {
2025-10-17 08:28:46 +08:00
// console.log("处理前",contentNodes.innerHTML)
2025-09-15 09:58:52 +08:00
let htmlContent = this.convertXmlContentToHtml(contentNodes.innerHTML)
let htmlContent2 = this.completeModel3DTags(htmlContent)
2025-10-17 08:28:46 +08:00
// console.log("处理后",htmlContent2)
2025-09-15 09:58:52 +08:00
const htmlContent3 = this.replaceModel3dToImg(htmlContent2);
// this.editor.txt.html(htmlContent)
//处理过后再导入
// this.restoreContent(htmlContent)
this.restoreContentXh(htmlContent3)
}
},
//测试发送给后端信息
2025-07-25 13:28:47 +08:00
sendMessageToHost() {
2025-09-15 09:58:52 +08:00
//调用后端 sendToDotNet
2025-07-25 13:28:47 +08:00
this.$sendToDotNet(this.val1,this.val2);
2025-10-11 11:08:42 +08:00
},
2025-09-15 09:58:52 +08:00
initEditor() {//初始化编辑器配置
2025-07-25 13:28:47 +08:00
this.editor = new WangEditor(this.$refs.editor)
2025-10-11 11:08:42 +08:00
const editorEl = this.$refs.editor;
if (!editorEl) {
console.warn('编辑器容器不存在');
return;
}
2025-07-25 13:28:47 +08:00
// 配置编辑器
this.editor.config.uploadImgShowBase64 = true // 使用 base64 保存图片
this.editor.config.onchange = (html) => {
2025-09-15 09:58:52 +08:00
this.editorContent = html;
2025-07-25 13:28:47 +08:00
}
let dm = this.editor.config.menus;
console.log("默认菜单",dm)
2025-09-15 09:58:52 +08:00
2025-07-25 13:28:47 +08:00
2025-07-28 17:01:13 +08:00
// 启用颜色选择功能
this.editor.config.colors = [
'#000000', '#ffffff', '#eeeef1',
'#ff0000', '#ff5e5e', '#ffbbbb',
'#0033ff', '#0055ff', '#3d7eff',
'red',"#096","#9cf"
]
2025-07-25 13:28:47 +08:00
// 完全自定义菜单
this.editor.config.menus = [
'image', // 图片
'video', // 视频
2025-09-15 09:58:52 +08:00
// 'head', // 标题
2025-07-25 13:28:47 +08:00
'bold', // 粗体
2025-09-15 09:58:52 +08:00
'fontSize',//字号
2025-07-25 13:28:47 +08:00
// 'fontName',//字体
'italic', // 斜体
'underline', // 下划线
'strikeThrough', // 删除线
// 'line',//行高
'lineHeight',//
2025-07-28 17:01:13 +08:00
'foreColor', // 文字颜色
'backColor', // 背景颜色
2025-09-15 09:58:52 +08:00
'link', // 链接
2025-07-25 13:28:47 +08:00
'list', // 列表
// 'todo',//
'justify', // 对齐方式
2025-09-15 09:58:52 +08:00
'quote', // 引用
2025-07-25 13:28:47 +08:00
// 'emoticon',//表情
'table', // 表格
2025-09-15 09:58:52 +08:00
'code', // 代码
2025-07-25 13:28:47 +08:00
'splitLine',//分割线
'undo', // 撤销
2025-07-28 17:01:13 +08:00
'redo', // 重做
2025-07-25 13:28:47 +08:00
]
2025-09-15 09:58:52 +08:00
console.log("自定义菜单",this.editor.config)
// 自定义处理拖拽事件
this.editor.config.customUpload = true
// 监听拖拽事件
this.editor.config.uploadImgShowBase64 = false
this.editor.config.uploadVideoShowBase64 = false
this.editor.config.uploadAudioShowBase64 = false
// 设置自定义拖拽处理
// this.setupDragHandler()
// 保存原始的创建方法
const originalCreate = this.editor.create
// 重写创建方法,在创建完成后立即添加按钮
this.editor.create = () => {
// 执行原始创建方法
originalCreate.call(this.editor)
// 尝试获取工具栏
// 📌🔖
//
2025-10-11 11:08:42 +08:00
this.addCustomButton('警示', '<img src="'+this.imgUrlJs+'" alt="按钮图标" style="width: 20px; height: 20px; object-fit: contain;">',1) // 第一个按钮弹出123使用图钉图标
2025-09-15 09:58:52 +08:00
this.addCustomButton('警告', '<img src="'+this.imgUrlJg+'" alt="按钮图标" style="width: 20px; height: 20px; object-fit: contain;">',2) // 第一个按钮弹出123使用图钉图标
}
2025-07-25 13:28:47 +08:00
// 创建编辑器
this.editor.create();
2025-09-15 09:58:52 +08:00
// 特别注意:需要在编辑器创建完成后绑定事件
this.$nextTick(() => {
console.log("初始化 setupDragHandler")
this.setupDragHandler()
})
2025-07-25 13:28:47 +08:00
2025-09-15 09:58:52 +08:00
// 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()
2025-07-25 13:28:47 +08:00
2025-10-11 11:08:42 +08:00
},
//编辑书名
editBookName() {
console.log("编辑书名")
const getBookNameDf = this.getBookName;
this.getBookNameDf = getBookNameDf;
this.editBookNameDialog = true;
},
editBookFun(type) {
if(type){
this.catalogueAnalysis(this.treeData);
this.editBookNameDialog = false;
}else{
this.getBookName = this.getBookNameDf;
this.editBookNameDialog = false;
}
},
2025-09-15 09:58:52 +08:00
// 通用的添加自定义按钮方法,接收两个参数:提示内容和图标
addCustomButton(alertContent, icon,type) {
let toolbarElem = null
2025-07-25 13:28:47 +08:00
2025-09-15 09:58:52 +08:00
// 方式1: 通过编辑器内部属性获取工具栏
if (this.editor.$toolbarElem && this.editor.$toolbarElem[0]) {
toolbarElem = this.editor.$toolbarElem[0]
console.log('通过$toolbarElem获取到工具栏')
}
2025-07-25 13:28:47 +08:00
2025-09-15 09:58:52 +08:00
// 方式2: 直接通过容器查找
if (!toolbarElem) {
toolbarElem = this.$refs.editor.querySelector('.w-e-toolbar')
if (toolbarElem) {
console.log('通过容器查询获取到工具栏')
}
}
// 方式3: 全局查找
if (!toolbarElem) {
toolbarElem = document.querySelector('.w-e-toolbar')
if (toolbarElem) {
console.log('通过全局查询获取到工具栏')
}
}
// 如果还是找不到工具栏,直接创建一个简单的按钮放在编辑器上方
if (!toolbarElem) {
console.warn('仍然未找到工具栏,创建独立按钮')
this.createFallbackButton(alertContent, icon,type)
return
}
// 查找或创建菜单容器
let menuBar = toolbarElem.querySelector('.w-e-menu-bar')
if (!menuBar) {
menuBar = document.createElement('div')
menuBar.className = 'w-e-menu-bar'
menuBar.style.cssText = 'padding: 5px; border-bottom: 1px solid #e8e8e8;'
toolbarElem.appendChild(menuBar)
}
// 创建自定义按钮
const customBtn = document.createElement('div')
customBtn.className = 'w-e-menu'
customBtn.style.cssText = `
width: 32px;
height: 32px;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin: 0 2px;
background: #fff;
border-radius: 2px;
color: #333;
font-size: 18px;
`
customBtn.innerHTML = icon
customBtn.title = `${alertContent}`
// 绑定点击事件,使用传入的提示内容
customBtn.onclick = () => {
console.log("点击了111",type)
switch (type){
case 1:
case '1':
2025-10-11 11:08:42 +08:00
// this.editor.cmd.do('insertHTML', `<p data-we-empty-p=""><br></p><div style='
// padding: 20px;
// margin: 20px;
// background-image:url("`+this.brImg+`");
// '><p class='teshu' style="border-radius: 4px;padding: 10px;border: 3px solid #000;"></p></div>
// <p data-we-empty-p=""><br></p>`)
// this.editor.cmd.do('insertHTML', `<p class='jg'>[[]]</p>`)
// this.editor.cmd.do('insertHTML', `<p data-we-empty-p=""><br></p><div style='margin: 10px auto;
// padding: 10px;
// border: 10px solid;
// background:#fff;
// border-image: linear-gradient(45deg,
// #ffcc00 0%, #ffcc00 10%,
// #000000 10%, #000000 20%,
// #ffcc00 20%, #ffcc00 30%,
// #000000 30%, #000000 40%,
// #ffcc00 40%, #ffcc00 50%,
// #000000 50%, #000000 60%,
// #ffcc00 60%, #ffcc00 70%,
// #000000 70%, #000000 80%,
// #ffcc00 80%, #ffcc00 90%,
// #000000 90%, #000000 100%
// ) 1;' class='teshu2'></div><p data-we-empty-p=""><br></p>`)
this.editor.cmd.do('insertHTML', `<p data-we-empty-p=""><br></p><div style='margin: 10px auto;
padding: 10px;
background:#fff;' class='teshu2 borderStyle_yellow'></div><p data-we-empty-p=""><br></p>`)
2025-09-15 09:58:52 +08:00
break;
case 2:
case '2':
2025-10-11 11:08:42 +08:00
// this.editor.cmd.do('insertHTML', `<p class='js'><<>></p>`)
// this.editor.cmd.do('insertHTML', `<div class='jg' style='border:1px solid red;padding:10px;'></div>`)
// this.editor.cmd.do('insertHTML', `<p data-we-empty-p=""><br></p><div style="margin: 50px auto;
// padding: 20px;
// border: 12px solid;
// background:#fff;
// border-image: linear-gradient(-45deg,
// #ff0000 0%, #ff0000 10%,
// #000000 10%, #000000 20%,
// #ff0000 20%, #ff0000 30%,
// #000000 30%, #000000 40%,
// #ff0000 40%, #ff0000 50%,
// #000000 50%, #000000 60%,
// #ff0000 60%, #ff0000 70%,
// #000000 70%, #000000 80%,
// #ff0000 80%, #ff0000 90%,
// #000000 90%, #000000 100%
// ) 1;" class='teshu'></div><p data-we-empty-p=""><br></p>`)
this.editor.cmd.do('insertHTML', `<p data-we-empty-p=""><br></p><div style="margin: 10px auto;
padding: 10px;
background:#fff;" class='teshu borderStyle_red'></div><p data-we-empty-p=""><br></p>`)
2025-09-15 09:58:52 +08:00
break;
2025-07-25 13:28:47 +08:00
}
2025-09-15 09:58:52 +08:00
}
// 添加悬停效果
customBtn.onmouseover = () => {
customBtn.style.background = '#f0f0f0'
}
customBtn.onmouseout = () => {
customBtn.style.background = '#fff'
}
// 添加到菜单最前面
menuBar.insertBefore(customBtn, menuBar.firstChild)
console.log(`自定义按钮(弹出${alertContent})已成功添加到菜单栏`)
},
// 备用方案:如果找不到工具栏,直接在编辑器上方创建一个按钮
createFallbackButton(alertContent, icon,type) {
const fallbackBtn = document.createElement('div')
fallbackBtn.style.cssText = `
padding: 8px 15px;
background: #409eff;
color: white;
border-radius: 4px;
cursor: pointer;
display: inline-block;
margin: 0 5px 10px 0;
`
fallbackBtn.innerHTML = `${icon} 点击弹出${alertContent}`
fallbackBtn.onclick = () => {
console.log("点击了222",type)
switch (type){
case 1:
2025-10-11 11:08:42 +08:00
this.editor.cmd.do('insertHTML', `<p class="fine-stripe-border1"><div></div></p>`)
2025-09-15 09:58:52 +08:00
break;
case 2:
2025-10-11 11:08:42 +08:00
this.editor.cmd.do('insertHTML', `<p class="fine-stripe-border2"><div></div></p>`)
2025-09-15 09:58:52 +08:00
break;
2025-07-25 13:28:47 +08:00
}
2025-09-15 09:58:52 +08:00
}
// 添加到编辑器容器的最前面
this.$refs.editor.insertBefore(fallbackBtn, this.$refs.editor.firstChild)
console.log(`已创建备用按钮(弹出${alertContent})`)
},
2025-07-25 13:28:47 +08:00
2025-09-15 09:58:52 +08:00
setupDragHandler() {
console.log("进入setupDragHandler")
const editor = this.editor
const editorContainer = editor.$textElem.elems[0]
let that = this;
// console.log("进入参数",editor,editorContainer)
// // 阻止默认拖拽行为
editorContainer.addEventListener('dragover', (e) => {
// console.log("进入 dragover",e)
e.preventDefault()
e.stopPropagation()
2025-07-25 13:28:47 +08:00
})
2025-09-15 09:58:52 +08:00
editorContainer.addEventListener('drop', (e) => {
// console.log("进入 drop",)
e.preventDefault()
e.stopPropagation()
that.$sendToDotNet('GetMaterialPath');
// // 检查拖拽的文件类型
// const items = e.dataTransfer.items
// for (let i = 0; i < items.length; i++) {
// const item = items[i]
// if (item.kind === 'file') {
// const file = item.getAsFile()
// const fileType = file.type.split('/')[0]
// // 根据文件类型显示不同的提示
// switch(fileType) {
// case 'image':
// alert('检测到图片文件,已阻止上传')
// break
// case 'video':
// alert('检测到视频文件,已阻止上传')
// break
// case 'audio':
// alert('检测到音频文件,已阻止上传')
// break
// default:
// alert(`检测到${fileType}类型文件,已阻止上传`)
// }
// }
// }
2025-07-25 13:28:47 +08:00
})
2025-09-15 09:58:52 +08:00
},
// 上传图片
insertImage(src) {
2025-10-11 11:08:42 +08:00
if (!this.editor) {
console.error('编辑器未初始化,无法插入图片');
return;
}else{
// src = 'http://localhost:54610/a1.jpg';
// const imgUrl = 'http://youneed.top:10017/uploads/1.jpg'
// const imgUrl = 'https://ww2.sinaimg.cn/mw690/007ut4Uhly1hx4v37mpxcj30u017cgrv.jpg';
if(src){
const imgUrl = src?src:'http://localhost:5432/DM_Material/a1.jpg';
console.log("地址",src,imgUrl)
2025-10-17 08:28:46 +08:00
this.editor.cmd.do('insertHTML', `<img src="${imgUrl}" width="50%" alt="图片">`)
2025-10-11 11:08:42 +08:00
}
}
2025-09-15 09:58:52 +08:00
},
// 上传3D资源模拟占位
insert3d(imgUrl) {
2025-10-11 11:08:42 +08:00
this.editor.cmd.do('insertHTML', `<img src="${imgUrl}" class='model3d' style="width: 100%;" alt="图片"><p data-we-empty-p=""><br></p>`)
2025-09-15 09:58:52 +08:00
// this.editor.cmd.do('insertHTML', `<div>3D模型<model3d src="http://www.baidu.com" controls="controls" style="max-width: 100%"></model3d></div>`)
},
//上传3D资源模设置标识
replacemodel3dImages(htmlString) {
if (!htmlString) return '';
2025-07-25 13:28:47 +08:00
2025-09-15 09:58:52 +08:00
const regex = /<img([^>]*?)class="model3d"([^>]*?)\/?>/gi;
2025-07-25 13:28:47 +08:00
2025-09-15 09:58:52 +08:00
return htmlString.replace(regex, (match, prefix, suffix) => {
const attributes = (prefix || '') + (suffix || '');
return `<model3d class="model3d" ${attributes}></model3d>`;
});
2025-07-25 13:28:47 +08:00
},
2025-09-15 09:58:52 +08:00
//解析3d资源标识
modelToImg(htmlString) {
// 匹配<model3d>标签且class中包含model3d
const regex = /<model3d([^>]*?)class="([^"]*?)model3d([^"]*?)"([^>]*?)>/gi;
// 替换标签名,保留所有属性
return htmlString.replace(regex, '<img$1class="$2model3d$3"$4>');
},
2025-10-17 08:28:46 +08:00
2025-10-11 11:08:42 +08:00
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;
},
2025-09-15 09:58:52 +08:00
2025-10-11 11:08:42 +08:00
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 "无效日期";
}
},
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);
}
},
2025-09-15 09:58:52 +08:00
// 插入视频
insertVideo(src) {
2025-10-11 11:08:42 +08:00
if (!this.editor) {
console.error('编辑器未初始化,无法插入插入视频');
return;
}else{
// const videoUrl = src?src:'https://r1.realme.net/general/20250530/17485780109181ed6767541a64e7d90626e0a3fd1aaae.mp4?type=video/mp4'
const videoUrl = src?src:'http://localhost:5432/DM_Material/video.mp4'
// 使用 editor.cmd.do 执行插入操作,支持撤销/重做
this.editor.cmd.do('insertHTML', `<p data-we-empty-p=""><div><video src="${videoUrl}" style="width: 100%;" controls="controls" style="max-width: 100%"></video></div><p data-we-empty-p=""><br></p><p data-we-empty-p=""><br></p></p>`)
}
2025-09-15 09:58:52 +08:00
// 或者使用更简单的插入方式
// this.editor.txt.append(`<video src="${videoUrl}" controls="controls" style="max-width: 100%"></video>`)
2025-07-25 13:28:47 +08:00
},
2025-09-15 09:58:52 +08:00
// 插入音频
insertAudio(src) {
2025-10-11 11:08:42 +08:00
if (!this.editor) {
console.error('编辑器未初始化,无法插入音频');
return;
}else{
// let audioUrl = 'https://m801.music.126.net/20250805103535/df94bdfa3bc8c3a07de64531c4925895/jdymusic/obj/wo3DlMOGwrbDjj7DisKw/14096444542/bafc/a068/39f8/9a9e06e5634410b5e7e81df24749e656.mp3?vuutv=6WGmbU7+iXWmpSMnJs8FQEYWEieNRcA9S4YcUYOjmx36NJRHK0ASi7jhIJz0R9gxcmMcAUDn9rf1k08lFtqC9TQYcOlc8ZofqvCCJho3eeBGH/hwnjUlaQHe2GQFyJ32rhYAydM3bCBfIg+ZnpfZTw==';
let audioUrl =src?src:'http://localhost:5432/DM_Material/music.mp3';
// 使用预设音频URL
// const audioHtml = `
// <div class="audio-container" style="margin: 10px 0;">
// <audio controls src="${audioUrl}" style="width: 100%;"></audio>
// <div style="text-align: center; color: #999; font-size: 12px;">音频文件</div>
// </div>
// `;
const audioHtml = `
<p data-we-empty-p=""><audio controls src="${audioUrl}" style="width: 100%;"></audio></p><p data-we-empty-p=""><br></p><p data-we-empty-p=""><br></p><p data-we-empty-p=""><br></p>
`;
// 插入到编辑器
this.editor.cmd.do('insertHTML', audioHtml);
}
2025-07-25 13:28:47 +08:00
2025-09-15 09:58:52 +08:00
// 或者使用更简单的方式
// this.editor.txt.append(audioHtml)
},
//循环处理标签
xh(oldSt,newSt,type,saveId){
let times = oldSt.length;
// const ht1 = this.tempDivData.innerHTML;
// console.log("3d转换之后2",ht1)
for(let i = 0;i<times;i++){
const headings = this.tempDivData.querySelectorAll(oldSt[i])
headings.forEach(heading => {
const dmTitle = document.createElement(newSt[i])
heading.parentNode.insertBefore(dmTitle, heading)
console.log("内容替换",dmTitle, heading)
dmTitle.appendChild(heading)
})
}
this.createXmlSt(type,saveId);
},
// 先清除已有的ID确保干净的基础
removeAllIds(htmlString) {
// 创建临时容器解析HTML
const tempContainer = document.createElement('div');
tempContainer.innerHTML = htmlString;
// 递归移除所有元素的id属性
const removeIdsFromElement = (element) => {
if (!element || element.nodeType !== 1) return;
// 移除当前元素的id
element.removeAttribute('id');
// 递归处理子元素
Array.from(element.children).forEach(child => {
removeIdsFromElement(child);
});
};
// 处理所有子元素
Array.from(tempContainer.children).forEach(child => {
removeIdsFromElement(child);
});
return tempContainer.innerHTML;
},
// 删除Colgroup
removeColgroup(str) {
// 1. 校验入参防止传入null/undefined导致报错
if (!str || typeof str !== 'string') {
console.warn('传入的内容不是有效字符串');
return str; // 入参无效时,直接返回原内容
}
// 2. 定义正则匹配colgroup标签不区分大小写、全局匹配
const colgroupReg = /<colgroup[\s\S]*?<\/colgroup>/gi;
// 3. 判断是否包含colgroup标签
const hasColgroupTag = colgroupReg.test(str);
// 4. 处理逻辑:包含则移除,不包含则返回原字符串
let processedStr;
if (hasColgroupTag) {
processedStr = str.replace(colgroupReg, '');
console.log('检测到colgroup标签已移除');
} else {
processedStr = str; // 关键不包含时返回原字符串而非null
console.log('未检测到colgroup标签返回原字符串');
}
// 5. 打印日志(便于调试)
console.log('解析前:', str);
console.log('解析后:', processedStr);
return processedStr;
},
/**
* 为HTML字符串中的所有标签添加唯一ID
* @param {string} htmlString - 原始HTML字符串
* @returns {string} 处理后的HTML字符串
*/
addUniqueIds(htmlString) {
// 先清除已有的ID确保干净的基础
const cleanHtml = this.removeAllIds(htmlString);
console.log("当前的所有html内容2",cleanHtml)
const tempContainer = document.createElement('div');
tempContainer.innerHTML = cleanHtml;
const usedIds = new Set();
// 生成唯一ID
const generateUniqueId = (tagName, content = '') => {
const pureTagName = tagName.toLowerCase().replace(/^p/, '');
const semanticSuffix = content.trim()
.replace(/\s+/g, '_')
.replace(/[^a-z0-9-]/g, '')
.slice(0, 10);
console.log('循环数据semanticSuffix',semanticSuffix)
let baseId = pureTagName + (semanticSuffix ? `id_${semanticSuffix}` : 'id');
let finalId = baseId;
let counter = 1;
2025-10-11 11:08:42 +08:00
// console.log('循环数据counter',counter)
// console.log('循环数据baseId',baseId)
2025-09-15 09:58:52 +08:00
while (usedIds.has(finalId)) {
finalId = `${baseId}_${counter}`;
counter++;
}
usedIds.add(finalId);
return finalId;
};
// 递归添加ID
const addIdsToElement = (element) => {
if (!element || element.nodeType !== 1) return;
const elementText = element.textContent || '';
const elementId = generateUniqueId(element.tagName, elementText);
element.setAttribute('id', elementId);
Array.from(element.children).forEach(child => {
addIdsToElement(child);
});
};
// 处理所有元素
Array.from(tempContainer.children).forEach(child => {
addIdsToElement(child);
});
return tempContainer.innerHTML;
},
/**
* 完整处理流程清除现有ID -> 添加新的唯一ID
* @param {string} originalHtml - 原始HTML字符串
*/
processHtmlWithIds(originalHtml) {
console.log("当前的所有html内容1",originalHtml)
let processedHtml = this.addUniqueIds(originalHtml);
console.log("添加完的富文本",processedHtml)
return processedHtml;
},
// 创建XML字符串
createXmlSt(type,saveId) {
let desStr = this.form;
// if(type||this.isNavEdit){
// desStr = this.form;
// this.isNavEdit = false;
// }else{
// desStr = '';
// }
console.log("当前",this.navIsAdd)
// const ht3 = this.tempDivData.innerHTML;
// console.log("3d转换之后3",ht3)
switch (this.navIsAdd){
case "create":
this.tempDivData.innerHTML = '';
break;
case "edit":
// this.tempDivData.innerHTML = this.tempDivData.innerHTML;
break;
case "other":
// this.tempDivData.innerHTML = this.tempDivData.innerHTML;
this.navIsAdd = 'create';
break;
default:
// this.tempDivData.innerHTML = '';
break;
}
// this.tempDivData.innerHTML = this.navIsAdd?"":this.tempDivData.innerHTML;
this.tempDivData.innerHTML = this.clearNbsp(this.tempDivData.innerHTML)
// const ht4 = this.tempDivData.innerHTML;
// console.log("3d转换之后4",ht4)
console.log("当前的所有html内容3",this.tempDivData.innerHTML)
let newDST = this.processHtmlWithIds(this.tempDivData.innerHTML)
// const ht5 = this.tempDivData.innerHTML;
// console.log("3d转换之后5",ht5)
console.log("结果cleanedStr 然后赋值",this.tempDivData.innerHTML)
console.log("加ID后的",newDST)
//去掉table里面的东西
2025-10-11 11:08:42 +08:00
if(newDST){
newDST = this.removeColgroup(newDST)
} else{
newDST = '';
}
2025-09-15 09:58:52 +08:00
// const ht6 = this.tempDivData.innerHTML;
// console.log("3d转换之后6",ht6)
if(this.loadFileDMC){
newDST = this.loadFileDMC;
}
console.log("解析出来后的",newDST)
const xmlString = `<?xml version="1.0" encoding="UTF-8"?>
2025-10-11 11:08:42 +08:00
<dmodule xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://www.purl.org/dc/elements/1.1/">
2025-09-15 09:58:52 +08:00
<rdf:Description>
<dc:title>`+desStr.name+`</dc:title>
<dc:creator>`+desStr.creator+`</dc:creator>
<dc:permission>`+desStr.permission+`</dc:permission>
<dc:subject/>
<dc:publisher>`+desStr.creator+`</dc:publisher>
<dc:contributor>`+desStr.contributor+`</dc:contributor>
<dc:version>`+desStr.version+`</dc:version>
<dc:level>`+desStr.level+`</dc:level>
<dc:date>`+desStr.date+`</dc:date>
<dc:applicabilityInformation>`+desStr.applicabilityInformation+`</dc:applicabilityInformation>
<dc:qualityVerification>`+desStr.qualityVerification+`</dc:qualityVerification>
<dc:type>text</dc:type>
<dc:format>text/xml</dc:format>
<dc:identifier>`+this.getDmName+`</dc:identifier>
<dc:language>`+desStr.language+`</dc:language>
<dc:rights>01</dc:rights>
</rdf:Description>
<identAndStatusSection>
<dmAddress>
<dmIdent>
<dmCode
modelIdentCode="EXAMPLE01"
systemDiffCode="A1"
systemCode="SYS"
subSystemCode="A"
subSubSystemCode="B"
assyCode="AS01"
disassyCode="DS"
disassyCodeVariant="001"
infoCode="INF"
infoCodeVariant="1"
itemLocationCode="A"
/>
<language languageIsoCode="en" countryIsoCode="US"/>
<issueInfo issueNumber="001" inWork="01"/>
</dmIdent>
<dmAddressItems>
<issueDate year="2023" month="06" day="15"/>
<dmTitle>
<techName>Example Technical Document</techName>
</dmTitle>
</dmAddressItems>
</dmAddress>
<dmStatus>
<security securityClassification="01"/>
<responsiblePartnerCompany enterpriseCode="COMP001">
<enterpriseName>Example Company</enterpriseName>
</responsiblePartnerCompany>
<originator>John Doe</originator>
<brexDmRef>BREX001</brexDmRef>
<qualityAssurance>QA passed</qualityAssurance>
</dmStatus>
</identAndStatusSection>
<content>`
+newDST+
`</content>
</dmodule>`
// this.tempDivData.innerHTML
// ${this.convertHtmlToXmlContent(this.editorContent)}
console.log("${tempDiv.innerHTML}",this.tempDivData.innerHTML)
console.log("${tempDiv}",this.tempDivData)
let xmlData = this.fixHrTagsInContent(this.fixBrTagsInContent(this.fixImgTagsInContent(xmlString, false), false),false);
2025-10-11 11:08:42 +08:00
console.log("存储最终1",this.tempDivData)
console.log("存储最终2",xmlString)
console.log("存储最终3",xmlData)
2025-09-15 09:58:52 +08:00
//存富文本信息
// const ht7 = this.tempDivData.innerHTML;
// console.log("3d转换之后7",ht7)
// const ht8 = xmlData;
// console.log("3d转换之后8",ht8)
// xmlData = this.replacemodel3dImages(xmlData);
if(type){
console.log("存富文本内容时候1",type,this.nowMaxId,xmlData)
this.$sendToDotNet('SaveFile','DMC',this.nowMaxId,xmlData,'000');
}else{
console.log("存富文本内容时候2",type,saveId,this.currentNode,xmlData)
this.$sendToDotNet('SaveFile','DMC',saveId?saveId:this.currentNode.id,xmlData,this.currentNode.lagreVersion);
this.lastClick = this.currentNode.id;
}
2025-10-11 11:08:42 +08:00
this.contentXmlStr = this.editor.txt.html();
2025-09-15 09:58:52 +08:00
if(this.navIsAdd == 'create'){
// this.currentNode = '';
// this.getDmName = this.domNameStr[0]+this.domNameStr[1]+this.domNameStr[2]+this.nowMaxId+this.domNameStr[3]+this.domNameStr[4];
// console.log("新建目录以后调到新的DMC",this.getDmName)
// this.loadFWBFile(this.getDmName);
}
// this.successTips('目录保存完成')
// 处理content标签内的img标签
// this.xmlDownload(xmlData)
// this.xmlDownload(this.fixImgTagsInContent(xmlString, false))
},
// 创建XML文件然后下载
xmlDownload(xmlString) {
// Create download link
const blob = new Blob([xmlString], { type: 'text/xml' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = 'document.xml'
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
URL.revokeObjectURL(url)
},
// // XML文件标签剔除
// restoreContent(html) {
// console.log("XML初始内容",html)
// if (html) {
// const tempDiv = document.createElement('div')
// tempDiv.innerHTML = html
// // 处理所有dmTitle标签
// const dmTitles = tempDiv.querySelectorAll('dmTitle')
// dmTitles.forEach(dmTitle => {
// // 获取dmTitle的子节点
// const children = Array.from(dmTitle.childNodes)
// // 在dmTitle之前插入所有子节点
// children.forEach(child => {
// dmTitle.parentNode.insertBefore(child.cloneNode(true), dmTitle)
// })
// // 移除dmTitle
// dmTitle.parentNode.removeChild(dmTitle)
// })
// console.log('内容还原完成dmTitle标签已被移除')
// console.log("tempDiv.innerHTML",tempDiv.innerHTML)
// this.editor.txt.html(tempDiv.innerHTML)
// }else{
// console.log("空白文档")
// this.editor.txt.html('')
// }
// this.editor.txt.html(tempDiv.innerHTML)
// },
//删除视频
deleteAllVideos() {
const videoWrappers = document.querySelectorAll('.video-wrapper')
if (videoWrappers.length === 0) {
console.log('没有找到可删除的视频')
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()}`
console.log("Date.now",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')
console.log("headings.length",headings.length)
if (headings.length === 0) {
2025-07-25 13:28:47 +08:00
navContainer.innerHTML = '<p>没有找到标题元素,无法生成目录。</p>'
return
}
const tocList = document.createElement('ul')
tocList.style.listStyleType = 'none'
tocList.style.paddingLeft = '0'
headings.forEach(heading => {
2025-09-15 09:58:52 +08:00
console.log("heading",)
2025-07-25 13:28:47 +08:00
const level = parseInt(heading.tagName.substring(1))
const listItem = document.createElement('li')
2025-09-15 09:58:52 +08:00
listItem.style.marginLeft = `${(level - 1) *1.2}rem`;
listItem.style.marginBottom = '5px';
let fontSize = '12px'
switch(level){
case 1:
fontSize = '30px'
break;
case 2:
fontSize = '26px'
break;
case 3:
fontSize = '22px'
break;
case 4:
fontSize = '18px'
break;
case 5:
fontSize = '20px'
break;
}
listItem.style.fontSize = fontSize;
2025-07-25 13:28:47 +08:00
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)
2025-09-15 09:58:52 +08:00
tocList.appendChild(listItem)
2025-07-25 13:28:47 +08:00
})
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)
2025-07-28 17:01:13 +08:00
},
2025-09-15 09:58:52 +08:00
// 处理所有标题元素的ID
processHeadingIds() {
if (!this.editor) return
// 获取当前时间戳简化版只取后8位
const timestamp = Date.now().toString().slice(-8);
let timestamps = parseInt(Date.now().toString().slice(-8));
console.log("时间戳",timestamp,timestamps)
// 获取编辑器内容
const editorHtml = this.editor.txt.html()
if (!editorHtml) return
// 创建一个临时div来操作DOM
const tempDiv = document.createElement('div')
tempDiv.innerHTML = editorHtml
// 获取所有标题元素
const headings = tempDiv.querySelectorAll('h1, h2, h3, h4, h5, h6')
headings.forEach((heading, index) => {
console.log("index",index)
// 生成3个随机字母 + 时间戳后8位
// const newId = `heading-${randomLetters}-${timestamp}`
const randomLetters = this.getRandomLetters(this.idLength)
// const newId = `${heading.id}${randomLetters}${timestamps}`
timestamps++;
console.log("timestamp",timestamps)
const newId = `${randomLetters}`
if(heading.id.length<this.idLength){
heading.id = newId
}
})
// 将修改后的HTML设置回编辑器
this.editor.txt.html(tempDiv.innerHTML);
setTimeout(() => {
this.generateTOC()
}, 200);
},
// 生成随机字母
getRandomLetter() {
const letters = 'abcdefghijklmnopqrstuvwxyz1234567890'
return letters.charAt(Math.floor(Math.random() * letters.length))
},
// 生成随机字母组合
getRandomLetters(length) {
let result = ''
for (let i = 0; i < length; i++) {
result += this.getRandomLetter()
}
return result
},
2025-10-11 11:08:42 +08:00
2025-07-28 17:01:13 +08:00
// XML特殊字符转义
escapeXml(unsafe) {
return unsafe.replace(/[<>&'"]/g, (c) => {
switch (c) {
case '<': return '&lt;';
case '>': return '&gt;';
case '&': return '&amp;';
case '\'': return '&apos;';
case '"': return '&quot;';
default: return c;
}
});
},
2025-10-11 11:08:42 +08:00
2025-07-28 17:01:13 +08:00
// 从S1000D XML导入
handleS1000DUpload(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.extractContentFromS1000D(xmlString);
2025-09-15 09:58:52 +08:00
// const parser = new DOMParser();
// const xmlDoc = parser.parseFromString(html, 'text/xml');
// 获取 content 元素
const contentElement = html.querySelector('content');
console.log("contentElement",contentElement)
if (contentElement) {
// 提取 content 内部的所有子节点并转换为字符串
let innerHtml = '';
Array.from(contentElement.childNodes).forEach(node => {
innerHtml += new XMLSerializer().serializeToString(node);
});
console.log("innerHtml",innerHtml)
this.editor.txt.html(innerHtml)
2025-10-11 11:08:42 +08:00
}
2025-07-28 17:01:13 +08:00
// 重置input值允许重复选择同一文件
event.target.value = '';
};
reader.readAsText(file);
},
// 从S1000D XML提取内容
extractContentFromS1000D(xmlString) {
try {
// 简单提取description内容
const descriptionMatch = xmlString.match(/<description>([\s\S]*?)<\/description>/i);
if (!descriptionMatch || !descriptionMatch[1]) {
throw new Error('未找到description内容');
}
// 反转义XML特殊字符
let content = descriptionMatch[1]
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&amp;/g, '&')
.replace(/&apos;/g, "'")
.replace(/&quot;/g, '"');
// 移除可能的多余空格和换行
content = content.trim();
return content;
} catch (e) {
console.error('S1000D导入错误:', e);
alert(`导入S1000D XML失败: ${e.message}`);
return '';
}
},
2025-09-15 09:58:52 +08:00
rgbToHex(r, g, b) {//色号转换
console.log("colors",this.colors)
return `#${[r, g, b].map(x => x.toString(16).padStart(2, '0')).join('')}`;
2025-10-11 11:08:42 +08:00
},
2025-07-25 13:28:47 +08:00
2025-09-15 09:58:52 +08:00
//保存内容到XML
generateXml(type,saveId) {
this.dataXmlProcessing(type,saveId);
},
//测试 保存目录到XML
navXml() {
const xmlString = `<?xml version="1.0" encoding="UTF-8"?>
<dmodule xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<identAndStatusSection>
<dmAddress>
<dmIdent>
<dmCode
modelIdentCode="EXAMPLE01"
systemDiffCode="A1"
systemCode="SYS"
subSystemCode="A"
subSubSystemCode="B"
assyCode="AS01"
disassyCode="DS"
disassyCodeVariant="001"
infoCode="INF"
infoCodeVariant="1"
itemLocationCode="A"
/>
<language languageIsoCode="en" countryIsoCode="US"/>
<issueInfo issueNumber="001" inWork="01"/>
</dmIdent>
<dmAddressItems>
<issueDate year="2023" month="06" day="15"/>
<dmTitle>
<techName>Example Technical Document</techName>
</dmTitle>
</dmAddressItems>
</dmAddress>
<dmStatus>
<security securityClassification="01"/>
<responsiblePartnerCompany enterpriseCode="COMP001">
<enterpriseName>Example Company</enterpriseName>
</responsiblePartnerCompany>
<originator>John Doe</originator>
<brexDmRef>BREX001</brexDmRef>
<qualityAssurance>QA passed</qualityAssurance>
</dmStatus>
</identAndStatusSection>
<content><infoCode>`
+JSON.stringify(this.treeData)+
`</infoCode></content>
</dmodule>`;
2025-07-25 13:28:47 +08:00
2025-09-15 09:58:52 +08:00
const blob = new Blob([xmlString], { type: 'text/xml' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = 'mulu.xml'
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
URL.revokeObjectURL(url)
},
//测试 加载XML
loadXml() {
this.$refs.fileInput.click()
},
//测试 选择文件
handleFileUpload(event) {
const file = event.target.files[0]
if (!file) return
const reader = new FileReader()
reader.onload = (e) => {
const xmlContent = e.target.result
// console.log("xmlContent",xmlContent)
const parser = new DOMParser()
const xmlDoc = parser.parseFromString(xmlContent, "text/xml")
console.log("xmlDoc",xmlDoc)
const contentNodes = xmlDoc.getElementsByTagName('content')[0];
console.log("xmlDoc.getElementsByTagName('content')",xmlDoc.getElementsByTagName('content'))
console.log("contentNodes",contentNodes)
if (contentNodes) {
const htmlContent = this.convertXmlContentToHtml(contentNodes.innerHTML)
// this.editor.txt.html(htmlContent)
//处理过后再导入
// this.restoreContent(htmlContent)
this.restoreContentXh(htmlContent)
}
2025-07-25 13:28:47 +08:00
}
2025-09-15 09:58:52 +08:00
reader.readAsText(file)
},
completeModel3DTags(htmlString) {
// 处理自闭合的model3d标签替换为完整的闭合标签
return htmlString.replace(/<model3d([^>]*?)\/>/g, (match, attributes) => {
// 返回带有相同属性的完整闭合标签
return `<model3d${attributes}></model3d>`;
});
},
2025-07-25 13:28:47 +08:00
2025-09-15 09:58:52 +08:00
// 解析xml里面 content内容
convertXmlContentToHtml(xmlContent) {
return xmlContent
.replace(/<para>/g, '<p>')
.replace(/<\/para>/g, '</p>')
.replace(/<emphasis emphasisType="bold">/g, '<strong>')
.replace(/<\/emphasis>/g, '</strong>')
.replace(/<emphasis emphasisType="italic">/g, '<em>')
},
2025-07-25 13:28:47 +08:00
2025-09-15 09:58:52 +08:00
/**
* 修复content标签内的img标签闭合符
* @param {string} inputStr 输入HTML
* @param {boolean} useSlash 是否使用自闭合
* @returns {string} 修正后的HTML
*/
fixImgTagsInContent(inputStr, useSlash) {
const contentRegex = /<content>([\s\S]*?)<\/content>/g
return inputStr.replace(contentRegex, (contentMatch, innerContent) => {
const fixedInnerContent = innerContent.replace(
/<img\b([^>]*)>/g,
(imgMatch, imgAttributes) => {
// 已有闭合符则不处理
if (imgMatch.endsWith('/>') || imgMatch.includes('</img>')) {
return imgMatch
}
// 根据参数决定闭合方式
return useSlash
? `<img${imgAttributes} />`
: `<img${imgAttributes}></img>`
}
)
return `<content>${fixedInnerContent}</content>`
})
},
2025-07-25 13:28:47 +08:00
2025-09-15 09:58:52 +08:00
// 检测hr标签是否闭合
fixHrTagsInContent(inputStr, useSlash) {
const contentRegex = /<content>([\s\S]*?)<\/content>/g
return inputStr.replace(contentRegex, (contentMatch, innerContent) => {
const fixedInnerContent = innerContent.replace(
/<hr\b([^>]*)>/g,
(imgMatch) => {
// 已有闭合符则不处理
if (imgMatch.endsWith('/>') || imgMatch.includes('</hr>')) {
return imgMatch
}
// 根据参数决定闭合方式
return useSlash
? `<hr/>`
: `<hr></hr>`
}
)
return `<content>${fixedInnerContent}</content>`
})
},
2025-07-25 13:28:47 +08:00
2025-09-15 09:58:52 +08:00
// 检测br标签是否闭合
fixBrTagsInContent(inputStr, useSlash) {
const contentRegex = /<content>([\s\S]*?)<\/content>/g
return inputStr.replace(contentRegex, (contentMatch, innerContent) => {
const fixedInnerContent = innerContent.replace(
/<br\b([^>]*)>/g,
(imgMatch, imgAttributes) => {
// 已有闭合符则不处理
if (imgMatch.endsWith('/>') || imgMatch.includes('</br>')) {
return imgMatch
}
// 根据参数决定闭合方式
return useSlash
? `<br${imgAttributes} />`
: `<br${imgAttributes}></br>`
}
)
return `<content>${fixedInnerContent}</content>`
})
},
2025-07-25 13:28:47 +08:00
2025-09-15 09:58:52 +08:00
//富文本内容打标签
dataXmlProcessing(type,saveId) {
2025-10-17 08:28:46 +08:00
let html_1 = '';
let html = '';
if(this.editor){
html = this.editor.txt.html()
console.log('保存内容',html);
// 正则表达式匹配img、audio、video标签的src属性
// 支持三种标签:<img ...>、<audio ...>、<video ...>
// 捕获组1: 标签名和src="之前的部分
// 捕获组2: 提取文件名(最后一个/后面的内容)
// 捕获组3: 保留"及之后的部分
const reg = /(<(img|audio|video)[^>]+src=")[^"]+\/([^"]+)("[^>]*>)/gi;
// 替换为src="文件名"
html_1 = html.replace(reg, '$1$3$4');
console.log('解析地址:',html_1)
}
2025-09-15 09:58:52 +08:00
2025-07-25 13:28:47 +08:00
2025-09-15 09:58:52 +08:00
// const reg2 = /(<(img|audio|video)[^>]+src=")(?!http:\/\/)([^"]+)("[^>]*>)/gi;
// let jc = 'http://localhost:5432/';
// // 替换为src="基础URL+文件名"
// // 这里假设原路径可能包含DM_Material目录如果不需要可以去掉
// let html_2 = html_1.replace(reg2, `$1${jc}$3$4`);
// console.log('还原地址:',html_2)
this.tempDivData = document.createElement('div')
html_1 = this.replacemodel3dImages(html_1);
// const ht1 = html_1;
// console.log("3d转换之后1",ht1)
this.tempDivData.innerHTML = html_1;
this.xh(this.oldSelector,this.newSelector,type,saveId);
},
2025-10-17 08:28:46 +08:00
countDomNodes() {
// 重置计数
this.domCount = 0
this.elementCount = 0
this.textCount = 0
this.commentCount = 0
// 这里可以改为你需要统计的容器选择器
// 例如: '#editor' 或 '.tree-container' 或 'body'
const targetSelector = '#editor'
const container = document.querySelector(targetSelector)
if (!container) {
this.$message.error('未找到目标容器')
return
}
this.countTarget = targetSelector
// 递归统计所有节点
this.traverseNodes(container)
// 显示结果弹窗
this.countDialogVisible = true
},
2025-09-15 09:58:52 +08:00
2025-10-17 08:28:46 +08:00
// 递归遍历节点并计数
traverseNodes(node) {
if (!node) return
// 总节点数+1
this.domCount++
// 分类计数
switch(node.nodeType) {
case 1: // 元素节点
this.elementCount++
break
case 3: // 文本节点
// 过滤空白文本节点
if (node.textContent.trim()) {
this.textCount++
}
break
case 8: // 注释节点
this.commentCount++
break
}
// 递归处理子节点
if (node.childNodes && node.childNodes.length) {
Array.from(node.childNodes).forEach(child => {
this.traverseNodes(child)
})
}
},
2025-09-15 09:58:52 +08:00
// XML文件标签剔除
restoreContentXh(html) {
2025-10-17 08:28:46 +08:00
// console.log("XML初始内容",html)
2025-09-15 09:58:52 +08:00
if (html) {
this.tempDivData = document.createElement('div')
this.tempDivData.innerHTML = html
let times = this.oldSelector.length;
for(let i =0;i<times;i++){
// 处理所有dmTitle标签
const dmTitles = this.tempDivData.querySelectorAll(this.newSelector[i])
dmTitles.forEach(dmTitle => {
// 获取dmTitle的子节点
const children = Array.from(dmTitle.childNodes)
2025-10-17 08:28:46 +08:00
// console.log("剔除标签:",dmTitles,children)
2025-09-15 09:58:52 +08:00
// 在dmTitle之前插入所有子节点
children.forEach(child => {
dmTitle.parentNode.insertBefore(child.cloneNode(true), dmTitle)
})
// 移除dmTitle
dmTitle.parentNode.removeChild(dmTitle)
2025-10-17 08:28:46 +08:00
// console.log("剔除标签移除:",dmTitle,'替换成',dmTitle)
2025-09-15 09:58:52 +08:00
})
}
console.log('内容还原完成dmTitle标签已被移除')
2025-10-17 08:28:46 +08:00
// console.log("tempDiv.innerHTML",this.tempDivData.innerHTML)
2025-09-15 09:58:52 +08:00
const reg2 = /(<(img|audio|video)[^>]+src=")(?!http:\/\/)([^"]+)("[^>]*>)/gi;
let jc = this.lisenPath;
// 检查并去除开头的双引号
if (jc.startsWith('"')) {
jc = jc.substring(1);
}
// 检查并去除结尾的双引号
if (jc.endsWith('"')) {
jc = jc.substring(0, jc.length - 1);
}
// 替换为src="基础URL+文件名"
// 这里假设原路径可能包含DM_Material目录如果不需要可以去掉
let html_2 = this.tempDivData.innerHTML.replace(reg2, `$1${jc}$3$4`);
// html_2 = this.modelToImg(html_2);
2025-10-17 08:28:46 +08:00
// console.log('还原地址:',html_2)
2025-09-15 09:58:52 +08:00
this.editor.txt.html(html_2)
this.contentXmlStr = this.editor.txt.html();
}else{
console.log("空白文档")
this.editor.txt.html('')
this.contentXmlStr = this.editor.txt.html();
}
},
// XML文件标签剔除
restoreContentXh2(html) {
2025-10-17 08:28:46 +08:00
// console.log("XML初始内容",html)
2025-09-15 09:58:52 +08:00
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)
2025-10-17 08:28:46 +08:00
// console.log("剔除标签:",dmTitles,children)
2025-09-15 09:58:52 +08:00
// 在dmTitle之前插入所有子节点
children.forEach(child => {
dmTitle.parentNode.insertBefore(child.cloneNode(true), dmTitle)
})
// 移除dmTitle
dmTitle.parentNode.removeChild(dmTitle)
2025-10-17 08:28:46 +08:00
// console.log("剔除标签移除:",dmTitle,'替换成',dmTitle)
2025-09-15 09:58:52 +08:00
})
}
console.log('内容还原完成dmTitle标签已被移除')
2025-10-17 08:28:46 +08:00
// console.log("tempDiv.innerHTML",this.tempDivData1.innerHTML)
2025-09-15 09:58:52 +08:00
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+'/';
}
// 替换为src="基础URL+文件名"
// 这里假设原路径可能包含DM_Material目录如果不需要可以去掉
2025-10-11 11:08:42 +08:00
let html_2 = this.tempDivData1.innerHTML.replace(reg2, `$1${jc}$3$4`);
2025-09-15 09:58:52 +08:00
// html_2 = this.modelToImg(html_2);
2025-10-17 08:28:46 +08:00
// console.log("大豪科技等哈时间",this.viewLis)
// console.log('加载还原地址:',html_2)
2025-10-11 11:08:42 +08:00
let processedL = this.hintFun(html_2)
this.neirong = this.modelToImg(processedL);
2025-09-15 09:58:52 +08:00
// document.getElementsByClassName("loadContent")[0].innerHTML=html_2;
// document.getElementsByClassName("loadContent1")[0].innerHTML=html_2;
2025-10-11 11:08:42 +08:00
// console.log('加载还原地址:',html_3)
2025-09-15 09:58:52 +08:00
// this.editor.txt.html(html_2)
// this.contentXmlStr = this.editor.txt.html();
}else{
console.log("空白文档")
// this.editor.txt.html('')
// this.contentXmlStr = this.editor.txt.html();
}
},
2025-10-11 11:08:42 +08:00
hintFun(html_2) {
let html = html_2;
// 先定义所有需要用到的变量,确保初始化顺序
// 需要移除的class
// const classesToRemove = ['borderStyle_yellow', 'borderStyle_red'];
// // 处理class属性 - 先替换指定class
// html = html.replace(/class="([^"]*)"/g, (match, classValues) => {
// let newClassValues = classValues;
// // 在替换函数内部定义class映射确保在使用前初始化
// const classMappings = {
// 'teshu': 'testBo',
// 'teshu2': 'testBo2'
// };
// // 替换class
// Object.keys(classMappings).forEach(oldClass => {
// const newClass = classMappings[oldClass];
// const regex = new RegExp(`\\b${oldClass}\\b`, 'g');
// newClassValues = newClassValues.replace(regex, newClass);
// });
// // 移除不需要的class
// classesToRemove.forEach(classToRemove => {
// const regex = new RegExp(`\\b${classToRemove}\\b\\s*`, 'g');
// newClassValues = newClassValues.replace(regex, '').trim();
// });
// return `class="${newClassValues}"`;
// });
// 定义需要替换的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}`;
});
2025-09-15 09:58:52 +08:00
2025-10-11 11:08:42 +08:00
return html;
// const regex = /\s*class\s*=\s*"teshu"\s*/gi;
// const regex2 = /\s*class\s*=\s*"teshu2"\s*/gi;
// // 将匹配到的class替换为class="testBo"
// const styleRegex = /(<div[^>]*?)style\s*=\s*"[^"]*?"\s*([^>]*?class\s*=\s*"teshu"[^>]*?>)/gi;
// html_2 = html_2.replace(styleRegex, '$1$2');
// const styleRegex2 = /(<div[^>]*?)style\s*=\s*"[^"]*?"\s*([^>]*?class\s*=\s*"teshu2"[^>]*?>)/gi;
// html_2 = html_2.replace(styleRegex2, '$1$2');
// let html_3 = html_2.replace(regex, ' class="testBo"');
// let html_4 = html_3.replace(regex2, ' class="testBo2"');
// // let html_4 = html_3;
// // 正则表达式匹配class="testBo"的div标签
// // 匹配模式:<div class="testBo"[属性...]>内容</div>
// const regex1 = /(<div\s+class="testBo"[^>]*>)(.*?)(<\/div>)/gi;
// const regex22 = /(<div\s+class="testBo2"[^>]*>)(.*?)(<\/div>)/gi;
// // 替换匹配到的内容
// // 在原内容外层包裹<div style='background:#fff'>...</div>
// let processed = html_4.replace(regex22, (match, startTag, content, endTag) => {
// return `${startTag}<div style='background:#fff;padding: 10px;
// border: 3px solid #000;
// border-radius: 8px;
// '>${content}</div>${endTag}`;
// });
// console.log("预览数据processed",processed)
// let processedL = processed.replace(regex1, (match, startTag, content, endTag) => {
// return `${startTag}<div style='background:#fff;padding: 10px;
// border: 3px solid #000;
// border-radius: 8px;
// '>${content}</div>${endTag}`;
// });
// console.log("预览数据processedL",processedL)
// return processedL
},
2025-09-15 09:58:52 +08:00
//处理 3d模型标签
replaceModel3dToImg(htmlString) {
// 创建临时DOM元素处理HTML
const tempDiv = document.createElement('div');
tempDiv.innerHTML = htmlString;
// 查找所有model3d标签
const model3dElements = tempDiv.querySelectorAll('model3d');
model3dElements.forEach(model3d => {
// 创建新的img元素
const img = document.createElement('img');
// 复制所有属性
Array.from(model3d.attributes).forEach(attr => {
img.setAttribute(attr.name, attr.value);
});
// 替换元素
model3d.parentNode.replaceChild(img, model3d);
});
return tempDiv.innerHTML;
},
//判断富文本内容是否更改
dmcIsChange() {
2025-10-11 11:08:42 +08:00
if(this.editor){//初始化时候
console.log("this.editor.txt.html()",this.editor.txt.html())
console.log("this.contentXmlStr",this.contentXmlStr)
console.log("验证结果",this.editor.txt.html() == this.contentXmlStr)
return this.editor.txt.html() == this.contentXmlStr;
}else{
return true
}
2025-09-15 09:58:52 +08:00
},
//测试 启用右键功能
enableContextMenu() {
console.log("进入isContextMenuEnabled",this.isContextMenuEnabled)
if (this.isContextMenuEnabled) return;
this.isContextMenuEnabled = true;
// 获取#nav下的所有li元素
const tocItems = document.querySelectorAll('.elTree .el-tree-node__content');
// 为每个li元素绑定右键事件
tocItems.forEach((item, index) => {
// 为元素设置唯一ID
const elementId = `toc-item-${index}`;
item.id = elementId;
// 初始化参数存储
if (!this.itemParams[elementId]) {
this.$set(this.itemParams, elementId, '');
}
item.addEventListener('contextmenu', (e) => {
e.preventDefault();
this.showContextMenu(e, item);
});
item.addEventListener('click', (e) => {
console.log("左键",e,item)
this.dialogVisible = true;
});
});
// alert('右键菜单功能已启用!');
},
//测试 显示右键菜单
showContextMenu(e, element) {
console.log("ID",element)
// 获取该 <a> 元素
// const linkElement = element.querySelector('#toc-item-0 a');
// 提取 # 后面的参数
// const hashValue = linkElement.getAttribute('href');
// const hashValue2 = hashValue.split('#')[1];
// console.log(hashValue,hashValue2);
if (!this.isContextMenuEnabled) return;
// 设置右键菜单位置和当前选中元素
this.contextMenu = {
visible: true,
x: e.clientX,
y: e.clientY,
selectedElement: element,
selectedParam: this.itemParams[element.id] || ''
}
// 点击其他地方关闭菜单
document.addEventListener('click', this.closeContextMenu, { once: true });
},
//测试 关闭右键菜单
closeContextMenu() {
this.contextMenu.visible = false;
},
//测试 选择右键菜单选项
selectMenuOption(option) {
if (this.contextMenu.selectedElement) {
const element = this.contextMenu.selectedElement;
// 更新元素的参数
this.$set(this.itemParams, element.id, option);
// 在元素上显示参数(可选)
const paramSpan = element.querySelector('.param-display');
if (paramSpan) {
paramSpan.textContent = `(${option})`;
} else {
const span = document.createElement('span');
span.className = 'param-display';
span.style.cssText = 'color: #f00; margin-left: 10px;';
span.textContent = `(${option})`;
element.appendChild(span);
}
this.closeContextMenu();
}
},
// 新增方法打印nav内容
logTocItems() {
const navElement = document.getElementById('nav');
if (!navElement) {
console.error('未找到ID为"nav"的容器');
return;
}
// 获取nav内的HTML内容
const navHtml = navElement.innerHTML;
// 获取nav内的文本内容
const navText = navElement.innerText || navElement.textContent;
// 获取结构化数据(包括参数)
const structuredData = this.getStructuredNavData();
console.log('====== nav的HTML内容 ======');
console.log(navHtml);
console.log('====== nav的文本内容 ======');
console.log(navText);
console.log('====== nav的结构化数据 ======');
console.log(structuredData);
},
// 获取结构化数据
getStructuredNavData() {
const items = document.querySelectorAll('#nav ul li');
return Array.from(items).map(item => {
return {
id: item.id,
text: item.innerText.trim(),
html: item.innerHTML,
param: this.itemParams[item.id] || '未设置'
};
});
},
//测试 查看图片
openDialog() {
// this.imageStyle();
const imgItems = document.querySelectorAll('#main img');
console.log("imgItems",imgItems)
imgItems.forEach((item, index) => {
item.addEventListener('click', (e) => {
console.log("左键",e,item,index,item.src)
// 通过选择器获取
// let imgSrc = e.src;
this.scale = 1;
this.rotation = 0;
this.currentImage = item.src;
this.dialogVisibleImg = true;
});
});
// this.currentImage = this.images[index]
// this.dialogVisible = true
// this.reset() // 每次打开重置状态
},
//测试 放大
zoomIn() {
console.log("放大")
this.scale = 1.1*this.scale
},
//测试 缩小
zoomOut() {
if (this.scale > 0.5) {
this.scale -= 0.2
}
},
//测试 旋转
rotate() {
this.rotation += 90
},
//测试 重置
reset() {
this.scale = 1
this.rotation = 0
this.translateX = 0
this.translateY = 0
},
//测试 开始拖动
2025-10-17 08:28:46 +08:00
startDrag(e) {
this.isDragging = true;
const startX = e.clientX;
const startWidth = this.leftWidth;
2025-09-15 09:58:52 +08:00
2025-10-17 08:28:46 +08:00
const handleMouseMove = (e) => {
if (!this.isDragging) return;
const diffX = e.clientX - startX;
// 限制最小宽度
const newWidth = Math.max(100, startWidth + diffX);
// 限制最大宽度
this.leftWidth = Math.min(500, newWidth);
this.getWindowSize();
};
const handleMouseUp = () => {
this.isDragging = false;
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
};
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
e.preventDefault();
2025-09-15 09:58:52 +08:00
},
//测试 拖动图片
dragImage(e) {
if (!this.isDragging) return
const clientX = e.type === 'mousemove' ? e.clientX : e.touches[0].clientX
const clientY = e.type === 'mousemove' ? e.clientY : e.touches[0].clientY
this.translateX += (clientX - this.startX) / this.scale
this.translateY += (clientY - this.startY) / this.scale
this.startX = clientX
this.startY = clientY
},
//测试 停止拖动
endDrag() {
this.isDragging = false
document.removeEventListener('mousemove', this.dragImage)
document.removeEventListener('touchmove', this.dragImage)
document.removeEventListener('mouseup', this.endDrag)
document.removeEventListener('touchend', this.endDrag)
},
//测试 图片样式
imageStyle() {
return {
transform: `
scale(${this.scale})
rotate(${this.rotation}deg)
translate(${this.translateX}px, ${this.translateY}px)
`,
cursor: this.isDragging ? 'grabbing' : 'grab'
}
2025-10-17 08:28:46 +08:00
},
2025-09-15 09:58:52 +08:00
//获取屏幕尺寸
getWindowSize() {
// this.windowW = window.innerWidth
// this.windowH = window.innerHeigh
// t
2025-10-17 08:28:46 +08:00
// this.leftHeight = window.innerHeight - 200;
// this.editorHeight = window.innerHeight - 250;
2025-10-11 11:08:42 +08:00
if(this.currentNode){
const element = document.querySelector('.w-e-toolbar')
const container = document.querySelector('.w-e-text-container');
const rightDivHeight = document.querySelector(".rightDiv").scrollHeight;
2025-10-17 08:28:46 +08:00
container.style.height = (rightDivHeight -element.scrollHeight - 80 ) +'px' ;
console.log("内容高度2", (rightDivHeight -element.scrollHeight - 80 ) +'px')
2025-10-11 11:08:42 +08:00
}
2025-10-17 08:28:46 +08:00
this.windowH = window.innerHeight;
this.leftHeight = window.innerHeight - 200; // 检查此值是否合理
this.editorHeight = window.innerHeight - 250;
// 强制刷新滚动条
this.$nextTick(() => {
const scrollbar = this.$refs.scrollbar; // 需给 el-scrollbar 添加 ref="scrollbar"
if (scrollbar) scrollbar.update();
});
2025-09-15 09:58:52 +08:00
},
// 尺寸变化时的处理函数
handleResize() {
// 使用节流优化性能(频繁触发时限制执行频率)
if (this.resizeTimer) clearTimeout(this.resizeTimer)
this.resizeTimer = setTimeout(() => {
this.getWindowSize()
console.log('窗口尺寸变化:', this.windowW, this.windowH)
// 在这里可以添加尺寸变化后的业务逻辑
// 例如:调整组件布局、重新计算元素位置等
}, 100) // 100ms 节流延迟,可根据需求调整
},
// 加载XML文件 dmc
loadFileBtn() {
this.$sendToDotNet('GetExistenceDMContent')
},
// 获取屏幕和窗口尺寸
getScreenSize() {
// 屏幕整体尺寸(设备的屏幕尺寸)
this.screenWidth = window.screen.width;
this.screenHeight = window.screen.height;
// 浏览器窗口尺寸(可视区域尺寸)
this.windowW = window.innerWidth;
this.windowH = window.innerHeight;
console.log("屏幕变化的尺寸",window.screen.width,window.screen.height,window.innerWidth,window.innerHeight)
// 可以在这里添加需要根据尺寸执行的逻辑
this.handleSizeChange();
},
// 处理窗口大小变化(使用防抖优化性能)
// handleResize() {
// // 清除之前的定时器
// if (this.resizeTimer) {
// clearTimeout(this.resizeTimer);
// }
// // 防抖50ms后再执行避免频繁触发
// this.resizeTimer = setTimeout(() => {
// this.getScreenSize();
// this.resizeTimer = null;
// }, 50);
// },
// 根据尺寸变化执行的逻辑
handleSizeChange() {
// 这里可以添加尺寸变化时需要执行的操作
console.log('尺寸变化:', {
screenWidth: this.screenWidth,
screenHeight: this.screenHeight,
windowWidth: this.windowW,
windowHeight: this.windowH
});
},
//预览加载的XML
viewLoadDMFile() {
this.maskViewShow = true;
// this.draggableVis = true;
// localStorage.setItem("fileName",'dassad')
this.$sendToDotNet('DMPreview','UserLocalDMPreview')
},
//解析加载的DMC
parseXmlDmc() {
try {
// 解析XML字符串
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(this.loadFileXML, "text/xml");
// 检查解析错误
const errorNode = xmlDoc.querySelector("parsererror");
if (errorNode) {
throw new Error("XML解析错误: " + errorNode.textContent);
}
// 提取content标签内容
this.extractContent(xmlDoc);
// 解析rdf:Description
this.parseRdfDescription(xmlDoc);
} catch (error) {
console.error("解析失败:", error);
// alert("解析XML失败: " + error.message);
}
},
//解析新建目录时候的DMC文件
parseXmlDmc_loadFile() {
try {
// 解析XML字符串
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(this.viewXml, "text/xml");
2025-10-11 11:08:42 +08:00
console.log("得到的1",xmlDoc)
2025-09-15 09:58:52 +08:00
// 检查解析错误
const errorNode = xmlDoc.querySelector("parsererror");
2025-10-11 11:08:42 +08:00
console.log("得到的2",errorNode)
2025-09-15 09:58:52 +08:00
if (errorNode) {
throw new Error("XML解析错误: " + errorNode.textContent);
}
// 提取content标签内容
this.extractContent2(xmlDoc);
} catch (error) {
console.error("解析失败:", error);
// alert("解析XML失败: " + error.message);
}
},
//验证是否修改过的dmc文件
handleCheckVersion() {
this.showModifyBtn = true;
// 可选若需高亮有01版本的节点可在此处触发树重渲染
this.$nextTick(() => {
this.$refs.tree.updateKeyChildren(); // 强制树更新节点
});
},
// 3. 递归判断当前节点或其所有子节点是否存在minorVersion: '01'
hasMinorVersion01(node) {
// 边界条件节点不存在则返回false
if (!node) return false;
// 第一步检查当前节点是否为01版本
if (node.minorVersion === '01') {
return true;
}
// 第二步:若有子节点,递归检查所有子节点
if (node.children && node.children.length > 0) {
// 只要有一个子节点满足就返回true
return node.children.some(child => this.hasMinorVersion01(child));
}
// 第三步无子孙节点且当前节点不是01版本返回false
return false;
},
// 4. 【修改】文字点击事件(可根据需求扩展修改逻辑)
handleModify(node) {
console.log('当前需要修改的节点:', node);
// 示例:可打开修改弹窗、跳转修改页面等
// this.$emit('openModifyDialog', node);
},
// 提取content标签内的内容
extractContent(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.loadFileDMC = contentHtml.trim();
console.log("解析出来DMC内容",contentHtml)
console.log("解析出来DMC内容",contentHtml.trim())
// this.contentResult = contentHtml.trim();
},
// 提取新建目录时候的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);
}
}
2025-10-11 11:08:42 +08:00
// this.viewXmlContent = contentHtml.trim();
2025-09-15 09:58:52 +08:00
console.log("加载解析出来DMC内容",contentHtml)
console.log("加载解析出来DMC内容",contentHtml.trim())
2025-10-11 11:08:42 +08:00
this.restoreContentXh2(contentHtml.trim())
2025-09-15 09:58:52 +08:00
// this.contentResult = contentHtml.trim();
},
// 解析rdf:Description为对象
parseRdfDescription(xmlDoc) {
const rdfObj = {};
const rdfNamespace = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
const rdfNode = xmlDoc.getElementsByTagNameNS(rdfNamespace, "Description")[0];
if (!rdfNode) {
// this.rdfResult = { error: "未找到rdf:Description标签" };
return;
}
// 解析dc命名空间下的所有子节点
2025-10-11 11:08:42 +08:00
const dcNamespace = "http://www.purl.org/dc/elements/1.1/";
2025-09-15 09:58:52 +08:00
const dcNodes = rdfNode.getElementsByTagNameNS(dcNamespace, "*");
Array.from(dcNodes).forEach(node => {
const key = node.localName; // 获取不带命名空间前缀的标签名
const value = node.textContent.trim() || ""; // 处理空标签
rdfObj[key] = value;
});
console.log("解析出来DMC目录内容",rdfObj)
// this.rdfResult = rdfObj;
for(let key in this.form){
this.form[key] = rdfObj[key]?rdfObj[key]:'';
}
this.form.name = rdfObj.title;
this.form.version = '000';
},
//转换时间值
timeChange(isoTime){
const date = new Date(isoTime);
// 3. 提取时间组件(注意:月份从 0 开始,需 +1数字不足 2 位时补 0
const year = date.getFullYear(); // 年份2025
const month = String(date.getMonth() + 1).padStart(2, "0"); // 月份09getMonth() 返回 8+1 后补 0
const day = String(date.getDate()).padStart(2, "0"); // 日期01
const hours = String(date.getHours()).padStart(2, "0"); // 小时1624小时制
const minutes = String(date.getMinutes()).padStart(2, "0"); // 分钟39
const seconds = String(date.getSeconds()).padStart(2, "0"); // 秒07
// 4. 拼接成正常时间格式
const normalTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
return normalTime;
},
// 关闭预览弹窗
handleCloseMask() {
this.maskViewShow = false;
2025-10-11 11:08:42 +08:00
},
// 关闭修改书名弹窗
handleCloseEditBookName() {
this.getBookName = this.getBookNameDf;
this.editBookNameDialog = false;
2025-09-15 09:58:52 +08:00
},
//关闭弹窗节点
handleClose(type) {
2025-10-11 11:08:42 +08:00
this.loadFileDMC = '';
2025-09-15 09:58:52 +08:00
console.log('点',type);
this.dialogVisibleHistory = false;
this.dialogVisibleNav = false;
this.dialogVisibleRight = false;
this.dialogVisibleTips = false;
this.dialogVisibleTips2 = false;
this.dialogVisibleBland = false;
this.dialogVisibleBland = false;
this.currentNode = null;
this.clearNodeState();
},
handleClose2() {
this.dialogVisibleHistory = false;
this.dialogVisibleNav = false;
this.dialogVisibleRight = false;
this.dialogVisibleTips = false;
this.dialogVisibleTips2 = false;
this.dialogVisibleBland = false;
this.dialogVisibleBland = false;
},
//测试 保存当前目录信息
saveNowDmcClick() {
const targetNode = this.findNodeById(this.treeData,this.currentNode.id);
targetNode.minorVersion = '01';
const aaa = this.editor.txt.html();
console.log("当前的所有html内容4",aaa)
this.catalogueAnalysis(this.treeData);
this.generateXml(false,this.currentNode.id);
// this.$sendToDotNet('RefreshTree');
this.contentXmlStr = this.editor.txt.html();
},
//保存当前DMC信息
saveNowDmc2(type) {
2025-10-17 08:28:46 +08:00
if(this.editor){
const html4 = this.editor.txt.html();
console.log("保存内容4",html4)
}
2025-09-15 09:58:52 +08:00
console.log("保存时候点击",this.lastClick)
if(type == 'save'){
console.log("保存时候点击 this.currentNode",this.currentNode,this.currentNode.minorVersion)
// if(this.currentNode.minorVersion == '00'){
const targetNode = this.findNodeById(this.treeData,this.lastClick);
targetNode.minorVersion = '01';
// }
console.log("保存时候点击 treedata",this.treeData)
this.catalogueAnalysis(this.treeData);
this.generateXml(false,this.lastClick);
2025-10-17 08:28:46 +08:00
this.contentXmlStr = this.editor.txt.html();
2025-09-15 09:58:52 +08:00
// const targetNode = this.findNodeById(this.treeData, this.lastClick);
// if (targetNode) {
// targetNode.minorVersion = '01';
// }
// this.catalogueAnalysis(this.treeData);
}else if(type == 'noSave'){
this.getDmName = this.domNameStr[0]+this.domNameStr[1]+this.domNameStr[2]+this.lastClick+this.domNameStr[3]+this.domNameStr[4];
console.log("加载富文本的文件名",this.getDmName)
this.loadFWBFile(this.getDmName);
console.log("不保存")
}
this.dialogVisibleTips2 = false;
console.log("saveNowDmc2",type)
},
//保存当前DMC信息
saveNowDmc(type){
if(type == 'save'){
this.navIsAdd = 'other'
this.generateXml(false);
this.dialogVisibleTips = false;
this.dialogVisibleNav = true;
}else if(type == 'noSave'){
this.getDmName = this.domNameStr[0]+this.domNameStr[1]+this.domNameStr[2]+this.lastClick+this.domNameStr[3]+this.domNameStr[4];
this.loadFWBFile(this.getDmName);
this.dialogVisibleTips = false;
this.dialogVisibleNav = true;
}
2025-10-11 11:08:42 +08:00
this.loadFileDMC = '';
2025-09-15 09:58:52 +08:00
this.clearFormData();
this.showView = false;
this.$sendToDotNet('CancelUserHistoy')
},
//测试 绑定资源弹窗显示
showBand() {
this.dialogVisibleRight = false;
this.dialogVisibleBland = true;
},
//测试 历史版本展示
showHistory() {
this.dialogVisibleRight = false;
this.dialogVisibleHistory = true;
this.getDmName = this.domNameStr[0]+this.domNameStr[1]+this.domNameStr[2]+this.currentNode.id+this.domNameStr[3]+this.domNameStr[4];
console.log("历史版本查询时候的名字",this.getDmName)
console.log("历史版本查询时候的domNameStr",this.domNameStr)
console.log("历史版本查询时候的currentNode",this.currentNode)
this.$sendToDotNet("GetHistoryVesions",this.getDmName)
},
//版本定稿
finalVersion() {
console.log("定版时候的参数",this.currentNode)
const newStr = 'A-A_'+this.currentNode.lagreVersion+'_00';
// let versionName = this.domNameStr[0]+this.domNameStr[1]+this.domNameStr[2]+this.currentNode.id+this.domNameStr[3]+this.domNameStr[4]+'.xml';
const versionName = this.domNameStr[0]+this.domNameStr[1]+this.domNameStr[2]+this.currentNode.id+newStr+this.domNameStr[4]+'.xml';
// this.currentNode.minorVersion = '00';
const targetNode = this.findNodeById(this.treeData,this.currentNode.id);
targetNode.minorVersion = '00';
2025-10-11 11:08:42 +08:00
// targetNode.lagreVersion = this.currentNode.lagreVersion
const num = parseInt(this.currentNode.lagreVersion, 10);
// 3. 加1运算
const newNum = num + 1;
// 4. 格式化为3位带前导零的字符串
this.form.version = String(newNum).padStart(3, "0");
2025-09-15 09:58:52 +08:00
2025-10-11 11:08:42 +08:00
console.log("定稿时候逇form",this.form)
2025-09-15 09:58:52 +08:00
this.catalogueAnalysis(this.treeData);
2025-10-11 11:08:42 +08:00
this.generateXml(false);
2025-09-15 09:58:52 +08:00
this.$sendToDotNet("CreatVersion",versionName)
},
//显示新建弹窗
showAddDialog(type) {
console.log("点击新建",type)
this.$sendToDotNet("CancelPriview")
this.navIsAdd = type;
if(type == "create"){
this.form.name = '';
this.isLoadOldDmc = '2',
this.clearFormData();
}else{
this.form.name = this.currentNode.name;
}
if(this.dmcIsChange()){
this.dialogVisibleNav = true;
2025-10-11 11:08:42 +08:00
this.loadFileDMC = '';
2025-09-15 09:58:52 +08:00
this.showView = false;
}else{
this.dialogVisibleTips = true;
}
// this.$sendToDotNet('CancelUserHistoy')
this.dialogVisibleRight = false;
},
//截取路径信息
removeQuotationMarks(data) {
const result = data.replace(/^"|"$/g, '');
return result;
},
//目录节点点击
2025-10-17 08:28:46 +08:00
handleNodeClick(data) {
// this.currentNode = data; //有问题
2025-10-11 11:08:42 +08:00
this.navIsAdd = '';
2025-09-15 09:58:52 +08:00
console.log("这一次点击的节点信息",data);
console.log("上一次点击的时候的ID",this.lastClick)
console.log("这一次点击的时候的ID",this.nowClick)
if(this.lastClick == this.nowClick.id){
2025-10-17 08:28:46 +08:00
this.currentNode = data;
2025-09-15 09:58:52 +08:00
this.nowClick = data;
2025-10-17 08:28:46 +08:00
this.lastClick = data.id;
}else{
2025-09-15 09:58:52 +08:00
console.log("中中中中中",this.lastClick,this.dmcIsChange())
if(this.lastClick&&!this.dmcIsChange()){
this.dialogVisibleTips2 = true;
console.log("dialogVisibleTips2出现")
console.log("恢复成上一次点击",this.lastClick)
// this.$refs.tree.setCheckedKeys([this.lastClick]);
// 确保DOM更新后再重置状态
this.$nextTick(() => {
this.$refs.tree.setCheckedKeys([this.lastClick]);
this.$refs.tree.setCurrentKey(this.lastClick);
});
}else{
2025-10-17 08:28:46 +08:00
this.currentNode = data;
2025-09-15 09:58:52 +08:00
const target = this.domNameStr[3];
// 假设需要替换的格式是 "前缀_xxx_yy"其中xxx是3位yy是2位
// 先找到最后两个下划线的位置
const lastUnderlineIndex = target.lastIndexOf('_');
const secondLastUnderlineIndex = target.lastIndexOf('_', lastUnderlineIndex - 1);
if (lastUnderlineIndex > -1 && secondLastUnderlineIndex > -1) {
// 截取前缀部分(到第二个下划线)
const prefix = target.substring(0, secondLastUnderlineIndex + 1);
// 截取中间部分3位和末尾部分2位并用新值替换
// const newValue = `${prefix}${data.lagreVersion}_${data.minorVersion}`;
const newValue = `${prefix}${data.lagreVersion}_00`;
// 更新数组
this.domNameStr.splice(3, 1, newValue);
this.replaced = true;
}
console.log("点击时候的节点data",data.id)
this.getDmName = this.domNameStr[0]+this.domNameStr[1]+this.domNameStr[2]+data.id+this.domNameStr[3]+this.domNameStr[4];
console.log("加载富文本的文件名",this.getDmName)
this.loadFWBFile(this.getDmName);
this.lastClick = data.id;
}
// if(this.lastClick){
// if(!this.dmcIsChange()){
// this.navIsAdd = 'edit';
// this.generateXml(false,this.lastClick);
// }
// }
// this.getDmName = this.domNameStr[0]+this.domNameStr[1]+this.domNameStr[2]+data.id+this.domNameStr[3]+this.domNameStr[4];
// console.log("加载富文本的文件名",this.getDmName)
// this.loadFWBFile(this.getDmName);
}
console.log("当前节点点击",data);
2025-10-17 08:28:46 +08:00
setTimeout(() => {
this.getWindowSize();
}, 30);
2025-09-15 09:58:52 +08:00
// this.$sendToDotNet('GetFilePath','PMC',data.id,'');
},
2025-10-11 11:08:42 +08:00
zy(dataStr) {
try {
// 1. 清理字符串
const cleaned = dataStr.replace(/;$/g, '');
// 2. 转义双引号
const escaped = cleaned.replace(/"/g, '\\"');
// 3. 解码 Unicode
let unicodeDecoded = JSON.parse(`"${escaped}"`);
// 4. 处理反斜杠
let a = unicodeDecoded.replace(/\\\\/g, "\\")
return a;
} catch (e) {
// 捕获解析错误,避免页面崩溃
console.error("字符串解析失败:", e);
return "解析错误";
}
},
2025-09-15 09:58:52 +08:00
//确认新建目录
confirmAdd(type) {
if(type){
this.loadFileDMC = '';
}else{
this.$sendToDotNet('CopyToWorkDire');
}
this.$refs.form.validate((valid) => {
if (!valid) return
// if(!this.dmcIsChange()){
// }else{
// }
const newNode = {
id: this.queryMaxId(),
maxId:this.mId,
name: this.form.name,
attributes: [],
formMes:this.form,
lagreVersion:this.form.version,//大版本
minorVersion:'00',//临时版本
children: []
}
console.log("新建章节目录时候的参数",newNode)
this.nowMaxId = newNode.id;
if (this.currentNode) {
if (!this.currentNode.children) {
this.$set(this.currentNode, 'children', [])
}
this.currentNode.children.push(newNode)
} else {
this.treeData.push(newNode)
}
this.dialogVisibleNav = false
this.$nextTick(() => {
this.$refs.tree.setCurrentKey(newNode.id)
2025-10-11 11:08:42 +08:00
// this.currentNode = newNode;
this.currentNode = '';
2025-09-15 09:58:52 +08:00
this.catalogueAnalysis(this.treeData);
// this.$sendToDotNet('SaveFile','PMC',newNode.id,JSON.stringify(this.currentNode));
//创建目录时候同时创建一个空DM文件
2025-10-17 08:28:46 +08:00
console.log("创建目录时候同时创建一个空DM文件")
2025-10-11 11:08:42 +08:00
this.generateXml(true);
2025-09-15 09:58:52 +08:00
})
})
},
//编辑目录时候点击确认进行保存
confirmEdit() {
this.currentNode.name = this.form.name;
console.log("点击编辑确定",this.currentNode,this.treeData)
this.currentNode.minorVersion = '01';
this.catalogueAnalysis(this.treeData);
this.isNavEdit = true;
this.dialogVisibleNav = false;
this.generateXml(false,this.treeData.id)
// let targetNode = this.findNodeById(this.treeData,this.currentNode.id);
// if (targetNode) {
// // 替换attributes
// // targetNode.name = ...this.currentNode.name];
// // this.hasReplaced = true;
// console.log('替换成功,新的节点数据:', targetNode);
// } else {
// console.warn('未找到节点');
// }
// console.log('获取当前节点',this.currentNode)
},
// 删除时候的二次确认弹窗
deleteDialog() {
console.log("currentNode.children",this.currentNode)
this.dialogVisibleNavDel = true;
},
// 删除绑定资源按钮
deleteAttr(name,index) {
this.nowAttr ={
name:name,
index:index,
}
this.dialogVisibleAttrDel = true;
},
// 删除绑定资源二次确定
deleteAttrSure() {
this.currentNode.attributes.splice(this.nowAttr.index, 1);
this.catalogueAnalysis(this.treeData);
this.dialogVisibleAttrDel = false;
},
//删除节点时候判断是否有子节点。
deleteNode() {
if (this.currentNode.children && this.currentNode.children.length > 0) {
this.$message({
type: 'warning',
message: '该节点包含子节点,不能删除!'
})
}else{
let isDel = this.deleteNodeFromTree(this.treeData, this.currentNode.id)
2025-10-11 11:08:42 +08:00
console.log("删除是否成功",isDel,this.currentNode)
2025-09-15 09:58:52 +08:00
// this.currentNode = null;
const fileId = this.currentNode.id;
this.catalogueAnalysis(this.treeData);
this.dialogVisibleNavDel = false;
// this.$sendToDotNet('RefreshTree');
console.log('删除RMDMfile fileId',fileId)
2025-10-11 11:08:42 +08:00
this.$sendToDotNet('RMDMfile','DMC',fileId,this.currentNode.lagreVersion)
this.currentNode = '';
2025-09-15 09:58:52 +08:00
// this.$message({
// type: 'success',
// message: '删除成功!'
// })
}
},
// 更新指定节点的版本号
updateNodeVersion(id,vs) {
const targetNode = this.findNodeById(this.treeData2, id);
if (targetNode) {
targetNode.lagreVersion = vs;
}
},
//删除节点
deleteNodeFromTree(nodes, id) {
for (let i = 0; i < nodes.length; i++) {
if (nodes[i].id === id) {
nodes.splice(i, 1)
return true
}
if (nodes[i].children && nodes[i].children.length > 0) {
if (this.deleteNodeFromTree(nodes[i].children, id)) {
return true
}
}
}
return false
},
//重置输入框
resetForm() {
this.$refs.form.resetFields()
},
// 搜索相关方法
handleSearch() {
if (!this.searchText.trim()) {
this.$refs.tree.filter(this.searchText);
// 搜索内容为空时,重置所有节点的可见性
this.resetTreeVisibility(this.treeData)
}else{
this.$refs.tree.filter(this.searchText)
}
},
//清除搜索
handleSearchClear() {
this.searchText = '';
// 清空搜索时重置所有节点的可见性
this.$refs.tree.filter('');
this.resetTreeVisibility(this.treeData)
},
//重置目录节点信息
resetTreeVisibility(nodes) {
nodes.forEach(node => {
// 重置节点的可见性
node.visible = true
if (node.children && node.children.length > 0) {
this.resetTreeVisibility(node.children)
}
})
// 强制刷新树组件
this.$refs.tree.updateKeyChildren()
},
//目录节点信息
filterNode(value, data) {
if (!value) return true; // 空值时显示所有节点
// 这里假设你要搜索的是节点的name属性
return data.name.toLowerCase().includes(value.toLowerCase());
},
//筛选后高亮class
isHighlight(data) {
return this.searchText && data.name.toLowerCase().includes(this.searchText.toLowerCase())
},
// 保存属性
saveAttributes() {
console.log("this.currentNode.id",this.currentNode.id)
this.$sendToDotNet('GetFilePath','PMC',this.currentNode.id,'');
// if (this.currentNode) {
// // 保存选中的属性到当前节点
// this.currentNode.attributes = [...this.selectedAttributes];
// // 刷新树结构
// this.$refs.tree.setCurrentKey(this.currentNode.id);
// }
// this.dialogVisibleRight = false;
},
//查询最大ID值
queryMaxId() {
// maxId = '00001'
console.log("初始化ID",this.treeData)
// if(this.treeData[0]){
let maxId = this.mId?this.mId:'00001';
const length = maxId.length;
// 将字符串转换为数字并加1
const number = parseInt(maxId, 10) + 1;
// 格式化数字为指定长度的字符串,不足的前面补零
maxId = number.toString().padStart(length, '0');
// }
this.mId = maxId;
return maxId;
// let maxId = 0;
// let treeData = this.treeData;
// // 递归遍历函数
// const traverse = (nodes) => {
// if (!nodes || nodes.length === 0) return;
// nodes.forEach(node => {
// // 比较当前节点ID与最大值
// if (node.id > maxId) {
// maxId = node.id;
// }
// // 递归处理子节点
// traverse(node.children);
// });
// };
// // 开始遍历
// traverse(treeData);
// console.log("当前数据最大ID",maxId)
// const length = maxId.length;
// // 将字符串转换为数字并加1
// const number = parseInt(maxId, 10) + 1;
// // 格式化数字为指定长度的字符串,不足的前面补零
// maxId = number.toString().padStart(length, '0');
// if(maxId == 1){
// maxId = '00001'
// }
// return maxId;
},
//解析XML目录暂时不用
extractDmCode(xmlString) {
// 1. 解析 XML 字符串
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
// 2. 获取所有 dmCode 节点
const dmCodeNodes = xmlDoc.getElementsByTagName("dmCode");
const issueInfoNodes = xmlDoc.getElementsByTagName("issueInfo");
const languageNodes = xmlDoc.getElementsByTagName("language");
// 3. 遍历节点,提取属性
let dmCodeList = Array.from(dmCodeNodes).map(node => {
const attributes = {};
// 遍历节点的所有属性
for (let i = 0; i < node.attributes.length; i++) {
const attr = node.attributes[i];
attributes[attr.name] = attr.value;
}
return attributes;
});
let issueInfoList = Array.from(issueInfoNodes).map(node => {
const attributes = {};
// 遍历节点的所有属性
for (let i = 0; i < node.attributes.length; i++) {
const attr = node.attributes[i];
attributes[attr.name] = attr.value;
}
return attributes;
});
let languageList = Array.from(languageNodes).map(node => {
const attributes = {};
// 遍历节点的所有属性
for (let i = 0; i < node.attributes.length; i++) {
const attr = node.attributes[i];
attributes[attr.name] = attr.value;
}
return attributes;
});
// 处理函数:将对象按指定字段集拼接成字符串
let dmCodeTitle = ['modelIdentCode','systemDiffCode','systemCode','subSystemCode','subSubSystemCode','disassyCode','disassyCodeVariant','infoCode','infoCodeVariant','itemLocationCode']
let issueInfoTitle = ['issueNumber','inWork'];
let languageTitle = ['languageIsoCode','countryIsoCode']
// 处理三组数据
let dmCodeResult = this.joinFields(dmCodeList, dmCodeTitle,'-');
let issueInfoResult = this.joinFields(issueInfoList, issueInfoTitle,'_');
let languageResult = this.joinFields(languageList, languageTitle,'_');
console.log("参数 dmCodeResult",dmCodeResult)
console.log("参数 issueInfoResult",issueInfoResult)
console.log("参数 languageResult",languageResult)
// let dmCodeResult2 = [];
let newList = [];
for(let i = 0;i<dmCodeResult.length;i++){
// let strA = dmCodeResult[0]+'_'+dmCodeResult[0]
let str = dmCodeResult[i]+"-"+issueInfoResult[i]+"-"+languageResult[i]
newList.push(str);
}
console.log("结果",newList)
},
//解析目录节点数据
generateTreeData(xmlContent) {
2025-10-17 08:28:46 +08:00
// console.log("加载XML解析内容 初始化内容",xmlContent)
2025-09-15 09:58:52 +08:00
// 1. 解析XML
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlContent, "text/xml");
2025-10-17 08:28:46 +08:00
// console.log("加载XML解析内容 初始化XML",xmlDoc)
2025-09-15 09:58:52 +08:00
// 2. 获取根节点content下的所有pmEntry
const contentNode = xmlDoc.querySelector("content");
2025-10-17 08:28:46 +08:00
// console.log("加载XML解析内容 content",contentNode)
2025-09-15 09:58:52 +08:00
const rootPmEntries = contentNode ? Array.from(contentNode.children).filter(node => node.tagName === "pmEntry") : [];
2025-10-11 11:08:42 +08:00
let getBookName = xmlDoc.getElementsByTagName('pmTitle');
this.getBookName = getBookName[0].textContent;
console.log("得到的书名",this.getBookName)
2025-09-15 09:58:52 +08:00
// 3. 递归处理节点,构建树形结构
this.treeData = this.parsePmEntries(rootPmEntries);
this.handleCheckVersion();
// console.log("")
console.log("重新解析结果",this.treeData)
// if(this.treeData.length>0){
// this.clearNodeState();
// }
// this.enableContextMenu();//绑定右键
// 获取最大ID
const simpleParaNode = xmlDoc.querySelector("simplePara");
console.log("加载XML解析内容 id",simpleParaNode)
const maxId = simpleParaNode.getAttribute("maxId") || "00001";
console.log("当前目录最大ID",maxId)
this.mId = maxId;
2025-10-11 11:08:42 +08:00
const issueInfoNode = xmlDoc.querySelector("issueInfo");
this.minLevel = issueInfoNode.getAttribute("minLevel")
this.maxLevel = issueInfoNode.getAttribute("maxLevel")
this.maxPermission = issueInfoNode.getAttribute("maxPermission")
this.minPermission = issueInfoNode.getAttribute("minPermission")
console.log("版本号上各种参数",this.minLevel,this.maxLevel,this.minPermission,this.maxPermission)
2025-09-15 09:58:52 +08:00
},
/**
* 递归解析pmEntry节点列表生成树形数据
* @param {NodeList} pmEntries - pmEntry节点列表
* @param {Object} parent - 父节点用于处理嵌套关系
* @returns {Array} 树形结构数组
*/
parsePmEntries(pmEntries, parent = null) {
const treeNodes = [];
console.log("parent",parent)
pmEntries.forEach(entry => {
// const lagreVersion = parent.getAttribute("lagreVersion") || "";
// const minorVersion = parent.getAttribute("minorVersion") || "";
// console.log("数循环结果 大版本",lagreVersion)
// console.log("数循环结果 小版本",minorVersion)
// a. 提取当前节点的id、name、attributes
const titleNode = entry.querySelector("pmEntryTitle") || entry.querySelector("techName");
if (!titleNode) return; // 跳过无标题的节点
const id = titleNode.getAttribute("id");
const name = titleNode.textContent.trim();
const attributesStr = titleNode.getAttribute("attributes") || "";
const lagreVersion = titleNode.getAttribute("lagreVersion") || "000";
const minorVersion = titleNode.getAttribute("minorVersion") || "00";
// const maxID = titleNode.getAttribute("maxId") || "00001";
const attributes = attributesStr ? attributesStr.split(",").map(item => item.trim()) : [];
// b. 创建节点基本结构
const node = {
id,
name,
// maxId:maxID,
attributes,
formMes: {}, // 固定空对象
children: [],
lagreVersion:lagreVersion,//大版本
minorVersion:minorVersion,//临时版本
};
// c. 处理子节点当前pmEntry下的子pmEntry
const childEntries = Array.from(entry.children).filter(child => child.tagName === "pmEntry");
if (childEntries.length > 0) {
node.children = this.parsePmEntries(childEntries, node);
}
treeNodes.push(node);
});
return treeNodes;
},
//测试 解析xml 暂未使用
parseXml(xmlInput) {
this.errorMessage = '';
this.parsedData = [];
try {
// 创建DOMParser实例
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlInput, "text/xml");
console.log("xmlDoc",xmlDoc)
// 检查XML解析错误
const parserError = xmlDoc.getElementsByTagName("parsererror")[0];
if (parserError) {
throw new Error("XML格式错误: " + parserError.textContent);
}
// 获取所有顶级pmEntry节点
const pmEntries = xmlDoc.querySelectorAll('content > pmEntry');
let parsedData = [];
// 解析每个pmEntry
pmEntries.forEach(pmEntry => {
const entryData = this.parsePmEntry(pmEntry);
if (entryData) {
parsedData.push(entryData);
}
});
parsedData.map((res)=>{
if(res.infoCode){
return res.is = res.infoCode,res.name = res.title;
}
})
this.treeData = parsedData;
console.log("parsedData",parsedData)
} catch (error) {
this.errorMessage = "解析失败: " + error.message;
console.error("XML解析错误:", error);
}
},
/**
* 获取指定节点的值
* @param {Element} parentNode - 父节点
* @param {string} selector - 节点选择器
* @returns {string} 节点值
*/
getNodeValue(parentNode, selector) {
const node = parentNode.querySelector(selector);
return node ? node.textContent.trim() : '';
},
//格式化数据提取节点内容
parsePmEntry(pmEntryElement) {
// 获取pmEntryTitle
const titleElement = pmEntryElement.querySelector('pmEntryTitle');
if (!titleElement) return null;
const title = titleElement.textContent.trim();
const result = {
title,
children: [],
subItems: []
};
// 获取当前pmEntry下的所有子节点
const childNodes = Array.from(pmEntryElement.childNodes);
// 查找子pmEntry和dmRef节点
childNodes.forEach(node => {
if (node.nodeType !== 1) return; // 只处理元素节点
if (node.tagName === 'pmEntry') {
// 递归解析子pmEntry
const childData = this.parsePmEntry(node);
if (childData) {
result.children.push(childData);
}
} else if (node.tagName === 'dmRef') {
// 解析dmRef中的infoCode
const dmCode = node.querySelector('dmRefIdent > dmCode');
if (dmCode && dmCode.hasAttribute('infoCode')) {
result.subItems.push({
infoCode: dmCode.getAttribute('infoCode')
});
}
}
});
// 如果没有子节点但有subItems设置当前节点的infoCode为第一个subItem的infoCode
if (result.children.length === 0 && result.subItems.length > 0) {
result.infoCode = result.subItems[0].infoCode;
}
return result;
},
// 处理数据信息
joinFields(dataList, fields) {
return dataList.map(item => {
return fields.map(field => item[field]).join('_');
});
},
//处理目录节点信息
catalogueAnalysis(treeData) {
console.log("处理每个节点信息 treeData",treeData)
// 递归处理每个节点跟踪路径用于生成infoName
const processNode = (node, path = [], level = 0) => {
let nodeStr = '';
console.log("处理每个节点信息 node",node)
// 每个节点都用pmEntry标签包裹
nodeStr += '<pmEntry>\n';
// 计算当前节点的路径用于生成infoName
const currentPath = [...path, node.name];
// 如果有子节点添加pmEntryTitle标签
if (node.children && node.children.length > 0) {
nodeStr += `\t<pmEntryTitle attributes='${node.attributes}' lagreVersion="${node.lagreVersion}" minorVersion="${node.minorVersion}" id="${node.id}">${node.name}</pmEntryTitle>\n`;
// 递归处理子节点
node.children.forEach((child, index) => {
console.log("index",index)
// 递归处理子节点传入当前路径移除了未使用的infoCode和issueDate参数
nodeStr += processNode(child, currentPath, level + 1);
});
} else {
// 没有子节点的节点用dmRef标签包裹
nodeStr += '\t<dmRef>\n';
// 添加dmRefIdent部分包含动态生成的dmCode
nodeStr += `\t\t<dmRefIdent>\n`;
nodeStr += `\t\t\t<dmCode itemLocationCode="A" infoCodeVariant="A" infoCode="${getInfoCode(level)}" disassyCodeVariant="A" disassyCode="00" assyCode="00" subSubSystemCode="${getSubSubSystemCode(level)}" subSystemCode="${getSubSystemCode(level)}" systemCode="P4" systemDiffCode="A" modelIdentCode="YSC001"/>\n`;
nodeStr += `\t\t\t<issueInfo issueNumber="001" inWork="01"/>\n`;
nodeStr += `\t\t\t<language languageIsoCode="zh" countryIsoCode="CN"/>\n`;
nodeStr += `\t\t</dmRefIdent>\n`;
// 添加dmRefAddressItems标签
nodeStr += `\t\t<dmRefAddressItems>\n`;
// 添加dmTitle标签包含techName和infoName
nodeStr += `\t\t\t<dmTitle>\n`;
nodeStr += `\t\t\t\t<techName attributes='${node.attributes}' lagreVersion="${node.lagreVersion}" minorVersion="${node.minorVersion}" id="${node.id}">${node.name}</techName>\n`;
nodeStr += `\t\t\t\t<infoName>${currentPath.join('-')}</infoName>\n`;
nodeStr += `\t\t\t</dmTitle>\n`;
// 添加issueDate标签
nodeStr += `\t\t\t<issueDate year="2024" month="06" day="${getIssueDay(level)}"/>\n`;
// 闭合dmRefAddressItems标签
nodeStr += `\t\t</dmRefAddressItems>\n`;
// 闭合dmRef标签
nodeStr += `\t</dmRef>\n`;
}
// 闭合当前节点的pmEntry标签
nodeStr += '</pmEntry>\n';
return nodeStr;
};
// 根据层级和索引生成infoCode
const getInfoCode = (level, index = 0) => {
if (level === 1 && index === 0) return "042";
if (level === 1 && index === 1) return "041";
return "040";
};
// 根据层级生成subSystemCode
const getSubSystemCode = (level) => {
if (level === 0) return "0";
if (level === 1) return "1";
if (level === 2) return "3";
return "0";
};
// 根据层级生成subSubSystemCode
const getSubSubSystemCode = (level, index = 0) => {
if (level === 1) return "1";
if (level === 2) return index + 1;
return "0";
};
// 根据层级生成issueDay
const getIssueDay = (level) => {
return level === 1 ? "13" : "12";
};
// 处理所有根节点
let result = '';
treeData.forEach(node => {
result += processNode(node);
});
2025-10-11 11:08:42 +08:00
// console.log('catalogueString 目录字符串',result);
2025-09-15 09:58:52 +08:00
this.catalogueString = result;
this.saveNav();
// console.log(this.treeData)
},
//生成目录节点XML信息 并保存目录pmc
saveNav() {
2025-10-11 11:08:42 +08:00
let a1 = this.form.permission;//2
let a2 = this.form.level;//2
// let minP = this.minPermission;//1
let maxP = this.maxPermission;//5
// let minL = this.minLevel;//1
let maxL = this.maxLevel;//5
if(a1>maxP){
maxP = a1;
}
if(a2>maxL){
maxL = a2;
}
2025-09-15 09:58:52 +08:00
let xmlStr = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE pm [
]>
<pm xsi:noNamespaceSchemaLocation="http://www.s1000d.org/S1000D_4-1/xml_schema_flat/pm.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://www.purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink">
<identAndStatusSection>
<pmAddress>
<pmIdent>
<pmCode modelIdentCode="YSC001" pmIssuer="732380192B" pmNumber="00001" pmVolume="00"/>
<language countryIsoCode="CN" languageIsoCode="zh"/>
2025-10-11 11:08:42 +08:00
<issueInfo minLevel="1" maxLevel="`+maxL+`" maxPermission="`+maxP+`" minPermission="1" issueNumber="000" inWork="01"/>
2025-09-15 09:58:52 +08:00
</pmIdent>
<pmAddressItems>
<issueDate year="2024" month="06" day="24"/>
2025-10-11 11:08:42 +08:00
<pmTitle>`+this.getBookName+`</pmTitle>
2025-09-15 09:58:52 +08:00
</pmAddressItems>
</pmAddress>
<pmStatus issueType="new">
<security securityClassification="01"/>
<responsiblePartnerCompany enterpriseCode=" "/>
<originator/>
<applic>
<displayText>
<simplePara maxId='`+this.mId+`'>A0304-1A无人机系统地面运输方舱</simplePara>
</displayText>
</applic>
<brexDmRef>
<dmRef xlink:type="simple" xlink:actuate="onRequest" xlink:show="replace" xlink:href="URN:S1000D:DMC-S1000D-E-04-10-0301-00A-022A-D">
<dmRefIdent>
<dmCode modelIdentCode="YSC001" systemDiffCode="A" systemCode="P4" subSystemCode="0" subSubSystemCode="0" assyCode="00" disassyCode="00" disassyCodeVariant="A" infoCode="022" infoCodeVariant="A" itemLocationCode="A"/>
</dmRefIdent>
</dmRef>
</brexDmRef>
<qualityAssurance>
<unverified/>
</qualityAssurance>
</pmStatus>
</identAndStatusSection>
<content>`
+this.catalogueString+
`</content>
</pm>`
2025-10-11 11:08:42 +08:00
// console.log("传递字符串",this.catalogueString)
// console.log("存时候",xmlStr)
2025-09-15 09:58:52 +08:00
this.$sendToDotNet('SaveFile','PMC','',xmlStr);
2025-10-11 11:08:42 +08:00
// if(this.dialogVisibleNav){
// this.dialogVisibleNav = false;
// this.getDmName = this.domNameStr[0]+this.domNameStr[1]+this.domNameStr[2]+this.currentNode.id+this.domNameStr[3]+this.domNameStr[4];
// console.log("加载富文本的文件名997",this.getDmName)
// setTimeout(() => {
// this.loadFWBFile(this.getDmName);
// console.log("加载富文本的文件名997")
// }, 500);
// }
2025-09-15 09:58:52 +08:00
},
//测试 加载目录
jzml() {
let a = `<!DOCTYPE pm [
]>
<pm xsi:noNamespaceSchemaLocation="http://www.s1000d.org/S1000D_4-1/xml_schema_flat/pm.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://www.purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink">
<identAndStatusSection>
<pmAddress>
<pmIdent>
<pmCode modelIdentCode="YSC001" pmIssuer="732380192B" pmNumber="00001" pmVolume="00"/>
<language countryIsoCode="CN" languageIsoCode="zh"/>
<issueInfo issueNumber="000" inWork="01"/>
</pmIdent>
<pmAddressItems>
<issueDate year="2024" month="06" day="24"/>
<pmTitle>无人机系统地面运输方舱使用维护说明书</pmTitle>
</pmAddressItems>
</pmAddress>
<pmStatus issueType="new">
<security securityClassification="01"/>
<responsiblePartnerCompany enterpriseCode=" "/>
<originator/>
<applic>
<displayText>
<simplePara>A0304-1A无人机系统地面运输方舱</simplePara>
</displayText>
</applic>
<brexDmRef>
<dmRef xlink:type="simple" xlink:actuate="onRequest" xlink:show="replace" xlink:href="URN:S1000D:DMC-S1000D-E-04-10-0301-00A-022A-D">
<dmRefIdent>
<dmCode modelIdentCode="YSC001" systemDiffCode="A" systemCode="P4" subSystemCode="0" subSubSystemCode="0" assyCode="00" disassyCode="00" disassyCodeVariant="A" infoCode="022" infoCodeVariant="A" itemLocationCode="A"/>
</dmRefIdent>
</dmRef>
</brexDmRef>
<qualityAssurance>
<unverified/>
</qualityAssurance>
</pmStatus>
</identAndStatusSection>
<content><pmEntry>
<pmEntryTitle>装备概况</pmEntryTitle>
<pmEntry>
<pmEntryTitle>方舱概述</pmEntryTitle>
<pmEntry>
<dmRef>
<dmRefIdent>
<dmCode itemLocationCode="A" infoCodeVariant="A" infoCode="040" disassyCodeVariant="A" disassyCode="00" assyCode="00" subSubSystemCode="1" subSystemCode="3" systemCode="P4" systemDiffCode="A" modelIdentCode="YSC001"/>
<issueInfo issueNumber="000" inWork="01"/>
<language languageIsoCode="zh" countryIsoCode="CN"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<techName attributes="[]" id="00003">无人机系统</techName>
<infoName>装备概况-方舱概述-功能介绍</infoName>
</dmTitle>
<issueDate year="2024" month="06" day="12"/>
</dmRefAddressItems>
</dmRef>
</pmEntry>
<pmEntry>
<dmRef>
<dmRefIdent>
<dmCode itemLocationCode="A" infoCodeVariant="A" infoCode="040" disassyCodeVariant="A" disassyCode="00" assyCode="00" subSubSystemCode="1" subSystemCode="3" systemCode="P4" systemDiffCode="A" modelIdentCode="YSC001"/>
<issueInfo issueNumber="000" inWork="01"/>
<language languageIsoCode="zh" countryIsoCode="CN"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<techName attributes="[]" id="00004">无人机系统</techName>
<infoName>装备概况-方舱概述-规格介绍</infoName>
</dmTitle>
<issueDate year="2024" month="06" day="12"/>
</dmRefAddressItems>
</dmRef>
</pmEntry>
</pmEntry>
<pmEntry>
<dmRef>
<dmRefIdent>
<dmCode itemLocationCode="A" infoCodeVariant="A" infoCode="042" disassyCodeVariant="A" disassyCode="00" assyCode="00" subSubSystemCode="1" subSystemCode="1" systemCode="P4" systemDiffCode="A" modelIdentCode="YSC001"/>
<issueInfo issueNumber="000" inWork="01"/>
<language languageIsoCode="zh" countryIsoCode="CN"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<techName attributes='["金","木","水"]' id="00005">无人机系统</techName>
<infoName>装备概况-舱体</infoName>
</dmTitle>
<issueDate year="2024" month="06" day="13"/>
</dmRefAddressItems>
</dmRef>
</pmEntry>
<pmEntry>
<dmRef>
<dmRefIdent>
<dmCode itemLocationCode="A" infoCodeVariant="A" infoCode="042" disassyCodeVariant="A" disassyCode="00" assyCode="00" subSubSystemCode="1" subSystemCode="1" systemCode="P4" systemDiffCode="A" modelIdentCode="YSC001"/>
<issueInfo issueNumber="000" inWork="01"/>
<language languageIsoCode="zh" countryIsoCode="CN"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<techName attributes="[]" id="00006">无人机系统</techName>
<infoName>装备概况-机身转运小车</infoName>
</dmTitle>
<issueDate year="2024" month="06" day="13"/>
</dmRefAddressItems>
</dmRef>
</pmEntry>
<pmEntry>
<dmRef>
<dmRefIdent>
<dmCode itemLocationCode="A" infoCodeVariant="A" infoCode="042" disassyCodeVariant="A" disassyCode="00" assyCode="00" subSubSystemCode="1" subSystemCode="1" systemCode="P4" systemDiffCode="A" modelIdentCode="YSC001"/>
<issueInfo issueNumber="000" inWork="01"/>
<language languageIsoCode="zh" countryIsoCode="CN"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<techName attributes="[]" id="00007">无人机系统</techName>
<infoName>装备概况-无人机部件存储装置</infoName>
</dmTitle>
<issueDate year="2024" month="06" day="13"/>
</dmRefAddressItems>
</dmRef>
</pmEntry>
<pmEntry>
<dmRef>
<dmRefIdent>
<dmCode itemLocationCode="A" infoCodeVariant="A" infoCode="042" disassyCodeVariant="A" disassyCode="00" assyCode="00" subSubSystemCode="1" subSystemCode="1" systemCode="P4" systemDiffCode="A" modelIdentCode="YSC001"/>
<issueInfo issueNumber="000" inWork="01"/>
<language languageIsoCode="zh" countryIsoCode="CN"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<techName attributes="[]" id="00008">无人机系统</techName>
<infoName>装备概况-机身转运小车</infoName>
</dmTitle>
<issueDate year="2024" month="06" day="13"/>
</dmRefAddressItems>
</dmRef>
</pmEntry>
<pmEntry>
<pmEntryTitle>附件及工具</pmEntryTitle>
<pmEntry>
<dmRef>
<dmRefIdent>
<dmCode itemLocationCode="A" infoCodeVariant="A" infoCode="040" disassyCodeVariant="A" disassyCode="00" assyCode="00" subSubSystemCode="1" subSystemCode="3" systemCode="P4" systemDiffCode="A" modelIdentCode="YSC001"/>
<issueInfo issueNumber="000" inWork="01"/>
<language languageIsoCode="zh" countryIsoCode="CN"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<techName attributes="[]" id="00010">无人机系统</techName>
<infoName>装备概况-附件及工具-灭火器</infoName>
</dmTitle>
<issueDate year="2024" month="06" day="12"/>
</dmRefAddressItems>
</dmRef>
</pmEntry>
<pmEntry>
<dmRef>
<dmRefIdent>
<dmCode itemLocationCode="A" infoCodeVariant="A" infoCode="040" disassyCodeVariant="A" disassyCode="00" assyCode="00" subSubSystemCode="1" subSystemCode="3" systemCode="P4" systemDiffCode="A" modelIdentCode="YSC001"/>
<issueInfo issueNumber="000" inWork="01"/>
<language languageIsoCode="zh" countryIsoCode="CN"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<techName attributes="[]" id="00011">无人机系统</techName>
<infoName>装备概况-附件及工具-应急灯</infoName>
</dmTitle>
<issueDate year="2024" month="06" day="12"/>
</dmRefAddressItems>
</dmRef>
</pmEntry>
<pmEntry>
<dmRef>
<dmRefIdent>
<dmCode itemLocationCode="A" infoCodeVariant="A" infoCode="040" disassyCodeVariant="A" disassyCode="00" assyCode="00" subSubSystemCode="1" subSystemCode="3" systemCode="P4" systemDiffCode="A" modelIdentCode="YSC001"/>
<issueInfo issueNumber="000" inWork="01"/>
<language languageIsoCode="zh" countryIsoCode="CN"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<techName attributes="[]" id="00012">无人机系统</techName>
<infoName>装备概况-附件及工具-土木工具</infoName>
</dmTitle>
<issueDate year="2024" month="06" day="12"/>
</dmRefAddressItems>
</dmRef>
</pmEntry>
<pmEntry>
<dmRef>
<dmRefIdent>
<dmCode itemLocationCode="A" infoCodeVariant="A" infoCode="040" disassyCodeVariant="A" disassyCode="00" assyCode="00" subSubSystemCode="1" subSystemCode="3" systemCode="P4" systemDiffCode="A" modelIdentCode="YSC001"/>
<issueInfo issueNumber="000" inWork="01"/>
<language languageIsoCode="zh" countryIsoCode="CN"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<techName attributes="[]" id="00013">无人机系统</techName>
<infoName>装备概况-附件及工具-机械工具</infoName>
</dmTitle>
<issueDate year="2024" month="06" day="12"/>
</dmRefAddressItems>
</dmRef>
</pmEntry>
</pmEntry>
</pmEntry>
<pmEntry>
<pmEntryTitle>使用说明</pmEntryTitle>
<pmEntry>
<dmRef>
<dmRefIdent>
<dmCode itemLocationCode="A" infoCodeVariant="A" infoCode="042" disassyCodeVariant="A" disassyCode="00" assyCode="00" subSubSystemCode="1" subSystemCode="1" systemCode="P4" systemDiffCode="A" modelIdentCode="YSC001"/>
<issueInfo issueNumber="000" inWork="01"/>
<language languageIsoCode="zh" countryIsoCode="CN"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<techName attributes="[]" id="00014">无人机系统</techName>
<infoName>使用说明-无人机出舱</infoName>
</dmTitle>
<issueDate year="2024" month="06" day="13"/>
</dmRefAddressItems>
</dmRef>
</pmEntry>
<pmEntry>
<dmRef>
<dmRefIdent>
<dmCode itemLocationCode="A" infoCodeVariant="A" infoCode="042" disassyCodeVariant="A" disassyCode="00" assyCode="00" subSubSystemCode="1" subSystemCode="1" systemCode="P4" systemDiffCode="A" modelIdentCode="YSC001"/>
<issueInfo issueNumber="000" inWork="01"/>
<language languageIsoCode="zh" countryIsoCode="CN"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<techName attributes="[]" id="00015">无人机系统</techName>
<infoName>使用说明-无人机入舱</infoName>
</dmTitle>
<issueDate year="2024" month="06" day="13"/>
</dmRefAddressItems>
</dmRef>
</pmEntry>
<pmEntry>
<dmRef>
<dmRefIdent>
<dmCode itemLocationCode="A" infoCodeVariant="A" infoCode="042" disassyCodeVariant="A" disassyCode="00" assyCode="00" subSubSystemCode="1" subSystemCode="1" systemCode="P4" systemDiffCode="A" modelIdentCode="YSC001"/>
<issueInfo issueNumber="000" inWork="01"/>
<language languageIsoCode="zh" countryIsoCode="CN"/>
</dmRefIdent>
<dmRefAddressItems>
<dmTitle>
<techName attributes="[]" id="00016">无人机系统</techName>
<infoName>使用说明-灭火器使用</infoName>
</dmTitle>
<issueDate year="2024" month="06" day="13"/>
</dmRefAddressItems>
</dmRef>
</pmEntry>
</pmEntry>
</content>
</pm>`
this.parseToTreeData(a);
},
//清除新建目录弹窗内容信息。
clearFormData() {
this.form = {
name: '',
version:'000',
date:'',
language:'',
2025-10-11 11:08:42 +08:00
level:'1',
2025-09-15 09:58:52 +08:00
contributor:'',
2025-10-11 11:08:42 +08:00
creator:'四威高科',
2025-09-15 09:58:52 +08:00
applicabilityInformation:'',
qualityVerification:'',
2025-10-11 11:08:42 +08:00
permission:'1'
2025-09-15 09:58:52 +08:00
}
},
//测试 格式化目录信息
parseToTreeData(xmlString) {
// 创建DOMParser实例
const parser = new DOMParser();
// 解析XML字符串
const xmlDoc = parser.parseFromString(xmlString, 'text/xml');
// 获取根节点下的所有pmEntry节点顶级节点
const rootPmEntries = xmlDoc.querySelectorAll('content > pmEntry');
// 递归解析节点的函数
const parseNode = (xmlNode) => {
// 检查是否有pmEntryTitle子节点
const titleNode = xmlNode.querySelector('pmEntryTitle');
if (titleNode) {
// 有标题节点,说明是父节点
const node = {
id: '', // 后续会从子节点中查找合适的id
name: titleNode.textContent.trim(),
children: [],
attributes: []
};
// 修复选择器错误:使用更兼容的方式获取直接子节点
const childNodes = xmlNode.childNodes;
const childPmEntries = [];
// 遍历所有子节点筛选出直接子pmEntry元素
for (let i = 0; i < childNodes.length; i++) {
const child = childNodes[i];
// 检查是否是元素节点且标签名为pmEntry
if (child.nodeType === 1 && child.tagName === 'pmEntry') {
childPmEntries.push(child);
}
}
// 递归解析每个子节点
childPmEntries.forEach(childEntry => {
const childNode = parseNode(childEntry);
if (childNode) {
node.children.push(childNode);
}
});
// 为父节点生成合适的id
if (!node.id && node.children.length > 0) {
// 取第一个子节点id的前缀并生成父节点id
const firstChildId = node.children[0].id;
// 简单处理取前面的数字部分并减1根据实际情况调整
node.id = (parseInt(firstChildId, 10) - 1).toString().padStart(firstChildId.length, '0');
}
return node;
} else {
// 没有标题节点说明是叶子节点从dmRef中获取信息
const dmRef = xmlNode.querySelector('dmRef');
if (!dmRef) return null;
// 获取techName节点中的id和内容
const techNameNode = dmRef.querySelector('techName');
const id = techNameNode.getAttribute('id');
const attributes = techNameNode.getAttribute('attributes');
// 从infoName获取名称路径
const infoNameNode = dmRef.querySelector('infoName');
const infoName = infoNameNode.textContent.trim();
// 取最后一部分作为名称
const nameParts = infoName.split('-');
const name = nameParts[nameParts.length - 1];
return {
id,
name,
children: [],
attributes: attributes
};
}
};
// 解析所有顶级节点
const treeData = [];
rootPmEntries.forEach(entry => {
const node = parseNode(entry);
if (node) {
treeData.push(node);
}
});
console.log("打印",treeData)
console.log("打印String",JSON.stringify(treeData))
this.treeData = treeData;
},
//和后台交互 加载需要读取的dmc
loadFWBFile(dmName) {
// this.$sendToDotNet('LoadDM','DMC--A-P4-20-00-00A-00001A-A_000_01_zh_cn');
console.log("需要读取的富文本:",dmName)
this.$sendToDotNet('LoadDM','DMC',dmName);
// this.$sendToDotNet('GetFilePath','PMC',data.id,'');
},
//和后台交互 查看历史版本
lookHistoryFile(path) {
let newPath = path+'\\'+this.getLastPartOfPath(path)+'.xml';
this.historyVsPath = path;
console.log("发送路径",newPath)
this.$sendToDotNet('DMPreview','HistoryDMPreview',newPath)
// this.$sendToDotNet('GetHistoryDMContent',newPath);
// localStorage.setItem('filePath',newPath);
// const url = this.$router.resolve({ name: 'WangG2' }).href
// // 打开新窗口,可指定窗口大小和位置
// window.open(
// url,
// '_blank',
// 'width=800,height=600,top=100,left=100'
// )
},
//清除 NBSP str
clearNbsp(originalStr) {
const cleanedStr = originalStr.replace(/&nbsp;/g, '');
console.log("结果cleanedStr",cleanedStr)
return cleanedStr;
},
//测试 测试拼接地址;
ceshi() {
this.lisenPath = '"http://localhost:61980/"';
let e = {
detail:'"\\1.jpg"'
}
const parsedA = this.lisenPath.replace(/"/g, '');
const parsedB = e.detail.replace(/"/g, '');
// 2. 处理转义字符(如斜杠)
const processedA = parsedA.replace(/\\/g, '');
const processedB = parsedB.replace(/\\/g, '');
// 3. 确保基础URL以斜杠结尾
let baseUrl = processedA;
if (baseUrl && !baseUrl.endsWith('/')) {
baseUrl += '/';
}
this.insertImage( baseUrl + processedB)
},
//判断拖拽进富文本的文件类型;
isImageSuffix(a) {
let type = '';
// 检查参数是否为字符串
if (typeof a !== 'string') {
return false;
}
// 转换为小写后判断(忽略大小写)
const lowerCaseA = a.toLowerCase();
if(this.allImgType.has(lowerCaseA)){
type = 'img';
}else if(this.allMusicType.has(lowerCaseA)){
type = 'music';
}else if(this.allVideoType.has(lowerCaseA)){
type = 'video';
}else if(this.otherType.has(lowerCaseA)){
type = '3d'
}else {
type = 'other'
}
return type;
},
//解析字符串信息
parseSpecialString(str) {
return str.replace(/['"\\]/g, '')
// 处理步骤:移除引号 → 替换转义反斜杠 → 解析Unicode
// return str
// .replace(/^"|"$/g, '')
// .replace(/\\\\/g, '\\')
// .replace(/\\\\/g, '\\')
// .replace(/""/g, '')
// .replace(/\\u([0-9a-fA-F]{4})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)));
},
//根据ID查询节点 已经需要替换的内容信息
replaceAttributes() {
// 找到treeData中id为xx节点
const targetNode = this.findNodeById(this.treeData,this.currentNode.id);
if (targetNode) {
// 替换attributes
targetNode.attributes = [...this.currentNode.attributes];
// this.hasReplaced = true;
console.log('替换成功新的attributes:', targetNode.attributes);
}
this.catalogueAnalysis(this.treeData);
},
/**
* 查找树形结构中指定id的节点
* @param {Array} nodes - 节点数组
* @param {string} id - 要查找的节点id
* @returns {Object|null} 找到的节点或null
*/
findNodeById(nodes, id) {
// 遍历节点数组
for (const node of nodes) {
// 找到目标节点
if (node.id === id) {
return node;
}
// 递归查找子节点
if (node.children && node.children.length > 0) {
const found = this.findNodeById(node.children, id);
if (found) {
return found;
}
}
}
return null;
},
//成功信息 暂未使用
successTips(msg) {
this.$message({
message: msg,
type: 'success'
});
},
2025-10-11 11:08:42 +08:00
//目录节点拖拽结束后
handleDragEnd() {
//拖拽完成后保存目录节点。
this.catalogueAnalysis(this.treeData)
},
2025-09-15 09:58:52 +08:00
// 处理节点右键点击
// 处理节点右键点击
handleNodeContextMenu(event, data, node, component) {
event.preventDefault();
event.stopPropagation();
console.log("node",node)
console.log("component",component)
this.navIsAdd = '';
this.contextMenuNode = data;
this.currentNode = data;
2025-10-11 11:08:42 +08:00
this.nowRightHint = data.name;
2025-09-15 09:58:52 +08:00
console.log("右键以后赋值:",this.currentNode,data)
this.getDmName = this.domNameStr[0]+this.domNameStr[1]+this.domNameStr[2]+data.id+this.domNameStr[3]+this.domNameStr[4];
console.log("删除的DM名字",this.getDmName)
// return;
// 获取鼠标位置
let clientX = event.clientX;
let clientY = event.clientY;
// 预估菜单高度(可根据实际菜单内容调整)
const menuHeight = 200; // 包含4个选项+分隔线+关闭按钮的大概高度
const windowHeight = window.innerHeight;
// 计算菜单底部位置
const menuBottom = clientY + menuHeight;
// 如果菜单底部超出窗口高度,向上调整位置
if (menuBottom > windowHeight) {
// 调整后的位置 = 鼠标Y - 菜单高度(确保菜单顶部不超出窗口顶部)
clientY = Math.max(0, clientY - menuHeight);
}
// 设置调整后的菜单位置
this.contextMenuLeft = clientX;
this.contextMenuTop = clientY;
this.contextMenuVisible = true;
// 点击其他区域关闭菜单 - 修复版
const handleClickOutside = (e) => {
// 先判断菜单元素是否存在
const menuElement = document.querySelector('.custom-context-menu');
if (!menuElement) {
// 元素不存在时直接移除监听
document.removeEventListener('click', handleClickOutside);
return;
}
// 元素存在再判断点击位置
if (!menuElement.contains(e.target)) {
this.contextMenuVisible = false;
document.removeEventListener('click', handleClickOutside);
}
};
// 确保移除之前可能存在的监听,避免重复绑定
setTimeout(() => {
document.removeEventListener('click', handleClickOutside);
document.addEventListener('click', handleClickOutside);
}, 0);
}
,
// 处理菜单选项点击
handleMenuClick(option) {
console.log('选择了选项:', option, ',节点数据:', this.contextMenuNode);
// 根据选项执行对应操作
switch(option) {
case 'a':
this.showAddDialog('edit');
// 处理选项a逻辑
break;
case 'b':
this.showBand();
// 处理选项b逻辑
break;
case 'c':
this.finalVersion();
// 处理选项b逻辑
break;
case 'd':
this.showHistory();
// 处理选项c逻辑
break;
case 'e':
// 处理选项d逻辑
this.deleteDialog();
break;
}
// 关闭菜单
this.contextMenuVisible = false;
},
// 复用路径截取函数
getLastPartOfPath(path) {
if (!path || typeof path !== 'string') return '';
const lastBackslashIndex = path.lastIndexOf('\\');
return lastBackslashIndex === -1 ? path : path.slice(lastBackslashIndex + 1);
},
//转译 多个反斜杠
fixJsonEscapes(str) {
// 步骤1先将所有单个\转义为\\(基础转义修复)
let fixed = str.replace(/(?<!\\)\\/g, '\\\\');
// // 步骤2将所有实际换行符\n替换为字符串\\n
// fixed = fixed.replace(/\n/g, '\\n');
// // 步骤3处理可能存在的\r回车符
// fixed = fixed.replace(/\r/g, '\\r');
return fixed;
},
//测试 新开一个浏览器窗口
openWangG2InNewWindow(sendStr) {
let str = "[{\"Path\":\"C:\\Users\\sw\\Desktop\\net8.0-windows7.0\\DM_Material\\Version\\DMC-testNew2-A-P4-20-00-00A-00001A-A\\DMC-testNew2-A-P4-20-00-00A-00001A-A_000_00_zh_cn\",\"Name\":\"DMC-testNew2-A-P4-20-00-00A-00001A-A_000_00_zh_cn\",\"CreationTime\":\"2025-09-01T16:39:07.0578892+08:00\"},{\"Path\":\"C:\\Users\\sw\\Desktop\\net8.0-windows7.0\\DM_Material\\Version\\DMC-testNew2-A-P4-20-00-00A-00001A-A\\DMC-testNew2-A-P4-20-00-00A-00001A-A_001_00_zh_cn\",\"Name\":\"DMC-testNew2-A-P4-20-00-00A-00001A-A_001_00_zh_cn\",\"CreationTime\":\"2025-09-01T16:41:46.4181541+08:00\"},{\"Path\":\"C:\\Users\\sw\\Desktop\\net8.0-windows7.0\\DM_Material\\Version\\DMC-testNew2-A-P4-20-00-00A-00001A-A\\DMC-testNew2-A-P4-20-00-00A-00001A-A_002_00_zh_cn\",\"Name\":\"DMC-testNew2-A-P4-20-00-00A-00001A-A_002_00_zh_cn\",\"CreationTime\":\"2025-09-01T16:42:06.7153697+08:00\"},{\"Path\":\"C:\\Users\\sw\\Desktop\\net8.0-windows7.0\\DM_Material\\Version\\DMC-testNew2-A-P4-20-00-00A-00001A-A\\DMC-testNew2-A-P4-20-00-00A-00001A-A_003_00_zh_cn\",\"Name\":\"DMC-testNew2-A-P4-20-00-00A-00001A-A_003_00_zh_cn\",\"CreationTime\":\"2025-09-01T16:42:25.8314261+08:00\"},{\"Path\":\"C:\\Users\\sw\\Desktop\\net8.0-windows7.0\\DM_Material\\Version\\DMC-testNew2-A-P4-20-00-00A-00001A-A\\DMC-testNew2-A-P4-20-00-00A-00001A-A_004_00_zh_cn\",\"Name\":\"DMC-testNew2-A-P4-20-00-00A-00001A-A_004_00_zh_cn\",\"CreationTime\":\"2025-09-01T16:51:02.3778949+08:00\"},{\"Path\":\"C:\\Users\\sw\\Desktop\\net8.0-windows7.0\\DM_Material\\Version\\DMC-testNew2-A-P4-20-00-00A-00001A-A\\DMC-testNew2-A-P4-20-00-00A-00001A-A_005_00_zh_cn\",\"Name\":\"DMC-testNew2-A-P4-20-00-00A-00001A-A_005_00_zh_cn\",\"CreationTime\":\"2025-09-02T15:59:19.5476416+08:00\"}]"
// let strb = JSON.parse(str);
console.log("解析的结果",str)
// // 获取wangG2页面的路由路径
const wangG2Url = this.$router.resolve({ name: 'WangG2' }).href
// // 打开新窗口,可指定窗口大小和位置
// window.open(
// url,
// '_blank',
// 'width=800,height=600,top=100,left=100'
// )
// 打开新窗口假设wangG2.vue的路由路径是/wangG2
// const wangG2Url = this.$router.resolve({ path: '/wangG2' }).href;
// 打开新窗口并设置尺寸
this.wangG2Window = window.open(
wangG2Url,
'WangG2Window',
'width=800,height=600,left=200,top=100'
);
// 检查窗口是否被浏览器拦截
if (!this.wangG2Window) {
this.$message.error('窗口被浏览器拦截,请允许弹出窗口');
return;
}
// 定时检查窗口是否加载完成并发送数据
this.checkWindowTimer = setInterval(() => {
// 窗口已关闭
if (this.wangG2Window.closed) {
clearInterval(this.checkWindowTimer);
this.$message.info('wangG2窗口已关闭');
return;
}
try {
// 尝试发送消息,确保窗口已加载
this.wangG2Window.postMessage(
{
type: 'INIT_DATA',
// payload: this.dataToSend,
payload: sendStr,
sender: 'MainPage'
},
window.location.origin // 限制只发送到同源地址
);
// 发送成功后清除定时器
clearInterval(this.checkWindowTimer);
this.$message.success('数据已发送到wangG2窗口');
} catch (error) {
// 窗口未加载完成时会抛出错误,继续等待
console.log('等待wangG2窗口加载...');
}
}, 100);
},
// 将处理逻辑提取为单独的方法,便于绑定和解绑
handleFilePathSend(e) {
const newStr = this.parseSpecialString(e.detail);
console.log('路径接收:', this.currentNode, e, e.detail, newStr);
// 访问 currentNode 前先判断是否存在,避免 null 错误
if (this.currentNode && this.currentNode.attributes) {
this.currentNode.attributes.push(newStr);
this.replaceAttributes();
console.log("当前节点", this.currentNode, this.treeData);
} else {
console.warn('currentNode 不存在或无 attributes 属性');
}
},
},
watch: {
// 监听新建目录的弹窗状态
dialogVisibleNav(newVal, oldVal) {
console.log("弹窗",newVal,oldVal)
if(newVal == true){
this.loadFileDMC = '';
}
2025-10-11 11:08:42 +08:00
},
currentNode(newVal) {
if (newVal) {
this.$nextTick(() => {
// 先销毁旧编辑器
if (this.editor) {
this.editor.destroy();
}
// 初始化新编辑器
this.initEditor();
});
} else {
// 节点为空时销毁编辑器
if (this.editor) {
this.editor.destroy();
this.editor = null;
}
}
2025-09-15 09:58:52 +08:00
}
},
created() {
// let that = this;
// 方式1直接访问全局变量
this.$watch(
() => this.$dotNetMessage,
(newMsg) => {
console.log('收到消息:', newMsg)
}
)
//和后台交互 获取对应的DMC的历史版本列表
window.addEventListener('GetHistoryVesions', (e) => {
if(e.detail){
const aa = this.fixJsonEscapes(e.detail);
console.log("1第一次接收历史版本信息this.historyData", e.detail,aa)
this.historyData = JSON.parse(aa);
console.log("1第二次接收历史版本信息this.historyData", this.historyData)
}
})
//和后台交互 暂未使用
window.addEventListener('GetHistoryDMContent', (e) => {
console.log('GetHistoryDMContent接收历史版本信息XML:', e.detail)
})
//和后台交互 新建章节目录时候点击加载DMC文件
window.addEventListener('GetExistenceDMContent', (e) => {
// console.log('接收历史版本DMC的XML内容:',e, e.detail)
if(e.detail){
this.isLoadOldDmc = '2';
this.showView = true;
this.loadFileXML = e.detail;
if (this.loadFileXML.startsWith('"')) {
this.loadFileXML = this.loadFileXML.substring(1);
}
// 检查并去除结尾的双引号
if (this.loadFileXML.endsWith('"')) {
this.loadFileXML = this.loadFileXML.substring(0, this.loadFileXML.length - 1);
}
this.parseXmlDmc();
}
})
2025-10-11 11:08:42 +08:00
//和后台交互 接收富文本XML
window.addEventListener('FrontLoadProjectNew', this.FrontLoadDM_g2)
2025-09-15 09:58:52 +08:00
//和后台交互 接收目录XML
2025-10-11 11:08:42 +08:00
// window.addEventListener('FrontLoadProjectNew', (e) => {
// })
2025-09-15 09:58:52 +08:00
//和后台交互 单独获取DM的文文件(暂未使用)
window.addEventListener('GetDMDta', (e) => {
// 加载目录
console.log('GetDMDta 参数接收:',e,e.detail)
})
//和后台交互 接收富文本XML
window.addEventListener('FrontLoadDM', this.FrontLoadDM_g1)
//和后台交互 获取文件地址
window.addEventListener('SendResourcePath', (e) => {
console.log('拖拽文件地址:',e,e.detail)
2025-10-11 11:08:42 +08:00
let newData = this.zy(e.detail);
2025-09-15 09:58:52 +08:00
// 1. 去除双引号
2025-10-11 11:08:42 +08:00
const parsedA = this.lisenPath.replace(/"/g, '');
const parsedB = newData.replace(/"/g, '');
2025-09-15 09:58:52 +08:00
// 2. 处理转义字符(如斜杠)
const processedA = parsedA.replace(/\\/g, '');
2025-10-11 11:08:42 +08:00
// const processedB = parsedB.replace(/\\/g, '');
const processedB = parsedB.replace(/\\\\/g, "\\");
console.log("processedB",processedB,parsedB)
2025-09-15 09:58:52 +08:00
// 3. 确保基础URL以斜杠结尾
let baseUrl = processedA;
if (baseUrl && !baseUrl.endsWith('/')) {
baseUrl += '/';
}
const cleanedFile = parsedB.replace(/\\/g, '');
// 2. 提取后缀名
const lastDotIndex = cleanedFile.lastIndexOf('.');
const suffix = cleanedFile.substring(lastDotIndex + 1).toLowerCase();
// allImgType allMusicType allVideoType
console.log("后缀",suffix)
switch (this.isImageSuffix(suffix)){
case 'img':
this.insertImage( baseUrl + processedB)
// this.insertImage( baseUrl + '/zw.jpg')
break;
case 'music':
this.insertAudio( baseUrl + processedB)
break;
case 'video':
this.insertVideo( baseUrl + processedB)
break;
case '3d':
this.insert3d(baseUrl + '/zw.jpg')
break;
default:
this.$message({
message: '当前文件不支持',
type: 'warning'
});
break;
}
})
2025-10-11 11:08:42 +08:00
console.log('监听器开始注册11', Date.now()) // 打印注册时间戳
2025-09-15 09:58:52 +08:00
//和后台交互 获取文件地址
window.addEventListener('SendLisentPath', this.SendLisentPathFun)
//和后台交互 获取项目名
window.addEventListener('SendProjectName', (e) => {
this.domNameStr[1] = this.removeQuotationMarks(e.detail);
console.log('获取项目文件夹名子:',this.domNameStr,e,e.detail)
2025-10-17 08:28:46 +08:00
this.isLoadMsg = true;
2025-09-15 09:58:52 +08:00
})
2025-10-11 11:08:42 +08:00
2025-09-15 09:58:52 +08:00
//和后台交互 定稿之后获取最新的dm名称
window.addEventListener('SendNewVersionDMFileName', (e) => {
console.log("定稿以后的信息",e.detail)
let str = this.removeQuotationMarks(e.detail);
console.log("定稿以后的 str",str)
const firstUnderline = str.indexOf('_');
console.log("定稿以后的 firstUnderline",firstUnderline)
const secondUnderline = str.indexOf('_', firstUnderline + 1);
console.log("节点属性",this.currentNode)
console.log("定稿以后的secondUnderline",secondUnderline)
if(this.currentNode){
this.currentNode.lagreVersion =str.substring(
firstUnderline + 1,
secondUnderline
);
this.updateNodeVersion(this.currentNode.id,this.currentNode.lagreVersion)
console.log("定稿以后的currentNode",this.currentNode)
console.log("定稿以后的树",this.treeData)
this.catalogueAnalysis(this.treeData);
}
})
//和后台交互 获取加载时候的DMC文件预览服务器端口号
window.addEventListener('handPrePath', (e) => {
if(e){
this.viewLis = e.detail;
}
})
//和后台交互 获取加载时候的DMC文件具体内容
window.addEventListener('handreContent', (e) => {
if(e){
this.maskViewShow = true;
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);
}
2025-10-11 11:08:42 +08:00
console.log("得到的0",this.viewXml)
this.parseRdfDescriptions(this.viewXml)
2025-09-15 09:58:52 +08:00
this.parseXmlDmc_loadFile();
}
})
// window.addEventListener('handleMessageFromDotNet', this.fun1)
},
}
2025-10-17 08:28:46 +08:00
</script>
<style scoped>
.drag-handle {
position: absolute;
top: 0;
right: 0;
width: 5px;
height: 100%;
cursor: col-resize;
/* background-color: #aaa; */
background-color: rgba(0,0,0,.1);
z-index: 2;
}
.drag-handle:hover {
/* background-color: #666; */
}
.el-main{
padding:0 10px ;
}
</style>