当前位置: 首页 > news >正文

多种拖拽= =自用留档

<template>

  <div class="main-drag">

    <div v-if="stencil === '0'" class="mapped-fields">

      <el-form ref="mapped" :model="mapped" class="demo-fieldsForm">

        <el-form-item label="切换数据集" prop="dataset" class="demo-fieldsForm">

          <el-select v-model="mapped.dataset" placeholder="请选择数据集" @change="changeDataset">

            <el-option v-for="(item) in mappedFieldsList" :key="item.fieldId" :label="item.fieldName"

              :value="item.fieldId" />

          </el-select>

        </el-form-item>

      </el-form>

    </div>

    <!--使用draggable组件-->

    <div class="itxst">

      <div class="drag-drop">

        <div class="drag-drop-col calculators">

          <p class="font-weight">拖拽字段到计算区域</p>

          <transition>

            <draggable v-model="calculators" v-bind="{ group: { name: 'itxst', pull: 'clone', put: false }, sort: false }"

              animation="300" :move="onMove" @end="endCalculators">

              <transition-group>

                <div v-for="(item, index) in calculators" :key="index + 'number'"

                  :class="item.type === 'Number' ? 'calculators-item' : 'calculators-item-blue'">{{ item.name }}</div>

              </transition-group>

            </draggable>

          </transition>

        </div>

        <!-- 数据集模块 -->

        <div class="drag-drop-col">

          <p class="font-weight">

            {{ stencil === "0" ? '数据集的模板字段' : '数据源字段' }}

          </p>

          <draggable v-model="fields" v-bind="{ group: { name: 'itxst', pull: 'clone', put: false }, sort: false }"

            animation="300" :move="onMove" @end="endFields">

            <transition-group class="transition-groups">

              <div v-for="(item, index) in fields" :key="index + 'fieldName'" class="field-item">

                <Vptip :content="item.fieldName" :width="'100%'" style="max-width: 500px;" class="item">

                  {{ `${item.fieldName}` }}

                </Vptip>

                <!-- <el-tooltip class="item" effect="dark" :content="item.fieldName" placement="top"

                  style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">

                  <div>{{ item.fieldName }}</div>

                </el-tooltip> -->

              </div>

            </transition-group>

          </draggable>

        </div>

        <!-- 指标拖拽模块 -->

        <div class="drag-drop-col">

          <p class="font-weight">当前模板的指标字段</p>

          <draggable v-model="indicators" v-bind="{ group: { name: 'itxst', pull: 'clone', put: false }, sort: false }"

            animation="300" :move="onMove" @end="endFields">

            <transition-group class="transition-groups">

              <div v-for="(item, index) in indicators" :key="index + 'templateFieldName'" class="field-item"

                style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">

                <Vptip :content="item.templateFieldName" :width="'100%'" style="max-width: 500px;" class="item">

                  {{ `${item.templateFieldName}` }}

                </Vptip>

                <!-- <el-tooltip class="item" effect="dark" :content="item.templateFieldName"

                  style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;" placement="top">

                  <div>{{ item.templateFieldName }}</div>

                </el-tooltip> -->

              </div>

            </transition-group>

          </draggable>

        </div>

      </div>

      <!-- 公式模块 -->

      <div class="col-operations">

        <div class="operations-left">

          <p class="font-weight">计算区域</p>

          <transition>

            <draggable v-model="operations" group="itxst" animation="300" :move="onMove" @end="endOperationsOne">

              <transition-group class="group-over">

                <!-- 此处只能是index,因为存在上面两个列表拉下来两个的情况会产生相同的id -->

                <div v-for="(item, index) in operations" :key="index" :class="decideSstyle(item.type, item.name)">

                  <div class="contains-item-name" v-if="item.name">

                    {{ item.name }}

                  </div>

                  <el-tooltip class="contains-item-names" effect="dark" placement="top" :open-delay="400"

                    v-if="item.templateFieldName">

                    <div slot="content">

                      <span>类型:指标字段</span><br />

                      <span>名称:{{ item.templateFieldName }}</span>

                    </div>

                    <div class="contains-item-name" v-if="item.templateFieldName">

                      {{ item.templateFieldName }}

                    </div>

                  </el-tooltip>

                  <el-tooltip class="contains-item-names" effect="dark" placement="top" :open-delay="400"

                    v-if="item.fieldName">

                    <div slot="content">

                      <span>{{ stencil === "0" ? '数据集名称' : '数据源名称' }}:{{ item.fieldBelongName }} </span><br />

                      <span>类型:{{ stencil === "0" ? '模板字段' : '数据源字段' }}</span><br />

                      <span>名称:{{ item.fieldName }} </span>

                    </div>

                    <div class="contains-item-name" v-if="item.fieldName">

                      {{ item.fieldName }}

                    </div>

                  </el-tooltip>

                  <div v-if="(item.name === 'SUM' || item.name === 'AVG') && item.open === false" class="margin-auto"

                    @click="item.open = true"><i class="el-icon-d-arrow-right"></i></div>

                  <div v-if="item.name === 'SUM' && item.open === true" class="sum-class">

                    <draggable :key="item.sumId + 'sum'" v-model="sumList[getSumIndex(item.sumId)].list" group="itxst"

                      animation="300" :move="onMove" @end="endOperationsTwo">

                      <transition-group class="trans-group">

                        <!-- 此处只能是index,因为存在上面两个列表拉下来两个的情况会产生相同的id -->

                        <div v-for="(itm, idx) in sumList[getSumIndex(item.sumId)].list" :key="idx + 'sum'"

                          class="field-item-father">

                          <div class="field-item" v-if="itm.name">

                            {{ itm.name }}

                          </div>

                          <el-tooltip class="tooltip-div" effect="dark" placement="top" :open-delay="200"

                            v-if="itm.templateFieldName">

                            <div slot="content">

                              <span>类型: 指标字段</span><br />

                              <span>名称:{{ itm.templateFieldName }}</span>

                            </div>

                            <div class="field-item" v-if="itm.templateFieldName">

                              {{ itm.templateFieldName }}

                            </div>

                          </el-tooltip>

                          <el-tooltip class="tooltip-div" effect="dark" placement="top" :open-delay="200"

                            v-if="itm.fieldName">

                            <div slot="content">

                              <span>{{ stencil === "0" ? '数据集名称' : '数据源名称' }}:{{ itm.fieldBelongName }}</span><br />

                              <span>类型: {{ stencil === "0" ? '模板字段' : '数据源字段' }}</span><br />

                              <span>名称:{{ itm.fieldName }}</span>

                            </div>

                            <div class="field-item" v-if="itm.fieldName">

                              {{ itm.fieldName }}

                            </div>

                          </el-tooltip>

                        </div>

                      </transition-group>

                    </draggable>

                  </div>

                  <div v-if="item.name === 'AVG' && item.open === true" class="sum-class">

                    <draggable :key="item.averageId + 'avg'" v-model="averageList[getAverageIndex(item.averageId)].list"

                      group="itxst" animation="300" :move="onMove" @end="endOperationsThree">

                      <transition-group class="trans-group">

                        <!-- 此处只能是index,因为存在上面两个列表拉下来两个的情况会产生相同的id -->

                        <div v-for="(itm, idx) in averageList[getAverageIndex(item.averageId)].list" :key="idx + 'avg'"

                          class="field-item-father">

                          <div class="field-item" v-if="itm.name">

                            {{ itm.name }}

                          </div>

                          <el-tooltip class="tooltip-div" effect="dark" placement="top" :open-delay="200"

                            v-if="itm.templateFieldName">

                            <div slot="content">

                              <span>类型: 指标字段</span><br />

                              <span>名称:{{ itm.templateFieldName }}</span>

                            </div>

                            <div class="field-item" v-if="itm.templateFieldName">

                              {{ itm.templateFieldName }}

                            </div>

                          </el-tooltip>

                          <el-tooltip class="tooltip-div" effect="dark" placement="top" :open-delay="200"

                            v-if="itm.fieldName">

                            <div slot="content">

                              <span>{{ stencil === "0" ? '数据集名称' : '数据源名称' }}:{{ itm.fieldBelongName }}</span><br />

                              <span>类型:{{ stencil === "0" ? '模板字段' : '数据源字段' }}</span><br />

                              <span>名称:{{ itm.fieldName }}</span>

                            </div>

                            <div class="field-item" v-if="itm.fieldName">

                              {{ itm.fieldName }}

                            </div>

                          </el-tooltip>

                        </div>

                      </transition-group>

                    </draggable>

                  </div>

                  <div v-if="(item.name === 'SUM' || item.name === 'AVG') && item.open === true" class="margin-auto"

                    @click="item.open = false"><i class="el-icon-d-arrow-left"></i></div>

                </div>

              </transition-group>

            </draggable>

          </transition>

          <el-button class="button-calculation" size="mini" type="primary" @click="calculation()">生成计算</el-button>

        </div>

        <!-- 垃圾回收站 -->

        <div class="operations-right" style="position: relative;">

          <i class="el-icon-delete" style="position: absolute;top: 150px;left: 43%; "></i>

          <draggable v-model="recycleBin" group="itxst" animation="300" :move="onMove" @end="endOperations">

            <transition-group class="recycle recycle-group">

              <!-- 此处只能是index,因为存在上面两个列表拉下来两个的情况会产生相同的id -->

              <div v-for="(item, index) in recycleBin" :key="index" class="calculators-item">{{ item.name }}</div>

            </transition-group>

          </draggable>

        </div>

      </div>

    </div>

  </div>

</template>

<script>

// 拖拽组件

import Vptip from "@/components/vptip" // 自定义Tooltip 文字提示

import draggable from 'vuedraggable'

export default {

  name: 'customField',

  components: {

    draggable,

    Vptip

  },

  props: {

    // 数据源字段

    mappedFieldsList: {

      type: Array,

      default: () => []

    },

    // 区分模板还是评价 1:模板 0:评价

    stencil: {

      type: String,

      default: ''

    },

    // 数据条件范围

    rangeFieldList: {

      type: Array,

      default: () => []

    },

    // 页面初始渲染数据

    formFieldsOne: {

      type: Array,

      default: () => []

    }

  },

  data() {

    return {

      // 数据集

      mapped: {

        dataset: ''

      },

      // 计算器元素数组

      calculators: [

        { id: 1, name: '1', type: 'Number' },

        { id: 2, name: '2', type: 'Number' },

        { id: 3, name: '3', type: 'Number' },

        { id: 4, name: '(', type: 'BracketsLeft' },

        { id: 5, name: '4', type: 'Number' },

        { id: 6, name: '5', type: 'Number' },

        { id: 7, name: '6', type: 'Number' },

        { id: 8, name: ')', type: 'BracketsRight' },

        { id: 9, name: '7', type: 'Number' },

        { id: 10, name: '8', type: 'Number' },

        { id: 11, name: '9', type: 'Number' },

        { id: 12, name: 'SUM', sumId: 1, open: true },

        { id: 13, name: '0', type: 'Number' },

        { id: 14, name: '.', type: 'DecimalPoint' },

        { id: 15, name: '/', type: 'Symbols' },

        { id: 16, name: 'AVG', averageId: 1, open: true },

        { id: 17, name: '+', type: 'Symbols' },

        { id: 18, name: '-', type: 'Symbols' },

        { id: 19, name: '*', type: 'Symbols' }

      ],

      // 可拖拽的计算字段

      fields: [],

      // 可拖拽的指标字段

      indicators: [],

      // 计算生成的算式

      operations: [],

      // 进行回收的字段

      recycleBin: [],

      // 拖拽的是什么

      moveId: '',

      // 空数组之在的样式,设置了这个样式才能拖入

      style: 'min-height:200px;display: block;',

      // 是否通过校验

      passingCalibration: true,

      // SUM之中的字段

      sumList: [],

      // AVG之中的字段

      averageList: [],

      // 计算num数组从第几个开始算起

      listSumId: 1,

      // 计算AVG数组从第几个开始算起

      listAverageId: 1,

      // numId:进行新添加的id的时候从第几个开始加

      numId: 20

    }

  },

  computed: {

    getSumIndex() {

      return this.findSumIndex

    },

    getAverageIndex() {

      return this.findAverageIndex

    }

  },

  watch: {

    formFieldsOne: {

      handler(item1, item2) {

        this.rest(this.formFieldsOne)

      },

      immediate: true

    }

  },

  mounted() {

    // 放入对应的数据源字段

    if (this.stencil === '0') {

      this.fields = []

    } else {

      this.fields = this.mappedFieldsList

    }

    // 对应指标字段

    this.indicators = this.rangeFieldList

  },

  methods: {

    // 重置操作

    rest(ruleForm) {

      // 数据集

      this.mapped.dataset = ''

      if (this.stencil === '0') {

        // 可拖拽的计算字段

        this.fields = []

      }

      // 计算生成的算式

      this.operations = ruleForm[0] !== undefined ? ruleForm[0] : []

      // AVG之中的字段

      this.averageList = ruleForm[1] !== undefined ? ruleForm[1] : []

      // SUM之中的字段

      this.sumList = ruleForm[2] !== undefined ? ruleForm[2] : []

      // 计算num数组从第几个开始算起

      let numSum = 0

      for (let i = 0; i < this.sumList.length; i++) {

        if (numSum < this.sumList[i].sumId) {

          numSum = this.sumList[i].sumId

        }

      }

      this.calculators.splice(11, 1, { id: 12, name: 'SUM', sumId: numSum + 1, open: true })

      this.listSumId = numSum + 1

      // 计算AVG数组从第几个开始算起

      let numAvg = 0

      for (let i = 0; i < this.averageList.length; i++) {

        if (numAvg < this.averageList[i].averageId) {

          numAvg = this.averageList[i].averageId

        }

      }

      this.calculators.splice(15, 1, { id: 16, name: 'AVG', averageId: numAvg + 1, open: true })

      this.listAverageId = numAvg + 1

      // numId:进行新添加的id的时候从第几个开始加

      this.numId = 20

    },

    // 更改选项对父组件进行传值

    changeDataset() {

      for (let i = 0; i < this.mappedFieldsList.length; i++) {

        if (this.mapped.dataset === this.mappedFieldsList[i].fieldId) {

          this.fields = this.mappedFieldsList[i].fieldList

        }

      }

    },

    // 进行渲染的计算属性计算

    findSumIndex(sumId) {

      return this.sumList.findIndex(item => item.sumId === sumId)

    },

    findAverageIndex(averageId) {

      return this.averageList.findIndex(item => item.averageId === averageId)

    },

    // 进行计算器拖拽

    endCalculators(e) {

      // 阻止拖拽事件

      if (e.relatedContext && e.relatedContext.element instanceof HTMLElement &&

        e.draggedContext.element.type === 'Symbols' &&

        e.relatedContext.element.classList.contains('sum-class')) {

        e.cancel()

      }

      // 如果拖拽的是SUM

      if (this.moveId === 'SUM') {

        this.calculators.splice(11, 1, { id: this.numId, name: 'SUM', sumId: this.listSumId + 1, open: true })

        this.listSumId++

        this.numId++

      }

      // 如果拖拽的是AVG

      if (this.moveId === 'AVG') {

        this.calculators.splice(15, 1, { id: this.numId, name: 'AVG', averageId: this.listAverageId + 1, open: true })

        this.listAverageId++

        this.numId++

      }

      const that = this

      that.recycleBin = []

    },

    //  进行元素字段拖拽

    endFields(e) {

      const that = this

      that.recycleBin = []

    },

    // 进行删除拖动

    endOperations(e) {

      this.recycleBin = []

    },

    // 进行删除拖动

    endOperationsOne(e) {

      this.recycleBin = []

    },

    // 进行删除拖动

    endOperationsTwo(e) {

      this.recycleBin = []

    },

    // 进行删除拖动

    endOperationsThree(e) {

      this.recycleBin = []

    },

    // move回调方法

    onMove(e, originalEvent) {

      if (this.sumList.length === 0) this.sumList = []

      if (this.averageList.length === 0) this.averageList = []

      this.moveId = e.draggedContext.element.name

      let index = -1

      for (let i = 0; i < this.sumList.length; i++) {

        if (this.sumList[i].sumId === this.listSumId) {

          index = i

        }

      }

      // 如果是在进行sum拖拽添加空数组

      if (e.draggedContext.element.name === 'SUM') {

        if (index !== -1) {

          this.sumList.splice(index, 1, { sumId: this.listSumId, list: [] })

        } else {

          this.sumList.push({ sumId: this.listSumId, list: [] })

        }

      }

      // 如果是在进行AVERAGE拖拽添加空数组

      let indexAvg = -1

      for (let i = 0; i < this.averageList.length; i++) {

        if (this.averageList[i].averageId === this.listAverageId) {

          indexAvg = i

        }

      }

      if (e.draggedContext.element.name === 'AVG') {

        if (indexAvg !== -1) {

          this.averageList.splice(indexAvg, 1, { averageId: this.listAverageId, list: [] })

        } else {

          this.averageList.push({ averageId: this.listAverageId, list: [] })

        }

      }

      /**

      *   禁止往SUM中拖拽计算器内容

      * if(拖拽位置停靠在SUM内||停靠位置为第一个数据且外围有数据)

      *    &&不是向回收站拖拽

      *    &&(类型不是undefined名称&&不是SUM){不允许拖拽}

      */

      if ((e.related.className === 'field-item-father' ||

        (this.operations.length !== 0 && e.relatedContext.list.length === 0)) &&

        e.related.className !== 'recycle recycle-group' &&

        (e.draggedContext.element.type !== undefined || e.draggedContext.element.name === 'SUM' || e.draggedContext.element.name === 'AVG')

      ) {

        return false

      }

      return true

    },

    // 操控计算区域样式

    decideSstyle(type, name) {

      // 如果是字段或者求和求差

      if (type === undefined) {

        if (name === 'AVG' || name === 'SUM') {

          return 'contains-item'

        }

        return 'field-item-down'

        // 如果是数字

      } else if (type === 'Number') {

        return 'calculators-item-down'

        // 如果是运算符

      } else {

        return 'calculators-item-blue-down'

      }

    },

    sureFieldOne() {

      this.calculation()

      if (this.passingCalibration === true) {

        return true

      } else {

        return false

      }

    },

    // 生成计算

    calculation() {

      this.passingCalibration = true

      // 如果计算区域为空

      if (this.operations.length === 0) {

        // Msg0052:运算表达式不符合规则

        this.$message.error(this.$manages.Msg0052)

        return

      }

      // 括号栈

      const stack = []

      for (let i = 0; i < this.operations.length; i++) {

        // 进行括号堆栈的判断

        // 存在左括号就将左括号存进去

        if (this.operations[i].type === 'BracketsLeft') {

          stack.push('(')

        }

        // 存在右括号

        if (this.operations[i].type === 'BracketsRight') {

          // 如果在没有左括号的前提下存在了右括号为不合理

          if (stack.length === 0) {

            this.passingCalibration = false

          }

          // 正常情况下存在了右括号将堆栈删掉一个

          stack.pop()

        }

        // 只看前一个和后一个的情况下

        if (i > 0 && i < this.operations.length - 1) {

          // 当当前为字段时

          if (this.operations[i].type === undefined) {

            // 上一个不能为字段

            // 上一个不能为数字

            // 上一个不能为小数点

            // 下一个不能为字段

            // 下一个不能为数字

            // 下一个不能为小数点

            if (this.operations[i - 1].type === undefined ||

              this.operations[i - 1].type === 'Number' ||

              this.operations[i - 1].type === 'DecimalPoint' ||

              this.operations[i + 1].type === undefined ||

              this.operations[i + 1].type === 'Number' ||

              this.operations[i + 1].type === 'DecimalPoint'

            ) {

              this.passingCalibration = false

            }

            // 当当前为数字时

          } else if (this.operations[i].type === 'Number') {

            // 上一个不能为字段

            // 下一个不能为字段

            if (this.operations[i - 1].type === undefined ||

              this.operations[i + 1].type === undefined

            ) {

              this.passingCalibration = false

            }

            // 当当前为运算符的时候

          } else if (this.operations[i].type === 'Symbols') {

            // 上一个不能为运算符

            // 上一个不能为小数点

            // 上一个不能为左括号

            // 下一个不能为运算符

            // 下一个不能为小数点

            // 下一个不能为右括号

            if (this.operations[i - 1].type === 'Symbols' ||

              this.operations[i - 1].type === 'DecimalPoint' ||

              this.operations[i - 1].type === 'BracketsLeft' ||

              this.operations[i + 1].type === 'Symbols' ||

              this.operations[i + 1].type === 'DecimalPoint' ||

              this.operations[i + 1].type === 'BracketsRight'

            ) {

              this.passingCalibration = false

            }

            // 当当前为左括号的时候

          } else if (this.operations[i].type === 'BracketsLeft') {

            // 上一个不能为小数点

            // 下一个不能为小数点

            if (this.operations[i - 1].type === 'DecimalPoint' ||

              this.operations[i + 1].type === 'DecimalPoint' ||

              this.operations[i - 1].type === 'Number' ||

              this.operations[i - 1].type === undefined

            ) {

              this.passingCalibration = false

            }

            // 当当前为右括号的时候

          } else if (this.operations[i].type === 'BracketsRight') {

            // 上一个不能为小数点

            // 下一个不能为小数点

            if (this.operations[i - 1].type === 'DecimalPoint' ||

              this.operations[i + 1].type === 'DecimalPoint' ||

              this.operations[i + 1].type === 'Number' ||

              this.operations[i + 1].type === undefined

            ) {

              this.passingCalibration = false

            }

            // 当为小数点时

          } else if (this.operations[i].type === 'DecimalPoint') {

            // 下一个只能为数字

            // 上一个只能为数字

            if (this.operations[i - 1].type !== 'Number' ||

              this.operations[i + 1].type !== 'Number'

            ) {

              this.passingCalibration = false

            }

            let j = i

            j++

            // 对小数点后面的数字进行判断

            while (j < this.operations.length - 1) {

              j++

              const type = this.operations[j].type

              // 如果进入到了运算符,括号证明此数字结束可以进行跳出

              if (type === 'Symbols' ||

                type === 'BracketsLeft' ||

                type === 'BracketsRight') {

                j = this.operations.length

                // 如果在跳出前再次遇见小数点则证明不合理

              } else if (type === 'DecimalPoint') {

                this.passingCalibration = false

                j = this.operations.length

              }

            }

          }

        }

      }

      // 如果最后括号数没归零则等式不合理

      if (stack.length !== 0) {

        this.passingCalibration = false

      }

      // 开头如果不是数字字段百分号左括号就不符合

      if (this.operations[0].type !== 'Number' &&

        this.operations[0].type !== undefined &&

        this.operations[0].type !== 'BracketsLeft') {

        this.passingCalibration = false

      }

      // 结尾如果不是数字字段右括号就不符合

      if (this.operations[this.operations.length - 1].type !== 'Number' &&

        this.operations[this.operations.length - 1].type !== undefined &&

        this.operations[this.operations.length - 1].type !== 'BracketsRight') {

        this.passingCalibration = false

      }

      // 排除掉仅有两位且还不同字段的情况,

      // 排除掉两个都为后端字段的情况

      if (this.operations.length === 2 && (

        this.operations[0].type === undefined ||

        this.operations[1].type === undefined)) {

        this.passingCalibration = false

      }

      // 如果仅为一位的时候

      if (this.operations.length === 1) {

        if (this.operations[0].type === 'Number' || this.operations[0].type === undefined) {

          this.passingCalibration = true

        }

      }

      // 进行SUM和AVG是否有值的判断

      for (let i = 0; i < this.operations.length; i++) {

        if (this.operations[i].name === 'SUM') {

          const presence = this.sumList.findIndex(item => item.sumId === this.operations[i].sumId)

          // 如果SUM内容为空

          if (this.sumList[presence].list.length === 0) {

            this.passingCalibration = false

          }

        } else if (this.operations[i].name === 'AVG') {

          const presence = this.averageList.findIndex(item => item.averageId === this.operations[i].averageId)

          // 如果AVG内容为空

          if (this.averageList[presence].list.length === 0) {

            this.passingCalibration = false

          }

        }

      }

      // 如果计算列式不合理

      if (this.passingCalibration === false) {

        // Msg0052:运算表达式不符合规则

        this.$message.error(this.$manages.Msg0052)

        // 如果计算列式合理

      } else {

        this.$emit('get-custom-calculation', this.operations, this.averageList, this.sumList)

      }

    }

  }

}

// 原生拖拽自带逻辑

// eslint-disable-next-line no-extend-native

Array.prototype.filter = Array.prototype.filter || function (func) {

  var arr = this

  var r = []

  for (var i = 0; i < arr.length; i++) {

    if (func(arr[i], i, arr)) {

      r.push(arr[i])

    }

  }

  return r

}

</script>

<style lang="scss" scoped>

.main-drag {

  width: 60vw;

  height: auto;

  overflow: hidden;

}

.mapped-fields {

  height: 10vh;

  width: calc(60vw - 2px);

  min-height: 60px;

  min-width: 530px;

  border: solid 1px #DCDFE6;

  border-radius: 3px;

  display: flex;

  flex-direction: column;

  justify-content: center;

  margin-bottom: 20px;

  .demo-fieldsForm {

    margin-left: 20px;

    ::v-deep .el-form-item {

      margin-bottom: 0;

    }

  }

}

.itxst {

  width: 60vw;

  height: auto;

  overflow: hidden;

  text-align: left;

}

.drag-drop {

  display: flex;

  border: solid 1px #DCDFE6;

  border-radius: 5px;

  margin-bottom: 20px;

  padding: 10px 10px;

  .calculators {

    width: 200px;

  }

}

.col-operations {

  height: auto;

  display: flex;

  margin-top: 10px;

  overflow: hidden;

  .operations-left {

    height: auto;

    min-height: 200px;

    width: 88%;

    border: solid 1px #DCDFE6;

    border-radius: 5px;

    margin-right: 2%;

    padding: 1%;

    .button-calculation {

      float: right;

    }

  }

  .operations-right {

    height: auto;

    min-height: 200px;

    width: 10%;

    border: dashed 1px #DCDFE6;

    border-radius: 5px;

    background: #dfdfdf;

  }

}

.drag-drop-col {

  height: 250px;

  padding: 10px;

  float: left;

  overflow: auto;

  width: calc(29vw - 100px);

}

.drag-drop-col+.drag-drop-col {

  border-left: 1px dashed #DCDFE6;

}

.col {

  width: 100%;

  height: 200px;

  flex: 1;

  padding: 10px;

  border: solid 1px #DCDFE6;

  border-radius: 5px;

  float: left;

}

.calculators-item {

  height: 22px;

  line-height: 20px;

  width: auto;

  min-width: 32px;

  float: left;

  border: 1px solid #b3d8ff;

  color: #409eff;

  background: #ecf5ff;

  font-size: 14px;

  text-align: center;

  border-radius: 3px;

  margin: 4px;

}

.calculators-item:hover {

  cursor: move;

}

.calculators-item-down {

  height: 30px;

  line-height: 30px;

  width: auto;

  min-width: 32px;

  float: left;

  border: 1px solid #b3d8ff;

  color: #409eff;

  background: #ecf5ff;

  font-size: 14px;

  text-align: center;

  border-radius: 3px;

  margin: 5px;

}

.calculators-item-down:hover {

  cursor: move;

}

.calculators-item-blue {

  height: 22px;

  line-height: 20px;

  width: auto;

  min-width: 32px;

  float: left;

  border: 1px solid #409eff;

  color: #fff;

  background: #409eff;

  font-size: 12px;

  text-align: center;

  border-radius: 3px;

  margin: 4px;

}

.calculators-item-blue:hover {

  cursor: move;

}

.calculators-item-blue-down {

  height: 30px;

  line-height: 30px;

  width: auto;

  min-width: 32px;

  float: left;

  border: 1px solid #409eff;

  color: #fff;

  background: #409eff;

  font-size: 12px;

  text-align: center;

  border-radius: 3px;

  margin: 5px;

}

.calculators-item-blue-down:hover {

  cursor: move;

}

.field-item {

  color: #e6a23c;

  text-align: center;

  width: 93px;

  height: 24px;

  line-height: 24px;

  border-radius: 4px;

  border: 1px solid #e6a23c;

  background-color: #fdf6ec;

  float: left;

  overflow: hidden;

  text-overflow: ellipsis;

  white-space: nowrap;

  margin: 2px;

  font-size: 12px;

}

.field-item-father {

  float: left;

}

.field-item:hover {

  cursor: move;

}

.field-item-down {

  color: #e6a23c;

  text-align: center;

  width: 93px;

  height: 30px;

  line-height: 30px;

  border-radius: 4px;

  border: 1px solid #e6a23c;

  background-color: #fdf6ec;

  float: left;

  overflow: hidden;

  text-overflow: ellipsis;

  white-space: nowrap;

  margin: 5px;

}

.field-item-down:hover {

  cursor: move;

}

.contains-item {

  min-height: 28px;

  line-height: 28px;

  width: auto;

  min-width: 25px;

  float: left;

  margin: 5px;

  color: #fff;

  background: #409eff;

  text-align: center;

  display: flex;

  border: 1px solid #409eff;

  border-radius: 3px;

  // height: 30px;

}

.contains-item:hover {

  cursor: move;

}

.contains-item-name {

  overflow: hidden;

  text-overflow: ellipsis;

  white-space: nowrap;

  min-width: 35px;

  margin: auto;

}

.contains-item-names {

  overflow: hidden;

  text-overflow: ellipsis;

  white-space: nowrap;

  min-width: 35px;

  margin: auto;

}

.sum-class {

  min-height: 26px;

  min-width: 100px;

  height: auto;

  border-left: 1px solid #c0c0c0;

  border-radius: 3px;

  float: left;

  background-color: #fff;

}

.group-over {

  overflow: auto;

  max-height: 250px;

  height: auto;

  min-height: 200px;

  display: block;

}

.font-weight {

  font-weight: 700;

}

::v-deep .transition-groups {

  display: flex;

  flex-wrap: wrap;

  justify-content: flex-start;

}

.margin-auto {

  margin: auto;

}

.trans-group {

  height: auto;

  min-height: 28px;

  display: block;

}

.recycle-group {

  height: 200px;

  display: block;

}

::v-deep .tooltip-div {

  width: 93px !important;

  height: 24px !important;

}

</style>

相关文章:

多种拖拽= =自用留档

<template> <div class"main-drag"> <div v-if"stencil 0" class"mapped-fields"> <el-form ref"mapped" :model"mapped" class"demo-fieldsForm"> <el-form-item label"切换数…...

贝叶斯与认知——读《贝叶斯的博弈》有感

关于对贝叶斯与认知问题的相关思考 一、贝叶斯定理二、贝叶斯与认知的本质三、经验的偏见四、总结 自古以来&#xff0c;人们就在思考知识来自何处&#xff0c;“冯翼惟象&#xff0c;何以识之&#xff1f;”&#xff0c;对此的思考逐渐发展成哲学的认识论分支。德国哲学家康德…...

MySQL安装失败starting the sever

MySQL安装失败starting the sever 如果电脑是第一次安装MySQL&#xff0c;一般不会出现这样的报错。starting the sever失败&#xff0c;通常是因为上次安装该软件没有清除干净。 第一种解决方法&#xff1a;完全卸载mysql&#xff0c;重新安装 完全卸载该软件的办法&#…...

合并文件夹中所有文件,并输出重复的条形码值

文章目录 一、需求二、处理方式三、代码实现 一、需求 每天会生成一个记录文件&#xff08;文件名按日期yyyyMMdd格式命名&#xff09;&#xff0c;记录文件中记录有条形码的内容&#xff0c;需要合并最近20次的数据&#xff0c;并提取出有重复的条形码。 也可以进行最近30天数…...

P3089 [USACO13NOV] Pogo-Cow S 弹簧踩高跷

P3089 [USACO13NOV] Pogo-Cow S 弹簧踩高跷 洛谷题目传送门 文章目录 P3089 [USACO13NOV] Pogo-Cow S 弹簧踩高跷题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示题目大意方法一&#xff08;线段树维护dp&#xff09;code 方法二 &#xff08;单调队列维护dp&…...

计算机网络 - 第一章(下)

1.2_1 分层结构、协议、接口、服务_哔哩哔哩_bilibili1.2_1 分层结构、协议、接口、服务是王道计算机考研 计算机网络的第7集视频&#xff0c;该合集共计76集&#xff0c;视频收藏或关注UP主&#xff0c;及时了解更多相关视频内容。https://www.bilibili.com/video/BV19E411D78…...

【Uniapp】小程序携带Token请求接口+无感知登录方案2.0

本次改进原文《【Uniapp】小程序携带Token请求接口无感知登录方案》&#xff0c;在实际使用过程中我发现以下bug&#xff1a; 若token恰好在用户访问接口时到期&#xff0c;就会直接查询为空&#xff0c;不反映token过期问题&#xff08;例如&#xff1a;弹窗显示订单查询记录…...

Ubuntu常用命令

文章目录 1&#xff1a;文件管理2&#xff1a;文档编辑3&#xff1a;系统管理4&#xff1a;磁盘管理5&#xff1a;文件传输6&#xff1a;网络通讯7&#xff1a;设备管理8&#xff1a;备份压缩9&#xff1a;其他命令扩展&#xff1a;知识干货 1&#xff1a;文件管理 ls命令 –…...

ERP重构-SLA子分类账-分布式实现方案

背景 ERP中的GL总账模块&#xff0c;明细数据来源于各个业务模块如库存、成本、应收、应付、费控、资产等&#xff0c;统称为子模块&#xff0c;生成的账叫做子分类账。然而记账的业务逻辑各式各样&#xff0c;但是最终输出都是来源、类型、期间、科目、借贷金额等等关键信息。…...

IP路由协议(RIP、IGRP、OSPF、IS-IS、BGP)

文章目录 1、路由分类2、RIP协议1&#xff09;RIP的工作原理2&#xff09;RIP路由表的更新过程3&#xff09;RIP路由表的更新原则4&#xff09;RIP的特性5&#xff09;RIP协议的版本 4、IGRP协议1&#xff09;IGRP路由表的更新2&#xff09;IGRP的度量标准 5、OSPF协议1&#x…...

互斥锁、自旋锁、读写锁、悲观锁、乐观锁的应用场景

多线程访问共享资源的时候&#xff0c;避免不了资源竞争而导致数据错乱的问题&#xff0c;所以我们通常为了解决这一问题&#xff0c;都会在访问共享资源之前加锁。 最常用的就是互斥锁&#xff0c;当然还有很多种不同的锁&#xff0c;比如自旋锁、读写锁、乐观锁等&#xff0…...

Python WSGI 与 Web 开发框架

目录 文章目录 目录WSGIWSGI 的工作原理environ 参数start_resposne 参数 WSGI 的中间件 WSGI Web 开发框架OpenStack 中的应用案例进程入口WSGI Application 加载Paste/PasteDeployRoutesWebOb WSGI Server 启动 WSGI WSGI&#xff08;Web Server Gateway Interface&#xff…...

[洛谷]P6464 [传智杯 #2 决赛] 传送门

看到数据范围&#xff1a;n<100&#xff0c;嗯......脑子闪过&#xff1a;还在想什么呢&#xff01;Floyd啊。哈哈哈 思路&#xff1a; 详细注释&#xff1a; 话不多说&#xff0c;上ACcode&#xff01;: #include<bits/stdc.h> using namespace std; #define int lo…...

Http协议和RestTemplate协议有什么区别?

目录 一、功能不同 二、技术不同 三、使用场景不同 四、总结 RestTemplate 是一个 Spring 框架提供的用于发送 HTTP请求的客户端工具&#xff0c;它封装了 Java 原生的 HTTP 客户端库&#xff0c;并提供了一组简洁易用的 API 来发送 HTTP 请求和处理响应。而 HTTP&#xff…...

基于SpringBoot+微信小程序的医院预约叫号小程序

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 该项目是基于uniappWe…...

springboot整合RabbitMQ 消费端处理数据

pom 依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>写一个rabbitmq配置文件 import org.springframework.amqp.core.Binding; import org.springframewo…...

计算机中CPU、内存、缓存的关系

CPU&#xff08;Central Processing Unit&#xff0c;中央处理器&#xff09; 内存&#xff08;Random Access Memory&#xff0c;随机存取存储器&#xff09; 缓存&#xff08;Cache&#xff09; CPU、内存和缓存之间有着密切的关系&#xff0c;它们共同构成了计算机系统的核…...

【Linux实验】构造一个简单的 shell

一、实验目的 l 用 C/C++构造一个简单的 shell; l 理解 shell 程序的功能; l 学会 shell 的使用;...

【电路原理学习笔记】第2章:电压、电流和电阻:2.6 电路

第2章&#xff1a;电压、电流和电阻 2.6 电路 2.6.1 电流的方向 电流方向有两种说法&#xff0c;一种按电子流动方向&#xff0c;另一种是传统的认为从正极流出到负极&#xff0c;这本教材采用传统电流方法。&#xff08;事传统派&#xff0c;维新派输了&#xff0c;1&#…...

基于深度学习的人脸检测技术

用到环境 1、pycharm community edition 2022.3.2 2、Python 3.10 整篇内容都已上传至我的csdn资源中&#xff0c;想用的请移步。 流程 多任务级联卷积神经网络(Multi-task Cascaded Convolutional Networks, MTCNN)算法进行人脸检测 普通人脸检测 单人人脸检测 图1 单人人…...

【linux kernel】一文总结linux内核通知链

文章目录 1、通知链简介2、通知链的类型3、原理分析和API&#xff08;1&#xff09;注销通知器&#xff08;2&#xff09;注销通知器&#xff08;3&#xff09;通知链的通知 4、实例代码&#xff08;1&#xff09;定义一个通知链&#xff08;2&#xff09;实现观察者模块&#…...

kafka入门,Kafka 副本(十三)

Kafka副本 副本基本信息 1&#xff09;Kafka副本作用&#xff0c;提高数据可靠性 2&#xff09;Kafka默认副本1个&#xff0c;生产环境一般配置2个&#xff0c;保证数据可靠性&#xff0c;太多副本会增加磁盘存储空间&#xff0c;增加网络上数据传输&#xff0c;降低效率 3&a…...

利用PPT制作简单的矢量图

1.用PPT画一个图形&#xff08;可以多个图&#xff09; 2.鼠标圈住图形 3.利用 Ctrl G 组合图形&#xff0c;再用 Ctrl C 复制 4.打开word—粘贴—选择性粘贴—图片&#xff08;增强性图元文件&#xff09; 确认即可。...

18-Linux 常用命令

目录 1.ls PS&#xff1a;FinalShell设置背景和字体 2.pwd 3.cd PS&#xff1a;认识 Linux 目录结构——Linux 是一个树形目录结构 PS&#xff1a;绝对路径 vs 相对路径 PS&#xff1a;使用 tab 键补全 PS&#xff1a;使用 ctrl c 重新输入 4.touch PS&#xff1a;L…...

2024考研408-计算机组成原理第六章-总线学习笔记

文章目录 前言初识总线一、总线概述1.1、总线的概述1.1.1、认识总线1.1.2、设计总线需要的特性1.1.3、总线的分类①按照数据传输格式分&#xff08;串行、并行&#xff09;②按照总线功能连接的总线&#xff08;片内总线、系统总线、通信总线&#xff09;③按照时序控制方式&am…...

uni_app 微信小程序 苹果手机 边框显示不全

![在这里插入图片描述](https://img-blog.csdnimg.cn/3a4c4ab1a146444c84c72d360a057c01.png 解决方案&#xff1a; 原因&#xff1a;是因为我们在设置边框的时候设置的rpx &#xff0c;自适应会自动换算px, 两者之间的比例一般都是1.5-2之间&#xff0c;对于边框 border 来说…...

vue 访问第三方 跨域, 配置vue.config.js

目录 0 config 文件被修改 一个要重启vscode 配置文件才会生效 1 第一种 (有两种写法) 1.1 配置vue.config.js 1.2 axios 使用 1.3 终端打印 2 第二种方法 --> 错误 --> 没有运行成功 2.1 配置vue.config.js --> 就是api 不被设置成 替换为 / 2.2 axios 使用…...

使用gradio库的File模块实现文件上传和展示

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…...

网络安全进阶学习第四课——SSRF服务器请求伪造

文章目录 一、什么是SSRF&#xff1f;二、SSRF成因三、SSRF简析四、PHP存在SSRF的风险函数五、后台源码获取方式六、SSRF危害七、SSRF漏洞挖掘从WEB功能上寻找&#xff0c;从URL关键字中寻找 八、SSRF具体利用ssrf常利用的相关协议PHP伪协议读取文件端口扫描 九、SSRF存在的必要…...

js处理扁平数组和树结构相互转换

一、将扁平的数据转为树形结构 在 js中&#xff0c;可以使用递归算法将扁平的数据转换为树形结构。 扁平数据通常是一个带有 parentId 属性的数组&#xff0c;而树形结构通常是一个带有 children 属性的对象。 1、方法一 下面是一个简单的例子&#xff0c;演示如何将扁平数…...