浏览代码

选择元素页面

duy 4 天之前
父节点
当前提交
7533b52bb0
共有 1 个文件被更改,包括 446 次插入7 次删除
  1. 446 7
      src/views/formula/component/table-form-write.vue

+ 446 - 7
src/views/formula/component/table-form-write.vue

@@ -1,19 +1,458 @@
 <template>
-  <div>66666</div>
+  <div class="excelHtnl">
+    <div
+      class="excelBox hc-excel-table-form"
+      style="margin-top:40px;height: 100%;"
+      @click="parentClick($event)"
+    >
+      <div style="width:100%;height: 100%;overflow: scroll;" class='parent' :id="containerId"></div>
+    </div>
+  </div>
 </template>
 
 <script>
+import Vue from 'vue'
+import { getExcelHtml } from '@/api/exctab/excelmodel'
+
 export default {
-  name: "table-form-write",
-  props: {
-  
+  props: [
+    'pkeyId', 
+    'initTableName',
+    'selectedTableKey',
+    'containerId',
+    'multipleSelect'  // 是否允许多选,默认为false
+  ],
+  data() {
+    return {
+      selectedElements: [],
+      exHtml: '',
+      currentComponent: null
+    }
+  },
+  created() {
+    if (!this.containerId) {
+      this.containerId = `excel-container-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
+    }
+  },
+  watch: {
+    pkeyId: {
+      immediate: true,
+      deep: true,
+      handler(newVal) {
+        if (newVal) {
+          this.exHtml = ''
+          this.getExcelHtml(newVal)
+        } else {
+          this.exHtml = ''
+          this.clearForm()
+        }
+      }
+    },
+    selectedTableKey: {
+      handler(newKey) {
+        this.clearAllSelected();
+        if (newKey && newKey.startsWith('key_')) {
+          this.highlightElementsByKey(newKey);
+        }
+      },
+      immediate: true
+    },
+    containerId: {
+      handler(newVal) {
+        this.clearForm()
+        this.selectedElements = [];
+      },
+      immediate: true
+    },
+    multipleSelect: {
+      handler(newVal) {
+        // 当多选模式改变时,清空当前选择
+        if (!newVal && this.selectedElements.length > 1) {
+          // 如果关闭多选且当前有多个选中,只保留最后一个
+          const lastElement = this.selectedElements[this.selectedElements.length - 1];
+          this.clearAllSelected();
+          this.selectElements([lastElement]);
+        }
+      },
+      immediate: true
+    }
   },
   methods: {
+    // 获取当前组件容器元素,封装为工具方法
+    getContainer() {
+      return document.getElementById(this.containerId);
+    },
+    
+    // 获取当前所有有橙色背景且去重的元素列表
+    getCurrentSelectedElements() {
+      const container = this.getContainer();
+      if (!container) return [];
+      
+      // 获取所有有橙色背景的元素
+      const orangeElements = container.querySelectorAll('[style*="background-color: rgb(255, 165, 0)"], [style*="background-color:#ffa500"]');
+      
+      // 根据 tableElementKey 去重
+      const uniqueElements = [];
+      const seenKeys = new Set();
+      
+      orangeElements.forEach(el => {
+        if (el.id) {
+          const tableElementKey = this.initTableName + ':' + this.extractKeyPrefix(el.id);
+          if (!seenKeys.has(tableElementKey)) {
+            seenKeys.add(tableElementKey);
+            const keyName = el.placeholder || '';
+            uniqueElements.push({
+              tableElementKey: tableElementKey,
+              eName: keyName,
+              id: el.id
+            });
+          }
+        }
+      });
+      
+      return uniqueElements;
+    },
+    
+    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 })
+        if (res.code === 200) {
+          this.exHtml = res.data
+          this.cop();
+        }
+      } catch (error) {
+        console.error('获取HTML失败:', error)
+      }
+    },
+    
+    clearForm() {
+      const container = this.getContainer();
+      if (container) {
+        container.innerHTML = '';
+      }
+      this.clearAllSelected();
+    },
+    
+    async cop() {
+      const container = this.getContainer();
+      if (!container) {
+        console.error('父容器不存在:', this.containerId);
+        return;
+      }
+      
+      try {
+        const MyComponent = Vue.extend({
+          template: this.exHtml,
+          data() {
+            return {
+              formData: {},
+              getTokenHeader: {},
+              dap_site_data: {}
+            }
+          },
+          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();
+        }
+        
+        // 创建新组件
+        this.currentComponent = new MyComponent().$mount();
+        
+        // 添加到当前容器
+        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; // 不是当前组件内的点击,不处理
+      }
+      
+      // 检测Control键是否按下 (e.ctrlKey 对Windows/Linux有效,e.metaKey对Mac的Command键有效)
+      const isCtrlPressed = e.ctrlKey || e.metaKey;
+      // 只有在multipleSelect为true时才允许通过Control键进行多选
+      const isMultiSelectMode = this.multipleSelect && isCtrlPressed;
+      
+      // 只在当前容器内查找目标元素
+      let target = e.target;
+      while (target && target !== container && !target.id) {
+        target = target.parentNode;
+      }
+      
+      if (!target || !target.id || !container.contains(target)) {
+        return;
+      }
+      
+      // 检查警告样式
+      let hasWarnStyle = false;
+      if (target.classList.contains('warnstyle') || 
+          (target.parentNode && target.parentNode.classList.contains('warnstyle'))) {
+        hasWarnStyle = true;
+      }
 
+      if (hasWarnStyle) {
+        this.$message({
+          type: "warning",
+          message: "当前位置未配置元素,请重新选择或配置元素后再试"
+        });
+        return;
+      }
+      
+      const id = target.id;
+      const elementId = this.initTableName + ':' + this.extractKeyPrefix(id);
+      
+      // 检查是否已经有相同 tableElementKey 的元素被选中
+      const isSameKeySelected = this.selectedElements.some(item => 
+        item.tableElementKey === elementId
+      );
+      
+      // 根据是否按下Control键决定是否清空已选元素
+      if (!isMultiSelectMode) {
+        this.clearAllSelected();
+      }
+      
+      if (!isSameKeySelected) {
+        if (id.startsWith('key_')) {
+          const keyPrefix = this.extractKeyPrefix(id);
+          // 只在当前容器内查找同前缀元素
+          const samePrefixElements = container.querySelectorAll(`[id^="${keyPrefix}__"]`);
+          this.selectElements(samePrefixElements);
+        } else {
+          this.handleNormalElement(target, id);
+        }
+      } else {
+        // 如果已经有相同 tableElementKey 的元素被选中,在多选模式下点击会取消选择所有相同key的元素
+        if (isMultiSelectMode) {
+          this.deselectElementsByKey(elementId);
+        }
+      }
+    },
+    
+    extractKeyPrefix(id) {
+      const parts = id.split('__');
+      return parts.length > 0 ? parts[0] : id;
+    },
+    
+    selectElements(elements) {
+      const container = this.getContainer();
+      if (!container) return;
+      
+      // 先取消选择所有相同 tableElementKey 的元素(避免重复)
+      if (elements.length > 0) {
+        const firstElementId = this.initTableName + ':' + this.extractKeyPrefix(elements[0].id);
+        this.deselectElementsByKey(firstElementId);
+      }
+      
+      elements.forEach(el => {
+        // 确保元素属于当前容器
+        if (!container.contains(el)) return;
+        
+        const index = this.selectedElements.findIndex(item => item.id === el.id);
+        
+        if (index === -1) {
+          el.style.backgroundColor = '#ffa500';
+          const elementId = this.initTableName + ':' + this.extractKeyPrefix(el.id);
+          const keyName = el.placeholder || '';
+          const newElement = { tableElementKey: elementId, eName: keyName, id: el.id };
+          this.selectedElements.push(newElement);
+          
+          // 传递当前所有有橙色背景且去重的元素
+          const currentSelected = this.getCurrentSelectedElements();
+          this.$emit('element-selected', newElement, true, currentSelected);
+        }
+      });
+    },
+    
+    // 取消选择所有具有相同 tableElementKey 的元素
+    deselectElementsByKey(tableElementKey) {
+      const container = this.getContainer();
+      if (!container) return;
+      
+      // 找出所有相同 tableElementKey 的元素
+      const elementsToDeselect = this.selectedElements.filter(item => 
+        item.tableElementKey === tableElementKey
+      );
+      
+      if (elementsToDeselect.length === 0) return;
+      
+      // 清除样式并从选中列表中移除
+      elementsToDeselect.forEach(item => {
+        const element = container.querySelector(`#${item.id}`);
+        if (element) {
+          element.style.backgroundColor = '';
+        }
+        // 传递当前所有有橙色背景且去重的元素
+        const currentSelected = this.getCurrentSelectedElements();
+        this.$emit('element-selected', item, false, currentSelected);
+      });
+      
+      // 从选中列表中移除这些元素
+      this.selectedElements = this.selectedElements.filter(item => 
+        item.tableElementKey !== tableElementKey
+      );
+    },
+    
+    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 || '';
+      
+      if(!keyName){
+        this.$message({
+          type: "warning",
+          message: "当前位置未配置元素,请重新选择或配置元素后再试"
+        });
+        return;
+      }
+      
+      // 先取消选择相同 tableElementKey 的元素
+      this.deselectElementsByKey(elementId);
+      
+      target.style.backgroundColor = '#ffa500';
+      const newElement = { tableElementKey: elementId, eName: keyName, id };
+      this.selectedElements.push(newElement);
+      
+      // 传递当前所有有橙色背景且去重的元素
+      const currentSelected = this.getCurrentSelectedElements();
+      this.$emit('element-selected', newElement, true, currentSelected);
+    },
+    
+    clearAllSelected() {
+      const container = this.getContainer();
+      if (!container) return;
+      
+      this.selectedElements.forEach(item => {
+        // 只清除当前容器内的元素样式
+        const element = container.querySelector(`#${item.id}`);
+        if (element) {
+          element.style.backgroundColor = '';
+          // 传递当前所有有橙色背景且去重的元素
+          const currentSelected = this.getCurrentSelectedElements();
+          this.$emit('element-selected', { 
+            tableElementKey: item.tableElementKey, 
+            eName: item.eName, 
+            id: item.id 
+          }, false, currentSelected);
+        }
+      });
+      this.selectedElements = [];
+    }
   }
 }
 </script>
 
-<style scoped lang="scss">
-</style>
-    
+<style lang="scss" scoped>
+/* 样式保持不变 */
+.excelHtnl {
+  margin: 0 0 0 10px;
+  background-color: #fff;
+  box-sizing: border-box;
+  padding: 0 20px 100px 20px;
+  height: 100%;
+}
+
+.hc-upload-table-form {
+  position: relative;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.hc-upload-table-form .el-upload {
+  position: relative;
+  flex: 1;
+  height: 100%;
+  color: #ccc;
+}
+.hc-upload-table-form .el-upload .hc-table-form-icon {
+  font-size: 24px;
+  font-weight: 100;
+}
+.hc-upload-table-form .el-upload .hc-table-form-img {
+  width: 100%;
+  height: 100%;
+}
+
+.excelBox {
+  ::v-deep .oldlace-bg {
+    background-color: oldlace;
+  }
+  ::v-deep .select-td {
+    border-width: 4px;
+    border-color: #E6A23C;
+    border-style: solid;
+  }
+}
+
+::v-deep .warnstyle .el-input__inner {
+  background-image: url('/img/login/warn.png') !important;
+  background-repeat: no-repeat;
+  background-size: cover;
+  background-position: center
+}
+
+::v-deep .warnstyle .el-textarea__inner {
+  background-image: url('/img/login/warn.png') !important;
+  background-repeat: no-repeat;
+  background-position-x: 45%;
+  background-position-y: 46%;
+}
+</style>