乐趣区

关于vue.js:atreeselect-和-aselect的区别及使用

实现 select 的复选、全选、清空、搜寻等性能

<template>
  <a-spin :spinning="loading" tip="申请中...">
    <div class="workCurve">
      <x-card>
        <div slot="content" class="table-page-search-wrapper">
          <a-form layout="inline">
            <span class="search-form-left" style="width:100%">
              <a-row :gutter="0">
                <a-col :md="4" :sm="24">
                  <a-form-item label="">
                    <a-radio-group v-model="type" style="width:230px" @change="typeChange">
                      <a-radio value="0">
                        投产日期
                      </a-radio>
                      <a-radio value="1">
                        措施日期
                      </a-radio>
                    </a-radio-group>
                  </a-form-item>
                </a-col>
                <a-col :md="4" :sm="12" style="margin-left:20px">
                  <a-form-item label="拉齐数据">
                    <a-select
                      :maxTagCount="1"
                      mode="multiple"
                      style="width: 100%;min-width:240px"
                      placeholder="请抉择拉齐数据"
                      v-model="lqData"
                    >
                      <a-select-option v-for="(item, index) in lqOptions" :key="index" :value="item.value">{{item.name}}</a-select-option>
                    </a-select>
                  </a-form-item>
                </a-col>
                <a-col :md="4" :sm="24">
                  <a-form-item label="向前拉齐点数">
                    <a-input-number
                      :disabled="type ==='0'"v-model="beforeCount":precision="0"style="width: 100%;"
                    />
                  </a-form-item>
                </a-col>
                <a-col :md="4" :sm="24">
                  <a-form-item label="向前每段天数">
                    <a-input-number :disabled="type ==='0'"v-model="spanLenth":precision="0"style="width: 100%;" />
                  </a-form-item>
                </a-col>
                <a-col :md="4" :sm="24">
                  <a-form-item label="向后拉齐点数">
                    <a-input-number v-model="afterCount" :precision="0" style="width: 100%;" />
                  </a-form-item>
                </a-col>
                <a-col :md="4" :sm="24">
                  <a-form-item label="向后每段天数">
                    <a-input-number v-model="afterDaily" :precision="0" style="width: 100%;" />
                  </a-form-item>
                </a-col>
                <a-col :md="4" :sm="24">
                  <a-form-item>
                    <a-button type="primary" @click="handleQuery"
                      ><img style="width:12px;margin-right:4px" src="@/assets/search-icon.png" alt="" /> 查问 </a-button
                    >
                  </a-form-item>
                </a-col>
                <span class="table-page-search-submitButtons button-group-right">
                  <a-button type="primary" @click="visible = true"> 查看数据表 </a-button>
                </span>
              </a-row>
            </span>
          </a-form>
        </div>
      </x-card>
      <div>
        <a-row :gutter="[5, 5]" type="flex">
          <a-col :span="4" flex="240px">
            <QkTree
              ref="qkTree"
              :type="'well'"
              :disabledJh="type ==='0'? true : false"
              :multiple="false"
              :treeStyle="'height:calc(100vh - 227px)'"
              :checkable="false"
              @selectedNode="selectedNodeHandle"
            ></QkTree>
          </a-col>
          <a-col :span="15" flex="calc(100% - 240px - 340px - 10px)" style="width:calc(100% - 240px - 340px - 10px)">
            <a-card class="charts-contaniner">
              <div class="charts-box">
                <curve-chart ref="curveChart"></curve-chart>
              </div>
            </a-card>
          </a-col>
          <a-col :span="5" flex="340px">
            <a-card class="charts-contaniner">
              <div style="height: calc(100vh - 395px);overflow: auto;">
                <a-tree-select
                  v-if="false"
                  v-model="rightJh"
                  :maxTagCount="1"
                  @change="rightJhChange"
                  :dropdownStyle="{maxHeight:'300px', overflow:'auto'}"
                  style="width:100%;margin-bottom:10px"
                  :tree-data="rightTreeData"
                  tree-checkable
                  allowClear
                  :treeDefaultExpandAll="true"
                  :replaceFields="{children:'children', title:'jh', key:'jh', value:'jh'}"
                  placeholder="请输出井号前缀并抉择"
                >
                </a-tree-select>
                <a-select
                  style="width:100%;margin-bottom:10px"
                  class="select"
                  mode="multiple"
                  v-model="rightJh"
                  :maxTagCount="1"
                  placeholder="请输出井号前缀并抉择"
                  @change="rightJhChange"
                >
                  <div slot="dropdownRender" slot-scope="menu">
                    <div style="padding:4px; cursor: pointer;" @mousedown="e => e.preventDefault()">
                      <!-- 全选、重置 -->
                      {{checkAllLoading}}
                      <a-button
                        class="btn"
                        type="primary"
                        style="margin-right:10px"
                        @click="checkAllField"
                        :loading="checkAllLoading"
                      >
                        全选
                      </a-button>
                      <a-button class="btn" @click="resetRightJh"> 重置 </a-button>
                    </div>
                    <a-divider style="margin: 4px 0;" />
                    <VNodes :vnodes="menu" />
                  </div>
                  <a-select-option v-for="item in dataImport" :key="item.jh" :value="item.jh">
                    {{item.jh}}
                  </a-select-option>
                </a-select>
                <!-- :show-checked-strategy="SHOW_PARENT" -->
                <a-table
                  :loading="loadingImport"
                  :scroll="{y:'calc(100vh - 495px)'}"
                  :rowSelection="{
                    selectedRowKeys: selectedRowKeys,
                    onChange: onSelectChange,
                    fixed: true,
                    columnWidth: 50
                  }":columns="columnsImport":data-source="rightTableData"
                  bordered
                  size="small"
                  :pagination="false"
                  :rowKey="(record, index) => record.jh"
                >
                  <span slot="rqStr" slot-scope="text, record">
                    <a-input
                      :placeholder="''"@change="e => handleChange(e, record.rqStr, 'rqStr')"v-model="record.rqStr"
                    >
                    </a-input>
                  </span>
                </a-table>
              </div>
              <div style="width: 100%;text-align: center;">
                <a-button style="margin-top: 15px;" type="primary" @click="handleDownload"> 模板下载 </a-button><br />
                <a-upload
                  name="file"
                  :before-upload="beforeUpload"
                  :customRequest="handleUpload"
                  accept=".xls,.xlsx"
                  :showUploadList="false"
                >
                  <a-button type="primary" style="margin-top: 15px;"> <a-icon type="import" /> 导入 </a-button>
                </a-upload>
                <br />
                <a-button style="margin-top: 15px;" type="primary" @click="handleClear"> 清空 </a-button>
              </div>
            </a-card>
          </a-col>
        </a-row>
      </div>

      <a-modal
        :footer="null"
        v-model="visible"
        :width="1200"
        title="拉齐比照数据"
        :destroyOnClose="true"
        @cancel="cancelTableData"
        @ok="setTableData"
      >
        <a-table :columns="columns" size="small" :data-source="data" bordered>
          <div v-for="col in columns.map(it => it.dataIndex)" :key="col" :slot="col" slot-scope="text, record">
            <div>
              <a-input-number
                :min="-999999"
                :max="999999"
                v-if="record.editable"
                style="margin: -5px 0;width:100%"
                :value="text"
                @change="e => handleChange(e, record.key, col)"
              />
              <template v-else>
                {{text}}
              </template>
            </div>
          </div>
          <template slot="operation" slot-scope="text, record">
            <div class="editable-row-operations">
              <span v-if="record.editable">
                <a @click="() => save(record.key)"> 保留 </a>
                <a @click="() => cancel(record.key)" style="margin-left:15px"> 勾销 </a>
              </span>
              <span v-else>
                <a :disabled="editingKey !==''" @click="() => edit(record.key)"> 编辑 </a>
              </span>
            </div>
          </template>
        </a-table>
      </a-modal>
    </div>
  </a-spin>
</template>

<script>
import {XCard} from '@/components'
import {handleXlsRes} from '@/utils/exportXls.js'
import CurveChart from '../components/CurveChart.vue'

import QkTree from '@/components/QkTree/index.vue'
import _ from 'lodash'
import {
  curveApi,
  importApi,
  getTcrqJhListApi,
  getImportTemplateApi
} from '@/api/modular/main/prodIndicator/compair.js'
export default {
  components: {
    XCard,
    QkTree,
    CurveChart,
    VNodes: {
      functional: true,
      render: (h, ctx) => ctx.props.vnodes
    }
  },
  data() {
    return {
      checkAllLoading: false,
      selectedRowKeys: [],
      selectedRows: [],
      lqOptions: [
        // 总井数、开井数、日产液量、日产油量、含水、动液面、阶段累计产液、阶段累计产油
        {name: '总井数', value: 'zjs'},
        {name: '开井数', value: 'kjs'},
        {name: '日产液量', value: 'rcyel'},
        {name: '日产油量', value: 'rcyl'},
        {name: '含水', value: 'hsb'},
        {name: '动液面', value: 'dym'},
        {name: '阶段累计产液', value: 'ljcyel'},
        {name: '阶段累计产油', value: 'ljcyl'}
      ],
      lqData: ['zjs', 'kjs', 'rcyel', 'rcyl', 'hsb', 'dym', 'ljcyel', 'ljcyl'],
      loading: false,
      mode: ['month', 'month'],
      month: [],
      queryParam: {},
      columns: [
        {
          title: '阶段号',
          dataIndex: 'stage',
          scopedSlots: {customRender: 'stage'}
        },
        {
          title: '总井数',
          dataIndex: 'zjs',
          scopedSlots: {customRender: 'zjs'}
        },
        {
          title: '开井数',
          dataIndex: 'kjs',
          scopedSlots: {customRender: 'kjs'}
        },
        {
          title: '日产液量',
          dataIndex: 'rcyel',
          scopedSlots: {customRender: 'rcyel'}
        },
        {
          title: '日产油量',
          dataIndex: 'rcyl',
          scopedSlots: {customRender: 'rcyl'}
        },
        {title: '动液面 (m)',
          dataIndex: 'dym',
          scopedSlots: {customRender: 'dym'}
        },
        {title: '含水 (%)',
          dataIndex: 'hsb',
          scopedSlots: {customRender: 'hsb'}
        },
        {
          title: '阶段累计产液',
          dataIndex: 'ljcyel',
          scopedSlots: {customRender: 'ljcyel'}
        },
        {
          title: '阶段累计产油',
          dataIndex: 'ljcyl',
          scopedSlots: {customRender: 'ljcyl'}
        }
      ],
      wellOptions: [],
      visible: false,
      editingKey: '',
      data: [],
      cacheData: [],

      renderData: {xdata: [],
        data: []},
      chartsYName: ['总井 \n 数 ( 口)',
        '开井 \n 数 (口)',
        '日产 \n 液 (t)',
        '日产 \n 油 (t)',
        '含水 \n(%)',
        '动液 \n 面 (m)',
        '阶段累计产液',
        '阶段累计产油'
      ], //'开井 \n 数 (口)',
      chartsName: [
        {
          name: '总井数',
          index: 0,
          color: '#4b5cc4',
          type: 'line',
          key: 'zjs'
        },
        {
          name: '开井数',
          index: 1,
          color: '#0c8918',
          type: 'line',
          key: 'kjs'
        },
        {
          name: '日产液',
          index: 2,
          color: '#ff2aff',
          type: 'line',
          key: 'rcyel'
        },
        {
          name: '日产油',
          index: 3,
          color: 'red',
          type: 'line',
          key: 'rcyl'
        },
        {
          name: '含水',
          index: 4,
          color: '#6fff6f',
          type: 'line',
          key: 'hsb'
        },
        {
          name: '动液面',
          index: 5,
          color: '#ffe16b',
          type: 'line',
          key: 'dym'
        },
        {
          name: '阶段累计产液',
          index: 6,
          color: '#f05654',
          type: 'line',
          key: 'ljcyel'
        },
        {
          name: '阶段累计产油',
          index: 7,
          color: '#c9dd22',
          type: 'line',
          key: 'ljcyl'
        }
      ],
      miningStatusData: {},
      devHistory: '',
      maxmonth: 100,
      tabPosition: 'jzzjg',
      sliderValue: [0, 0],
      btnLabel: '锁定距离',
      isLock: false,
      intervalDate: 0,
      monthDate: [],
      columnsImport: [
        {
          title: '井号',
          dataIndex: 'jh',
          align: 'center'
        },
        {
          title: '日期',
          dataIndex: 'rqStr',
          align: 'center',
          width: 140,
          scopedSlots: {customRender: 'rqStr'}
        }
      ],
      tcJhList: [],
      rightJh: [],
      rightTableData: [],
      dataImport: [],
      spanLenth: 1,
      beforeCount: 1,
      afterCount: 1,
      afterDaily: 1,
      type: '0',
      loadingImport: false,
      selectedQk: {},
      selectedCw: {}}
  },
  computed: {jhList() {if (this.selectedQk.title && this.selectedQk.qkdm) {if (this.type === '1') {
          this.loadingImport = true
          // 措施日期,jh 取值为左侧树; 投产日期, 井号 list 数据为接口返回
          let jhArr = _.map(this.selectedQk.children, 'jh')
          let tableData = []
          jhArr.filter(item => {if (!!item) {tableData.push({ jh: item})
            }
            return !!item
          })
          this.loadingImport = false
          return tableData
        }
      } else {if (this.type === '1') {this.$message.warning('请抉择区块')
        }
      }
      return []},
    queryData() {
      return {
        beforeCount: this.beforeCount,
        beforeDaily: this.beforeDaily,
        afterCount: this.afterCount,
        afterDaily: this.afterDaily,
        wellList: this.selectedRows
      }
    },
    selectedQkInfo() {let arr = [this.selectedQk]
      return {zyqdm: arr && arr[0] ? arr[0].zyqdm : null,
        qkdm: arr && arr[0] ? arr[0].qkdm : null,
        cyddm: arr && arr[0] ? arr[0].cyddm : null
      }
    },
    rightTreeData() {let arr = []
      if (this.dataImport?.length) {arr = [{ jh: '全选', children: this.dataImport}]
      }
      return arr
    }
  },
  methods: {resetRightJh() {this.rightJh = []
      this.rightJhChange(this.rightJh)
    },
    checkAllField() {
      this.checkAllLoading = true
      let jhArr = []
      this.dataImport.forEach(item => {jhArr.push(item.jh)
      })
      this.rightJh = jhArr
      this.rightJhChange(this.rightJh)
    },
    rightJhChange(val) {console.log(this.checkAllLoading)
      // console.log(22, val)
      let arr = []
      let arr2 = []
      this.dataImport.forEach(iitem => {
        let obj = val.find(valItem => {return iitem.jh === valItem})
        if (!obj) {arr.push(iitem)
        } else {arr2.push(iitem)
        }
      })
      this.rightTableData = arr2.concat([])
      this.defaultCheckedAll(arr2) // 选中以后下拉井号
      if (this.checkAllLoading) {// setTimeout(() => {
        //   this.checkAllLoading = false
        // }, 1000)
      }
    },
    filterOption(input, option) {return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
    },
    typeChange(val) {this.dataImport = []
      // 类型变更,表格选中项重置
      this.selectedRowKeys = []
      this.selectedRows = []
      if (this.type === '0') {
        this.beforeCount = null
        this.beforeDaily = null
        this.getTcJhList() // 切换时, 从新申请} else {
        this.beforeCount = 1
        this.beforeDaily = 1
        this.dataImport = this.jhList
        this.rightTableData = []
        this.defaultCheckedAll([])
      }
      // 重置选中数据
      this.rightTableData = []
      this.defaultCheckedAll([])
      // 重置曲线
      this.setCurveData([])
      this.data = []},
    onSelectChange(selectedRowKeys, selectedRows) {
      this.selectedRowKeys = selectedRowKeys
      this.selectedRows = selectedRows
      this.rightJh = this.selectedRowKeys // 表格抉择内容变更同步批改 a -tree-select 项
    },
    getTcJhList() {if (!this.selectedQk.title) {this.tcJhList = []
        this.dataImport = []
        this.defaultCheckedAll([])
        return
      }
      // 获取投产日期下所有井号
      let params = Object.assign({}, this.queryData, this.selectedQkInfo)
      // 点击 作业区 和采油队时 提醒用户点击 请抉择区块。if (!params.qkdm) {this.$message.warning('请抉择区块')
        return
      }
      this.loadingImport = true
      getTcrqJhListApi(params)
        .then(res => {
          this.loadingImport = false
          if (res.data) {
            this.tcJhList = res.data
            this.rightJh = []
            this.dataImport = this.tcJhList
            this.rightTableData = []
            this.defaultCheckedAll([])
          } else {this.$message.warning(res.message)
          }
        })
        .catch(() => {this.loadingImport = false})
    },
    defaultCheckedAll(arr) {let indArr = []
      arr.forEach(item => {indArr.push(item.jh)
      })
      // 默认选中全副
      this.onSelectChange(indArr, arr)
    },
    selectedNodeHandle(value) {
      this.selectedQk = value
      if (this.type === '0') {this.getTcJhList()
      } else {
        this.dataImport = this.jhList
        this.rightTableData = []
        this.defaultCheckedAll([])
      }
    },
    // 用表格编辑后的数据从新绘制曲线
    setTableData() {
      this.visible = false
      this.setCurveData(this.data)
    },
    cancelTableData() {
      this.visible = false
      this.cancel(this.editingKey)
    },
    handleChange(value, key, column) {const newData = [...this.dataImport]
      const target = newData.find(item => key === item.key)
      if (target) {target[column] = value
        this.dataImport = newData
      }
    },
    edit(key) {const newData = [...this.data]
      const target = newData.find(item => key === item.key)
      this.editingKey = key
      if (target) {
        target.editable = true
        this.data = newData
      }
    },
    save(key) {const newData = [...this.data]
      const newCacheData = [...this.cacheData]
      const target = newData.find(item => key === item.key)
      const targetCache = newCacheData.find(item => key === item.key)
      if (target && targetCache) {
        delete target.editable
        this.data = newData
        Object.assign(targetCache, target)
        this.cacheData = newCacheData
      }
      this.editingKey = ''
    },
    cancel(key) {const newData = [...this.data]
      const target = newData.find(item => key === item.key)
      this.editingKey = ''
      if (target) {
        Object.assign(
          target,
          this.cacheData.find(item => key === item.key)
        )
        delete target.editable
        this.data = newData
      }
    },
    getCurveData() {let params = Object.assign({}, this.queryData, {})
      if (this.type === '0') {
        params.beforeCount = null
        params.beforeDaily = null
        //  向前拉齐点数:禁用,并且不传参置为 null
        // 向前拉齐每段天数:禁用,并且不传参置为 null
      }
      let _this = this
      _this.loading = true
      curveApi(params)
        .then(res => {if (res.code != 200) {this.$message.warning(res.message)
            _this.setCurveData([])
            _this.data = []
            return
          }
          if (res.success && res.data.length > 0) {
            _this.data = res.data
            for (var m = 0; m < _this.data.length; m++) {_this.data[m]['key'] = m.toString()}
            _this.cacheData = _this.data.map(item => ({ ...item}))
            _this.miningStatusData = res.data[0]
            _this.setCurveData(res.data)
          } else {_this.setCurveData([])
            _this.data = []}

          _this.loading = false
        })
        .finally(err => {_this.loading = false})
    },
    setCurveData(data) {let chartsNameData = []
      this.renderData = {xdata: [],
        data: [],
        chartsYName: []}
      let showCurveData = this.lqData
      let chartsNameShow = []
      let chartsYNameShow = []
      showCurveData.forEach((currentItem, index) => {
        let obj = this.chartsName.find(item => {return item.key === currentItem})
        if (obj) {
          obj.index = index
          let name = obj.name.length > 3 ? obj.name.slice(0, 3) + '\n' + obj.name.slice(3) : obj.name
          chartsYNameShow.push(name)
          chartsNameShow.push(obj)
        }
      })
      chartsNameData = chartsNameShow
      this.renderData.chartsYName = chartsYNameShow || this.chartsYName
      for (var i = 0; i < data.length; i++) {this.renderData.xdata.push('阶段' + data[i].stage)
      }
      for (var n = 0; n < chartsNameData.length; n++) {
        let obj = {name: chartsNameData[n].name,
          index: chartsNameData[n].index,
          color: chartsNameData[n].color,
          type: chartsNameData[n].type,
          data: []}
        for (var i = 0; i < data.length; i++) {let key = chartsNameData[n].key
          obj.data.push(data[i][key] ? data[i][key] - 0 : 0)
        }
        this.renderData.data.push(obj)
      }
      this.$refs.curveChart.setData(this.renderData)
    },
    handleQuery() {if (!this.afterCount) {return this.$message.warning('请输出向后拉齐点数')
      }
      if (!this.afterDaily) {return this.$message.warning('请输出向后每段天数')
      }
      if (!this.selectedRows.length) {return this.$message.warning('井号不能为空')
      }
      let flag = true
      if (this.selectedRows) {
        this.selectedRows.forEach(item => {if (!item.rqStr) {flag = false}
        })
      }
      if (!flag) {this.$message.warning('所选井号日期不能为空')
        return
      }
      this.getCurveData()},
    // 模板下载
    handleDownload() {getImportTemplateApi().then(res => {// handleXlsRes(res)
        const dataJson = res.data
        const aLink = document.createElement('a')
        const blob = new Blob([dataJson], {type: 'application/force-download; charset=UTF-8'})
        aLink.href = URL.createObjectURL(blob)
        aLink.setAttribute('download', '拉齐比照模板.xls') // 设置下载文件名称
        aLink.click()})
    },
    // 导入
    beforeUpload(file) {const extension = file.name.substring(file.name.lastIndexOf('.') + 1)
      if (extension !== 'xlsx' && extension !== 'xls') {this.$message.error('只能上传 excel 文件')
        return false
      }
      const isLt10M = file.size / 1024 / 1024 < 10
      if (!isLt10M) {this.$message.error('大小不能超过 10MB!')
        return false
      }
      return extension && isLt10M
    },
    handleUpload(file) {
      const _this = this
      const formData = new FormData()
      formData.append('file', file.file)
      importApi(formData)
        .then(response => {if (Object.prototype.toString.call(response.data) === '[object Blob]') {
            // 先判断是不是 blob 格局
            if (response.data.type.includes('application/json')) {// 判断是不是非凡状况 (json)
              const reader = new FileReader()
              reader.onload = function() {
                const res = reader.result
                const result = JSON.parse(res) // blob 格局转成 json
                if (result.code === 200) {
                  // 导出超出限度
                  _this.$message.success('导入胜利')
                  _this.dataImport = result.data
                  _this.rightTableData = []
                  _this.defaultCheckedAll([])
                } else {_this.$message.error(result.message)
                }
              }
              reader.readAsText(response.data)
            } else {
              // 导入格局谬误
              handleXlsRes(response)
            }
          }
        })
        .catch(e => {
          // 接管异样 并提醒
          _this.$message.error(e.message)
        })
    },
    handleClear() {this.dataImport = []
      this.rightTableData = []
      this.defaultCheckedAll([])
    }
  },
  created() {}
}
</script>
<style lang="less" scoped>
.charts-contaniner {
  overflow: auto;

  ul,
  li {
    margin: 0;
    padding: 0;
    list-style-type: none;
  }

  .charts-box {
    width: 100%;
    height: calc(100vh - 253px);
    overflow: hidden;
  }
}

.cardContent {
  min-height: 200px;

  p {
    margin-bottom: 6px;
    color: #1890ff;
  }
}

.workCurve {
  /deep/ .ant-card-body {padding: 12px;}

  /deep/ .ant-form-item {margin-bottom: 6px;}

  /deep/ .ant-modal-body {padding: 12px;}
}

.btnBoxRight {
  padding-top: 12px;
  text-align: right;

  button {margin: 0;}
}

.bottomTabs {
  background-color: #fff;
  padding-top: 8px;

  /deep/ .ant-radio-button-wrapper {
    width: 50%;
    text-align: center;
  }
}

/deep/.ant-table-small > .ant-table-content > .ant-table-body {margin: 0 !important;}
</style>
退出移动版