<template>
  <el-main ref="tablePanel" class="ht-table-panel">
    <div
      v-if="!noHeader && !justShowSearch"
      ref="toolbarPanel"
      class="toolbar-panel"
    >
      <div
        v-if="!justShowSearch"
        class="toolbar-panel__search"
        :class="{ 'ht-quick__search': !hideTableSearch }"
      >
        <ht-input
          v-if="quickSearchConfig && quickSearchConfig.length > 0"
          ref="quickSearch"
          v-model.lazy="quickSearchWord"
          class="quick-search"
          :style="quickSearchWidthStyle"
          :placeholder="quickSearchPlaceholder"
          :autofocus="true"
          :disabled="loading || showAdvancedSearch"
          :debounce="2000"
          suffix-icon="el-icon-search"
          style="margin-right: 20px"
          @keydown.enter.native="doQuickSearch"
          @click.native="clickQuickSearch"
        ></ht-input>
        <div class="common-tools">
          <el-tooltip
            v-if="hasSearchPanel && !justShowSearch"
            :content="showAdvancedSearch ? '基础搜索' : '高级搜索'"
            placement="top"
            effect="light"
          >
            <el-button
              icon="icon-shaixuan"
              class="refresh-btn-icon"
              @click="showAdvancedSearch = !showAdvancedSearch"
            ></el-button>
          </el-tooltip>
          <el-tooltip
            v-if="showExport"
            content="导出数据"
            placement="top"
            effect="light"
          >
            <el-button @click="$emit('export')">
              <ht-icon name="arrow" />
            </el-button>
          </el-tooltip>
          <el-tooltip content="刷新数据" placement="top" effect="light">
            <el-button
              icon="el-icon-refresh"
              class="refresh-btn-icon"
              @click="load(true)"
            ></el-button>
          </el-tooltip>
        </div>
      </div>
    </div>
    <el-collapse-transition>
      <div
        v-show="showAdvancedSearch || justShowSearch"
        ref="searchPanel"
        class="search-panel"
      >
        <slot name="search"></slot>
      </div>
    </el-collapse-transition>
    <div v-if="hasToolBar" ref="toolbarContainer" class="toolbar-container">
      <slot name="toolbar"></slot>
    </div>

    <GanttMain
      :gantt-config="ganttConfig"
      :data="data"
      :manage-permission="managePermission"
      :bpm-data-template="bpmDataTemplate"
      :pk-field="pkField"
      :table-max-height="
        `${tableMaxHeight > 400 || customTableHeight ? tableMaxHeight : 400}` +
        'px'
      "
      :custom-table-max-height="customTableMaxHeight"
      @gantt-btn-click="
        (action, script, param) =>
          $emit('gantt-btn-click', action, script, param)
      "
      @gantt-task-update="(data, id) => $emit('gantt-task-update', data, id)"
    />

    <div v-if="!nopagination" ref="paginationPanel" class="pagination-panel">
      <el-row type="flex" :justify="tablePaginationJustify">
        <el-pagination
          :small="small"
          :class="{ 'page-sizes__hidden': hidePageSizes }"
          :disabled="loading"
          :current-page="pagination.page"
          :page-sizes="pageSizes"
          :page-size="pagination.pageSize"
          :pager-count="pagerCount"
          :background="$paginationBackground"
          :layout="layout"
          :total="pagination.total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        ></el-pagination>
      </el-row>
    </div>
  </el-main>
</template>
<script>
  import Locale from '@/mixins/locale'
  import Emitter from '@/mixins/emitter'
  import utils from '@/utils.js'
  import GanttMain from './GanttMain.vue'
  import elementResizeDetectorMaker from 'element-resize-detector'
  export default {
    name: 'HtGantt',
    components: { GanttMain },
    mixins: [Locale, Emitter],
    props: {
      //是否使用小型分页样式
      small: {
        type: Boolean,
        default: false,
      },
      size: {
        type: String,
        default: 'mini',
      },
      tooltipEffect: {
        type: String,
        default: 'dark',
      },
      justShowSearch: {
        //为true时只显示高级搜索中的查询条件
        type: Boolean,
        default: false,
      },
      paginationJustify: {
        type: String,
        default: 'start',
        validator: function (value) {
          return ['start', 'end', 'center'].indexOf(value) !== -1
        },
      },
      data: Array,
      showHeader: {
        type: Boolean,
        default: true,
      },
      pageResult: {
        type: Object,
        default: () => {
          return { page: 1, pageSize: 50, total: 0 }
        },
      },
      pageSizes: {
        type: Array,
        default: () => {
          return [10, 20, 50, 100, 200, 300]
        },
      },
      pagerCount: {
        type: Number,
        default: 7,
      },
      nopagination: {
        type: Boolean,
        default: false,
      },
      highlightCurrentRow: {
        type: Boolean,
        default: false,
      },
      selectable: {
        type: Boolean,
        default: true,
      },
      quickSearchProps: [String, Array],
      headerRowClassName: [String, Function],
      headerCellClassName: [String, Function],
      rowClassName: [String, Function],
      cellClassName: [String, Function],
      showExport: {
        type: Boolean,
        default: false,
      },
      showCustomColumn: {
        type: Boolean,
        default: true,
      },
      defaultQuerys: {
        type: Array,
        default() {
          return []
        },
      },
      defaultSorter: {
        type: Array,
        default() {
          return []
        },
      },
      isLoadTable: {
        //是否默认在mounted函数中请求table数据
        type: Boolean,
        default: true,
      },
      quickSearchWidth: {
        type: Number,
        default: 400,
      },
      customTableHeight: {
        type: [String, Number], //自定义传入固定高度
        validator: (val) => {
          if (typeof val == 'number' && !Number.isNaN(val)) {
            return val > 0
          } else if (typeof val == 'string') {
            const numVal = Number(val)
            return !isNaN(numVal) && numVal > 0
          } else {
            return false
          }
        },
      }, //自定义传入最大高度，与 customTableHeight的区别是 customTableHeight是参与高度计算，customTableMaxHeight是GanttMain的最大高度
      customTableMaxHeight: {
        type: [String, Number],
        validator: (val) => {
          if (typeof val == 'number') {
            return val > 0
          } else if (typeof val == 'string') {
            const numVal = Number(val)
            return !isNaN(numVal) && numVal > 0
          } else {
            return false
          }
        },
      },

      noHeader: {
        // 不显示整个工具栏
        type: Boolean,
        default: false,
      },
      emptyText: String,
      rowClickSelect: {
        // 单击行时是否选中该行数据
        type: Boolean,
        default: true,
      },
      autoFix: {
        //是否在表头高度改变时，触发doLayout操作
        type: Boolean,
        default: false,
      },
      hidePageSizes: {
        type: Boolean,
        default: false,
      },
      tableNoDataImg: {
        type: String,
        default: require('@/assets/table-no-data.png'),
      },
      noLoading: {
        type: Boolean,
        default: false,
      },
      rowKey: {
        type: [Function, String],
      },
      reserveSelection: {
        type: Boolean,
        default: false,
      },
      stripe: {
        type: Boolean,
        default: false,
      },
      layout: {
        type: String,
        default: 'total, sizes, prev, pager, next, jumper',
      },
      ganttConfig: {
        type: String,
        default: '',
      },
      bpmDataTemplate: Object,
      managePermission: {
        type: String,
        default: '',
      },
      pkField: {
        type: String,
      },
    },
    data() {
      return {
        querys: [],
        sorter: null,
        quickSearchWord: null,
        quickSearchPlaceholder: '请输入搜索内容',
        quickSearchConfig: null,
        hasSearchPanel: false,
        filters: {},
        pagination: { ...this.pageResult },
        tableMaxHeight: 400,
        showAdvancedSearch: false,
        loading: false,
        columns: [],
        customColumns: [],
        selection: [],
        tablePanelHeight: 0,
        isCardView: this.cardView,
      }
    },
    computed: {
      calDefaultQuerys: function () {
        let calQuerys = []
        let query = {
          group: 'defaultQueryGroup',
          operation: 'EQUAL',
          relation: 'AND',
        }
        this.defaultQuerys.forEach((c) => {
          calQuerys.push({ ...query, ...c })
        })
        return calQuerys
      },
      hasToolBar() {
        return this.$slots.toolbar && this.$slots.toolbar.length > 0
      },
      hideTableSearch() {
        const hasQuickSearch =
          this.quickSearchConfig && this.quickSearchConfig.length > 0
        return !this.showAdvancedSearch && !this.hasToolBar && !hasQuickSearch
      },
      customTableHeightNum() {
        return typeof this.customTableHeight == 'number'
          ? this.customTableHeight
          : Number(this.customTableHeight)
      },
      quickSearchWidthStyle() {
        return { width: `${this.quickSearchWidth}` + 'px' }
      },
      tablePaginationJustify() {
        return this.$allPaginationJustify || this.paginationJustify
      },
    },
    watch: {
      justShowSearch: {
        handler(val) {
          if (val) {
            this.showAdvancedSearch = true
          }
        },
        immediate: true,
      },
      isCardView: function (newVal, oldVal) {
        if (newVal !== oldVal) {
          this.selection = []
          this.$emit('view-change', newVal)
        }
      },
      customTableHeight() {
        this.calcTableHeight()
      },
    },
    created() {
      this.initCustomColumns()
      this.$on('advance-search', (data, isSearchBtn) =>
        this.advanceSearch(data, isSearchBtn)
      )
      setTimeout(() => {
        this.quickSearchProps && this.generateQuickSearchConfig()
      }, 100)
    },
    activated() {
      this.doLayout()
    },
    mounted() {
      // 判断是否有高级搜索面板
      this.hasSearchPanel = !!this.$scopedSlots.search
      if (this.isLoadTable) {
        this.load()
      }
      this.calcTableHeight()
      this.$watch('showAdvancedSearch', (n, o) => {
        if (n !== o) {
          if (n) {
            this.quickSearchWord = null
          }
          // 显示或收起搜索面板时，重新计算表格高度
          this.calcTableHeight(300)
          this.$emit('advanced-show', n)
        }
      })
      this.$watch('pageResult', (n, o) => {
        if (n !== o) {
          this.pagination = { ...n }
        }
      })
      this.$root.$on('resize', this.handleResize)
      if (this.autoFix) {
        this.addResizeListener()
      }
    },
    beforeDestroy() {
      this.$root.$off('resize', this.handleResize)
    },
    methods: {
      handleResize() {
        this.tablePanelHeight = 0
        this.calcTableHeight(300)
      },
      setColumns(n) {
        if (n && n.componentOptions) {
          this.columns.push(n.componentOptions.propsData)
        }
        if (n && n.componentOptions && n.componentOptions.children) {
          n.componentOptions.children.forEach((i) => {
            this.setColumns(i)
          })
        }
      },
      initCustomColumns() {
        const me = this
        const ary = []
        setTimeout(() => {
          if (
            !me.$slots ||
            !me.$slots.default ||
            me.$slots.default.length == 0
          ) {
            return
          }
          const count = me.$slots.default.length
          // 从插槽中获取到当前表格的所有列
          me.$slots.default &&
            me.$slots.default.forEach((n, index) => {
              // 将当前表格的列放入一个数组 多表头时需递归改造
              me.setColumns(n)
              if (n && n.componentOptions) {
                const pd = n.componentOptions.propsData
                // 将当前有有prop和label的列放入自定义列表项的数组中
                if (pd.label) {
                  const hasChildren =
                    n.componentOptions.children &&
                    n.componentOptions.children.length > 0
                  ary.push({
                    key: pd.prop || pd.label,
                    value: pd.label,
                    checked:
                      !(pd.hidden === true || pd.hidden === '') ||
                      pd.required === true ||
                      pd.required === '' ||
                      index == count - 1 ||
                      hasChildren,
                    required:
                      pd.required === true ||
                      pd.required === '' ||
                      index == count - 1 ||
                      hasChildren,
                    width: pd.width || 'auto',
                  })
                }
              }
            })
          me.customColumns = ary
        }, 0)
      },
      handleApplyCustomColumn(columns) {
        this.broadcast('HtTableColumn', 'customColumn', columns)
        this.$nextTick(() => {
          setTimeout(() => this.doLayout(), 200)
        })
      },
      doQuickSearch() {
        // 先删除快速查询的查询条件
        this.clearQueryByGroupName('quick')
        this.clearQueryByGroupName('advance')
        this.quickSearchWord &&
          this.quickSearchConfig.forEach((c) => {
            let query = {
              property: c.prop,
              value: this.quickSearchWord.trim(),
              group: 'quick',
              relation: 'OR',
              operation: 'LIKE',
            }
            this.querys.push(query)
          })
        this.load('', true)
      },
      clickQuickSearch($event) {
        if (
          !(this.loading || this.showAdvancedSearch) &&
          $event &&
          $event.target &&
          $event.target.tagName == 'I'
        ) {
          this.$nextTick(() => {
            this.doQuickSearch()
          })
        }
      },
      advanceSearch(data, isSearchBtn) {
        if (this.loading || !this.showAdvancedSearch) {
          return
        }
        this.clearQueryByGroupName('quick')
        this.clearQueryByGroupName('advance')
        data &&
          data.forEach((d) => {
            const shouldPush =
              d.value != null && d.value != undefined && d.value != ''
            // 高级搜索中支持一个搜索框中关联多个属性进行搜索
            if (d.prop.indexOf(',') > 0) {
              const propAry = utils.stringSplit(d.prop, ',')
              if (propAry && propAry.length > 0) {
                const groupName = `group_${propAry[0]}`
                this.clearQueryByGroupName(groupName)
                shouldPush &&
                  propAry.forEach((p) => {
                    this.querys.push({
                      property: p,
                      value: d.value,
                      group: groupName,
                      relation: 'OR',
                      operation: d.operation,
                    })
                  })
              }
            } else {
              shouldPush &&
                this.querys.push({
                  property: d.prop,
                  value: d.value,
                  group: 'advance',
                  relation: d.relation,
                  operation: d.operation,
                })
            }
          })
        this.load('', isSearchBtn)
      },
      // 加载数据
      load(doNotResetPage, isSearchBtn) {
        this.loading = true
        // 默认重置页码为第一页
        if (!doNotResetPage) {
          this.pagination.page = 1
        }
        let param = {
          pageBean: this.pagination,
          sorter: [],
        }

        if (this.sorter && this.sorter.length > 0) {
          param.sorter = this.sorter
        }
        // 处理默认排序字段。只有当用户没有选择排序字段才使用默认排序
        if (this.defaultSorter.length > 0 && param.sorter.length == 0) {
          param.sorter = [...this.defaultSorter]
        }
        // 处理过滤条件
        this.handleFilters()

        if (this.querys && this.querys.length > 0) {
          param.querys = this.querys
        }

        // 处理查询条件
        if (this.calDefaultQuerys.length > 0) {
          if (!param.querys) {
            param.querys = []
          }
          this.calDefaultQuerys.forEach((item) => {
            param.querys.remove(item)
          })
          param.querys = param.querys.concat(this.calDefaultQuerys)
        }

        const me = this
        // 防止外部没有回调，设置10秒后自动取消加载中的状态
        let waitTime = 10000
        if (!this._events || !this._events.load || !this._events.load.length) {
          // 如果没有绑定在当前组件里的load事件，即组件仅仅作展示数据用 直接取消loading
          waitTime = 0
        }
        const finalTickCB = setTimeout(function () {
          me.loading = false
          this.selection = []
        }, waitTime)

        if (this.nopagination) {
          param.pageBean = {}
        }
        const loadedHandler = () => {
          // 外部已经回调的情况下，取消倒计时
          clearTimeout(finalTickCB)
          me.loading = false
          this.selection = []
          setTimeout(() => {
            me.$refs.quickSearch &&
              me.$refs.quickSearch.$children[0].$el.children[0].focus()
          })
        }

        this.$emit('load', { ...param }, loadedHandler, isSearchBtn)
        this.$emit('loading', { ...param }, loadedHandler, isSearchBtn)
      },
      // 通过列属性获取列标签
      getColumnLabelByProp(prop) {
        let label = null
        if (!prop) {
          return label
        }
        this.columns.forEach((c) => {
          if (c.prop && c.prop === prop) {
            label = c.label
          }
        })
        return label
      },
      // 构建快速搜索配置项
      generateQuickSearchConfig() {
        let labelAry = []
        if (typeof this.quickSearchProps == 'string') {
          const props = utils.stringSplit(this.quickSearchProps, ',')
          this.quickSearchConfig = []
          props.forEach((prop) => {
            const label = this.getColumnLabelByProp(prop)
            if (label) {
              labelAry.push(label)
              this.quickSearchConfig.push({ prop, label })
            }
          })
        }
        if (typeof this.quickSearchProps == 'object') {
          this.quickSearchProps.forEach((prop) => {
            if (prop && prop.label) {
              labelAry.push(prop.label)
            }
          })
          this.quickSearchConfig = [...this.quickSearchProps]
        }
        this.quickSearchPlaceholder = `${this.t(
          'ht.common.enter'
        )}${labelAry.join(',')}${this.t('ht.common.toSearch')}`
      },
      // 通过分组名称清除对应查询条件
      clearQueryByGroupName(groupName) {
        // 待删除的查询条件
        let toDelete = []
        this.querys &&
          this.querys.forEach((query) => {
            if (query.group == groupName) {
              toDelete.push(query)
            }
          })
        toDelete.forEach((d) => {
          this.querys.remove(d)
        })
      },
      handleFilters() {
        this.clearQueryByGroupName('filter')
        // 将过滤条件添加查询参数数组中
        if (this.filters && Object.keys(this.filters).length > 0) {
          Object.keys(this.filters).forEach((k) => {
            const filter = this.filters[k]
            let query = {
              property: k,
              value: filter[0],
              group: 'filter',
              relation: 'AND',
            }
            if (filter.length == 1) {
              query.operation = 'EQUAL'
              this.querys.push(query)
            } else if (filter.length > 1) {
              query.operation = 'IN'
              query.value = filter
              this.querys.push(query)
            }
          })
        }
      },
      handleSizeChange(pageSize) {
        this.pagination = { ...this.pagination, pageSize }
        this.$emit('size-change', pageSize)
        this.load()
      },
      handleCurrentChange(page) {
        this.pagination = { ...this.pagination, page }
        // 翻页时不重置页码
        this.$emit('current-change', page)
        this.load(true)
      },
      handleRowClick(row, column, event) {
        if (this.rowClickSelect) {
          if (this.selection.some((s) => s === row)) {
            this.selection.remove(row)
          } else {
            this.selection.push(row)
          }
          this.$refs.htTable.toggleRowSelection(row)
        }
        this.$emit('row-click', row, column, event)
      },
      handleTableSelect(selection, row) {
        this.selection = selection
        if (row) {
          this.$emit('select', selection, row)
        } else {
          this.$emit('select-all', selection)
        }
      },
      handleSortChange(column) {
        if (!column.order) {
          this.sorter = null
        } else {
          this.sorter = [
            {
              property: column.prop,
              direction: column.order == 'ascending' ? 'ASC' : 'DESC',
            },
          ]
        }
        this.load(true)
        this.$emit('sort-change', column)
      },
      handleFilterChange(m) {
        this.filters = { ...this.filters, ...m }
        Object.keys(this.filters).forEach((k) => {
          if (!this.filters[k] || this.filters[k].length == 0) {
            delete this.filters[k]
          }
        })
        this.load()
        this.$emit('filter-change', m)
      },
      doLayout() {
        this.$nextTick(() => {
          this.$refs.htTable && this.$refs.htTable.doLayout()
        })
      },
      initTablePanelHeight() {
        this.tablePanelHeight = this.$refs.tablePanel.$el.clientHeight
      },
      calcTableHeight(delay) {
        if (this.customTableMaxHeight) return
        // 动态计算表格的高度，自适应当前容器
        setTimeout(() => {
          const toolbarPanelHeight =
            (this.$refs.toolbarPanel && this.$refs.toolbarPanel.clientHeight) ||
            0

          const searchPanelHeight =
            (this.$refs.searchPanel && this.$refs.searchPanel.clientHeight) || 0

          const toolbarContainerHeight =
            (this.$refs.toolbarContainer &&
              this.$refs.toolbarContainer.clientHeight) ||
            0

          const paginationPanelHeight =
            (this.$refs.paginationPanel &&
              this.$refs.paginationPanel.clientHeight) ||
            0
          // 下外边距
          const searchPanelBottom = searchPanelHeight > 0 ? 18 : 0
          const toolbarPanelBottom = toolbarPanelHeight > 0 ? 6 : 0
          const toolbarContainerBottom = toolbarContainerHeight > 0 ? 6 : 0

          // 表格之外的高度
          const tableOuterHeight =
            toolbarPanelHeight +
            toolbarPanelBottom +
            searchPanelHeight +
            searchPanelBottom +
            toolbarContainerHeight +
            toolbarContainerBottom +
            paginationPanelHeight
          if (this.customTableHeightNum) {
            this.tableMaxHeight = this.customTableHeightNum - tableOuterHeight
          } else {
            if (!this.$refs.tablePanel) {
              return
            }
            if (this.tablePanelHeight == 0) {
              this.initTablePanelHeight()
            }
            const tableHeight = this.tablePanelHeight - tableOuterHeight
            this.tableMaxHeight = tableHeight
          }
        }, delay || 0)
      },
      addResizeListener() {
        //监听表头高度变化，如果
        this.$nextTick(() => {
          let erd = elementResizeDetectorMaker()
          this.$refs.htTable &&
            this.$refs.htTable.$refs.headerWrapper &&
            erd.listenTo(
              this.$refs.htTable.$refs.headerWrapper.getElementsByTagName(
                'tr'
              )[0],
              this.doLayout
            )
        })
      },
    },
  }
</script>
<style lang="scss" scoped>
  .ht-table-panel {
    padding: 0px;
    height: 100%;
    //overflow: hidden;

    .toolbar-panel,
    .toolbar-container {
      margin-bottom: 8px;
      box-sizing: border-box;
    }

    .search-panel {
      background-color: #f9f9f9;
      padding: 16px 16px 10px 16px;
      margin-bottom: 16px;
      box-sizing: border-box;
    }
  }

  .ht-table {
    width: 100%;
    //min-height: 500px;
  }
  .no-data-table {
    ::v-deep .el-table__body-wrapper {
      height: 100%;
      .el-table__empty-text {
        line-height: unset;
      }
      .no-data-text {
        margin: 8px 0;
        line-height: 20px;
        font-size: 14px;
      }
    }
  }
  .ht-card {
    .el-table__empty-block {
      height: 100%;
    }
  }
  .toolbar-panel__search {
    display: flex;
    justify-content: space-between;
  }

  .search-container__col {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-align: center;
    -ms-flex-align: center;
    flex-direction: row;
    align-items: center;
  }

  .ht-quick__search {
    margin-bottom: 8px;
    max-height: 32px;
  }

  .quick-search {
    margin-right: 20px;
  }

  .quick-search + .el-divider {
    margin-right: 20px;
  }

  ::v-deep .el-input__inner,
  ::v-deep .el-input-group__append {
    border-radius: 0;
  }

  .common-tools {
    display: flex;
    justify-content: flex-end;

    .el-button-group {
      margin: 0 0 0 16px;
    }

    .el-button {
      padding: 6px;
      border-radius: 0;
    }
    ::v-deep.el-button.refresh-btn-icon {
      i {
        font-size: 16px;
      }
    }
    .advance-search__button {
      padding: 6px 12px;
    }
  }

  ::v-deep .ht-table .sort-caret.descending {
    bottom: 0px;
  }

  ::v-deep .ht-table .sort-caret.ascending {
    top: -2px;
  }

  ::v-deep .ht-table .caret-wrapper {
    height: 20px;
  }

  ::v-deep .ht-table .el-table__column-filter-trigger {
    line-height: 20px;
  }

  .pagination-panel {
    padding: 10px 0;
  }

  .multiview-switcher {
    width: 59px;
    height: 32px;
    overflow: hidden;
  }

  .ht-card {
    @include base-scrollbar;
    overflow: auto;

    .ht-card__container {
      &::after {
        content: '';
        display: block;
        clear: both;
      }

      .el-card {
        cursor: pointer;
        float: left;
        margin: 8px;

        ::v-deep .el-card__body {
          padding: 16px;
        }
      }
    }
  }

  .page-sizes__hidden {
    ::v-deep .el-pagination__sizes {
      display: none;
    }
  }

  ::v-deep .gantt_grid_scale .gantt_grid_head_cell {
    color: #262626 !important;
    font-weight: 600 !important;
  }
  ::v-deep .gantt_grid_data .gantt_row.gantt_selected,
  .gantt_grid_data .gantt_row.odd.gantt_selected,
  .gantt_task_row.gantt_selected {
    background: #f5f7fa !important;
  }
  ::v-deep .gantt_task_line {
    background: #409eff !important;
    border-radius: 4px !important;
    border: 1px solid #409eff !important;
  }
  ::v-deep .gantt_line_wrapper div {
    background: #40cbff !important;
  }
  ::v-deep .gantt_link_arrow_right {
    border-left-color: #40cbff !important;
  }
  ::v-deep .gantt_task_link:hover .gantt_line_wrapper div {
    box-shadow: 0px 0px 0px 0px #40cbff;
  }
  //::v-deep .gantt_tooltip {
  //  color: yellow !important;
  //}
  ::v-deep .gantt_cal_light,
  .gantt_cal_quick_info,
  .gantt_container,
  .gantt_message_area,
  .gantt_modal_box,
  .gantt_tooltip {
    font-size: 18px !important;
    color: black !important;
  }
  ::v-deep .gantt_grid_data .gantt_row:hover {
    background: #f5f7fa;
  }
  ::v-deep .gantt_task_row.gantt_selected .gantt_task_cell {
    background: #f5f7fa;
    border: 1px solid #ebebeb;
  }
  ::v-deep .gantt_row,
  .gantt_task_row {
    width: 100% !important;
  }
  ::v-deep .gantt_row.odd,
  .gantt_task_row.odd {
    width: 100% !important;
  }
  ::v-deep .gantt_cal_light,
  .gantt_cal_quick_info,
  .gantt_container,
  .gantt_message_area,
  .gantt_modal_box,
  .gantt_tooltip {
    font-size: 18px !important;
  }
  ::v-deep .gantt_grid_data .gantt_cell {
    border-right: 1px solid #ebebeb;
  }
  ::v-deep .gantt_grid_scale .gantt_grid_head_cell {
    border-right: 1px solid #ebebeb;
    background: #f9f9f9;
  }
  ::v-deep .gantt_grid_scale,
  .gantt_task_scale {
    border-bottom: 1px solid #ebebeb;
  }
  .gantt_tooltip {
    font-size: 18px;
  }

  ::v-deep {
    .gantt_task_scale {
      background: #f9f9f9;
    }
  }
</style>
