فهرست منبع

合并标签优化推送

hml 5 ماه پیش
والد
کامیت
a042d36801

+ 143 - 0
src/components/Dataset-filter/filterNode.vue

@@ -0,0 +1,143 @@
+<template>
+  <div class="filter-node">
+    <div class="left" v-if="node?.relation" >
+      <div class="relation-line"></div>
+      <div  class="relation-btn" @click="onToggleRelation">
+        {{ node?.relation === "AND" ? "且" : "或" }}
+      </div>
+    </div>
+    <div class="right" v-if="node?.conditions">
+      <template v-for="(item, i) of node.conditions">
+        <div v-if="!item.conditions" class="relation" :key="item.uniqId" draggable @dragstart="onNodeDrag(node, i, type)">
+          <div class="name">{{ item.columnTitle }}</div>
+          <i v-show="level < maxLevel" class="el-icon-bottom-right icon" title="添加组合" @click="onAddGroup(item, i)"></i>
+<!--          <i class="el-icon-delete icon" @click="onDelFilter(item,node,i)"></i>-->
+          <i class="el-icon-setting icon" @click="editFilterByUniqId(item.uniqId)"></i>
+        </div>
+      </template>
+      <div class="virtual" @dragover="onDragOver" @drop="onNodeDrop(node, type)"></div>
+      <template v-if="node?.conditions">
+        <filter-node
+          v-for="(filter, i) of node.conditions"
+          :key="i"
+          :node="filter"
+          :level="level + 1"
+          :type="type"
+        ></filter-node>
+      </template>
+    </div>
+  </div>
+</template>
+<script>
+export default {
+  name: "filter-node",
+  props: ["node", "level", "type"],
+  inject: ["editFilterByUniqId", "onNodeDrag", "onNodeDrop", 'onDelFilter','maxLevel'],
+  data() {
+    return {};
+  },
+  created() {
+  },
+  methods: {
+    onToggleRelation() {
+      this.node.relation = this.node.relation == "AND" ? "OR" : "AND";
+    },
+    onAddGroup(item, index) {
+      this.node.conditions.splice(index, 1);
+      this.node.conditions.push({
+        conditions: [item],
+        relation: 'AND'
+      });
+    },
+    onDragOver(e) {
+      e.preventDefault();
+    },
+  },
+};
+</script>
+<style lang="scss">
+.filter-node {
+  display: flex;
+  .left {
+    width: 30px;
+    position: relative;
+    .relation-line {
+      position: absolute;
+      top: 10px;
+      bottom: 10px;
+      width: 2px;
+      background-color: #409eff;
+      left: 14px;
+      &::before {
+        content: "";
+        position: absolute;
+        background-color: #409eff;
+        height: 2px;
+        width: 13px;
+        left: 0;
+        top: 0;
+      }
+      &::after {
+        content: "";
+        position: absolute;
+        background-color: #409eff;
+        height: 2px;
+        width: 13px;
+        left: 0;
+        bottom: 0;
+      }
+    }
+    .relation-btn {
+      position: absolute;
+      left: 3px;
+      top: 50%;
+      transform: translateY(-12px);
+      z-index: 1;
+      background-color: white;
+      border: 1px solid #409eff;
+      color: #409eff;
+      box-sizing: border-box;
+      width: 24px;
+      height: 24px;
+      line-height: 24px;
+      font-size: 14px;
+      cursor: pointer;
+      border-radius: 2px;
+      text-align: center;
+    }
+  }
+  .right {
+    flex: 1;
+    .relation {
+      padding: 0 8px;
+      margin: 8px 4px;
+      width: 200px;
+      height: 26px;
+      line-height: 26px;
+      font-size: 14px;
+      box-sizing: border-box;
+      border: 1px solid #666;
+      color: #666;
+      display: flex;
+      align-items: center;
+      .name {
+        flex: 1;
+        overflow: hidden;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+      }
+      .icon {
+        margin-left: 8px;
+        cursor: pointer;
+      }
+    }
+    .virtual {
+      margin: 8px 4px;
+      box-sizing: border-box;
+      border: 1px dashed #666;
+      width: 200px;
+      height: 26px;
+    }
+  }
+}
+</style>

+ 690 - 0
src/components/Dataset-filter/filterSetting.vue

@@ -0,0 +1,690 @@
+<template>
+  <div class="filter-setting-box">
+    <div class="group">
+      <div class="name">过滤器</div>
+      <div class="middle" @click="onEditRelation">编辑结构</div>
+      <div :class="{ btn: 1, active }" >
+        <el-popover placement="bottom-start" trigger="click">
+          <div style="display: flex">
+            <div style="margin-right: 10px;max-height: 300px;overflow-y: auto">
+              <p>引用字段</p>
+              <template v-for="field of tobeChooseWeidu">
+                <div :key="field.columnTitle" :title="field.columnName" class="weidu" @click="setJarValueFun(field)">
+                  {{ field.columnTitle + '【' + field.columnName + '】' }}
+                </div>
+              </template>
+              <template v-for="field of tobeChooseZhibiao">
+                <div :key="field.columnTitle" :title="field.columnName" class="zhibiao" @click="setJarValueFun(field)">
+                  {{ field.columnTitle + '【' + field.columnName + '】' }}
+                </div>
+              </template>
+            </div>
+         </div>
+          <el-button slot="reference" type="text" size="mini">选择字段<i class="el-icon-d-arrow-right"></i></el-button>
+        </el-popover>
+
+      </div>
+    </div>
+    <draggable v-model="config.filter" :animation="150" :class="{ 'selected-box': 1, 'item-box': 1, active }">
+      <div :class="['item', 'selected', field.dimensionType]" v-for="(field, i) of config.filter" :key="i">
+        <div class="name" :title="field.columnTitle + ' ' + field.columnName">
+          {{ field.columnTitle + " " + field.columnName }}
+        </div>
+        <i class="el-icon-setting" style="margin-right: 5px; cursor: pointer" @click="onEditFilter(field, 1)"></i>
+        <i class="el-icon-close" @click="onFieldDel(i)"></i>
+      </div>
+    </draggable>
+    <!-- 过滤器编辑框 -->
+    <el-dialog append-to-body :visible.sync="showEditFilter" title="编辑过滤器" custom-class="bigdata-filter"
+               width="560px">
+      <div v-if="nowFilter">
+        <el-form size="mini" label-width="80px">
+          <el-form-item label="当前字段">
+            <div :class="['now-filter', nowFilter.dimensionType]">
+              <div class="name"> {{ nowFilter.columnTitle + " " + nowFilter.columnName }}</div>
+              <div style="color: #999"> {{ datatypeMap[nowFilter.viewDataType] }}</div>
+            </div>
+          </el-form-item>
+<!--          <el-form-item label="作为筛选">-->
+<!--            <el-switch v-model="nowFilter.asFilter"></el-switch>-->
+<!--          </el-form-item>-->
+          <el-form-item label="过滤时机" v-show="toggleType === 1">
+            <el-radio-group v-model="nowFilter.connectTime" @change="onConnectTimeChange">
+              <el-radio label="where">where</el-radio>
+<!--              <el-radio label="having" :disabled="countFilterTime()"> 聚合后(having)</el-radio>-->
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item label="聚合方式" v-if="countCanAggregation(nowFilter)">
+            <el-select v-model="nowFilter.aggregationType">
+              <el-option
+                v-for="item of fieldAggregates" :key="item.label" :label="item.label" :value="item.value"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="连接方式">
+            <el-radio-group v-model="nowFilter.connectType">
+              <el-radio label="and">且</el-radio>
+              <el-radio label="or">或</el-radio>
+            </el-radio-group>
+          </el-form-item>
+<!--          <el-form-item label="枚举来源" v-show="countEnumShow()">-->
+<!--            <el-radio-group v-model="nowFilter.enumSource" @change="nowFilter.enumId=''">-->
+<!--              <el-radio label="1">原始数据聚合</el-radio>-->
+<!--              <el-radio label="2">api</el-radio>-->
+<!--              <el-radio label="3">自定义字典</el-radio>-->
+<!--            </el-radio-group>-->
+<!--            <el-button-->
+<!--              size="mini" icon="el-icon-share" plain type="success" @click="onGetEnumData" style="margin-left: 20px"-->
+<!--            >-->
+<!--              获取-->
+<!--            </el-button>-->
+<!--          </el-form-item>-->
+<!--          <el-form-item label="选择api" v-if="countEnumShow() && nowFilter.enumSource === '2'">-->
+<!--            <el-cascader-->
+<!--              v-model="nowFilter.enumId" :options="apiList" filterable popper-class="bigdata-data-selector"-->
+<!--              :props="{ expandTrigger: 'hover', emitPath: false }" :show-all-levels="true" style="width: 400px"-->
+<!--            ></el-cascader>-->
+<!--          </el-form-item>-->
+<!--          <el-form-item label="选择字典" v-if="countEnumShow() && nowFilter.enumSource === '3'">-->
+<!--            <el-select v-model="nowFilter.enumId" filterable>-->
+<!--              <el-option v-for="(item, i) of dictList" :key="i" :value="item.id" :label="item.keyCode"></el-option>-->
+<!--            </el-select>-->
+<!--          </el-form-item>-->
+          <el-form-item label="过滤条件">
+            <div class="filter-item" v-for="(condition, i) of nowFilter.conditions" :key="i">
+              <el-select
+                size="mini" v-model="condition.function" style="width: 100px; margin-right: 10px"
+                placeholder="选择条件" @change="onFunctionChange"
+              >
+                <el-option
+                  v-for="func of functions[nowFilter.viewDataType]" :key="func.function" :value="func.function"
+                  :label="func.label"
+                ></el-option>
+              </el-select>
+              <!-- 日期类型 -->
+              <template v-if="nowFilter.viewDataType === 'DATETIME'">
+                <el-select
+                  v-model="condition.timeType" style="width: 95px; margin-right: 5px"
+                  @change="onTimeTypeChange(condition)"
+                >
+                  <el-option label="绝对时间" value="absolute"></el-option>
+                  <el-option label="相对时间" value="relative"></el-option>
+                </el-select>
+                <template v-if="condition.timeType === 'relative'">
+                  <el-input style="width: 120px; margin-right: 5px" v-model="condition.values[0]">
+                    <template slot="append"> {{ timeTypeMap[nowFilter.timeDataFormat] }}</template>
+                  </el-input>
+                  <el-select v-model="condition.countType" style="width: 60px">
+                    <el-option label="前" value="left"></el-option>
+                    <el-option label="后" value="right"></el-option>
+                  </el-select>
+                </template>
+                <template v-else>
+                  <template v-if="nowFilter.dateType === 'time'">
+                    <el-date-picker
+                      style="width: 200px" v-model="condition.values[0]" type="datetime"
+                      placeholder="选择日期时间" :value-format="nowFilter.dateFormat"
+                    ></el-date-picker>
+                    <el-date-picker
+                      v-if="condition.function === 'between'" style="width: 200px" v-model="condition.values[1]"
+                      type="datetime" placeholder="选择日期时间" :value-format="nowFilter.dateFormat"
+                    ></el-date-picker>
+                  </template>
+                  <template v-else-if="['year', 'month', 'date'].includes(nowFilter.dateType)">
+                    <el-date-picker
+                      style="width: 200px" v-model="condition.values[0]" :type="nowFilter.dateType"
+                      placeholder="选择日期" :value-format="nowFilter.dateFormat"
+                    ></el-date-picker>
+                    <el-date-picker
+                      v-if="condition.function === 'between'" style="width: 200px" v-model="condition.values[1]"
+                      :type="nowFilter.dateType" placeholder="选择日期" :value-format="nowFilter.dateFormat"
+                    ></el-date-picker>
+                  </template>
+                  <template v-else>
+                    <el-time-select
+                      style="width: 200px" v-model="condition.values[0]" placeholder="选择时间"
+                      :value-format="nowFilter.dateFormat"
+                    ></el-time-select>
+                    <el-time-select
+                      v-if="condition.function === 'between'" style="width: 200px" v-model="condition.values[1]"
+                      placeholder="选择时间" :value-format="nowFilter.dateFormat"
+                    ></el-time-select>
+                  </template>
+                </template>
+              </template>
+              <template v-else>
+                <template v-if="['in', 'notIn'].includes(condition.function)">
+                  <el-cascader
+                    v-model="condition.values" :options="nowFilter.options"
+                    :props="{expandTrigger: 'hover',emitPath: false,multiple: true,label: 'VALUE',value: 'KEY',}"
+                    filterable :show-all-levels="false" collapse-tags clearable
+                  ></el-cascader>
+                  <el-button size="mini" @click="onEnumSelectAll(nowFilter)" type="primary"> 全选</el-button>
+                </template>
+                <template v-else-if="['indexIn'].includes(condition.function)">
+                  <el-input style="width: 200px" size="mini" v-model="condition.values[0]" placeholder="默认使用第几条">
+                  </el-input>
+                </template>
+                <span v-else-if="['isnull', 'notnull'].includes(condition.function)"></span>
+                <el-input v-else style="width: 200px" size="mini" v-model="condition.values[0]" placeholder="输入值">
+                </el-input>
+              </template>
+              <i class="el-icon-delete" v-show="nowFilter.conditions.length > 1" @click="onConditionDel(i)"></i>
+            </div>
+            <el-button size="mini" type="success" plain @click="onConditionAdd" v-show="canAddCondition">
+              添加条件
+            </el-button>
+          </el-form-item>
+          <div class="btns" style="
+              display: flex;
+              justify-content: space-evenly;
+              margin-top: 30px;
+            ">
+            <el-button size="small" @click="showEditFilter = false" style="width: 100px"> 取消</el-button>
+            <el-button type="primary" size="small" @click="onConditionUpdate" style="width: 100px"> 确定
+            </el-button>
+          </div>
+        </el-form>
+      </div>
+    </el-dialog>
+    <el-dialog
+      :visible.sync="showRelationEdit" title="过滤器结构编辑" width="600px" custom-class="filter-relation-dialog"
+      append-to-body
+    >
+      <filter-node :node="relationNode" :level="1" type="where"></filter-node>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import {getEnumData, onEnumSelectAll} from "./util";
+import draggable from "vuedraggable";
+import {dictList} from "@/api/newbi/dict";
+import {dateTypeMap,functions, timeTypeMap, fieldAggregates,fieldDateFormats} from "./dict";
+import filterNode from "./filterNode.vue";
+import {cubeFieldList} from "@/api/newbi/dataset";
+import util from '@/utils/wey';
+
+export default {
+  components: {draggable, filterNode},
+  props: ["config", "active", "selectedFields", "apiList", "chartId", 'maxLevel','dbLinkId'],
+  data() {
+    return {
+      nowFilter: null,
+      showEditFilter: false,
+      functions,
+      timeTypeMap,
+      fieldAggregates,dateTypeMap,fieldDateFormats,
+      datatypeMap: {NUMBER: "数字", STRING: "字符串", DATETIME: "时间"},
+      showRelationEdit: false,
+      relationNode: {conditions: [], filters: [], relation: "AND"},
+      havingNode: {conditions: [], filters: [], relation: "AND"},
+      draggingNode: null,
+      draggingIndex: 0,
+      draggingType: "where",
+      dictList: [],
+      toggleType: 1,
+      tobeChooseWeidu:[],
+      tobeChooseZhibiao:[],
+      defaultRelation:
+        '{"where":{"conditions":[],"filters":[],"relation":"AND"},"having":{"conditions":[],"filters":[],"relation":"AND"}}',
+    };
+  },
+  computed: {
+    // 能否添加过滤条件
+    canAddCondition() {
+      if (!this.nowFilter) return false;
+      let func = this.nowFilter.conditions[0].function;
+      return !(func === "in" || func === "notIn" || func === "indexIn");
+    },
+    visualId() {
+      let {query, params, fullPath} = this.$route;
+      return fullPath.includes("/preview/") ? params.id : query.id;
+    },
+  },
+  watch: {
+    showRelationEdit(val) {
+      // 结构编辑框关闭时
+      if (!val) {
+        let filterRelation = {where: this.relationNode, having: this.havingNode,};
+        this.config.filterRelation = JSON.stringify(this.relationNode);
+      }
+    },
+  },
+  provide() {
+    return {
+      editFilterByUniqId: this.editFilterByUniqId,
+      onNodeDrag: this.onNodeDrag,
+      onNodeDrop: this.onNodeDrop,
+      onDelFilter: this.onDelFilter,
+      maxLevel: this.maxLevel,
+    };
+  },
+  created() {
+    dictList({current: 1, size: 10000}).then((res) => this.dictList = res.data.data.records);
+    //获取数据集
+    cubeFieldList({ cubeDataId: this.dbLinkId }).then((res) => {
+      let tableFieldsWeidu = res.data.data.filter((i) => i.dimensionType === 'WEIDU').sort((a, b) => a.sortNum - b.sortNum)
+      let tableFieldsZhibiao = res.data.data.filter((i) => i.dimensionType === 'ZHIBIAO').sort((a, b) => a.sortNum - b.sortNum)
+      this.tobeChooseWeidu = tableFieldsWeidu.filter((i) => i.columnAttr == 'NORMAL')
+      this.tobeChooseZhibiao = tableFieldsZhibiao.filter((i) => i.columnAttr == 'NORMAL')
+    })
+  },
+  methods: {
+    setJarValueFun(field){
+      field.connectTime = 'where'; // 过滤时机 where having
+      this.$set( field, 'connectType', 'and')
+      field.uniqId = util.getRandomStr(7)
+      if (field.viewDataType === 'DATETIME') {
+        this.$set( field, 'dateType', this.dateTypeMap[field.timeDataFormat])
+        this.$set( field, 'dateFormat', this.fieldDateFormats.find(i => i.value === field.timeDataFormat).label)
+      }
+      this.$set( field, 'conditions', [{function: "eq", values: ["", ""], timeType: "absolute", countType: "left",connectType:"and",asFilter:true,uniqId: util.getRandomStr(7)}])
+      this.config.filter.push(field);
+      document.body.click()
+      field.conditions.forEach((item,i)=>{
+        this.relationNode.conditions.push({uniqId: item.uniqId, columnTitle: field.columnTitle,})
+        this.config.filterRelation = JSON.stringify(this.relationNode)
+      })
+      // if (this.config.filterRelation){
+      //   let filterRelation = JSON.parse(this.config.filterRelation)
+      //   filterRelation.conditions.push({uniqId: field.uniqId, columnTitle: field.columnTitle,})
+      //   this.config.filterRelation = JSON.stringify(filterRelation)
+      // }
+    },
+    countCanAggregation(filter) {
+      if (filter.connectTime == 'where') return false;
+      if (filter.dimensionType == 'WEIDU') return false;
+      if (filter.columnAttr == 'NORMAL') return true;
+      return !filter.virtualAggregationStatus;
+    },
+    onDelFilter(item, node, i) {
+      let index = this.config.filter.findIndex(i => i.uniqId == item.uniqId);
+      if (index >= 0) {
+        this.onFieldDel(index);
+      } else {
+        node.conditions.splice(i, 1);
+      }
+    },
+    onGetEnumData() {
+      getEnumData(this.nowFilter, this.config.dataId, this.visualId, this.chartId, true);
+    },
+    // 过滤时机改变时
+    onConnectTimeChange() {
+      this.config.filterRelation = "";
+    },
+    // 清除空节点
+    clearNullNode(parent, item, index) {
+      if (item.conditions && item.conditions.length){
+        item.conditions.forEach((node, i) => this.clearNullNode(item, node, i));
+      }
+      if (item.conditions && !item.conditions.length) {
+        parent.conditions.splice(index, 1);
+      }
+    },
+    // 节点拖拽完成时
+    onNodeDrop(node, type) {
+      if (type != this.draggingType) return;
+      let item = this.draggingNode.conditions.splice(this.draggingIndex, 1)[0];
+      node.conditions.push(item);
+      if (type === "where") {
+        this.relationNode?.conditions?.forEach((node, index) => this.clearNullNode(this.relationNode, node, index));
+      } else {
+        this.havingNode.forEach((node, index) => this.clearNullNode(this.havingNode, node, index));
+      }
+    },
+    // 开始拖拽某节点
+    onNodeDrag(node, index, type) {
+      this.draggingNode = node;
+      this.draggingIndex = index;
+      this.draggingType = type;
+    },
+    // 结构编辑面板点击编辑过滤器时
+    editFilterByUniqId(uniqId) {
+      // 遍历 filter 中的每个对象
+      this.config.filter.forEach(item => {
+        // 检查 conditions 是否存在且不为空
+        if (item.conditions && item.conditions.length > 0) {
+          // 遍历 conditions 数组中的每个对象
+          item.conditions.forEach(condition => {
+            // 将 uniqId 添加到 uniqIds 数组中
+            if (condition.uniqId === uniqId){
+              this.onEditFilter(item, 2);
+            }
+          });
+        }
+      });
+    },
+    // 编辑结构时
+    onEditRelation() {
+      let relation = this.config.filterRelation;
+      if (relation) {
+        let where = JSON.parse(relation);
+        if (where.conditions && where.conditions.length) {
+          this.relationNode = where;
+        } else {
+          this.initRelation();
+        }
+      } else {
+        this.initRelation();
+      }
+      this.showRelationEdit = true;
+    },
+    // 初始化过滤器结构
+    initRelation() {
+      let filterRelation = this.config.filter.filter((i) => i.connectTime === "where");
+      // 遍历 filterRelation 定义filterRelation下每个对象为item,如果item下conditions 存在且有长度的 遍历item的 conditions map出来 {uniqId: i.uniqId, columnTitle: item.columnTitle}
+      let conditionsList = []
+      filterRelation.forEach((item) => {
+        let filterItem = item.conditions.map((i) => ({uniqId: i.uniqId, columnTitle: item.columnTitle,}));
+        conditionsList = [...conditionsList,...filterItem]
+      });
+      this.relationNode = {
+        conditions: conditionsList,
+        relation: "AND",
+      };
+    },
+    onEnumSelectAll(filter) {
+      onEnumSelectAll(filter);
+    },
+    onTimeTypeChange(condition) {
+      if (condition.timeType === "relative") {
+        condition.values = [1];
+      } else {
+        condition.values = [""];
+      }
+    },
+    // 去掉为空的children
+    clearChildren(node) {
+      if (!node.children) return;
+      if (!node.children.length) {
+        delete node.children;
+      } else {
+        node.children.forEach(this.clearChildren);
+      }
+    },
+    // 判断是否展示枚举选项
+    countEnumShow() {
+      let func = this.nowFilter.conditions[0].function;
+      return func === "in" || func === "notIn" || func === "indexIn";
+    },
+    // 计算函数变化时
+    async onFunctionChange(func) {
+      if (["in", "notIn", "indexIn"].includes(func)) {
+        this.nowFilter.conditions = [{function: func, values: [], timeType: "absolute", countType: "left",},];
+      }
+    },
+    // 判断过滤项是否可选择having方式
+    countFilterTime() {
+      let id = this.nowFilter.cubeColumnId;
+      return !this.selectedFields.find((i) => i.cubeColumnId === id);
+    },
+    // 过滤器添加条件
+    onConditionAdd() {
+      let addItem = {function: "eq", values: ["", ""], timeType: "absolute", countType: "left",uniqId: util.getRandomStr(7)}
+      this.nowFilter.conditions.push(addItem);
+      if (this.config.filterRelation){
+        this.relationNode.conditions.push({uniqId: addItem.uniqId, columnTitle: this.nowFilter.columnTitle,})
+        this.config.filterRelation = JSON.stringify(this.relationNode)
+      }
+    },
+    onConditionUpdate() {
+      this.showEditFilter = false
+      let itemUniqId = [];
+      // 遍历 filter 中的每个对象
+      this.config.filter.forEach(item => {
+        // 检查 conditions 是否存在且不为空
+        if (item.conditions && item.conditions.length > 0) {
+          // 遍历 conditions 数组中的每个对象
+          item.conditions.forEach(condition => {
+            // 将 uniqId 添加到 uniqIds 数组中
+            itemUniqId.push(condition.uniqId);
+          });
+        }
+      });
+      this.relationNode?.conditions?.forEach((node, index) => {
+        this.updateNullNode(this.relationNode, node,itemUniqId, index);
+      });
+      if (this.config.filterRelation){
+        this.config.filterRelation = JSON.stringify(this.relationNode)
+      }
+    },
+    // 清除空节点
+    updateNullNode(parent, item,itemUniqId, index) {
+      if (item?.conditions && item.conditions.length){
+        item.conditions.forEach((node, i) => this.updateNullNode(item, node, itemUniqId, i));
+      }
+      if (!item.conditions && !itemUniqId.includes(item.uniqId)) {
+        parent.conditions.splice(index, 1);
+      }
+    },
+    // 清除空节点
+    // clearNullNode(parent, item, index) {
+    //   if (item.conditions && item.conditions.length){
+    //     item.conditions.forEach((node, i) => this.clearNullNode(item, node, i));
+    //   }
+    //   if (item.conditions && !item.conditions.length) {
+    //     parent.conditions.splice(index, 1);
+    //   }
+    // },
+    // 过滤器删除条件
+    onConditionDel(i) {
+      this.nowFilter.conditions.splice(i, 1);
+    },
+    // 编辑某过滤器时
+    onEditFilter(field, toggleType) {
+      this.showEditFilter = true;
+      this.$nextTick(() => {
+        this.nowFilter = field;
+        this.toggleType = toggleType;
+        let relation = this.config.filterRelation;
+        if (relation) {
+          let where = JSON.parse(relation);
+          if (where.conditions && where.conditions.length) {
+            this.relationNode = where;
+          } else {
+            this.initRelation();
+          }
+        } else {
+          this.initRelation();
+        }
+      })
+      // let func = this.nowFilter.conditions[0].function;
+      // if (func === "in" || func === "notIn" || func === "indexIn") {
+      //   if (!this.nowFilter.options.length) {
+      //     getEnumData(this.nowFilter, this.config.dataId, this.visualId, this.chartId, true);
+      //   }
+      // }
+    },
+    onFieldDel(index) {
+      let item = this.config.filter.splice(index, 1)[0];
+      item.conditions.forEach((item1) => {
+        let uniqId = item1.uniqId;
+        if (this.config.filterRelation){
+          let where = JSON.parse(this.config.filterRelation);
+          let node = this.getIncludeNode(where, uniqId);
+          let index2 = node.conditions.findIndex((i) => i.uniqId === uniqId);
+          node.conditions.splice(index2, 1);
+          where.conditions.forEach((node, index) => {
+            this.clearNullNode(where, node, index);
+          });
+          this.config.filterRelation = JSON.stringify(where);
+          this.relationNode = where;
+          this.$forceUpdate();
+        }
+      })
+    },
+    getIncludeNode(node, uniqId) {
+      if (node.conditions && node.conditions.length){
+        if (node.conditions.find((i) => i.uniqId === uniqId)) {
+          return node;
+        } else {
+          for (let i = 0; i < node.conditions.length; i++) {
+            if (node.conditions[i].conditions && node?.conditions[i].conditions.length){
+              if (this.getIncludeNode(node?.conditions[i], uniqId)) {
+                return node.conditions[i];
+              }
+            }
+          }
+        }
+      }
+    },
+  },
+};
+</script>
+<style lang="scss">
+.filter-setting-box {
+  .group {
+    padding-right: 10px;
+    display: -webkit-box;
+    display: -ms-flexbox;
+    display: flex;
+    -webkit-box-align: center;
+    -ms-flex-align: center;
+    align-items: center;
+    height: 40px;
+    margin-top: 10px;
+    font-size: 14px;
+    .name{
+      -webkit-box-flex: 1;
+      -ms-flex: 1;
+      flex: 1;
+      font-weight: 600;
+      text-indent: 20px;
+    }
+    .midele{
+      margin-right: 10px;
+      color: #999;
+      cursor: pointer;
+    }
+    .btn {
+      color: #999;
+      padding: 5px;
+      cursor: pointer;
+    }
+    .btn.active {
+      color: #409eff;
+    }
+
+  }
+  .item-box {
+    min-height: 30px;
+    -webkit-box-sizing: border-box;
+    box-sizing: border-box;
+    border: 1px dashed #ccc;
+    margin-right: 10px;
+    padding-right: 0;
+    position: relative;
+    z-index: 1;
+  }
+  .item-box.active {
+    margin-right: 0;
+    padding-right: 10px;
+    border: 1px solid #ccc;
+    border-right-color: #fff;
+  }
+  .item {
+    display: -webkit-box;
+    display: -ms-flexbox;
+    display: flex;
+    -webkit-box-align: center;
+    -ms-flex-align: center;
+    align-items: center;
+    font-size: 14px;
+    margin: 8px;
+    padding: 0 5px 0 10px;
+    line-height: 26px;
+    height: 26px;
+    .name {
+      -webkit-box-flex: 1;
+      -ms-flex: 1;
+      flex: 1;
+      overflow: hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      margin-right: 5px;
+    }
+  }
+  .item.WEIDU {
+    border: 1px solid #1d54d5;
+  }
+  .item.ZHIBIAO {
+    border: 1px solid #00b375;
+  }
+}
+.bigdata-filter {
+  width: 660px;
+  .el-form-item {
+    margin-bottom: 10px;
+  }
+  .now-filter {
+    display: inline-flex;
+    font-size: 12px;
+    padding: 0 10px;
+    line-height: 28px;
+    width: 260px;
+    .name {
+      margin-right: 5px;
+      overflow: hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      flex: 1;
+    }
+    &.WEIDU {
+      border: 1px solid #1d54d5;
+    }
+    &.ZHIBIAO {
+      border: 1px solid #00b375;
+    }
+  }
+  .filter-item {
+    padding-bottom: 10px;
+    .el-icon-delete {
+      font-size: 14px;
+      margin-left: 5px;
+      color: #f56c6c;
+    }
+  }
+}
+.bigdata-data-setting {
+  .right-center-panel {
+    .group .middle {
+      margin-right: 10px;
+      color: #999;
+      cursor: pointer;
+    }
+  }
+}
+.filter-relation-dialog {
+  .el-dialog__body {
+    min-height: 600px;
+    .title {
+      line-height: 40px;
+      font-weight: 600;
+    }
+  }
+}
+.weidu {
+  line-height: 24px;
+  box-sizing: border-box;
+  border: 1px solid #1d54d5;
+  background-color: #e4eafa;
+  padding: 0 10px;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  margin: 3px 0;
+  cursor: pointer;
+}
+.zhibiao {
+  line-height: 24px;
+  box-sizing: border-box;
+  border: 1px solid #00b375;
+  background-color: #d4f2e8;
+  padding: 0 10px;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  margin: 3px 0;
+  cursor: pointer;
+}
+</style>

+ 32 - 0
src/components/Dataset-filter/report.js

@@ -549,3 +549,35 @@ export const BtnDataPermSubmit = (params) => {
     data: params
   })
 }
+
+//获取表单标签
+export const getDataPermLabel = (modelId,params) => request.get(`/visual-api/paas/visualdev/label/get/label/${modelId}`, {params})
+export const getDataPermLabelGroup = (modelId) => request.get(`/visual-api/paas/visualdev/label/get/group/${modelId}`, )
+
+export const addDataPermLabelGroup = (modelId,params) =>{
+  return request({
+    url: `/visual-api/paas/visualdev/label/add/group/${modelId}`,
+    method: 'post',
+    data: params
+  })
+}
+export const updateDataPermLabelGroup = (modelId,params) =>{
+  return request({
+    url: `/visual-api/paas/visualdev/label/update/group/${modelId}`,
+    method: 'post',
+    data: params
+  })
+}
+export const addLabel = (modelId,params) =>{
+  return request({
+    url: `/visual-api/paas/visualdev/label/add/label/${modelId}`,
+    method: 'post',
+    data: params
+  })
+}
+export const delLabel = (id,) =>{
+  return request({
+    url: `/visual-api/paas/visualdev/label/del/label/${id}`,
+    method: 'post',
+  })
+}

+ 417 - 0
src/components/Dataset-filter/tab-filter.vue

@@ -0,0 +1,417 @@
+<template>
+  <div class="newbi-dataset-filter">
+    <div class="wrapper">
+      <div class="left">
+        <el-tabs tab-position="left" v-model="nowName" @tab-click="onSelectItem">
+          <el-tab-pane v-for="(item, i) of list" :name="item.visualdevPermName" :key="item.id" :label="item.visualdevPermName"> </el-tab-pane>
+        </el-tabs>
+        <div class="add-tab">
+          <el-button size="small" type="success" plain icon="el-icon-plus" @click="onAddItem">添加标签组</el-button>
+        </div>
+      </div>
+      <div class="right" v-if="nowFilter">
+        <el-form size="mini" label-width="60px">
+          <el-form-item label="名称">
+            <el-input v-model="nowFilter.visualdevPermName"></el-input>
+          </el-form-item>
+          <el-form-item label="权限组">
+            <auth-group-selector @change="dataPermIdChange" v-model="nowFilter.dataPermId"></auth-group-selector>
+          </el-form-item>
+          <el-form-item label="标签默认填充色" label-width="120px">
+            <el-color-picker @change="$forceUpdate();"
+              v-model="nowFilter.defaultBgColor"
+              show-alpha
+              :predefine="predefineColors">
+            </el-color-picker>
+          </el-form-item>
+          <el-form-item label="标签选中填充色" label-width="120px">
+            <el-color-picker  @change="$forceUpdate();"
+              v-model="nowFilter.actionBgColor"
+              show-alpha
+              :predefine="predefineColors">
+            </el-color-picker>
+          </el-form-item>
+          <div style="margin-bottom: 10px;display: flex;justify-content: space-between;">
+            <el-button size="mini" type="primary" @click="addLabelGroup">{{ !nowFilter.id ? '新增标签组' : '更新标签组' }}</el-button>
+            <el-button size="mini" @click="addLabelClick">添加标签</el-button>
+          </div>
+          <el-table :data="newlabelList" border style="width: 100%">
+            <el-table-column label="标签名称" prop="visualdevPermName">
+            </el-table-column>
+            <el-table-column label="是否启用">
+              <template slot-scope="scope">
+                <el-switch @change="labelStatusChange($event, scope.row)" v-if="scope.row.visualdevPermName !== '全部' " :active-value="0" :inactive-value="1" v-model="scope.row.labelStatus">
+                </el-switch>
+              </template>
+            </el-table-column>
+            <el-table-column label="设置">
+              <template slot-scope="scope">
+                <el-button v-if="scope.row.visualdevPermName !== '全部' " size="mini" type="text" @click="onEditLabel(scope.row)">编辑</el-button>
+                <el-button v-if="scope.row.visualdevPermName !== '全部' " size="mini" type="text" @click="onDelLabel(scope.row)">删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-form>
+      </div>
+    </div>
+    <el-dialog title="新增标签" :visible.sync="dialogVisible" width="30%" append-to-body>
+      <el-form :model="addForm" size="mini" ref="addForm" :rules="rulesList" label-width="80px">
+        <el-form-item label="标签名称" prop="name">
+          <el-input v-model="addForm.name"></el-input>
+        </el-form-item>
+        <el-form-item label="标签发布状态" label-width="107px">
+          <el-switch v-model="addForm.states" :active-value="0" :inactive-value="1">
+          </el-switch>
+        </el-form-item>
+        <p style="padding-left: 10px">标签筛选条件</p>
+        <filter-setting :active="true" :config="addForm" :dbLinkId="cubeId" :max-level="3"/>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+    <el-button @click="dialogVisible = false">取 消</el-button>
+    <el-button type="primary" @click="addFormClick()">确 定</el-button>
+  </span>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import authGroupSelector from "./auth-group-selector";
+import {
+  addDataPermLabelGroup,
+  addLabel, delLabel,
+  getDataPermLabel,
+  getDataPermLabelGroup,
+  updateDataPermLabelGroup
+} from "@/components/Dataset-filter/report";
+import FilterSetting from "@/components/Dataset-filter/filterSetting.vue";
+import {deepClone} from "@/utils";
+
+export default {
+  name: "tab-filter",
+  components: {FilterSetting, authGroupSelector},
+  props:['modelId','activeName','cubeId','formData'],
+  data(){
+    return {
+      list: [],
+      nowName: '',
+      nowFilter: {},
+      predefineColors: [
+      '#ff4500',
+      '#ff8c00',
+      '#ffd700',
+      '#90ee90',
+      '#00ced1',
+      '#1e90ff',
+      '#c71585',
+      'rgba(255, 69, 0, 0.68)',
+      'rgb(255, 120, 0)',
+      'hsv(51, 100, 98)',
+      'hsva(120, 40, 94, 0.5)',
+      'hsl(181, 100%, 37%)',
+      'hsla(209, 100%, 56%, 0.73)',
+      '#c7158577'
+    ],
+      dialogVisible:false,
+      addForm: {
+        name:'',
+        states:0,
+        columnList:[],
+        filter:[],
+        filterRelation: '',
+      },
+      newlabelList:[],
+      rulesList:{
+        name: [{ required: true, message: '请输入标签名称', trigger: 'blur' }]
+      }
+    }
+  },
+  created() {
+    this.getInfo()
+  },
+  watch: {
+    activeName: {
+      deep: true,
+      handler(val) {
+        if (val && val === 'labelManage') {
+          this.getInfo()
+        }
+      }
+    }
+  },
+  methods:{
+    getInfo(){
+      getDataPermLabelGroup(this.modelId).then((res)=>{
+        this.list = res.data.data
+        if (!this.list.length) {
+          this.list.push({
+            visualdevPermName: '默认标签组',
+            dataPermId: '',
+            id: '',
+            labelJson: '',
+            labelList:[],
+            labelStatus: '',
+            visualdevId: this.modelId,
+            defaultBgColor: '#ffffff',
+            actionBgColor: '#1e90ff',
+          })
+        }
+        this.nowName = this.list[0].visualdevPermName
+        this.onSelectItem({ name: this.nowName })
+      })
+    },
+    // 选择过滤器时
+    async onSelectItem({name}) {
+      let now = this.list.find((i) => i.visualdevPermName == name)
+      this.nowName = now.visualdevPermName
+      this.nowFilter = now
+      try {
+        this.nowFilter.labelJson = now.labelJson ? deepClone(JSON.parse(now.labelJson)) : {}
+      }catch {
+        this.nowFilter.labelJson = now.labelJson ? deepClone(now.labelJson) : {}
+      }
+      this.nowFilter.defaultBgColor = this.nowFilter.labelJson.defaultBgColor
+      this.nowFilter.actionBgColor = this.nowFilter.labelJson.actionBgColor
+      let params = {groupId: now.id}
+      await getDataPermLabel(this.modelId, params).then((res) => {
+        this.newlabelList = res.data.data
+        this.newlabelList.unshift({visualdevPermName:'全部',labelStatus:true})
+      })
+    },
+    // 添加过滤器时
+    onAddItem() {
+      let visualdevPermName = this.list.length + 1 + '-新增标签组'
+      let newFilter = {
+        visualdevPermName,
+        dataPermId: '',
+        cubeDataId: parseInt(this.cubeId),
+        filterRelation: '',
+        filterList: [],
+        excludeColumn: []
+      }
+      this.list.push(newFilter)
+      this.nowName = visualdevPermName
+      this.nowFilter = newFilter
+    },
+    addLabelClick(){
+      this.dialogVisible = true
+      this.$nextTick(()=>{
+        this.addForm = {
+          visualdevPermName:'',
+          labelStatus:1,
+          columnList:[],
+          filter:[],
+          filterRelation: '',
+        }
+      })
+    },
+    addFormClick(){
+      this.$refs['addForm'].validate((valid) => {
+        if (valid) {
+          this.newlabelList = this.newlabelList.filter(item=> item.visualdevPermName !== '全部')
+          // let browserRequest = []
+          if (this.addForm.filter && this.addForm.filter.length) {
+            // this.addForm.filter.forEach((item,index)=>{
+            //   if (item.conditions && item.conditions.length) {
+            //     // 从this.formData.fields里查存在relationData的 并且itemRelationList有长度的 循环itemRelationList 找到drawId 等于 item.id 的 找到的话 将plaintext返回
+            //     let relationData = this.formData.fields.find(field=>field.relationData && field.relationData.itemRelationList && field.relationData.itemRelationList.length && field.relationData.itemRelationList.find(i=>i.drawId === item.id))
+            //     let associationColumnFlag = false
+            //     if (relationData) {
+            //       if (relationData.relationData.itemRelationList.find(i=>i.drawId === item.id).plaintext === 1) {
+            //         associationColumnFlag = true
+            //       }
+            //     }
+            //     item.conditions.forEach(condition => {
+            //       let conditionItem = {
+            //         cubeColumnId: item.id,
+            //         function: condition.function,
+            //         values: condition.values && condition.values.length ? condition.values[1] ? condition.values : [condition.values[0]] : [],
+            //         uniqId: item.uniqId
+            //       }
+            //       if (associationColumnFlag) conditionItem = {...conditionItem, associationColumn:false}
+            //       browserRequest.push(conditionItem)
+            //     })
+            //   }
+            // })
+            if (!this.addForm.filterRelation) {
+              console.log(this.addForm)
+              let filterRow = this.addForm.filter.filter((i) => i.connectTime === "where");
+              // 遍历 filterRelation 定义filterRelation下每个对象为item,如果item下conditions 存在且有长度的 遍历item的 conditions map出来 {uniqId: i.uniqId, columnTitle: item.columnTitle}
+              let conditionsList = []
+              filterRow.forEach((item) => {
+                let filterItem = item.conditions.map((i) => ({uniqId: i.uniqId, columnTitle: item.columnTitle,}));
+                conditionsList = [...conditionsList,...filterItem]
+              });
+              let filterRelation = {
+                conditions: conditionsList,
+                  relation: "AND",
+              }
+              this.addForm.filterRelation = JSON.stringify(filterRelation)
+            }
+          }
+          let params = {
+            visualdevPermName:this.addForm.name,
+            labelStatus: this.addForm.states,
+            labelJson:JSON.stringify({filter:this.addForm.filter,filterRelation:this.addForm.filterRelation}),
+            dataPermId:this.nowFilter.dataPermId,
+            labelGroupId:this.nowFilter.id,
+            id:this.addForm.id,
+            labelCss:JSON.stringify(this.nowFilter.labelJson)
+          }
+          addLabel(this.modelId,params).then((res)=>{
+            this.$message({ message: res.data.msg, type: 'success', duration: 1500 })
+            this.onSelectItem({ name: this.nowName })
+          })
+          this.$nextTick(()=>{
+            this.addForm = {
+              visualdevPermName:'',
+              labelStatus:false,
+              columnList:[],
+              filter:[],
+              filterRelation: '',
+            }
+            this.dialogVisible = false
+            this.newlabelList.unshift({visualdevPermName:'全部',labelStatus:true})
+          })
+        } else {
+          return false;
+        }
+      });
+    },
+    onEditLabel(row){
+      this.dialogVisible = true
+      let dataJson = JSON.parse(row.labelJson)
+      this.$nextTick(()=>{
+        this.addForm = {
+          name:row.visualdevPermName,
+          states:row.labelStatus,
+          filter:dataJson.filter,
+          filterRelation: dataJson.filterRelation,
+          id:row.id
+        }
+      })
+    },
+    onDelLabel(row){
+      delLabel(row.id).then((res)=>{
+        this.$message({ message: res.data.msg, type: 'success', duration: 1500 })
+        this.onSelectItem({ name: this.nowName })
+      })
+    },
+    addLabelGroup(){
+      let params = {
+        visualdevPermName:this.nowFilter.visualdevPermName,
+        labelJson:JSON.stringify({defaultBgColor:this.nowFilter.defaultBgColor,actionBgColor:this.nowFilter.actionBgColor}),
+        dataPermId:this.nowFilter.dataPermId,
+        id:this.nowFilter.id
+      }
+      const formMethod = this.nowFilter.id ? updateDataPermLabelGroup : addDataPermLabelGroup
+      formMethod(this.modelId,params).then((res)=>{
+        this.$message({ message: res.data.msg, type: 'success', duration: 1500 })
+        this.getInfo()
+      })
+    },
+    labelStatusChange(val,row){
+      let params = {
+        visualdevPermName:row.visualdevPermName,
+        labelStatus: val,
+        labelJson:row.labelJson,
+        dataPermId:row.dataPermId,
+        labelGroupId:this.nowFilter.id,
+        id:row.id,
+        labelCss:row.labelCss
+      }
+      addLabel(this.modelId,params).then((res)=>{
+        this.$message({ message: res.data.msg, type: 'success', duration: 1500 })
+        this.onSelectItem({ name: this.nowName })
+      })
+    },
+    dataPermIdChange(){
+      this.addLabelGroup()
+    },
+  }
+}
+</script>
+<style scoped lang="scss">
+.newbi-dataset-filter {
+  height: 100%;
+  .wrapper {
+    display: flex;
+    height: 100%;
+    .left {
+      .el-tabs {
+        height: 90%;
+        .el-tabs__content {
+          display: none;
+        }
+      }
+      .add-tab {
+        text-align: center;
+        margin-right: 9px;
+        padding: 13px 0;
+      }
+    }
+    .right {
+      flex: 1;
+      height: 100%;
+      overflow-y: auto;
+      .filter-item {
+        width: 300px;
+        display: flex;
+        height: 30px;
+        line-height: 30px;
+        align-items: center;
+        padding: 0 10px;
+        margin: 10px;
+        border: 1px solid #ccc;
+        .title {
+          flex: 1;
+          &.WEIDU {
+            color: #468cff;
+          }
+          &.ZHIBIAO {
+            color: #00c13a;
+          }
+        }
+        .type {
+          color: #777;
+        }
+      }
+      .column {
+        padding: 0 8px;
+        margin: 8px 4px;
+        width: 200px;
+        height: 26px;
+        line-height: 26px;
+        font-size: 14px;
+        box-sizing: border-box;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        &.WEIDU {
+          border: 1px solid #468cff;
+        }
+        &.ZHIBIAO {
+          border: 1px solid #00c13a;
+        }
+        .close {
+          color: #f56c6c;
+          cursor: pointer;
+          margin-left: 5px;
+        }
+      }
+      .el-tabs {
+        margin-left: 10px;
+      }
+      .el-tab-pane {
+        height: 93%;
+        //overflow-y: auto;
+      }
+    }
+  }
+  .btns {
+    margin-top: 20px;
+    text-align: center;
+    .el-button {
+      width: 80px;
+    }
+  }
+}
+</style>

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 2 - 2
src/utils/request.js


+ 127 - 11
src/views/basic/dynamicModel/list/index.vue

@@ -36,6 +36,7 @@
     <div class="JNPF-common-layout-center">
       <topForm ref="topForm" v-if="columnData.type === 4" />
       <Search ref="Search" :list="columnData.searchList" :columnData="columnData" :treeBoxSearch="treeBoxSearch" @reset="reset" @search="search" />
+
       <div class="JNPF-common-layout-main JNPF-flex-main" v-if="columnData.type !== 6">
         <!--        @row-dblclick="dbclick"-->
         <vxe-grid
@@ -247,7 +248,7 @@
               <el-dropdown>
                 <span class="el-dropdown-link">更多<i class="el-icon-arrow-down el-icon--right"></i> </span>
                 <el-dropdown-menu slot="dropdown">
-                  <div v-for="item in getPreconditionObj[scope.row[columnDict[idKey]]]" :key="item">
+                  <div v-for="item in getPreconditionObj[scope.row[columnDict[idKey]]]" :key="item.id">
                     <el-dropdown-item>
                       <el-button size="mini" type="text" :icon="item.icon" @click="isCustomBtnsHandel(item, scope)">{{ item.buttonName }}</el-button>
                     </el-dropdown-item>
@@ -331,6 +332,14 @@
             </el-popover>
             <vxe-button title="刷新" style="margin-right: 12px" circle icon="el-icon-refresh" @click="refreshTableLayout()"></vxe-button>
           </template>
+          <template #top>
+            <div style="padding: 0 0 10px 0;background: #ffffff" v-if="permLabelList.length">
+              <el-button :style="{color:permLabelList[0].labelCss && JSON.parse(permLabelList[0].labelCss).defaultBgColor ? '#ffffff' : '',background: !paramLabelId && permLabelList[0].labelCss ? JSON.parse(permLabelList[0].labelCss).actionBgColor : JSON.parse(permLabelList[0].labelCss).defaultBgColor}" @click="permLabelList.forEach((item)=>{item.active = false});paramLabelId = '';search()">全部</el-button>
+              <template v-for="(item,index) in permLabelList">
+                <el-button v-if="item.labelStatus !== 1" :key="item.id" :style="{color:JSON.parse(item.labelCss).defaultBgColor ? '#ffffff' : '', background: item.active ? JSON.parse(item.labelCss).actionBgColor : JSON.parse(item.labelCss).defaultBgColor}"  @click="permLabelSeach(item)">{{item.visualdevPermName}}</el-button>
+              </template>
+            </div>
+          </template>
           <template v-slot:pager>
             <vxe-pager
               v-if="columnData.hasPage"
@@ -556,7 +565,7 @@ import {
   updateModel,
   uploadModel
 } from '@/api/onlineDev/visualDev'
-import { deepClone, detail, formatDate, getSeachPrimaryAndForeignTable, loopRelationList } from '@/utils'
+import {deepClone, detail, formatDate, getSeachPrimaryAndForeignTable, loopRelationList} from '@/utils'
 import Form from './Form'
 import FlowBox from '@/views/workFlow/components/FlowBox'
 import Detail from './detail'
@@ -571,17 +580,18 @@ import recycleList from './recycleList'
 import batchEdit from './batchEdit'
 import topForm from './topForm'
 import moment from 'moment'
-import { dictDetail } from '@/api/newbi/dict'
+import {dictDetail} from '@/api/newbi/dict'
 import RelationForm from '@/components/Generator/components/RelationForm'
 import swiperWrapper from './../components/swiperWrapper'
-import { getAPIData, getTreeAPIData } from '@/components/Dataset-filter/util'
+import {getAPIData, getTreeAPIData} from '@/components/Dataset-filter/util'
 import AmisSdk from '@/components/AmisSdk.vue'
-import { userInfo } from '@/api/user'
-import { getToken } from '@/utils/auth'
-import { getFileById } from '@/api/common'
-import { comUrl } from '@/utils/define'
+import {userInfo} from '@/api/user'
+import {getToken} from '@/utils/auth'
+import {getFileById} from '@/api/common'
+import {comUrl} from '@/utils/define'
 
 import CardTemplate from '@/components/CardTemplate/index.vue'
+import {getDataPermLabel} from "@/components/Dataset-filter/report";
 
 export default {
   name: 'dynamicModel',
@@ -739,7 +749,11 @@ export default {
       itemRow: null,
       loading: true,
       cardData: [],
-      cardColumn: []
+      cardColumn: [],
+      permLabelList:[],
+      labelBrowserRequest: '',
+      paramCondition:'',
+      paramLabelId:'',
     }
   },
   filters: {
@@ -1895,6 +1909,8 @@ export default {
       if (!json) this.$refs.treeBox && this.$refs.treeBox.setCurrentKey(null)
       this.listQuery.json = json && json.length ? JSON.parse(json) : []
       this.listQuery.currentPage = 1
+      this.labelBrowserRequest = ''
+      this.paramLabelId = ''
       this.refreshTableLayout()
     },
     // 新版表格开始
@@ -2028,10 +2044,11 @@ export default {
         primaryTableId: this.config.dbLinkId,
         foreignTableId: foreignTableId,
         modelId: this.modelId,
-        browserRequest: listQuery ? JSON.stringify(listQuery) : JSON.stringify([]),
+        browserRequest: this.labelBrowserRequest ? this.labelBrowserRequest : listQuery ? JSON.stringify(listQuery) : JSON.stringify([]),
         subTableQueryParams: subTableQueryParams ? JSON.stringify(subTableQueryParams) : JSON.stringify([]),
         visualdevEntityDto
       }
+      if (this.paramLabelId) this.parmes.paramCondition = this.paramCondition
       if (this.listQuery.sidx) {
         this.parmes.pageQuery[[this.listQuery.sort]] = this.listQuery.sidx
       }
@@ -2363,6 +2380,13 @@ export default {
           this.cardData = res.data.data.pageData.records
         }
         this.loading = false
+        getDataPermLabel(this.modelId).then((res)=>{
+          this.permLabelList = res.data.data || []
+          if(this.permLabelList.length)
+            this.permLabelList.forEach((item)=>{
+              item.active = item.id === this.paramLabelId;
+            })
+        })
         // console.log(this.columnList)
       })
     },
@@ -3084,7 +3108,99 @@ export default {
         fontSize: this.columnData?.gridStyle?.headerFontSize + 'px',
         color: this.columnData?.gridStyle?.headerFontColor || '#606266'
       }
-    }
+    },
+    getFilterDate(filter,values,countType){
+      // 日期处理
+      let { dateType, dateFormat } = filter;
+      values = values.map(i => parseInt(i));
+      let now = new Date();
+      if (dateType === 'year') {
+        if (countType === 'left') {
+          now.setFullYear(now.getFullYear() - values[0]);
+        } else {
+          now.setFullYear(now.getFullYear() + values[0]);
+        }
+      } else if (dateType === 'month') {
+        if (countType === 'left') {
+          now.setMonth(now.getMonth() - values[0]);
+        } else {
+          now.setMonth(now.getMonth() + values[0]);
+        }
+      } else if (dateType === 'date') {
+        if (countType === 'left') {
+          now.setDate(now.getDate() - values[0]);
+        } else {
+          now.setDate(now.getDate() + values[0]);
+        }
+      } else if (dateType === 'hour') {
+        if (countType === 'left') {
+          now.setHours(now.getHours() - values[0]);
+        } else {
+          now.setHours(now.getHours() + values[0]);
+        }
+      } else if (dateType === 'minute') {
+        if (countType === 'left') {
+          now.setMinutes(now.getMinutes() - values[0]);
+        } else {
+          now.setMinutes(now.getMinutes() + values[0]);
+        }
+      } else {
+        if (countType === 'left') {
+          now.setSeconds(now.getSeconds() - values[0]);
+        } else {
+          now.setSeconds(now.getSeconds() + values[0]);
+        }
+      }
+      let fmt = dateFormat.replaceAll('d', 'D');
+      return [moment(now).format(fmt)]
+    },
+    permLabelSeach(item){
+      this.paramLabelId = item.id
+      if (item && item.labelJson){
+        this.permLabelList.forEach((item1)=>{
+          if(item1.id === item.id){
+            item1.active = true;
+            item.active = true;
+          }else {
+            item1.active = false;
+          }
+        })
+        let data = JSON.parse(item.labelJson)
+        let browserRequest = []
+        if (data.filter && data.filter.length) {
+          data.filter.forEach((item1,index)=>{
+            if (item1.conditions && item1.conditions.length) {
+              let relationData = this.formData.fields.find(field=>field.relationData && field.relationData.itemRelationList && field.relationData.itemRelationList.length && field.relationData.itemRelationList.find(i=>i.drawId === item1.id))
+              let associationColumnFlag = false
+              if (relationData) {
+                if (relationData.relationData.itemRelationList.find(i=>i.drawId === item1.id).plaintext === 1) {
+                  associationColumnFlag = true
+                }
+              }
+              item1.conditions.forEach(condition => {
+                if(item1.viewDataType === 'DATETIME' && condition.timeType === 'relative'){
+                  condition.values = this.getFilterDate(item1,condition.values,condition.countType)
+                }
+                let conditionItem = {
+                  cubeColumnId: item1.id,
+                  function: condition.function,
+                  values: condition.values && condition.values.length ? condition.values[1] ? condition.values : [condition.values[0]] : [],
+                  uniqId: condition.uniqId
+                }
+                if (associationColumnFlag) conditionItem = {...conditionItem, associationColumn:false}
+                browserRequest.push(conditionItem)
+              })
+            }
+          })
+        }
+        this.labelBrowserRequest = JSON.stringify(browserRequest)
+        this.paramCondition = data.filterRelation ? JSON.parse(data.filterRelation) : ''
+        this.$refs.Search.searchList = deepClone(this.columnData.searchList)
+        this.$refs.Search.buildOptions(deepClone(this.columnData.searchList))
+        this.reset()
+        this.refreshTableLayout()
+      }
+    },
   }
 }
 </script>

+ 5 - 1
src/views/form/webDesign/Form.vue

@@ -193,6 +193,9 @@
                 :activeName="activeName"
               />
             </el-tab-pane>
+            <el-tab-pane label="标签管理" name="labelManage" style="height: 100%">
+              <tabFilter :modelId="columnData.modelId"  :activeName="activeName" :cubeId="columnData.dbLinkId" :formData="formData"/>
+            </el-tab-pane>
             <el-tab-pane label="数据导入设置" name="importSet">
               <CustomImportSet :modelId="columnData.modelId" :activeName="activeName" />
             </el-tab-pane>
@@ -217,9 +220,10 @@ import tabManage from '@/views/form/webDesign/tabManage.vue'
 import CustomImportSet from '@/views/form/webDesign/customImportSet.vue'
 import Dataset from '@/views/dataset/edit.vue'
 import iconBox from "@/components/JNPF-iconBox/index.vue";
+import tabFilter from '@/components/Dataset-filter/tab-filter.vue'
 export default {
   mixins: [mixin],
-  components: {iconBox, Dataset, CustomButton, CustomEvent, tabManage, CustomImportSet, Generator, ColumnDesign, Process, TableForm },
+  components: {iconBox, Dataset, CustomButton, CustomEvent, tabManage, CustomImportSet, Generator, ColumnDesign, Process, TableForm,tabFilter },
   data() {
     return {
       dataRule: {