|
@@ -5,7 +5,7 @@
|
|
|
style="margin-top:40px;height: 100%;"
|
|
|
@click="parentClick($event)"
|
|
|
>
|
|
|
- <div style="width:100%;height: 100%;overflow: scroll;" class='parent' :id="containerId"></div>
|
|
|
+ <div style="width:100%;height: 100%;overflow: scroll;" class='parent' :id="containerId"></div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
@@ -13,25 +13,22 @@
|
|
|
<script>
|
|
|
import Vue from 'vue'
|
|
|
import { getExcelHtml } from '@/api/exctab/excelmodel'
|
|
|
-import { log } from '@antv/g2plot/lib/utils';
|
|
|
|
|
|
export default {
|
|
|
props: [
|
|
|
'pkeyId',
|
|
|
'initTableName',
|
|
|
- 'selectedTableKey' ,// 接收父组件传递的选中key
|
|
|
+ 'selectedTableKey',
|
|
|
'containerId'
|
|
|
],
|
|
|
data() {
|
|
|
return {
|
|
|
- selectedElements: [], // 存储已选中的元素
|
|
|
+ selectedElements: [],
|
|
|
exHtml: '',
|
|
|
currentComponent: null
|
|
|
}
|
|
|
},
|
|
|
- // 确保每个实例有独立的容器ID
|
|
|
created() {
|
|
|
- // 如果父组件没传,提供默认唯一ID
|
|
|
if (!this.containerId) {
|
|
|
this.containerId = `excel-container-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
|
}
|
|
@@ -43,7 +40,6 @@ export default {
|
|
|
handler(newVal) {
|
|
|
if (newVal) {
|
|
|
this.exHtml = ''
|
|
|
-
|
|
|
this.getExcelHtml(newVal)
|
|
|
} else {
|
|
|
this.exHtml = ''
|
|
@@ -51,13 +47,9 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
- // 监听选中的key变化,同步高亮显示
|
|
|
selectedTableKey: {
|
|
|
handler(newKey) {
|
|
|
- // 清除所有选中状态
|
|
|
this.clearAllSelected();
|
|
|
-
|
|
|
- // 如果有新的选中key,高亮对应的元素组
|
|
|
if (newKey && newKey.startsWith('key_')) {
|
|
|
this.highlightElementsByKey(newKey);
|
|
|
}
|
|
@@ -67,40 +59,39 @@ export default {
|
|
|
containerId: {
|
|
|
handler(newVal) {
|
|
|
this.clearForm()
|
|
|
- }
|
|
|
+ this.selectedElements = [];
|
|
|
+ },
|
|
|
+ immediate: true
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
- // 根据key高亮对应的元素组 // 确保所有DOM操作都限定在当前容器内
|
|
|
- getContainerElement() {
|
|
|
- return document.getElementById(this.containerId);
|
|
|
- }, // 修改所有使用document.getElementById的地方,使用动态容器ID
|
|
|
- highlightElementsByKey(key) {
|
|
|
- if (!key) return;
|
|
|
-
|
|
|
- // 确保在当前组件容器内操作
|
|
|
- const parent = document.getElementById(this.containerId);
|
|
|
- if (!parent) return;
|
|
|
-
|
|
|
- const keyPrefix = key.split('__')[0];
|
|
|
-
|
|
|
- // 修复:始终在当前容器内查找,避免污染其他实例
|
|
|
- const samePrefixElements = parent.querySelectorAll(`[id^="${keyPrefix}__"]`);
|
|
|
-
|
|
|
- if (samePrefixElements.length === 0) {
|
|
|
- // 修复:使用 parent.querySelector 而不是 document.getElementById
|
|
|
- const element = parent.querySelector(`#${key}`);
|
|
|
- if (element) {
|
|
|
- this.selectElements([element]);
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- this.selectElements(samePrefixElements);
|
|
|
-},
|
|
|
- async getExcelHtml(pkeyId) {
|
|
|
- console.log(pkeyId,'pkeyId');
|
|
|
+ // 获取当前组件容器元素,封装为工具方法
|
|
|
+ getContainer() {
|
|
|
+ return document.getElementById(this.containerId);
|
|
|
+ },
|
|
|
+
|
|
|
+ highlightElementsByKey(key) {
|
|
|
+ if (!key) return;
|
|
|
|
|
|
+ const container = this.getContainer();
|
|
|
+ if (!container) return;
|
|
|
+
|
|
|
+ const keyPrefix = key.split('__')[0];
|
|
|
+ // 只在当前容器内查找元素
|
|
|
+ const samePrefixElements = container.querySelectorAll(`[id^="${keyPrefix}__"]`);
|
|
|
+
|
|
|
+ if (samePrefixElements.length === 0) {
|
|
|
+ const element = container.querySelector(`#${key}`);
|
|
|
+ if (element) {
|
|
|
+ this.selectElements([element]);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ this.selectElements(samePrefixElements);
|
|
|
+ },
|
|
|
+
|
|
|
+ async getExcelHtml(pkeyId) {
|
|
|
this.clearForm();
|
|
|
try {
|
|
|
const { data: res } = await getExcelHtml({ pkeyId })
|
|
@@ -112,25 +103,18 @@ export default {
|
|
|
console.error('获取HTML失败:', error)
|
|
|
}
|
|
|
},
|
|
|
- clearForm() {
|
|
|
- // 使用动态容器ID
|
|
|
- const parentElement = document.getElementById(this.containerId)
|
|
|
- if (parentElement) {
|
|
|
- parentElement.innerHTML = ''
|
|
|
+
|
|
|
+ clearForm() {
|
|
|
+ const container = this.getContainer();
|
|
|
+ if (container) {
|
|
|
+ container.innerHTML = '';
|
|
|
}
|
|
|
- this.clearAllSelected()
|
|
|
+ this.clearAllSelected();
|
|
|
},
|
|
|
|
|
|
-
|
|
|
- async cop() {
|
|
|
- const _that = this;
|
|
|
- const parentElement = this.getContainerElement();
|
|
|
- if (!parentElement) {
|
|
|
- console.error('父容器不存在:', this.containerId);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (!parentElement) {
|
|
|
+ async cop() {
|
|
|
+ const container = this.getContainer();
|
|
|
+ if (!container) {
|
|
|
console.error('父容器不存在:', this.containerId);
|
|
|
return;
|
|
|
}
|
|
@@ -145,31 +129,29 @@ export default {
|
|
|
dap_site_data: {}
|
|
|
}
|
|
|
},
|
|
|
- methods: {
|
|
|
- contextmenuClick() {},
|
|
|
- getInformation() {},
|
|
|
- formUploadSuccess() {},
|
|
|
- formUploadExceed() {},
|
|
|
- formUploadLoading() {},
|
|
|
- delTableFormFile() {},
|
|
|
- formUploadError() {},
|
|
|
- uploadprogress() {},
|
|
|
- formRemoteMethod() {},
|
|
|
- getRegularExpression() {},
|
|
|
- checkboxGroupChange() {},
|
|
|
- formRemoteChange() {},
|
|
|
- dateKeydown() {},
|
|
|
- keyupShiftUp() {},
|
|
|
- keyupShiftDown() {},
|
|
|
- keyupShiftLeft() {},
|
|
|
- keyupShiftRight() {},
|
|
|
- inputLeftClick() {},
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- await Vue.nextTick();
|
|
|
+ methods: {
|
|
|
+ contextmenuClick() {},
|
|
|
+ getInformation() {},
|
|
|
+ formUploadSuccess() {},
|
|
|
+ formUploadExceed() {},
|
|
|
+ formUploadLoading() {},
|
|
|
+ delTableFormFile() {},
|
|
|
+ formUploadError() {},
|
|
|
+ uploadprogress() {},
|
|
|
+ formRemoteMethod() {},
|
|
|
+ getRegularExpression() {},
|
|
|
+ checkboxGroupChange() {},
|
|
|
+ formRemoteChange() {},
|
|
|
+ dateKeydown() {},
|
|
|
+ keyupShiftUp() {},
|
|
|
+ keyupShiftDown() {},
|
|
|
+ keyupShiftLeft() {},
|
|
|
+ keyupShiftRight() {},
|
|
|
+ inputLeftClick() {},
|
|
|
+ }
|
|
|
+ });
|
|
|
|
|
|
- // 先销毁可能存在的旧组件
|
|
|
+ // 销毁旧组件
|
|
|
if (this.currentComponent) {
|
|
|
this.currentComponent.$destroy();
|
|
|
}
|
|
@@ -177,36 +159,45 @@ export default {
|
|
|
// 创建新组件
|
|
|
this.currentComponent = new MyComponent().$mount();
|
|
|
|
|
|
- // 清空并添加新内容
|
|
|
- parentElement.innerHTML = '';
|
|
|
- parentElement.appendChild(this.currentComponent.$el);
|
|
|
- // 延迟执行高亮,确保DOM完全渲染
|
|
|
- this.$nextTick(() => {
|
|
|
- if (this.selectedTableKey) {
|
|
|
- this.highlightElementsByKey(this.selectedTableKey);
|
|
|
- }
|
|
|
- });
|
|
|
+ // 添加到当前容器
|
|
|
+ container.innerHTML = '';
|
|
|
+ container.appendChild(this.currentComponent.$el);
|
|
|
+
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.selectedTableKey) {
|
|
|
+ this.highlightElementsByKey(this.selectedTableKey);
|
|
|
+ }
|
|
|
+ });
|
|
|
} catch (error) {
|
|
|
console.error('组件渲染失败:', error);
|
|
|
}
|
|
|
},
|
|
|
+
|
|
|
async parentClick(e) {
|
|
|
+ e.stopPropagation(); // 阻止事件冒泡到其他组件
|
|
|
|
|
|
- // 原有点击处理逻辑保持不变
|
|
|
+ const container = this.getContainer();
|
|
|
+ if (!container || !container.contains(e.target)) {
|
|
|
+ return; // 不是当前组件内的点击,不处理
|
|
|
+ }
|
|
|
+
|
|
|
+ // 只在当前容器内查找目标元素
|
|
|
let target = e.target;
|
|
|
- while (target && !target.id && target.parentNode) {
|
|
|
+ while (target && target !== container && !target.id) {
|
|
|
target = target.parentNode;
|
|
|
}
|
|
|
|
|
|
- if (!target || !target.id) return;
|
|
|
- // 3. 关键:判断元素是否包含warnstyle类(处理父级可能带类的情况)
|
|
|
+ if (!target || !target.id || !container.contains(target)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查警告样式
|
|
|
let hasWarnStyle = false;
|
|
|
- // 先检查当前元素,再检查父级(因warnstyle可能加在el-input容器上)
|
|
|
- if (target.classList.contains('warnstyle') || target.parentNode.classList.contains('warnstyle')) {
|
|
|
+ if (target.classList.contains('warnstyle') ||
|
|
|
+ (target.parentNode && target.parentNode.classList.contains('warnstyle'))) {
|
|
|
hasWarnStyle = true;
|
|
|
}
|
|
|
|
|
|
- // 4. 含warnstyle类时触发警告并终止流程
|
|
|
if (hasWarnStyle) {
|
|
|
this.$message({
|
|
|
type: "warning",
|
|
@@ -216,17 +207,15 @@ export default {
|
|
|
}
|
|
|
|
|
|
const id = target.id;
|
|
|
-
|
|
|
-
|
|
|
const isAlreadySelected = this.selectedElements.some(item => item.id === id);
|
|
|
- console.log(isAlreadySelected,'isAlreadySelected');
|
|
|
|
|
|
this.clearAllSelected();
|
|
|
|
|
|
if (!isAlreadySelected) {
|
|
|
if (id.startsWith('key_')) {
|
|
|
const keyPrefix = this.extractKeyPrefix(id);
|
|
|
- const samePrefixElements = document.querySelectorAll(`[id^="${keyPrefix}__"]`);
|
|
|
+ // 关键修复:只在当前容器内查找同前缀元素
|
|
|
+ const samePrefixElements = container.querySelectorAll(`[id^="${keyPrefix}__"]`);
|
|
|
this.selectElements(samePrefixElements);
|
|
|
} else {
|
|
|
this.handleNormalElement(target, id);
|
|
@@ -240,21 +229,18 @@ export default {
|
|
|
},
|
|
|
|
|
|
selectElements(elements) {
|
|
|
-
|
|
|
-
|
|
|
+ const container = this.getContainer();
|
|
|
+ if (!container) return;
|
|
|
|
|
|
elements.forEach(el => {
|
|
|
- const index = this.selectedElements.findIndex(item => item.id === el.id);
|
|
|
- console.log(index,'index');
|
|
|
+ // 确保元素属于当前容器
|
|
|
+ if (!container.contains(el)) return;
|
|
|
|
|
|
+ const index = this.selectedElements.findIndex(item => item.id === el.id);
|
|
|
if (index === -1) {
|
|
|
- el.style.backgroundColor = '#ffa500'; // 橙色背景
|
|
|
- console.log(this.initTableName,'initTableName');
|
|
|
-
|
|
|
+ el.style.backgroundColor = '#ffa500';
|
|
|
const elementId = this.initTableName + ':' + this.extractKeyPrefix(el.id);
|
|
|
-
|
|
|
-
|
|
|
- const keyName = el.placeholder;
|
|
|
+ const keyName = el.placeholder || '';
|
|
|
this.selectedElements.push({ tableElementKey: elementId, eName: keyName, id: el.id });
|
|
|
this.$emit('element-selected', { tableElementKey: elementId, eName: keyName, id: el.id }, true);
|
|
|
}
|
|
@@ -262,8 +248,11 @@ export default {
|
|
|
},
|
|
|
|
|
|
handleNormalElement(target, id) {
|
|
|
+ const container = this.getContainer();
|
|
|
+ if (!container || !container.contains(target)) return;
|
|
|
+
|
|
|
const elementId = this.initTableName + ':' + target.id.split('__')[0];
|
|
|
-
|
|
|
+ const keyName = target.placeholder || '';
|
|
|
|
|
|
target.style.backgroundColor = '#ffa500';
|
|
|
this.selectedElements.push({ tableElementKey: elementId, eName: keyName, id });
|
|
@@ -271,11 +260,12 @@ export default {
|
|
|
},
|
|
|
|
|
|
clearAllSelected() {
|
|
|
- const container = this.getContainerElement();
|
|
|
- if (!container) return
|
|
|
-
|
|
|
+ const container = this.getContainer();
|
|
|
+ if (!container) return;
|
|
|
+
|
|
|
this.selectedElements.forEach(item => {
|
|
|
- const element = document.getElementById(item.id);
|
|
|
+ // 只清除当前容器内的元素样式
|
|
|
+ const element = container.querySelector(`#${item.id}`);
|
|
|
if (element) {
|
|
|
element.style.backgroundColor = '';
|
|
|
this.$emit('element-selected', {
|
|
@@ -286,17 +276,6 @@ export default {
|
|
|
}
|
|
|
});
|
|
|
this.selectedElements = [];
|
|
|
- },
|
|
|
-
|
|
|
- getParentTD(ele) {
|
|
|
- let targetParent = ele.parentNode;
|
|
|
- while (targetParent.nodeName !== "TD") {
|
|
|
- if (targetParent.id == 'parent') {
|
|
|
- return null;
|
|
|
- }
|
|
|
- targetParent = targetParent.parentNode;
|
|
|
- }
|
|
|
- return targetParent;
|
|
|
}
|
|
|
}
|
|
|
}
|