实现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>

云胡不喜
73 声望11 粉丝

前端的忠实粉丝