瀏覽代碼

master代码合并

duy 1 天之前
父節點
當前提交
f87f3ddd92

+ 1 - 1
public/version.json

@@ -1,3 +1,3 @@
 {
-  "value": "20251020142404"
+  "value": "20251111142404"
 }

+ 6 - 4
src/api/formula/formula.js

@@ -10,7 +10,7 @@ export const getTypeMap = (params) => {
   })
 }
 
-export const saveFormula = ({formula,remark,nodeId,elementId,scale,number,map,scope,projectId,dev,ver,formulas}) => {
+export const saveFormula = ({formula,remark,nodeId,elementId,scale,number,map,scope,projectId,dev,ver,formulas,method}) => {
   return request({
     url: '/api/blade-manager/formula/save',
     method: 'post',
@@ -26,12 +26,13 @@ export const saveFormula = ({formula,remark,nodeId,elementId,scale,number,map,sc
       projectId,
       dev,
       ver,
-      formulas
+      formulas,
+      method
     }
   })
 }
 
-export const updateFormula = ({id,formula,remark,nodeId,elementId,scale,number,map,scope,dev,formulas}) => {
+export const updateFormula = ({id,formula,remark,nodeId,elementId,scale,number,map,scope,dev,formulas,method}) => {
   return request({
     url: '/api/blade-manager/formula/update',
     method: 'post',
@@ -46,7 +47,8 @@ export const updateFormula = ({id,formula,remark,nodeId,elementId,scale,number,m
       map,
       scope,
       dev,
-      formulas
+      formulas,
+      method
     }
   })
 }

+ 4 - 1
src/config/index.json

@@ -1,6 +1,9 @@
 {
+  "target": "http://127.0.0.1:8090",
+
+
   "target22": "http://39.108.216.210:8090",
-  "target": "http://192.168.0.109:8090",
+  "target33": "http://192.168.0.109:8090",
   "target11": "http://219.151.181.73:8090",
   "target3": "http://183.247.216.148:28090",
   "target2": "http://192.168.0.109:8090",

+ 35 - 0
src/styles/common.scss

@@ -165,3 +165,38 @@ a{
   margin-right: 4px;
 }
 
+// 表单搜索框高亮显示
+.hc-search-highlight {
+   position: relative;
+}
+.hc-search-highlight::before {
+    content: '';
+    position: absolute;
+    background-color: rgba(157, 206, 255, 0.4) !important;
+    border-radius: 5px;
+    top: -2px;
+    left: -2px;
+    right: -2px;
+    bottom: -2px;
+    z-index: 1;
+    pointer-events: none;
+}
+
+// 文案关键词高亮显示
+.hc-keyword-highlight {
+   position: relative;
+   display: inline;
+}
+.hc-keyword-highlight::before {
+    content: '';
+    position: absolute;
+    background-color: rgba(157, 206, 255, 0.4) !important;
+    // border-radius: 3px;
+    top: -1px;
+    left: 0;
+    right: 0;
+    bottom: -1px;
+    // z-index: 1;
+    pointer-events: none;
+}
+

+ 16 - 0
src/util/util.js

@@ -391,4 +391,20 @@ export const downloadXls = (fileArrayBuffer, filename) => {
 }
 export const isObjectEmpty=(obj)=> {
   return JSON.stringify(obj) === '{}';
+}
+
+/**
+ * 关键词高亮
+ * @param {String} text   原始文本
+ * @param {String} key    关键词
+ * @returns {String}      返回带标签的字符串
+ */
+export function highlight(text = '', key = '') {
+  if (!key) return text
+  const reg = new RegExp(
+    // 把用户输入的特殊符号转义,防止正则报错
+    key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'),
+    'g', // g 全局  i 忽略大小写
+  )
+  return text.replace(reg, str => [...str].map( el => `<span class="hc-keyword-highlight">${el}</span>`).join(''))
 }

File diff suppressed because it is too large
+ 452 - 353
src/views/exctab/exceltab.vue


+ 20 - 2
src/views/formula/component/deviationRange/deviationRange.vue

@@ -21,12 +21,12 @@
       <span style="width:60px"></span>
       <template v-if="!(symbol == '<' || symbol== '≤')">
         <span class="textblod mg-r-10"></span>
-        <vue-tags-input v-model="tag1" :tags="tags1" @focus="curFocusIndex = 1" @blur="inputBlur(1)" placeholder="输入/参数" @before-adding-tag="beforeAddingTag"/>
+        <vue-tags-input v-model="tag1" :tags="tags1" @focus="curFocusIndex = 1" @blur="inputBlur(1)" placeholder="输入/参数" @before-adding-tag="beforeAddingTag"  @tag-clicked="handleTagClick($event,1)" ref="tagsInput1"/>
         <span style="width:20px"></span>
       </template>
       <template v-if="!(symbol == '>' || symbol== '≥')">
         <span class="textblod mg-r-10"></span>
-        <vue-tags-input v-model="tag2" :tags="tags2" @focus="curFocusIndex = 2" @blur="inputBlur(2)" placeholder="输入/参数" @before-adding-tag="beforeAddingTag"/>
+        <vue-tags-input v-model="tag2" :tags="tags2" @focus="curFocusIndex = 2" @blur="inputBlur(2)" placeholder="输入/参数" @before-adding-tag="beforeAddingTag"  @tag-clicked="handleTagClick($event,2)" ref="tagsInput2"/>
       </template>
     </div>
 
@@ -478,6 +478,24 @@ export default {
       })
       this.inputVisible = false;
     },
+    handleTagClick(info,index) {
+     
+       const {tag}=info;
+
+       
+      this.curFocusIndex = index
+     
+      
+      // 调用对应输入框的 focus() 方法
+        if (this.curFocusIndex === 1) {
+          this.$refs.tagsInput1.focus(); // 注意:确保组件已挂载,使用可选链避免报错
+        } else {
+          this.$refs.tagsInput2.focus();
+        }
+
+  
+       this.$emit('clickTag',tag)
+    },
 
   }
 }

+ 111 - 37
src/views/formula/component/formulaItem.vue

@@ -1,9 +1,28 @@
 <template>
-  <span :class="getItemClass(item)" @click="itemClick(item)">
-    {{item.name}}
+  <div class="inline-container">
+    <!-- 元素标签 -->
+    <el-tag 
+      v-if="item.type === 'Element'"
+      type="info"   
+      :effect="item.selected ? 'dark' : 'plain'"
+      @click="itemClick(item)"
+      class="ellipse-tag"
+      :class="{'selected-tag': item.selected}"
+    > 
+      {{ item.name }}
+    </el-tag>
+    <span 
+      :class="getItemClass(item)" 
+      @click="itemClick(item)" 
+      v-else
+      class="element-span"
+    >
+      {{ item.name }}
+    </span>
     
-  </span>
-  
+    <!-- 光标指示器 - 选中时或强制显示时显示 -->
+    <span v-if="isShowCursor&&(item.selected || showCursor)" class="cursor-blink"></span>
+  </div>
 </template>
 
 <script>
@@ -12,48 +31,103 @@ export default {
   props: {
     item: {
       type: Object,
-      default: function () {
-        return {};
-      }
+      default: () => ({})
     },
-   
-  },
-  data(){
-    return{
-
-    }
+    // 新增属性:用于强制显示光标
+    showCursor: {
+      type: Boolean,
+      default: false
+    },
+    isShowCursor: {
+      type: Boolean,
+      default: true
+    }//是否显示光标
   },
-  methods:{
-    itemClick(item){
+  methods: {
+    itemClick(item) {
+      // 切换选中状态
       item.selected = !item.selected;
-      this.$emit('click',{
-        selected:item.selected,
+      this.$emit('click', {
+        selected: item.selected,
         item
-      })
+      });
     },
-    getItemClass(item){
-      let obj = {};
-      // obj[item.type.toLocaleLowerCase()+'-class']=true;
-      obj['element-class']=true;
-      if(item.selected){
-        obj.selected = true;
-      }
-      return obj;
+    getItemClass(item) {
+      return {
+        'element-class': true,
+        'selected': item.selected
+      };
     }
   }
 }
 </script>
+
 <style scoped lang="scss">
-  .element-class{
-    cursor: pointer;
-    padding: 0 3px;
-    &.selected{
-      color: rgba(64,149,229,1);
-    }
+// 共用样式
+.element-class, .ellipse-tag {
+  display: inline-flex;
+  align-items: center; // 纵向居中对齐
+  justify-content: center;
+  vertical-align: middle; // 确保与其他元素对齐
+  box-sizing: border-box;
+}
+
+.element-class {
+  cursor: pointer;
+  padding: 0 3px;
+  height: 32px; // 与tag保持一致高度
+  
+  &.selected {
+    color: #f0720a;
   }
-  .text-blue{
-    font-size: 20px;
-    color: rgba(64,149,229,1);
-    font-weight:bold;
+}
+
+// 标签样式
+.ellipse-tag {
+  border-radius: 50px !important; // 椭圆样式
+  padding: 0 12px !important;
+  height: 32px; // 固定高度确保对齐
+  transition: all 0.2s ease; // 平滑过渡效果
+  background-color: #E7E7E7 !important; // 默认背景色
+  border-color: #E7E7E7 !important;    // 默认边框色
+  color: #333 !important;              // 默认文字色
+  
+  &.selected-tag {
+    background-color: #909399 !important; // 选中状态背景色
+    border-color: #909399 !important;    // 选中状态边框色
+    color: #fff !important;              // 选中状态文字色
+    transform: scale(1.05);
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
+    margin-left: 8px;
+    margin-right: 5px;
   }
-</style>
+}
+
+// 确保span和tag在同一行时对齐
+.element-span {
+  display: inline-flex;
+  align-items: center;
+  height: 32px;
+}
+
+// 新增样式
+.inline-container {
+  display: inline-flex;
+  align-items: center;
+}
+
+// 光标样式 - 模拟输入框闪烁效果
+.cursor-blink {
+  width: 2px;
+  height: 1.2em;
+  background-color: #333;
+  margin: 0 1px;
+  animation: blink 1s step-end infinite;
+}
+
+@keyframes blink {
+  from, to { background-color: transparent }
+  50% { background-color: #333 }
+}
+
+</style>

+ 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>

File diff suppressed because it is too large
+ 218 - 320
src/views/formula/edit.vue


+ 505 - 31
src/views/formula/edit1.vue

@@ -57,7 +57,7 @@
             <div slot="content">{{item.tableName }}</div>
             <formula-item
               :getname="getItemTableName(item)"
-              :item="item" @click="obj => equationClick(obj,index,'processFormula')"
+              :item="item" @click="obj => equationClick(obj,index,'processFormula')" :isShowCursor="false"
             >
             </formula-item>
           </el-tooltip>
@@ -119,7 +119,7 @@
             </el-card>
           </el-col>
           <el-col :span="16" class="h-100p flex flex-d-c ov-hidden">
-             <div style="display:flex">
+             <!-- <div style="display:flex">
                       <el-input placeholder="请输入你想搜索的元素字段" v-model="inputele"  clearable  @clear="clearinput" >  </el-input>
                         <el-button type="primary" icon="el-icon-search"  size="small"  @click="searchChange">搜索</el-button>
                </div>
@@ -130,7 +130,7 @@
                     <div class="ele-box">
                       <span v-if="item.k">{{item.name}}</span>
                       <span v-else>{{item.eName}}</span>
-                       <!-- <span >{{item.title}}</span> -->
+                     
 
                       <el-checkbox v-model="item.checked" @change="value => eleChang(value,item)"></el-checkbox>
                     </div>
@@ -139,7 +139,7 @@
               </el-scrollbar>
             </div>
             <div class="flex jc-sb">
-              <!-- <div>定位数据位置:</div> -->
+       
               <div class="icon-box">
                 <el-link :underline="false" icon="el-icon-delete" type="danger" @click="removeSelect"></el-link>
                 <el-link :underline="false" type="primary" @click="addOperator('+')" icon="el-icon-circle-plus-outline"></el-link>
@@ -148,11 +148,10 @@
                 <el-link :underline="false" type="primary" @click="addOperator('%')">÷</el-link>
               </div>
               <div>
-                <!-- <el-link :underline="false" type="primary" class="mg-r-20" @click="eleAddFormula">元素添加到公式</el-link> -->
+                
                 <el-link :underline="false" type="primary" class="mg-r-10" @click="addBrackets('(',false)">(</el-link>
                 <el-link :underline="false" type="primary" class="mg-r-10" @click="addBrackets(')',true)">)</el-link>
-                <!-- <el-link :underline="false" type="primary" class="mg-r-10" @click="addBrackets('[',false)">【</el-link>
-                <el-link :underline="false" type="primary" class="mg-r-10" @click="addBrackets(']',true)">】</el-link> -->
+       
                 <el-link :underline="false" type="primary" @click="addText">输入值</el-link>
               </div>
             </div>
@@ -164,6 +163,74 @@
                 >
                 </formula-item>
               </draggable>
+            </div> -->
+            <div class="operation-box">
+              <!-- 运算符选择区域 -->
+                <div class="flex jc-sb operation-symbol-box">
+                    
+                    <div class="icon-box ">
+                        <span class="text-sm" >插入运算符:</span>
+                    
+                      <el-link type="primary" @click="addOperator('+')" icon="el-icon-circle-plus-outline" size="mini"></el-link>
+                      <el-link  type="primary" @click="addOperator('-')" icon="el-icon-remove-outline"></el-link>
+                      <el-link type="primary" @click="addOperator('*')" icon="el-icon-circle-close"></el-link>
+                      <el-link  type="primary" @click="addOperator('%')">÷</el-link>
+                       <el-link type="primary" class="mg-r-10" @click="addBrackets('(',false)">(</el-link>
+                      <el-link  type="primary" class="mg-r-10" @click="addBrackets(')',true)">)</el-link>
+                        <el-link type="primary" @click="addText">固定值</el-link>
+                    </div>
+                    <div>
+                      操作
+                    <el-link  icon="el-icon-delete" type="danger" @click="removeSelect"></el-link>
+                    </div>
+                  </div>
+      
+               <div 
+                  class="border-grey sele-ele-box1"  
+               
+                  tabindex="0"
+                  @keydown.left="handleLeftArrow"
+                  @keydown.right="handleRightArrow"
+                  @keydown.delete="handleDelete"
+                  @keydown.shift.189="addOperator('-')" 
+                  @keydown.shift.191="addOperator('/')" 
+                  @keydown.shift.57="addBrackets('(')"  
+                  @keydown.shift.48="addBrackets(')')" 
+                  @keydown.shift.187="addOperator('+')" 
+                  @keydown.shift.56="addOperator('*')" 
+                  @focus="containerFocused = true"
+                  @blur="containerFocused = false"
+                >
+                  <draggable v-model="selectEleFormula">
+                    <formula-item
+                      v-for="(item,index) in selectEleFormula" 
+                      :key="index"
+                      :item="item" 
+                      @click="obj => eleFormulaClick(obj,index)"  
+                    >
+                    </formula-item>
+                  </draggable>
+                </div>
+            
+                  <div class="flex mg-t-10" style="justify-content: space-between;width:100%;">
+                    <el-select v-model="eleTableId" @change="getTableEle" placeholder="请选择元素表1" style="width:45%"  size="small">
+                      <el-option v-if="paramDataList.length" label="选择节点参数2" value="选择节点参数"></el-option>
+                      <el-option  v-for="item in eleTableList" :key="item.id" :label="item.title" :value="(item.pkeyId!==null&&item.pkeyId!==-1)?item.pkeyId:item.id"></el-option>
+                    </el-select>
+
+                     <div class="text-align-c">
+                      <el-button size="small" @click="canceloperationVisible ">取消</el-button>
+                      <el-button size="small" @click="operationHandle" type="primary">保存</el-button>
+                    </div>
+                  </div>
+           
+                <div class="mg-t-10 no-mb-col flex1" >
+                  <el-scrollbar style="height: 450px">
+        
+                     <tableFormWrite :pkeyId="eleTableId" @element-selected="handleElementSelected" :initTableName="initTableName"  :selectedTableKey="selectedTableKey"  :key="1" :container-id="'excel-container-1'" ></tableFormWrite>
+                  </el-scrollbar>
+                </div>
+         
             </div>
           </el-col>
         </el-row>
@@ -213,7 +280,24 @@
           <template v-else>
             <div class="flex" >
               <div class=" flex-d-c"  style="width:40%">
-                <component ref="dynamiccomponent" v-bind:is="componentMap[item.name]" :formulainfo="item" :curele="equationSelectEle" :formulamap="formulaMap" @uncheck="unCheckEleComp" class="flex1"></component>
+                <component 
+                  ref="dynamiccomponent" 
+                  v-bind:is="componentMap[item.name]" 
+                  :formulainfo="item" :curele="equationSelectEle" 
+                  :formulamap="formulaMap" 
+                    :map="formulaDetailMap"
+                  @uncheck="unCheckEleComp" 
+                  class="flex1"
+                  :moreConditions="moreConditions" 
+                  :isMore="isMore"
+                  :isGetData="isGetData"
+                  :dataListGet="dataListGet"
+                  :isDataChange="isDataChange"
+                  :dataForm="dataForm"
+                  :remark="remark"
+                  
+                  >
+                </component>
                 <div class="flex1" v-show="item.showSelectEle" style="margin-top:10px;margin-bottom:30px">
                   <div class="flex">
                       <el-input
@@ -490,8 +574,8 @@ import {formulaStringToArray} from "./formulaStringToArray"
 
 
 import draggable from 'vuedraggable'
-
-
+import tableFormWrite from "./component/table-form-write.vue";
+import {formatArrayMore,restoreArrayMore,generateResult} from './component/funComponent/multiIfElseTools'
 export default {
   components: {
     draggable,
@@ -509,7 +593,8 @@ export default {
     datasJoin,
     ifelse,
 
-    deviationRange
+    deviationRange,
+    tableFormWrite
   },
   props: {
     wbsid:{
@@ -663,8 +748,15 @@ export default {
       inputele:'',
       inputelepian:'',
       inputelejudge:'',
-
-
+      moreConditions:[],//多条件判断数组
+      isMore:false,//是否多条件
+      isGetData:false,//是否获取数据
+      dataListGet:[],//获取的数据列表
+      isDataChange:false,//数据是否变化
+      dataForm:'',
+      remark:'',
+      formulaDetailMap:{},//公式详情map
+      containerFocused:false,//公式编辑区域是否聚焦
     };
   },
   computed: {
@@ -698,6 +790,20 @@ export default {
     },
 
 
+  },
+  watch: {
+    selectEleFormula: {
+      handler() {
+        this.checkDefaultSelection();
+          this.$nextTick(() => {
+            this.$el.querySelector('.sele-ele-box1').focus();
+          });
+      },
+      deep: true
+    },
+  
+
+
   },
 
   created() {
@@ -705,6 +811,10 @@ export default {
     // this.eleid = this.$route.query.eleid;
     // this.nodeid = this.$route.query.nodeid;
      this.pid = this.$route.query.pid;//项目id 私有树才有
+     console.log(this.pid,'this.pid');
+     console.log(this.globaltype,'this.globaltype');
+     
+     
     this.init();
   },
   methods: {
@@ -897,6 +1007,11 @@ export default {
     operationEdit(){
       this.selectEleFormula= JSON.parse(JSON.stringify(this.processFormula));
       this.operationVisible = true;
+
+         // 确保容器获得焦点
+        this.$nextTick(() => {
+          this.$el.querySelector('.sele-ele-box1').focus();
+        });
     },
 
     eleAddFormula(){
@@ -1158,17 +1273,34 @@ export default {
     },
 
     //点选公式中的元素
-    eleFormulaClick({selected,item},index){
-      if(selected){
-        this.selectEleFormula.forEach((ele)=>{
-          ele.selected = false;
-        })
-        item.selected = true;
-        this.curSeleEleIndex = index;
-      }else{
-        this.curSeleEleIndex = -1;
+    eleFormulaClick(obj, index) {
+      // 先取消所有选中状态
+      this.selectEleFormula.forEach(item => {
+        item.selected = false;
+      });
+      
+      // 设置当前选中项
+      obj.item.selected = obj.selected;
+      this.curSeleEleIndex = index;
+      
+      // 确保容器获得焦点以接收键盘事件
+       this.$el.querySelector('.sele-ele-box1').focus();
+    // 处理类型为ELEMENT的元素,提取tableElementKey
+    console.log(obj.item,'obj.item.');
+    
+      if (obj.item.type === 'Element' && obj.item.tableElementKey) {
+        // 从类似"m_20220928142210_1575007943793836032:key_1"的格式中提取key部分
+        const keyParts = obj.item.tableElementKey.split('key');
+        this.selectedTableKey = keyParts.length > 1 ? 'key'+keyParts[1] : null;
+   
+        
+      } else {
+        // 非ELEMENT类型清空选中状态
+        this.selectedTableKey = null;
       }
+      
     },
+    
 
     //取消勾选
     unCheckEleFormulac(eleId){
@@ -1425,6 +1557,185 @@ export default {
     saveFormula(){
       console.log('保存1',this.pid);
       // let obj = formulaArrayToString(this.processFormula,this.resultFormula);
+      if(this.$refs.dynamiccomponent&&this.$refs.dynamiccomponent.length>0&&this.$refs.dynamiccomponent[0]&& this.$refs.dynamiccomponent[0].symbol=='more'){
+        //多条件保存公式
+
+        console.log('this.$refs.conditionList[0]',this.$refs.dynamiccomponent[0].conditionList);
+        let resMore=formatArrayMore(this.$refs.dynamiccomponent[0].conditionList);
+        const resJson=generateResult(this.$refs.dynamiccomponent[0].conditionList);
+        let remark=this.$refs.dynamiccomponent[0].remark;
+        console.log(remark,'remark');
+
+        console.log(resJson,'resJson');
+        
+     
+            if(this.formulaid){
+              updateFormula({
+                id:this.formulaid,
+                formula:'',
+                formulas:resMore,
+                remark:remark,
+                nodeId:this.nodeid,
+                elementId:this.eleid,
+                scale:this.isRetain?this.retainNum:'',
+                number:number,
+                map:JSON.stringify(resJson),
+                scope:this.globaltype,
+                // projectId:this.curProjiect.id||this.projectId,
+                projectId:this.curProjiect.id||this.pid,
+                dev:deviationRangeText
+              }).then(()=>{
+                this.formulaStringToArray();
+                this.$message({
+                  type: "success",
+                  message: "修改成功"
+                });
+              })
+            }else{
+              saveFormula({
+                formula:'',
+                formulas:resMore,
+                remark:remark,
+                nodeId:this.nodeid,
+                elementId:this.eleid,
+                scale:this.isRetain?this.retainNum:'',
+                number:number,
+                map:JSON.stringify(resJson),
+                scope:this.globaltype,
+                dev:deviationRangeText,
+               
+                projectId:this.curProjiect.id||this.pid,
+                ver:this.version
+              }).then((res)=>{
+                if(res.data.data){
+                  this.formulaid = res.data.data;
+                }
+                this.formulaStringToArray();
+                this.$message({
+                  type: "success",
+                  message: "保存成功"
+                });
+              })
+            }
+            
+            return;
+        
+        
+      }else if(this.$refs.dynamiccomponent&&this.$refs.dynamiccomponent.length>0&&this.$refs.dynamiccomponent[0]&& this.$refs.dynamiccomponent[0].symbol=='getData'){
+       //数据获取保存公式
+        const dataRes = this.$refs.dynamiccomponent[0].getDataConditionData();
+       console.log(dataRes,'dataRes');
+       const result =dataRes.result;
+       const mapEle = JSON.stringify(dataRes.mapEle);
+       console.log(mapEle,'mapEle');
+       
+
+            if(this.formulaid){
+              updateFormula({
+                id:this.formulaid,
+               formula:"FC.switchCase"+'('+result+')',
+             
+                remark:'',
+                nodeId:this.nodeid,
+                elementId:this.eleid,
+                scale:this.isRetain?this.retainNum:'',
+                number:number,
+                map:mapEle,
+                scope:this.globaltype,
+                // projectId:this.curProjiect.id||this.projectId,
+                projectId:this.curProjiect.id||this.pid,
+                dev:deviationRangeText
+              }).then(()=>{
+                this.formulaStringToArray();
+                this.$message({
+                  type: "success",
+                  message: "修改成功"
+                });
+              })
+            }else{
+              saveFormula({
+                  formula:"FC.switchCase" +'('+result+')',
+          
+                remark:'',
+                nodeId:this.nodeid,
+                elementId:this.eleid,
+                scale:this.isRetain?this.retainNum:'',
+                number:number,
+                map:mapEle,
+                scope:this.globaltype,
+                dev:deviationRangeText,
+                // projectId:this.curProjiect.id||this.projectId,
+                projectId:this.curProjiect.id||this.pid,
+                ver:this.version
+              }).then((res)=>{
+                if(res.data.data){
+                  this.formulaid = res.data.data;
+                }
+                this.formulaStringToArray();
+                this.$message({
+                  type: "success",
+                  message: "保存成功"
+                });
+              })
+            }
+            
+            return;
+       
+      }else if(this.$refs.dynamiccomponent&&this.$refs.dynamiccomponent.length>0&&this.$refs.dynamiccomponent[0]&& this.$refs.dynamiccomponent[0].formData){
+        console.log(this.$refs.dynamiccomponent[0],'this.$refs.dynamiccomponent[0');
+        const resForm=this.$refs.dynamiccomponent[0].getDataChangeList();
+        console.log(resForm,'resForm');
+        
+        //数据自变保存
+
+             if(this.formulaid){
+              updateFormula({
+                id:this.formulaid,
+                formula:resForm.test,
+                remark:'',
+                nodeId:this.nodeid,
+                elementId:this.eleid,
+                scale:this.isRetain?this.retainNum:'',
+                number:number,
+                map:JSON.stringify(resForm.map),
+                scope:this.globaltype,
+                // projectId:this.curProjiect.id||this.projectId,
+                projectId:this.curProjiect.id||this.pid,
+                dev:deviationRangeText
+              }).then(()=>{
+                this.formulaStringToArray();
+                this.$message({
+                  type: "success",
+                  message: "修改成功"
+                });
+              })
+            }else{
+              saveFormula({
+                formula:resForm.test,
+                remark:'',
+                nodeId:this.nodeid,
+                elementId:this.eleid,
+                scale:this.isRetain?this.retainNum:'',
+                number:number,
+                map:JSON.stringify(resForm.map),
+                scope:this.globaltype,
+                dev:deviationRangeText,
+                // projectId:this.curProjiect.id||this.projectId,
+                projectId:this.curProjiect.id||this.pid,
+                ver:this.version
+              }).then((res)=>{
+                if(res.data.data){
+                  this.formulaid = res.data.data;
+                }
+                this.formulaStringToArray();
+                this.$message({
+                  type: "success",
+                  message: "保存成功"
+                });
+              })
+            }
+            return
+      }
        let arr=JSON.parse(JSON.stringify(this.processFormula));
       let filteredArr = arr.filter(item => item.id ===this.checkGsId);
       //  let obj = formulaArrayToString(filteredArr,this.resultFormula);
@@ -1531,6 +1842,41 @@ export default {
     async formulaStringToArray(){
       let detail = (await formulaDetail({elementId:this.eleid,scope:this.globaltype,nodeId:this.nodeid,projectId:this.curProjiect.id||this.pid})).data.data;
       console.log(detail);
+      this.remark== detail.remark;
+      //判断公式特殊处理
+      if(detail&&detail.formula.includes('FC.ifelseMulti')){
+        detail.formula = detail.formula.replace('FC.ifelseMulti','FC.ifelse');
+        this.isMore = true;
+            this.formulaDetailMap = detail.map;
+        this.moreConditions =  restoreArrayMore(detail.formulas,this.formulaDetailMap)
+    
+      }else if(detail&&detail.formula.includes('FC.switchCase')){
+        //数据获取
+        this.formulaDetailMap = detail.map;
+         detail.formula = detail.formula.replace('FC.switchCase','FC.ifelse');
+         this.isGetData = true;
+         this.dataListGet=detail.formula
+         console.log( this.dataListGet,' this.dataListGet');
+         
+      }else if(detail&&detail.formula.includes('FC.dataChange')){
+        //数据自变
+        this.formulaDetailMap = detail.map;
+      
+         this.isDataChange = true;
+         this.dataForm=detail.formula
+         console.log( this.dataForm,' this.dataListGet');
+         
+      }
+      else{
+        this.isMore = false;
+        this.moreConditions = []
+        this.formulaDetailMap ={}
+        this.isGetData = false;
+        this.dataListGet=''
+        this.isDataChange = false;
+        this.dataForm='';
+
+      }
       if(detail&&detail.id){
         //获取右边元素的字典
         let dictMap=detail.dict
@@ -1601,13 +1947,15 @@ export default {
       this.input3=''
         if(data.hasChildren===false||data.isLinkTable===2){
            this.eleListable=true;
-           getTableElments(data.initTableId ).then((res)=>{
-             if(res.data.code == 200){
-                this.eleList=res.data.data;
-                 this.eleTableList =res.data.data;
-                this.eleListable=false;
-             }
-           })
+          //  getTableElments(data.initTableId ).then((res)=>{
+          //    if(res.data.code == 200){
+          //       this.eleList=res.data.data;
+          //        this.eleTableList =res.data.data;
+          //       this.eleListable=false;
+          //    }
+          //  })
+          this.eleTableList=[this.curData]||[]
+          this.eleTableId=this.eleTableList[0].id;
         }
         else{
           this.eleListable=true;
@@ -1801,7 +2149,107 @@ export default {
           resolve();
         })
       })
-    }
+    },
+        // 左箭头导航
+    handleLeftArrow(e) {
+      e.preventDefault(); // 阻止默认行为
+      if (this.curSeleEleIndex > 0) {
+        // 取消当前选中项
+        if (this.selectEleFormula[this.curSeleEleIndex]) {
+          this.selectEleFormula[this.curSeleEleIndex].selected = false;
+        }
+        
+        // 选中左侧项
+        this.curSeleEleIndex--;
+        this.selectEleFormula[this.curSeleEleIndex].selected = true;
+        // this.selectedTableKey = this.selectEleFormula[this.curSeleEleIndex].tableElementKey;
+         const keyParts =  this.selectEleFormula[this.curSeleEleIndex].tableElementKey.split('key');
+        this.selectedTableKey = keyParts.length > 1 ? 'key'+keyParts[1] : null;
+      }
+    },
+    
+    // 右箭头导航
+    handleRightArrow(e) {
+      e.preventDefault(); // 阻止默认行为
+      if (this.curSeleEleIndex < this.selectEleFormula.length - 1) {
+        // 取消当前选中项
+        if (this.selectEleFormula[this.curSeleEleIndex]) {
+          this.selectEleFormula[this.curSeleEleIndex].selected = false;
+        }
+        
+        // 选中右侧项
+        this.curSeleEleIndex++;
+        this.selectEleFormula[this.curSeleEleIndex].selected = true;
+        // this.selectedTableKey = this.selectEleFormula[this.curSeleEleIndex].tableElementKey;
+               const keyParts =  this.selectEleFormula[this.curSeleEleIndex].tableElementKey.split('key');
+        this.selectedTableKey = keyParts.length > 1 ? 'key'+keyParts[1] : null;
+      }
+    },
+    
+        // 处理删除操作
+    handleDelete(e) {
+      e.preventDefault();
+      
+      // 增加更严格的索引检查
+      if (
+        this.curSeleEleIndex === null || 
+        this.curSeleEleIndex === undefined ||
+        this.curSeleEleIndex < 0 || 
+        this.curSeleEleIndex >= this.selectEleFormula.length
+      ) {
+        
+        return;
+      }
+      
+      // 保存当前要删除的元素索引(避免后续操作影响)
+      const indexToDelete = this.curSeleEleIndex;
+      const itemToDelete = this.selectEleFormula[indexToDelete];
+      
+    
+      
+      // 处理元素取消勾选
+      if (itemToDelete && itemToDelete.type === 'Element') {
+        this.deleEleIndex = indexToDelete;
+        this.unCheckEleFormulac(itemToDelete.id);
+      }
+      
+      // 执行删除(只删除指定索引的1个元素)
+      const deletedItems = this.selectEleFormula.splice(indexToDelete, 1);
+      
+      
+      // 正确更新当前选中索引
+      if (this.selectEleFormula.length > 0) {
+        // 如果删除的是最后一个元素,选中前一个
+        this.curSeleEleIndex = Math.min(
+          indexToDelete, 
+          this.selectEleFormula.length - 1
+        );
+          const keyParts =  this.selectEleFormula[this.curSeleEleIndex].tableElementKey.split('key');
+            this.selectedTableKey = keyParts.length > 1 ? 'key'+keyParts[1] : null;
+        // 确保选中状态正确
+        this.selectEleFormula.forEach((item, idx) => {
+          item.selected = idx === this.curSeleEleIndex;
+        });
+      } else {
+        this.curSeleEleIndex = -1;
+        this.selectedTableKey = null;
+      }
+    },
+    checkDefaultSelection() {
+      const hasSelected = this.selectEleFormula.some(item => item.selected);
+      if (!hasSelected && this.selectEleFormula.length > 0) {
+        // 取消所有选中
+        this.selectEleFormula.forEach(item => {
+          item.selected = false;
+        });
+        
+        // 选中最后一个元素
+        const lastIndex = this.selectEleFormula.length - 1;
+        this.selectEleFormula[lastIndex].selected = true;
+        this.curSeleEleIndex = lastIndex;
+   
+      }
+    },
   },
 
 
@@ -1854,7 +2302,7 @@ export default {
 }
 
 .icon-box .el-link{
-  font-size: 24px;
+  font-size: 14px;
   margin-right: 10px;
 }
 </style>
@@ -1878,3 +2326,29 @@ export default {
         display: inline-block;
    }
 </style>
+<style scoped>
+.operation-symbol-box{
+  display: flex;
+  align-items: center;
+  border: 1px solid rgb(229, 231, 235);
+  background-color: #F9FAFB;
+  padding: 10px 10px;
+  border-radius:  5px 5px 0px 0px;
+  margin-top: 10px;
+  
+}
+.sele-ele-box1{
+  padding: 10px;
+  border: 1px solid rgb(229, 231, 235);
+  border-radius: 0px 0px 5px 5px;
+
+  height: 50px;
+}
+.text-sm{
+  font-size: 14px;
+  margin-right: 10px;
+}
+.icon-box .el-icon {
+  font-size: 12px !important; /* 更小的尺寸,按需修改 */
+}
+</style>

File diff suppressed because it is too large
+ 868 - 719
src/views/manager/projectinfo/tree.vue


+ 372 - 313
src/views/manager/wbsinfo.vue

@@ -1,65 +1,122 @@
 <template>
   <basic-container>
-        <div class="search-box">
-        <div class="search-box-left">
-            <el-input v-model="query.wbsName" placeholder="请输入名称" style="width: 200px;" class="filter-item"   size="small"/>
-            <el-select v-model="query.projectId" placeholder="项目名称" clearable style="width: 200px" class="filter-item"   size="small">
-              <el-option v-for="item in projectList" :key="item.id" :label="item.projectAlias" :value="item.id" />
-            </el-select>
-            <el-select v-model="query.wbsType" placeholder="划分类型" clearable style="width: 200px" class="filter-item"   size="small">
-              <el-option v-for="item in tabTypeList"  :key="item.dictKey" :label="item.dictValue" :value="item.dictKey" />
-            </el-select>
-
-            <el-button type="primary" @click="searchClick" class="custom-primary-btn"   size="small">搜索</el-button>
-            <el-button type="info" @click="clearSearch"   size="small">清空</el-button>
+    <div class="search-box">
+      <div class="flex">
+        <div
+          class="filter-item"
+          style="width: 200px"
+          :class="[query.wbsName ? 'hc-search-highlight' : '']"
+        >
+          <el-input
+            v-model="query.wbsName"
+            placeholder="请输入名称"
+            clearable
+            size="small"
+          />
         </div>
-        <div class="header-box-right">
-           <el-button
-            type="primary"
+        <div
+          class="filter-item"
+          style="width: 200px"
+          :class="[query.projectId ? 'hc-search-highlight' : '']"
+        >
+          <el-select
+            v-model="query.projectId"
+            placeholder="项目名称"
+            clearable
             size="small"
-            icon="el-icon-plus"
-
-
-            @click="handleAdd"
-          >新增
-          </el-button>
-                <el-button
-            type="warning"
+          >
+            <el-option
+              v-for="item in projectList"
+              :key="item.id"
+              :label="item.projectAlias"
+              :value="item.id"
+            />
+          </el-select>
+        </div>
+        <div
+          class="filter-item"
+          style="width: 200px"
+          :class="[query.wbsType ? 'hc-search-highlight' : '']"
+        >
+          <el-select
+            v-model="query.wbsType"
+            placeholder="划分类型"
+            clearable
+            style="width: 200px"
+            class="filter-item"
             size="small"
-            icon="el-icon-sort"
-
+          >
+            <el-option
+              v-for="item in tabTypeList"
+              :key="item.dictKey"
+              :label="item.dictValue"
+              :value="item.dictKey"
+            />
+          </el-select>
+        </div>
 
-            @click="handleSort"
+        <el-button
+          type="primary"
+          @click="searchClick"
+          class="custom-primary-btn"
+          size="small"
+          >搜索</el-button
+        >
+        <el-button type="info" @click="clearSearch" size="small"
+          >清空</el-button
+        >
+      </div>
+      <div class="header-box-right">
+        <el-button
+          type="primary"
+          size="small"
+          icon="el-icon-plus"
+          @click="handleAdd"
+          >新增
+        </el-button>
+        <el-button
+          type="warning"
+          size="small"
+          icon="el-icon-sort"
+          @click="handleSort"
           >排序
-          </el-button>
-              <el-button
-            type="danger"
-            size="small"
-            icon="el-icon-delete"
-
-            v-if="permission.wbsinfo_delete"
-            @click="handleDelete"
+        </el-button>
+        <el-button
+          type="danger"
+          size="small"
+          icon="el-icon-delete"
+          v-if="permission.wbsinfo_delete"
+          @click="handleDelete"
           >删 除
-          </el-button>
-          <!-- 新增元素按钮 -->
-          <el-button
-            size="small"
-            style="background-color:#FFA042;color:white;font-weight:bold;border-color: #FFA042;"
-            plain
-            v-if="permission.wbsinfo_delete"
-            @click="handleElement"
+        </el-button>
+        <!-- 新增元素按钮 -->
+        <el-button
+          size="small"
+          style="
+            background-color: #ffa042;
+            color: white;
+            font-weight: bold;
+            border-color: #ffa042;
+          "
+          plain
+          v-if="permission.wbsinfo_delete"
+          @click="handleElement"
           >元素库
-          </el-button>
-          <el-button
-            size="small"
-            style="background-color:#2550A2;color:white;font-weight:bold;border-color: #2550A2;"
-            plain
-            v-if="permission.wbsinfo_delete"
-            @click="handleParameter"
+        </el-button>
+        <el-button
+          size="small"
+          style="
+            background-color: #2550a2;
+            color: white;
+            font-weight: bold;
+            border-color: #2550a2;
+          "
+          plain
+          v-if="permission.wbsinfo_delete"
+          @click="handleParameter"
           >参数库
-          </el-button>
-        </div>
-
+        </el-button>
+      </div>
     </div>
     <avue-crud
       :option="option"
@@ -80,108 +137,118 @@
       @size-change="sizeChange"
       @refresh-change="refreshChange"
       @on-load="onLoad"
-       :search.sync="search"
+      :search.sync="search"
     >
-
-<template slot-scope="{disabled,size}" slot="projectInfoListSearch">
-      <el-select v-model="search.projectId" placeholder="项目名称" filterable  clearable>
+      <template slot-scope="{ row }" slot="wbsName">
+        <span v-html="highlight(row.wbsName || '', query.wbsName)"></span>
+      </template>
+      <template slot-scope="{ disabled, size }" slot="projectInfoListSearch">
+        <el-select
+          v-model="search.projectId"
+          placeholder="项目名称"
+          filterable
+          clearable
+        >
           <el-option
             v-for="item in projectList"
             :key="item.id"
             :label="item.projectAlias"
-            :value="item.id">
+            :value="item.id"
+          >
           </el-option>
         </el-select>
-  </template>
-      <template slot="menuRight">
-
       </template>
-      <template
-        slot-scope="{row,index}"
-        slot="menu"
-      >
+      <template slot="menuRight"> </template>
+      <template slot-scope="{ row, index }" slot="menu">
         <el-button
           type="text"
           icon="el-icon-edit"
           size="mini"
           v-if="permission.wbsinfo_tree_edit"
-          @click="toEdit(row,index)"
-        >编辑wbs库</el-button>
+          @click="toEdit(row, index)"
+          >编辑wbs库</el-button
+        >
       </template>
-       <template
-            slot-scope="{row}"
-            slot="wbsType"
+      <template slot-scope="{ row }" slot="wbsType">
+        <!-- <el-tag>{{ row.wbsType }}</el-tag> -->
+        <el-tag
+          size="small"
+          v-for="item in generateTagItems(row.wbsType)"
+          :key="item.label"
+          :type="item.type"
+          effect="dark"
+          class="mr-3 custom-ellipse-tag"
+          :class="`custom-tag-type-${item.type}`"
+        >
+          {{ item.label }}
+        </el-tag>
+      </template>
+      <template slot-scope="{ row }" slot="projectInfoList">
+        <el-tooltip
+          v-for="item in row.projectInfoList"
+          :key="item.id"
+          :content="item.projectName"
+          placement="top"
+          :disabled="true"
+        >
+          <el-tag
+            size="small"
+            type="info"
+            class="custom-ellipse-tag1 ellipsis-tag"
           >
-            <!-- <el-tag>{{ row.wbsType }}</el-tag> -->
-                <el-tag
-                  size="small"
-                  v-for="item in generateTagItems(row.wbsType)"
-                  :key="item.label"
-                  :type="item.type"
-                  effect="dark"
-                  class="mr-3 custom-ellipse-tag"
-                  :class="`custom-tag-type-${item.type}`"
-                  >
-
-                  {{ item.label }}
-                </el-tag>
-
-          </template>
-          <template slot-scope="{row}" slot="projectInfoList">
-
-                    <el-tooltip
-                    v-for="item in row.projectInfoList"
-                    :key="item.id"
-                    :content="item.projectName"
-                    placement="top"
-                    :disabled="true"
-                  >
-                    <el-tag
-                      size="small"
-                      type="info"
-                      class="custom-ellipse-tag1 ellipsis-tag"
-
-                    >
-                      {{item.projectName}}
-                    </el-tag>
-                  </el-tooltip>
-          </template>
+            {{ item.projectName }}
+          </el-tag>
+        </el-tooltip>
+      </template>
     </avue-crud>
-           <!-- wbs排序弹窗 -->
-        <ContractSort
-         ref="contractSortRef"
-         title="wbs排序弹窗"
-         :sortProLoad="sortProLoad"
-        @confirm="handleSortConfirm"
-      />
+    <!-- wbs排序弹窗 -->
+    <ContractSort
+      ref="contractSortRef"
+      title="wbs排序弹窗"
+      :sortProLoad="sortProLoad"
+      @confirm="handleSortConfirm"
+    />
   </basic-container>
 </template>
 
 <script>
-import { getList, getDetail, add, update, remove,sortWbs } from "@/api/manager/wbsinfo";
+import {
+  getList,
+  getDetail,
+  add,
+  update,
+  remove,
+  sortWbs,
+} from "@/api/manager/wbsinfo";
 import { mapGetters } from "vuex";
-  import { getDictionary } from "@/api/system/dict";
-  import ContractSort from './ContractSort.vue'
+import { getDictionary } from "@/api/system/dict";
+import ContractSort from "./ContractSort.vue";
 import { getProjectListPage } from "@/api/manager/projectinfo";
+import { highlight } from "@/util/util";
 
 export default {
   components: {
-    ContractSort
+    ContractSort,
   },
-  data () {
+  data() {
     return {
+      highlight,
       form: {},
-      query: {},
+      query: {
+        wbsName: "",
+        wbsType: "",
+        projectId: "",
+      },
       loading: true,
       page: {
         pageSize: 20,
         currentPage: 1,
-        total: 0
+        total: 0,
       },
       selectionList: [],
       option: {
         menuWidth: 300,
-        height: 'auto',
+        height: "auto",
         calcHeight: 30,
         tip: false,
         searchMenuSpan: 6,
@@ -189,220 +256,217 @@ export default {
         border: true,
         index: true,
         viewBtn: true,
-          addBtn: false,
+        addBtn: false,
         selection: true,
-         refreshBtn:false,
+        refreshBtn: false,
         searchShowBtn: false,
         columnBtn: false,
         dialogClickModal: false,
-          searchShow: false,
+        searchShow: false,
         column: [
           {
             label: "创建时间",
             prop: "createTime",
             editDetail: true,
             addDisabled: true,
-               hide: true,
-
+            hide: true,
           },
           {
             label: "wbs名称",
             prop: "wbsName",
+            slot: true,
             search: true,
             width: 180,
-
-
-
-            rules: [{
-              required: true,
-              message: "请输入wbs名称",
-              trigger: "blur"
-            }]
+            rules: [
+              {
+                required: true,
+                message: "请输入wbs名称",
+                trigger: "blur",
+              },
+            ],
           },
           {
             label: "划分类型",
             slot: true,
-              search: true,
-              width: 120,
-
-
-
-
+            search: true,
+            width: 120,
 
             type: "select",
             dicUrl: "/api/blade-system/dict/dictionary?code=wbs_type",
             props: {
               label: "dictValue",
-              value: "dictKey"
+              value: "dictKey",
             },
             dataType: "number",
             prop: "wbsType",
-            rules: [{
-              required: true,
-              message: "请选择划分类型",
-              trigger: "blur"
-            }],
-
+            rules: [
+              {
+                required: true,
+                message: "请选择划分类型",
+                trigger: "blur",
+              },
+            ],
           },
           {
             label: "是否启用",
             prop: "status",
             hide: true,
 
-            rules: [{
-              required: true,
-              message: "是否启用",
-              trigger: "blur"
-            }],
+            rules: [
+              {
+                required: true,
+                message: "是否启用",
+                trigger: "blur",
+              },
+            ],
             type: "radio",
             dicData: [
               {
                 label: "否",
-                value: 0
+                value: 0,
               },
               {
                 label: "是",
-                value: 1
-              }
+                value: 1,
+              },
             ],
           },
-           {
+          {
             label: "引用项目",
             prop: "projectInfoList",
             display: false,
             search: true,
-            slot:true,
-
+            slot: true,
           },
-
-        ]
+        ],
       },
       data: [],
-      search:{
-        wbsName: '',
-        wbsType: '',
-        projectId:''
+      search: {
+        wbsName: "",
+        wbsType: "",
+        projectId: "",
       },
-       wbsTypeList:[],
-
-       sortProLoad:false,
-       wbsList:[],
-       sortWbsList:[],
-       projectList:[],
-       tabTypeList:[],
+      wbsTypeList: [],
 
+      sortProLoad: false,
+      wbsList: [],
+      sortWbsList: [],
+      projectList: [],
+      tabTypeList: [],
     };
   },
-  created () {
-    this.getTabTypeList()
-    this.getWbsList()
-    this.getProjectList()
+  created() {
+    this.getTabTypeList();
+    this.getWbsList();
+    this.getProjectList();
   },
   computed: {
     ...mapGetters(["permission"]),
-    permissionList () {
+    permissionList() {
       return {
         addBtn: this.vaildData(this.permission.wbsinfo_add, false),
         viewBtn: this.vaildData(this.permission.wbsinfo_view, false),
         delBtn: this.vaildData(this.permission.wbsinfo_delete, false),
-        editBtn: this.vaildData(this.permission.wbsinfo_edit, false)
+        editBtn: this.vaildData(this.permission.wbsinfo_edit, false),
       };
     },
-    ids () {
+    ids() {
       let ids = [];
-      this.selectionList.forEach(ele => {
+      this.selectionList.forEach((ele) => {
         ids.push(ele.id);
       });
       return ids.join(",");
-    }
+    },
   },
   methods: {
-  getProjectList () {
+    getProjectList() {
       getProjectListPage({
-        current:1,
-        size:999,
-        isCollect:0,
-
-
+        current: 1,
+        size: 999,
+        isCollect: 0,
       }).then((res) => {
         this.projectList = res.data.data.records;
-      })
+      });
     },
-  generateTagItems(wbsTypes){
-       const typeToLabelMap = {
-        1: '质检',
-        2: '试验',
-        3: '日志',
-        4: '计量',
-        5: '征拆',
-        6: '底层节点',
-
-    };
+    generateTagItems(wbsTypes) {
+      const typeToLabelMap = {
+        1: "质检",
+        2: "试验",
+        3: "日志",
+        4: "计量",
+        5: "征拆",
+        6: "底层节点",
+      };
       let tagItems = [];
-         // 如果 wbsTypes 不是数组,则将其转换为数组
-    if (!Array.isArray(wbsTypes)) {
+      // 如果 wbsTypes 不是数组,则将其转换为数组
+      if (!Array.isArray(wbsTypes)) {
         wbsTypes = [wbsTypes];
-    }
-      wbsTypes.forEach(type => {
+      }
+      wbsTypes.forEach((type) => {
         // 检查type是否在映射关系中存在
         if (typeToLabelMap.hasOwnProperty(type)) {
-            // 如果存在,则创建一个新的对象并添加到tagItems数组中
-            tagItems.push({
-                type: type,
-                label: typeToLabelMap[type]
-            });
+          // 如果存在,则创建一个新的对象并添加到tagItems数组中
+          tagItems.push({
+            type: type,
+            label: typeToLabelMap[type],
+          });
         }
-    });
-     return tagItems;
-  },
-     getTabTypeList(){
-           let code = "wbs_type";
-            getDictionary({
-                code,
-            }).then((res) => {
-                    this.tabTypeList = res.data.data;
-            });
-
-    },
-      //点击元素库
-    handleElement(){
-      console.log('元素库');
-      this.$router.push({
-        path: '/wbs/element',
-      })
+      });
+      return tagItems;
     },
-    rowSave (row, done, loading) {
-      row.projectInfoList=null
-      add(row).then(() => {
-        this.onLoad(this.page);
-        this.$message({
-          type: "success",
-          message: "操作成功!"
-        });
-        done();
-      }, error => {
-        loading();
-        window.console.log(error);
+    getTabTypeList() {
+      let code = "wbs_type";
+      getDictionary({
+        code,
+      }).then((res) => {
+        this.tabTypeList = res.data.data;
       });
     },
-    rowUpdate (row, index, done, loading) {
-      update(row).then(() => {
-        this.onLoad(this.page);
-        this.$message({
-          type: "success",
-          message: "操作成功!"
-        });
-        done();
-      }, error => {
-        loading();
-        console.log(error);
+    //点击元素库
+    handleElement() {
+      console.log("元素库");
+      this.$router.push({
+        path: "/wbs/element",
       });
     },
-    rowDel (row) {
+    rowSave(row, done, loading) {
+      row.projectInfoList = null;
+      add(row).then(
+        () => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!",
+          });
+          done();
+        },
+        (error) => {
+          loading();
+          window.console.log(error);
+        }
+      );
+    },
+    rowUpdate(row, index, done, loading) {
+      update(row).then(
+        () => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!",
+          });
+          done();
+        },
+        (error) => {
+          loading();
+          console.log(error);
+        }
+      );
+    },
+    rowDel(row) {
       this.$confirm("确定将选择数据删除?", {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
-        type: "warning"
+        type: "warning",
       })
         .then(() => {
           return remove(row.id);
@@ -411,15 +475,14 @@ export default {
           this.onLoad(this.page);
           this.$message({
             type: "success",
-            message: "操作成功!"
+            message: "操作成功!",
           });
         });
     },
     handleAdd(row) {
-
-        this.$refs.crud.rowAdd();
-      },
-    handleDelete () {
+      this.$refs.crud.rowAdd();
+    },
+    handleDelete() {
       if (this.selectionList.length === 0) {
         this.$message.warning("请选择至少一条数据");
         return;
@@ -427,7 +490,7 @@ export default {
       this.$confirm("确定将选择数据删除?", {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
-        type: "warning"
+        type: "warning",
       })
         .then(() => {
           return remove(this.ids);
@@ -436,48 +499,52 @@ export default {
           this.onLoad(this.page);
           this.$message({
             type: "success",
-            message: "操作成功!"
+            message: "操作成功!",
           });
           this.$refs.crud.toggleSelection();
         });
     },
-    beforeOpen (done, type) {
+    beforeOpen(done, type) {
       if (["edit", "view"].includes(type)) {
-        getDetail(this.form.id).then(res => {
+        getDetail(this.form.id).then((res) => {
           this.form = res.data.data;
         });
       }
       done();
     },
-    searchReset () {
+    searchReset() {
       this.query = {};
       this.onLoad(this.page);
     },
-    searchChange (params, done) {
+    searchChange(params, done) {
       this.query = params;
       this.page.currentPage = 1;
       this.onLoad(this.page, params);
       done();
     },
-    selectionChange (list) {
+    selectionChange(list) {
       this.selectionList = list;
     },
-    selectionClear () {
+    selectionClear() {
       this.selectionList = [];
       this.$refs.crud.toggleSelection();
     },
-    currentChange (currentPage) {
+    currentChange(currentPage) {
       this.page.currentPage = currentPage;
     },
-    sizeChange (pageSize) {
+    sizeChange(pageSize) {
       this.page.pageSize = pageSize;
     },
-    refreshChange () {
+    refreshChange() {
       this.onLoad(this.page, this.query);
     },
-    onLoad (page, params = {}) {
+    onLoad(page, params = {}) {
       this.loading = true;
-      getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+      getList(
+        page.currentPage,
+        page.pageSize,
+        Object.assign(params, this.query)
+      ).then((res) => {
         const data = res.data.data;
         this.page.total = data.total;
         this.data = data.records;
@@ -486,85 +553,77 @@ export default {
       });
     },
 
-    toEdit (row) {
+    toEdit(row) {
       console.log(row);
       this.$router.push({
-        path: '/wbs/edit',
+        path: "/wbs/edit",
         query: {
           id: row.id,
-          type: row.wbsType
-        }
-      })
+          type: row.wbsType,
+        },
+      });
       //this.$router.push('/wbs/edit/' + row.id);
     },
     //点击参数库
-    handleParameter(){
-       this.$router.push('/wbs/parameter');
+    handleParameter() {
+      this.$router.push("/wbs/parameter");
     },
-    getWbsList(){
-      getList(1, 1000).then(res => {
+    getWbsList() {
+      getList(1, 1000).then((res) => {
         const data = res.data.data;
 
-        this.wbsList=data['records']
+        this.wbsList = data["records"];
       });
     },
     //排序
-    handleSort(){
-         this.sortWbsList = JSON.parse(JSON.stringify(this.wbsList));
-        this.sortTitle = '合同段排序';
+    handleSort() {
+      this.sortWbsList = JSON.parse(JSON.stringify(this.wbsList));
+      this.sortTitle = "合同段排序";
 
-          this.$nextTick(() => {
-            this.$refs.contractSortRef.show(this.sortWbsList);
-          });
+      this.$nextTick(() => {
+        this.$refs.contractSortRef.show(this.sortWbsList);
+      });
     },
-     handleSortConfirm(sortedList) {
+    handleSortConfirm(sortedList) {
       // 这里处理排序后的数据
-      console.log('排序后的列表:', sortedList);
+      console.log("排序后的列表:", sortedList);
       // TODO: 调用接口保存排序结果
       this.wbsList = [...sortedList];
-        const ids = this.wbsList.map(item => item.id);
-     this. saveSort(ids);
-
+      const ids = this.wbsList.map((item) => item.id);
+      this.saveSort(ids);
     },
-    saveSort(ids){
-        sortWbs(ids).then((res) => {
-                    this.sortProLoad= false;
-                    if(res.data.code==200){
-                        this.$message.success(res.data.msg)
-
-                                 this.onLoad(this.page);
-                    }else{
-                        this.$message.error(res.data.msg)
-                    }
-                })
-
-
+    saveSort(ids) {
+      sortWbs(ids).then((res) => {
+        this.sortProLoad = false;
+        if (res.data.code == 200) {
+          this.$message.success(res.data.msg);
 
+          this.onLoad(this.page);
+        } else {
+          this.$message.error(res.data.msg);
+        }
+      });
     },
-    searchClick(){
-       this.page.currentPage = 1;
-      this.onLoad(this.page,this.query);
+    searchClick() {
+      this.page.currentPage = 1;
+      this.onLoad(this.page, this.query);
     },
-    clearSearch(){
-       this.page.currentPage = 1;
+    clearSearch() {
+      this.page.currentPage = 1;
       this.query = {};
-      this.onLoad(this.page,this.query);
-    }
-  }
+      this.onLoad(this.page, this.query);
+    },
+  },
 };
 </script>
 
 <style scoped lang="scss">
-.search-box{
+.search-box {
   display: flex;
   justify-content: space-between;
-  .search-item{
-    margin-right: 10px;
-    margin-left: 10px;
-  }
-
 }
-.filter-item{
+
+.filter-item {
   margin-right: 10px;
 }
 </style>

Some files were not shown because too many files changed in this diff