| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460 |
- <template>
- <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 {
- 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;
- console.log('Selecting elements:', elements, container);
-
- // 先取消选择所有相同 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 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>
|