osc/oscm/board/src/modules/components/VisualizedMouldModal.vue
2025-05-28 19:16:17 +08:00

637 lines
21 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

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

<template>
<el-dialog :close-on-click-modal="false"
title="规则编辑"
:visible.sync="dialogVisible"
:before-close="close"
width="95vw"
id="visualizedMould"
class="abow_dialog"
center>
<el-container>
<el-container>
<el-main>
<div class="browserarea">
<div class="browser-navigation panel-heading">
<el-row class="navbar-form ember-view">
<el-input id="url_input" style="width:90%" v-model="weburl"
@keyup.enter.native="getWeb(weburl)" autocomplete="off"></el-input>
<span>
<!-- <el-button class="nav-button nav-button-go" size="mini" icon="el-icon-right" @click="getWeb(weburl)"></el-button>-->
<el-button class="nav-button nav-button-refresh" :loading=loading size="mini" icon="el-icon-right"
@click="getWeb(weburl)"></el-button>
</span>
</el-row>
</div>
<div class="frame-container">
<!-- src="/static/save-index1611632019231.html" -->
<!-- <iframe :src="iframePath==''?'':'static/'+iframePath" style="border:0px;overflow:hidden"-->
<!-- @load="loadIframe" class="eidt-stauts-iframe" id="web-display-iframe" width="100%"-->
<!-- height="100%"></iframe>-->
<iframe :src="iframePath==''?'':iframePath" style="border:0px;overflow:hidden"
@load="loadIframe" class="eidt-stauts-iframe" id="web-display-iframe" width="100%"
height="100%"></iframe>
<div v-for="(mask,index) in maskDiv" class="mask" v-bind:key="mask.key+index"
:data-id="mask.key" :style="mask.style">
</div>
<div v-if="mouseMaskDiv!==null" class="mask" :style=mouseMaskDiv.style>
<span class="maskIcon">+</span>
</div>
</div>
</div>
<div class="parseresult">
<el-row v-for="(content,index) in parseContent" :key="index">
<el-col class="parse-label">{{content.colName}}</el-col>
<el-col :span="18" class="parse-content">{{content.text}}</el-col>
</el-row>
</div>
</el-main>
</el-container>
<el-aside width="400px">
<div style="height:92%">
<el-card class="pare-result-card temp-rule-card">
<div slot="header" class="clearfix">
<span>预览</span>
</div>
<el-row>
<el-col class="temp-parse-label">规则</el-col>
<el-col :span="18" class="temp-parse-content">{{tmpParseResult.xpath}}</el-col>
</el-row>
<el-row>
<el-col class="temp-parse-label">内容</el-col>
<el-col :span="18" class="temp-parse-content">{{tmpParseResult.text}}</el-col>
</el-row>
</el-card>
<el-card class="pare-result-card rule-card">
<div slot="header" class="clearfix">
<span>解析规则</span>
<i style="float: right; padding: 3px 0; margin-right: 5px;" @click="deleteAllRule"
class="el-icon-remove"></i>
</div>
<el-row v-for="(rule,index) in parseRule" :key="rule.value+'_'+index"
style="margin-bottom:10px;">
<el-col :span="8" class="parse-field">
<el-select size="mini" v-model="rule.field"
@change="ruleColChanged(rule.field,rule.parseContent,rule.value)"
placeholder="选择字段">
<el-option
v-for="item in esFields"
:key="item.columnProp"
:label="item.columnLabel"
:value="item.columnProp">
</el-option>
</el-select>
</el-col>
<el-col :span="14" class="parse-rule">
<el-input v-model="rule.value" autocomplete="off" size="mini"></el-input>
</el-col>
<el-col :span="2" class="parse-rule">
<i class="el-icon-remove" :style="'color:'+rule.color"
@click="deleteRule(index,rule.value)"></i>
</el-col>
</el-row>
</el-card>
</div>
<div align="right" class="footer_container" style="margin-right: 20px;">
<el-button @click="confirmRule" type="primary" icon="el-icon-check" size="mini">确认</el-button>
<el-button icon="el-icon-close" size="mini" @click="close">取消</el-button>
</div>
</el-aside>
</el-container>
</el-dialog>
</template>
<script>
import Vue from 'vue'
import {Dialog, Select, Message} from "element-ui";
const htmlHelperApi = require("../../js/api/htmlHelperApi");
Vue.use(Dialog);
Vue.use(Select);
export default {
name: 'VisualizedMouldModal',
props: ['dialogVisible', 'esFields'],
inject: ['reload'],
data() {
return {
formData: {},
maskDiv: [],
mouseMaskDiv: {},
tmpParseResult: {},
parseRule: [],
parseContent: [],
getColor: null,
multiSelectTemp: {},
weburl: "",
rules: [],
iframePath: "",
timer: null, //定时器定时刷新iframe高度
loading: false,
formrules: {},
usedColor: []
}
},
methods: {
close() {
this.$emit("close");
},
initModal(form_rules) {//父页面调用
this.tmpParseResult = {};
this.parseContent = [];
this.parseRule = [];
this.maskDiv = [];
this.usedColor = [];
this.formrules = form_rules;
this.weburl = form_rules.url;
if (form_rules.statichtml !== undefined && form_rules.statichtml !== null && form_rules.statichtml !== "") {
if (this.iframePath === form_rules.statichtml)
document.getElementById("web-display-iframe").contentWindow.location.reload(true);
this.iframePath = form_rules.statichtml
this.loading = true;
} else if (form_rules.url !== undefined && form_rules.url !== null && form_rules.url !== "") {
if (this.weburl === form_rules.url)
document.getElementById("web-display-iframe").contentWindow.location.reload(true);
this.getWeb(this.weburl);
this.loading = true;
} else
this.iframePath = "";
this.rules = form_rules.details;
// var iframe=document.getElementById('web-display-iframe');
//this.initDataByXpath(iframe);
},
loadIframe() {
if (this.weburl == null || this.weburl === "") {
this.loading = false;
return;
}
var iframe = document.getElementById('web-display-iframe');
this.color = this.getRandomColor();
var innerHtml = iframe.contentWindow.document.documentElement;
iframe.style.height = innerHtml.scrollHeight + 100 + "px";
iframe.style.width = innerHtml.scrollWidth + 100 + "px";
this.initDataByXpath(iframe);
// console.log(innerHtml)
this.loading = false;
iframe.contentWindow.document.addEventListener('mouseover', this.iframeMouseoverEvent);
iframe.contentWindow.document.addEventListener('mouseout', this.iframeMouseoutEvent);
iframe.contentWindow.document.addEventListener('click', this.iframeMouseClickEvent);
iframe.contentWindow.document.addEventListener('keyup', this.iframeKeyupEvent);
//this.setTimer();
},
iframeMouseoverEvent(event) {
event.preventDefault();
var doc = document.getElementById('web-display-iframe').contentWindow.document;
// var doc=document.getElementsByClassName("frame-container");
if (doc.addEventListener) {
doc.addEventListener("mousewheel", this.scrollFunc, {passive: false});
}
// doc.onmousewheel=this.scrollFunc;//IE/Opera/Chrome/Safari
var target = 'target' in event ? event.target : event.srcElement; // another IE hack
if (target.parentNode.nodeName !== "#document") {
var maskObj = new Object();
maskObj.style = this.getMaskStyle(target);
maskObj.key = this.getXpath(target);
maskObj.color = this.color;
this.mouseMaskDiv = maskObj;
this.tmpParseResult.xpath = maskObj.key;
this.tmpParseResult.text = target.innerText;
}
},
iframeMouseoutEvent(event) {
event.preventDefault();
var target = 'target' in event ? event.target : event.srcElement; // another IE hack
if (target.parentNode.nodeName !== "#document") {
this.mouseMaskDiv = null;
}
},
iframeMouseClickEvent() {
var target = 'target' in event ? event.target : event.srcElement; // another IE hack
if (target.parentNode.nodeName !== "#document") {
event.preventDefault();
var isMultiSelect = this.isContinueSelect();
var xpath = this.getXpath(target);
if (isMultiSelect == true) {
this.multiSelectTemp.xpath = this.multiSelectTemp.xpath == null || this.multiSelectTemp.xpath == "" ? xpath : this.multiSelectTemp.xpath + "|" + xpath;
this.multiSelectTemp.text = this.multiSelectTemp.text == null || this.multiSelectTemp.text == "" ? target.innerText : this.multiSelectTemp.text + "" + target.innerText;
} else {
this.getParseRule(xpath, target.innerText);
this.color = this.getRandomColor();
}
this.maskDiv.push(this.mouseMaskDiv);
}
},
iframeKeyupEvent(event) {
if (event.keyCode == "17") {
if (this.multiSelectTemp.xpath !== null && this.multiSelectTemp.xpath !== undefined && this.multiSelectTemp.xpath !== "")
this.getParseRule(this.multiSelectTemp.xpath, this.multiSelectTemp.text);
this.multiSelectTemp.xpath = "";
this.multiSelectTemp.text = "";
this.color = this.getRandomColor();
}
},
initDataByXpath(iframe) {
this.maskDiv = [];
this.parseRule = [];
this.parseContent = [];
for (var i = 0; i < this.rules.length; i++) {
var xpath = this.rules[i].value;
var colName = this.rules[i].field;
if (xpath == null || xpath == undefined || xpath == "")
continue;
var xpathArray = xpath.split('|');
var content = "";
if (iframe != null) {
for (var j = 0; j < xpathArray.length; j++) {
var iterate = iframe.contentWindow.document.evaluate(xpathArray[j], iframe.contentWindow.document);
if (iterate.resultType !== XPathResult.UNORDERED_NODE_ITERATOR_TYPE)
continue;
var target = iterate.iterateNext();
if (target == null || target == undefined)
continue;
var maskObj = new Object();
maskObj.style = this.getMaskStyle(target);
maskObj.key = xpathArray[j];
maskObj.color = this.color;
this.maskDiv.push(maskObj);
content = content == null || content == "" ? target.innerText : content + "" + target.innerText;
}
}
this.getParseRule(xpath, content, colName);
if (colName !== null && colName !== undefined && colName !== "") {
this.ruleColChanged(colName, content, xpath)
}
this.color = this.getRandomColor(); //更换显示颜色*/
}
},
confirmRule() {
this.formrules.url = this.weburl;
this.formrules.statichtml = this.iframePath;
this.formrules.details = [];
var tempRule = []
for (var i = 0; i < this.parseRule.length; i++) {
if (this.parseRule[i].field == 'es_urltitle' || this.parseRule[i].field == 'es_urlcontent')
this.formrules.details.push(this.parseRule[i])
else
tempRule.push(this.parseRule[i]);
}
if (this.formrules.details.length == 0) {
this.formrules.details.push({value: '', field: 'es_urltitle'});
this.formrules.details.push({value: '', field: 'es_urlcontent'});
} else if (this.formrules.details.length == 1 && this.formrules.details[0].field == 'es_urltitle') {
this.formrules.details.push({value: '', field: 'es_urlcontent'});
} else if (this.formrules.details.length == 1 && this.formrules.details[0].field == 'es_urlcontent') {
this.formrules.details.push({value: '', field: 'es_urltitle'});
}
if (tempRule.length > 0)
this.formrules.details = this.formrules.details.concat(tempRule);
this.$emit('sendRules', this.formrules);
},
cancelEidt() {
this.dialogVisible = false;
},
isContinueSelect() {
return window.event.ctrlKey ? true : false;
},
//右下侧规则展示
getParseRule(xpath, content, colName) {
var ruleObj = new Object();
ruleObj.value = xpath;
ruleObj.parseContent = content;
ruleObj.color = this.color;
if (colName !== null && colName !== undefined && colName !== "")
ruleObj.field = colName;
this.parseRule.push(ruleObj);
},
getMaskStyle(target) {
console.log(target)
console.log(target.getBoundingClientRect)
var style = "left: " + target.getBoundingClientRect().x + "px;"
+ "top: " + target.getBoundingClientRect().y + "px;" +
" width: " + target.offsetWidth + "px; "
+ "height: " + target.offsetHeight + "px; "
+ " background-color: " + this.color + ";";
return style;
},
ruleColChanged(val, text, xpath) {
var index = this.esFields.findIndex(r => r.columnProp == val);
if (index !== -1) {
val = this.esFields[index].columnLabel
}
var contentindex = this.parseContent.findIndex(r => r.xpath == xpath);
if (contentindex !== -1) {
this.parseContent[contentindex].colName = val;
return;
}
var contetnObj = new Object();
contetnObj.colName = val;
contetnObj.text = text;
contetnObj.xpath = xpath;
this.parseContent.push(contetnObj);
},
deleteRule(index, xpath) {
var color = this.parseRule[index].color;
this.parseRule.splice(index, 1);
//删除遮罩
var xpathArray = xpath.split('|');
for (var i = 0; i < xpathArray.length; i++) {
var maskindex = this.maskDiv.findIndex(r => r.key == xpathArray[i] && r.color == color);
if (maskindex !== -1)
this.maskDiv.splice(maskindex, 1);
}
//删除下方内容
var contentindex = this.parseContent.findIndex(r => r.xpath == xpath);
if (contentindex != -1)
this.parseContent.splice(contentindex, 1);
},
deleteAllRule() {
this.parseContent = [];
this.maskDiv = [];
this.parseRule = [];
},
getWeb(url) {
if (this.weburl == null || this.weburl == undefined || this.weburl == "") {
this.iframePath = "";
Message({
message: "请输入url",
type: "warning"
});
} else {
this.loading = true;
this.iframePath = 'http://47.115.228.133:28080/static/'+this.weburl
this.loading = false;
htmlHelperApi.default.downLoadHtml(url, (response) => {
if (response.data.code == 200) {
var fileName = response.data.content;
if (fileName !== null && fileName !== undefined && fileName !== "") {
document.getElementById('web-display-iframe').style.height = "100%"
document.getElementById('web-display-iframe').style.width = "100%"
this.iframePath = fileName;
}
} else {
this.loading = false;
Message({
message: "加载失败!",
type: "error"
});
}
});
}
},
scrollFunc(e) {
if (e.wheelDelta && e.ctrlKey) //IE/Opera/Chrome
e.returnValue = false;
else if (e.detail) // Firefox
e.returnValue = false;
},
getXpath(target) {
var xpath;
if (target.getAttribute("id") !== null) {
xpath = "//*[@id=\"" + target.getAttribute("id") + "\"]";
return xpath;
}
var iframeDoc = document.getElementById('web-display-iframe').contentWindow.document;
if (target.getAttribute("class") !== null) {
if (iframeDoc.getElementsByClassName(target.getAttribute("class")).length == 1) {
xpath = "//*[@class=\"" + target.getAttribute("class") + "\"]";
return xpath;
}
}
var targetIndex = this.getTargetIndex(target);
xpath = targetIndex == -1 ? target.tagName.toLowerCase() : target.tagName.toLowerCase() + "[" + targetIndex + "]";
var parentNode = target;
do {
parentNode = parentNode.parentNode;
var parentXpath;
if (parentNode.getAttribute("id") !== null) {
parentXpath = "//*[@id=\"" + parentNode.getAttribute("id") + "\"]"
return parentXpath + "/" + xpath;
}
if (parentNode.getAttribute("class") !== null) {
if (iframeDoc.getElementsByClassName(parentNode.getAttribute("class")).length == 1) {
return "//*[@class=\"" + parentNode.getAttribute("class") + "\"]" + "/" + xpath;
}
}
var parentTagName = parentNode.tagName.toLowerCase();
var parentNodeIndex = this.getTargetIndex(parentNode);
parentXpath = parentNodeIndex == -1 ? parentTagName.toLowerCase() : parentTagName.toLowerCase() + "[" + parentNodeIndex + "]";
xpath = parentXpath + "/" + xpath;
if (parentTagName.toLowerCase() == "html") {
xpath = "/" + xpath;
}
} while (parentTagName.toLowerCase() !== "html")
return xpath;
},
getTargetIndex(target) {
var targetIndex = 0, tagTotalCount = 0;
if (target.parentNode.children.length > 1) {
target.parentNode.childNodes.forEach(function (item) {
if (item.tagName == target.tagName)
tagTotalCount++;
if (item == target) {
targetIndex = tagTotalCount;
}
})
}
return tagTotalCount > 1 ? targetIndex : -1;
},
getRandomColor() {
var color;
do {
color = '#' + ('00000' + (Math.random() * 0x1000000 << 0).toString(16)).substr(-6);
} while (this.usedColor.indexOf(color) !== -1)
this.usedColor.push(color);
return '#' + ('00000' + (Math.random() * 0x1000000 << 0).toString(16)).substr(-6);
},
setTimer() {
clearInterval(this.timer)
this.timer = null
if (this.timer == null) {
this.timer = setInterval(() => {
var iframe = document.getElementById('web-display-iframe');
iframe.style.height = iframe.contentWindow.document.documentElement.offsetHeight + 100 + "px";
}, 1000)
}
}
}
}
</script>
<style>
#visualizedMould .el-dialog--center {
margin: 5vh auto !important;
height: 90vh;
overflow: hidden;
}
#visualizedMould .el-dialog__body {
position: absolute;
left: 0;
top: 54px;
bottom: 0;
right: 0;
padding: 0;
z-index: 1;
overflow: hidden;
overflow-y: auto;
}
#visualizedMould .el-container {
height: 100%;
}
#visualizedMould .browserarea {
height: 70%;
border: 1px solid #e7e7e7;
}
#visualizedMould .frame-container {
height: calc(100% - 65px);
overflow: auto;
position: relative;
}
#visualizedMould .browser-navigation {
padding: 7px;
border-bottom: 1px solid #e7e7e7;
background-color: #f5f5f5;
border-color: #ddd;
}
#visualizedMould .ember-view {
text-align: center;
}
#visualizedMould .el-main {
padding-top: 0px;
padding-right: 0px;
overflow: hidden;
}
#visualizedMould .el-aside {
padding-left: 10px;
}
#visualizedMould .parseresult {
height: 30%;
background-color: #f8f8f8;
border: 1px solid #e7e7e7;
border-radius: 0px;
overflow: auto;
padding-top: 10px;
}
#visualizedMould .temp-parse-label, #visualizedMould .parse-label {
width: 50px;
text-align: right;
vertical-align: middle;
float: left;
font-size: 14px;
color: #606266;
line-height: 40px;
box-sizing: border-box;
line-height: 28px;
}
#visualizedMould .temp-parse-content, #visualizedMould .parse-content {
line-height: 28px;
}
#visualizedMould .parse-label {
width: 80px;
}
#visualizedMould .pare-result-card {
margin-right: 20px;
margin-bottom: 20px;
overflow: auto;
}
#visualizedMould .temp-rule-card {
max-height: 40%;
}
#visualizedMould .rule-card {
max-height: 50%;
}
#visualizedMould .parse-rule {
padding-left: 10px;
}
#visualizedMould .el-card__header {
padding: 10px 20px;
background-color: #f8f8f8;
}
#url_input {
border-radius: 5px 0 0 5px;
}
#visualizedMould .nav-button {
padding: 10px;
font-size: 17px;
vertical-align: bottom;
}
#visualizedMould .nav-button-go {
border-radius: 0px;
}
#visualizedMould .nav-button-refresh {
border-radius: 0px 5px 5px 0;
margin-left: 0px;
}
#visualizedMould .eidt-stauts-iframe {
filter: grayscale(100%);
}
#visualizedMould .mask {
z-index: 999;
position: absolute;
opacity: 0.5;
pointer-events: none;
text-align: center;
vertical-align: middle;
display: table;
}
#visualizedMould .maskIcon {
display: table-cell;
vertical-align: middle;
color: white;
opacity: 1;
font-size: 16px;
}
#web-display-iframe html {
overflow: hidden;
}
#web-display-iframe .el-button:focus, .el-button:hover {
margin-right: 0px;
}
* {
touch-action: pan-y;
}
</style>