Skip to content

ui 组件库

datav

移动端滚动动画 better-scroll 参考 https://www.bilibili.com/video/BV1LV411z72g?p=118 2:00

无感刷新 token

ts
// 记录当前是否正在刷新 token
let is401 = false
// 创建一个新的请求模块避免死循环
const requestToken = axios.create()

export const instance = axios.create({
  timeout: 4000
})

function gotoLogin() {
  // 代码能走到这里说明本地要么没有存储 refresh_token 或者调用换 token 接口出错
  // 此处书写跳转登录页重新登录的逻辑
}

//配置响应拦截器
instance.interceptors.response.use(
  response => {
    if (response?.data?.code === 500) {
      message.error(response?.data?.message || '系统异常')
      return Promise.reject(response?.data)
    } else {
      // 当请求成功时重置状态
      is401 = false
      return response?.data
    }
  },
  async error => {
    if (error.response?.status === 401) {
      // 无感刷新token
      const refresh_token = localStorage.getItem('refresh_token')
      if (!refresh_token) return gotoLogin()
      // 请求新的 token
        const res = await requestToken({
          url: 'refresh_token',
          params: { refresh_token }
        }).catch(() => {
          gotoLogin()
        })
        if (res?.data?.code !== 200) return gotoLogin()
        return instance(error.config)
    }
    return Promise.reject(error)
  }
)

上传 exsl 整个文件请求方式

vue
<template>
  <el-dialog
    custom-class="uploader-dialog"
    width="25%"
    :title="title"
    :visible.sync="visible"
    :append-to-body="true"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    :before-close="beforeClose"
  >
    <el-upload
      ref="upload"
      class="upload-demo"
      :before-upload="beforeUpload"
      accept=".xlsx, .xls"
      drag
      action="http://10.126.18.85:8083/enterprise/importInvestOrgExcel"
      :on-error="uploadFail"
      :limit="1"
      :multiple="false"
      :auto-upload="false"
      :http-request="myUpload"
    >
      <img
        class="el-icon-upload"
        src="../../../static/images/container.png"
        alt=""
      />
      <div class="el-upload__text">点击或将文件拖拽到这里上传</div>
      <div class="el-upload__tip">
        导入文件不能超过20M,仅允许导入.xls或.xlsx格式文件 !
      </div>
    </el-upload>
    <span slot="footer" class="dialog-footer">
      <el-button size="small" @click="buttonLoading ? '' : (visible = false)"
        >取 消</el-button
      >
      <el-button
        size="small"
        type="primary"
        :loading="buttonLoading"
        @click="submit"
        >确 定</el-button
      >
    </span>
  </el-dialog>
</template>
<script>
// 导入解析 excel  表格插件
// import XLSX from 'xlsx'
export default {
  props: {
    title: {
      type: String,
      default: '覆盖导入数据'
    },
    // 判断是否是上传组织树信息
    isExportTree: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      visible: false,
      buttonLoading: false,
      file: ''
    }
  },
  methods: {
    beforeUpload(file) {
      this.file = file
      if (file) {
        this.buttonLoading = true
      }
      if (
        file.name.split('.')[1].includes('xls' || 'xlsx') &&
        file.size < 20 * 1024 * 1024
      ) {
      } else {
        this.$message('请上传符合要求的文件!')
        this.buttonLoading = false
        return false
      }
    },
    myUpload() {
      let param = new FormData()
      param.append('file', this.file)
      // 上传企业基本信息数据
      if (!this.isExportTree) {
        // console.log('上传企业基本信息数据')
        this.$axios
          .post(`/api/enterprise/batchUpateByExcel`, param, {
            headers: { 'Content-Type': 'multipart/form-data' }
          })
          .then(res => {
            if (res.data.success) {
              this.$message.success('上传成功!')
            } else {
              this.$message.error(res.data.message)
            }
            console.log(res.data)
          })
      } else {
        // 上传组织树信息
        // console.log('上传组织树信息')
        this.$axios
          .post(`/api/enterprise/importInvestOrgExcel`, param, {
            headers: { 'Content-Type': 'multipart/form-data' }
          })
          .then(res => {
            if (res.data.success) {
              this.$message.success('上传成功!')
            } else {
              this.$message.error(res.data.message)
            }
            console.log(res.data)
          })
      }
    },
    // 上传 exsl 数据
    submit() {
      this.$refs.upload.submit()
    },
    uploadFail() {
      this.$message('上传失败')
      this.buttonLoading = false
    },
    beforeClose(done) {
      this.buttonLoading ? '' : (this.visible = false)
    }
    // 获取读取到的 exsl 表格数据,header 表示所有表头数据,results 表示每一行的数据
    // generateData({ header, results }) {
    // this.excelData.header = header
    // this.excelData.results = results
    // this.onSuccess && this.onSuccess(this.excelData)
    // this.$nextTick(() => {
    //   this.$axios
    //     .post(`/api/enterprise/importInvestOrgExcel`, this.blob, {
    //       // responseType: 'blob'
    //     })
    //     .then(res => {
    //       console.log(res)
    //     })
    //   console.log(this.blob)
    // })
    // },
    // 读取 exsl
    // readerData(rawFile) {
    //   this.loading = true
    //   return new Promise((resolve, reject) => {
    //     const reader = new FileReader()
    //     reader.onload = e => {
    //       const data = e.target.result
    //       const workbook = XLSX.read(data, { type: 'array' })
    //       const firstSheetName = workbook.SheetNames[0]
    //       const worksheet = workbook.Sheets[firstSheetName]
    //       const header = this.getHeaderRow(worksheet)
    //       const results = XLSX.utils.sheet_to_json(worksheet)
    //       this.generateData({ header, results })
    //       this.loading = false
    //       resolve()
    //       this.blob = data
    //       // console.log(data)
    //       // this.$axios
    //       //   .post(`/api/enterprise/importInvestOrgExcel`, data, {
    //       //     // responseType: 'blob'
    //       //   })
    //       //   .then(res => {
    //       //     console.log(res)
    //       //   })
    //     }
    //     reader.readAsArrayBuffer(rawFile)
    //   })
    // },
    // 设置表头数据
    // getHeaderRow(sheet) {
    //   const headers = []
    //   const range = XLSX.utils.decode_range(sheet['!ref'])
    //   let C
    //   const R = range.s.r
    //   /* start in the first row */
    //   for (C = range.s.c; C <= range.e.c; ++C) {
    //     /* walk every column in the range */
    //     const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
    //     /* find the cell in the first row */
    //     let hdr = 'UNKNOWN ' + C // <-- replace with your desired default
    //     if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
    //     headers.push(hdr)
    //   }
    //   return headers
    // }
  }
}
</script>
<style lang="less" scoped>
.uploader-dialog {
  .upload-demo {
    text-align: center;
    /deep/.el-upload {
      width: 100%;
    }
    /deep/.el-upload-dragger {
      width: 100%;
      background: rgba(0, 0, 0, 0.03);
    }
    .el-upload__tip {
      color: rgba(0, 0, 0, 0.45);
    }
  }
}
</style>
  • 在其他组件中使用上传组件
vue
<Uploader ref="uploader" />
<script>
// 点击批量导入
    showDialog() {
      this.$refs.uploader.visible = true
    },
</script>

导出 excel 和导入

js
// 导出
handleExportXls(fileName) {
    if (!fileName || typeof fileName != 'string') {
      fileName = '导出文件'
    }
    let param = { ...this.queryParam }
    if (this.selectedRowKeys && this.selectedRowKeys.length > 0) {
      param['selections'] = this.selectedRowKeys.join(',')
    }
    downFile(this.url.exportXlsUrl, param).then((data) => {
      if (!data) {
        this.$message.warning('文件下载失败')
        return
      }
      if (typeof window.navigator.msSaveBlob !== 'undefined') {
        window.navigator.msSaveBlob(new Blob([data], { type: 'application/vnd.ms-excel' }), fileName + '.xls')
      } else {
        let url = window.URL.createObjectURL(new Blob([data], { type: 'application/vnd.ms-excel' }))
        let link = document.createElement('a')
        link.style.display = 'none'
        link.href = url
        link.setAttribute('download', fileName + '.xls')
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link) //下载完成移除元素
        window.URL.revokeObjectURL(url) //释放掉blob对象
      }
    })
  },
  /* 导入 */
  handleImportExcel(info) {
    if (info.file.status !== 'uploading') {
      console.log(info.file, info.fileList)
    }
    if (info.file.status === 'done') {
      if (info.file.response.success) {
        // this.$message.success(`${info.file.name} 文件上传成功`);
        if (info.file.response.code === 201) {
          let {
            message,
            result: { msg, fileUrl, fileName },
          } = info.file.response
          let href = window._CONFIG['domianURL'] + fileUrl
          this.$warning({
            title: message,
            content: (
              <div>
                <span>{msg}</span>
                <br />
                <span>
                  具体详情请{' '}
                  <a href={href} target="_blank" download={fileName}>
                    点击下载
                  </a>{' '}
                </span>
              </div>
            ),
          })
        } else {
          this.$message.success(info.file.response.message || `${info.file.name} 文件上传成功`)
        }
        this.loadData()
      } else {
        this.$message.error(`${info.file.name} ${info.file.response.message}.`)
      }
    } else if (info.file.status === 'error') {
      this.$message.error(`文件上传失败: ${info.file.msg} `)
    }
  },

注意在导出时对应 api 应加上如下配置

js
export function downFile(url, params) {
  return axios({
    url,
    method: 'get',
    // 注意必须加上这条配置
    responseType: 'blob',
    params
  })
}

利用递归根据 id 查询数据

js
var data = [
  {
    id: 1,
    name: '家电',
    goods: [
      {
        id: 11,
        gname: '冰箱',
        goods: [
          {
            id: 111,
            gname: '海尔'
          },
          {
            id: 112,
            gname: '美的'
          }
        ]
      },
      {
        id: 12,
        gname: '洗衣机',
        // #1
        goods: [
          {
            id: 666
          }
        ]
      }
    ]
  },
  {
    id: 2,
    name: '服饰'
    // #2
    // goods: [{
    //     id: 888
    // }]
  }
]
function getID(json, id, callback) {
  json.some(function (item) {
    if (item.id == id) {
      callback(item)
      return true
    } else if (item.goods && item.goods.length > 0) {
      getID(item.goods, id, callback)
    }
  })
}
getID(data, 11, function (data) {
  console.log(data)
})

结合 elementUI 读取 exsl 数据

vue
<template>
<el-upload
      ref="upload"
      class="upload-demo"
      :before-upload="beforeUpload"
      accept=".xlsx, xls"
      drag
      action="https://jsonplaceholder.typicode.com/posts/"
      :on-error="uploadFail"
      :limit="1"
      :multiple="false"
      :auto-upload="false"
    >
</template>

<script>
// 导入解析 excel  表格插件
import XLSX from 'xlsx'

methods: {
    beforeUpload(file) {
      this.file = file
      if (file) {
        this.buttonLoading = true
      }
      if (
        file.name.split('.')[1].includes('xls' || 'xlsx') &&
        file.size < 20 * 1024 * 1024
      ) {
        let param = new FormData()
        param.append('file', file)
        this.$axios
          .post(`/api/enterprise/importInvestOrgExcel`, param, {
            headers: { 'Content-Type': 'multipart/form-data' }
          })
          .then(res => {
            if (res.data.success) {
              this.$message.success('上传成功!')
            } else {
              this.$message.error(res.data.message)
            }
            console.log(res.data)
          })
      } else {
        this.$message('请上传符合要求的文件!')
        this.buttonLoading = false
        return false
      }
    },
    // 上传 exsl 数据
    submit() {
      this.$refs.upload.submit()
    },
    uploadFail() {
      this.$message('上传失败')
      this.buttonLoading = false
    },
    beforeClose(done) {
      this.buttonLoading ? '' : (this.visible = false)
    }
    // 获取读取到的 exsl 表格数据,header 表示所有表头数据,results 表示每一行的数据
    generateData({ header, results }) {
    this.excelData.header = header
    this.excelData.results = results
    this.onSuccess && this.onSuccess(this.excelData)
    },
    // 读取 exsl
    readerData(rawFile) {
      this.loading = true
      return new Promise((resolve, reject) => {
        const reader = new FileReader()
        reader.onload = e => {
          const data = e.target.result
          const workbook = XLSX.read(data, { type: 'array' })
          const firstSheetName = workbook.SheetNames[0]
          const worksheet = workbook.Sheets[firstSheetName]
          const header = this.getHeaderRow(worksheet)
          const results = XLSX.utils.sheet_to_json(worksheet)
          this.generateData({ header, results })
          this.loading = false
          resolve()
        }
        reader.readAsArrayBuffer(rawFile)
      })
    },
    // 设置表头数据
    getHeaderRow(sheet) {
      const headers = []
      const range = XLSX.utils.decode_range(sheet['!ref'])
      let C
      const R = range.s.r
      /* start in the first row */
      for (C = range.s.c; C <= range.e.c; ++C) {
        /* walk every column in the range */
        const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
        /* find the cell in the first row */
        let hdr = 'UNKNOWN ' + C // <-- replace with your desired default
        if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
        headers.push(hdr)
      }
      return headers
    }
  }
</script>

导出 excel 带下拉框

js
import ExcelJS from 'exceljs'

async function ecportExcel() {
  const wb = new ExcelJS.Workbook()

  const Sheet1 = wb.addWorksheet('企业基本信息')
  const Sheet2 = wb.addWorksheet('Sheet2')
  // 定义下拉框数据表头
  Sheet2.columns = [
    {
      header: '企业编码',
      key: 'enterpriseNum',
      width: 20
    },
    {
      header: '集团名称',
      key: 'groupName',
      width: 20
    }
  ]
  // 定义下拉框数据
  const Sheet2_data = [
    {
      enterpriseNum: '女',
      groupName: '1111'
    },
    {
      enterpriseNum: '男',
      groupName: '2222'
    }
  ]

  Sheet2.addRows(Sheet2_data)

  Sheet1.columns = sheeHeader // 需要导出的数据表头

  Sheet1.addRows(sheeData) // 将 sheeData (需要导出的数据)

  // 添加性别管理器
  /*const _data = sheeData.reduce((p, c) => {
        if (!p.has(c.enterpriseNum)) {
            p.set(c.enterpriseNum, [c.groupName])
        } else {
            const arr = p.get(c.enterpriseNum)
            arr.push(c.groupName)
        }
        return p
    }, new Map())*/
  // 添加下拉框
  new Array(1000).fill(0).forEach((_, idx) => {
    const row = idx + 2
    // 表示在第一列添加下拉框
    Sheet1.getCell(row, 1).dataValidation = {
      type: 'list',
      // 下拉框选项,Sheet2 表示要从这个工作表读取下拉框数据
      formulae: [`=Sheet2!$A$2:$A${Sheet2_data.length + 1}`]
    }
    // 使用indirect函数添加引用, 渲染性别值
    Sheet1.getCell(row, 2).dataValidation = {
      type: 'list',
      formulae: [`=Sheet2!$B$2:$B${Sheet2_data.length + 1}`]
    }
  })

  const buffer = await wb.xlsx.writeBuffer()

  const blob = new Blob([buffer], {
    type: 'application/octet-stream'
  })

  let url = blob,
    saveName = '企业信息表.xlsx'

  if (typeof url == 'object' && url instanceof Blob) {
    url = URL.createObjectURL(url) // 创建blob地址
  }
  const aLink = document.createElement('a')
  aLink.href = url
  aLink.download = saveName || '' // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
  var event
  if (window.MouseEvent) event = new MouseEvent('click')
  else {
    event = document.createEvent('MouseEvents')
    event.initMouseEvent(
      'click',
      true,
      false,
      window,
      0,
      0,
      0,
      0,
      0,
      false,
      false,
      false,
      false,
      0,
      null
    )
  }
  aLink.dispatchEvent(event)
  return
}
ecportExcel()

大屏适配方案

在 app.vue 中添加全局页面比例

vue
<template>
  <div id="app" :style="style">
    <router-view />
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      style: {
        transform: 'scale(1)',
        width: '1920px',
        height: '1080px',
        transformOrigin: '0 0'
      }
    }
  },
  mounted() {
    this.setScale()
    window.addEventListener('resize', this.setScale)
    this.$once('hook:beforeDestroy', () => {
      window.removeEventListener('resize', this.setScale)
    })
  },
  methods: {
    setScale() {
      const w = window.innerWidth / 1920
      const h = window.innerHeight / 1080
      this.style.transform = `scale(${w},${h})`
      this.style.transformOrigin = '0 0'
    }
  }
}
</script>

<style>
#app {
  transition: 0.5s;
}
</style>

在其他组件中使用

js
created() {
    // 控制页面缩放
    this.resize()
    window.addEventListener('resize', () => {
        this.resize()
    })
    window.onload = () => {
        return this.resize()
    }
    // 控制页面缩放
},
    methods: {
        // 控制页面缩放
        resize() {
            let appDom = document.querySelector('#app')
            appDom.style.transform = 'scale(1,1)'
            appDom.style.width = 100 + '%'
            appDom.style.height = 100 + '%'
        },

原生 js 实现视频

vue
<template>
  <div class="video">
    <video
      ref="myvideo"
      class="videoContent"
      @canplay="canplay"
      @timeupdate="timeupdate"
      @pause="videoisplay = false"
      @play="videoisplay = true"
      v-if="url !== ''"
    >
      <source :src="url" />
    </video>
    <div class="sess" v-if="url !== ''">
      <div class="star" @click="star">
        <i
          :class="
            videoisplay
              ? 'icon-24gf-pause2 iconfont'
              : 'icon-24gf-play iconfont'
          "
          style="font-size: 25px;"
        ></i>
      </div>
      <div class="time">{{ startime }}/{{ totaltime }}</div>
      <div ref="jin" class="jin" @click="progress">
        <div class="hua" :style="jinprease"></div>
        <div
          class="point"
          :style="jinprease === '' ? 'margin-left: 0;' : ''"
        ></div>
      </div>
      <div class="yin" @click="voice">
        <i
          :class="
            isvoice
              ? 'icon-mn_shengyinwu_fill iconfont'
              : 'icon-shengyin iconfont'
          "
        ></i>
      </div>
      <div
        ref="yin"
        class="jin"
        style="width: 100px; margin: 0 15px;"
        @click="yinprease"
      >
        <div class="hua" :style="yinpreasestyle"></div>
        <div class="point"></div>
      </div>
      <div class="full" @click="fullview">
        <i class="icon-quanping iconfont"></i>
      </div>
    </div>
    <div class="videocontent">
      <div class="title">{{ videoinfo }}</div>
      <div class="title2">
        <p class="span1">投资总额</p>
        <p class="span2">10000<span class="span3">亿元</span></p>
      </div>
      <div class="content">
        <echartsBox
          ref="layoutCharts4"
          refName="layoutCharts4"
          eChartsType="5"
          :chartsLoading="true"
        ></echartsBox>
      </div>
      <div class="content2">
        <div class="text">
          <p>本年计划投资</p>
          <div>80000<span>万元</span></div>
        </div>
        <div class="text">
          <p>本年计划投资</p>
          <div>80000<span>万元</span></div>
        </div>
      </div>
      <div class="content3">
        <p class="project" @click="selectitem(0)">
          项目概要<i
            class="icon-xiangxiajiantou iconfont"
            :style="select ? '' : 'transform: rotateZ(-90deg)'"
          ></i>
        </p>
        <div class="projectcontent" v-if="select">
          项目包括新建战勤保障综合楼1栋地下1层,地上由A座、B座和综合修理楼共3栋建筑组成油料供应站1个及室外配套工作项目包括新建战勤保障综合楼1
        </div>
        <p class="project" @click="selectitem(1)">
          问题跟踪<i
            class="icon-xiangxiajiantou iconfont"
            :style="select2 ? '' : 'transform: rotateZ(-90deg)'"
          ></i>
        </p>
        <div class="projectcontent" v-if="select2">
          项目包括新建战勤保障综合楼1栋地下1层,地上由A座、B座和综合修理楼共3栋建筑组成油料供应站1个及室外配套工作项目包括新建战勤保障综合楼1
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import echartsBox from '../../components/ChartsDemo/index.vue'
export default {
  components: {
    echartsBox
  },
  // 用户点击的视频信息
  props: {
    videoinfo: {
      type: String
    }
  },
  data() {
    return {
      videoisplay: false, // 记录视频是否播放
      url: '',
      startime: 0, // 记录已播放
      totaltime: 0, // 总时长
      totaltimestring: '', // 总时长时间秒数
      isvoice: false, // 是否静音
      voicenum: 20, // 默认音量大小
      clientwidth: 0, // 记录视频进度条长度
      clientwidth2: 0, // 记录音量进度条长度
      jinprease: '', // 控制视频进度条位置
      yinpreasestyle: '', // 控制音量进度条位置
      flag: true, // 控制进度条节流阀
      select: true, // 记录视频上手风琴当前选择的文本(项目概要/问题跟踪)代表是否展开
      select2: false // 记录视频上手风琴当前选择的文本(问题跟踪)代表是否展开
    }
  },
  created() {
    this.geturl()
  },
  methods: {
    // 获取视频链接
    geturl() {
      setTimeout(() => {
        this.url =
          'https://api.dogecloud.com/player/get.mp4?vcode=5ac682e6f8231991&userId=17&ext=.mp4'
      }, 1000)
    },
    // 控制视频暂停播放
    star() {
      this.videoisplay = !this.videoisplay
      if (this.videoisplay) {
        this.$refs.myvideo.play()
      } else {
        this.$refs.myvideo.pause()
      }
    },
    // 视频加载完毕
    canplay() {
      this.totaltime = this.formatTime(this.$refs.myvideo.duration)
      this.totaltimestring = this.$refs.myvideo.duration
      this.startime = this.formatTime(this.$refs.myvideo.currentTime)
      this.clientwidth = this.$refs.jin.clientWidth
      this.clientwidth2 = this.$refs.yin.clientWidth
    },
    // 获取已播放时间
    timeupdate(e) {
      this.startime = this.formatTime(e.target.currentTime)
      if (this.flag) {
        this.flag = false
        setTimeout(() => {
          this.jinprease = `width:${(
            (e.target.currentTime / this.totaltimestring) *
            100
          ).toFixed(2)}%`
          this.flag = true
        }, 1500)
      }
    },
    // 调节音量
    voice() {
      this.isvoice = !this.isvoice
      if (this.isvoice) {
        this.$refs.myvideo.volume = 0
      } else {
        this.$refs.myvideo.volume = this.voicenum / 100
      }
    },
    // 控制全屏
    fullview() {
      this.$refs.myvideo.requestFullscreen()
    },
    // 视频进度条交互
    progress(e) {
      // 根据用户点击区域控制进度条长度
      let fen = e.offsetX / this.clientwidth
      let bo = this.formatTime(fen * this.totaltimestring)
      this.jinprease = `width:${(fen * 100).toFixed(2)}%`
      //   修改已播放文本
      this.startime = bo
      //   修改视频到对应位置
      this.$refs.myvideo.currentTime = fen * this.totaltimestring
    },
    // 音量进度条交互
    yinprease(e) {
      // 根据用户点击区域控制进度条长度
      let fen = e.offsetX / this.clientwidth2
      this.yinpreasestyle = `width:${(fen * 100).toFixed(1)}%`
      this.$refs.myvideo.volume = fen
      this.voicenum = fen
    },
    // 视频上手风琴切换
    selectitem(i) {
      if (i) {
        // 当前选中的是问题跟踪
        if (this.select && !this.select2) {
          this.select = !this.select
          this.select2 = !this.select2
        } else {
          this.select2 = !this.select2
        }
      } else {
        // 当前选中的是项目概要
        if (!this.select && this.select2) {
          this.select = !this.select
          this.select2 = !this.select2
        } else {
          this.select = !this.select
        }
      }
    },
    initCharts() {
      let value = 50 // 数值
      let seriesData = [
        {
          type: 'gauge',
          startAngle: 180,
          endAngle: 0,
          z: 10,
          min: 0,
          max: 100,
          radius: '180%',
          // radius: ['100%', '50%'],
          center: ['50%', '100%'],
          axisLine: {
            show: false
            // lineStyle: {
            //     color: [
            //         [1, '#0a1f4a']
            //     ],
            //     width: 1,
            //     opacity: 1
            // }
          },
          title: {
            show: false
          },
          detail: {
            // backgroundColor: '#fff',
            // borderColor: '#999',
            // borderWidth: 2,
            width: '100%',
            // borderRadius: 4,
            offsetCenter: [0, '-20%'],

            formatter: function (value) {
              return (
                '{value|' + value.toFixed(0) + '}{unit|%}\n{unit2|形象进度}'
              )
            },
            rich: {
              value: {
                fontSize: 25,
                // fontWeight: 'bolder',
                color: '#fff'
              },
              unit: {
                fontSize: 10,
                color: '#fff',
                padding: [0, 0, 5, 0]
              },
              unit2: {
                fontSize: 10,
                color: '#fff'
                // padding: [0, 0, 15, 6]
              }
            }
          },
          // axisLine: {
          //     show: false
          // },
          axisTick: {
            // show:false,
            length: 3,
            lineStyle: {
              color: '#999'
            }
          },
          splitLine: {
            length: 0,
            lineStyle: {
              color: '#999',
              width: 3
            }
          },
          axisLabel: {
            show: false,
            color: '#999'
          },
          pointer: {
            show: false
            // width: 5,
            // length: '80%',
          },
          itemStyle: {
            color: '#0a204b'
            // shadowColor: '#eef2f6',
            // shadowBlur: 10,
            // shadowOffsetX: 2,
            // shadowOffsetY: 2
          },
          markPoint: {
            show: false
            // data: [
            //   {
            //     x: '50%',
            //     y: '100%',
            //     symbol: 'circle',
            //     symbolSize: 8,
            //     itemStyle: {
            //       color: '#fff'
            //     }
            //   }
            // ]
          },
          data: [
            {
              value: value
            }
          ]
        },
        {
          // 内层
          type: 'gauge',
          startAngle: 180,
          endAngle: 0,
          // splitNumber:20,
          min: 0,
          max: 100,
          radius: '145%',
          // radius: ['60%', '30%'],
          center: ['50%', '100%'],
          // axisLine: {
          //     show: false,
          //     // lineStyle: {
          //     //     color: [
          //     //         [1, '#999']
          //     //     ],
          //     //     width: 1,
          //     //     opacity: 1
          //     // }
          // },
          title: {
            show: false
          },
          detail: {
            show: false
          },
          axisLine: {
            show: false
          },
          axisTick: {
            length: 5,
            lineStyle: {
              color: '#999'
            }
          },
          splitLine: {
            length: 10,
            lineStyle: {
              color: '#999',
              width: 2
            }
          },
          axisLabel: {
            show: false,
            color: '#999'
          },
          pointer: {
            width: 3,
            length: '80%'
          },
          itemStyle: {
            color: '#2b4f7d',
            shadowColor: 'rgba(0,138,255,0.45)',
            shadowBlur: 5
            // shadowOffsetX: 2,
            // shadowOffsetY: 2
          },
          markPoint: {
            show: false
            // data: [
            //   {
            //     x: '50%',
            //     y: '50%',
            //     symbol: 'circle',
            //     symbolSize: 1,
            //     itemStyle: {
            //       color: '#fff'
            //     }
            //   }
            // ]
          },
          data: [
            {
              value: value
            }
          ]
        },
        {
          type: 'gauge',
          radius: '160%',
          // radius: ['90%', '90%'],
          center: ['50%', '100%'],
          startAngle: 180,
          endAngle: 0,
          min: 0,
          max: 100,
          title: {
            show: false
          },
          detail: {
            show: false
          },
          axisLine: {
            show: true,
            lineStyle: {
              width: 6,
              color: [
                [value / 100, '#00FFE6'],
                [1, '#324e9c']
              ]
            }
          },
          axisTick: {
            show: false
          },
          splitLine: {
            show: false
          },
          axisLabel: {
            show: false
          },
          pointer: {
            show: false
          },
          itemStyle: {
            normal: {
              color: '#54F200'
            }
          }
        }
      ]
      let extraOption = {}
      this.$refs.layoutCharts4.mergeOptoptions(seriesData, extraOption)
    },
    // 时间格式化
    formatTime(seconds) {
      let h = 0,
        m = 0,
        s = 0
      const formatNumber = n => (n > 9 ? n : `0${n}`)
      if (seconds > 3600) {
        h = parseInt(seconds / 3600)
        seconds = seconds - h * 3600
        h = formatNumber(h)
      }
      if (seconds > 60) {
        m = parseInt(seconds / 60)
        seconds = seconds - m * 60
        m = formatNumber(m)
      }
      s = formatNumber(parseInt(seconds))
      return `${h ? `${h}:` : ''}${m ? m : '00'}:${s ? s : '00'}`
    }
  },
  mounted() {
    this.initCharts()
  }
}
</script>

<style scoped lang="less">
.video {
  width: 100%;
  height: 100%;
  position: relative;
  video {
    width: 100%;
    height: 90%;
    object-fit: fill;
  }
  .sess {
    height: 46px;
    display: flex;
    align-items: center;
    .star {
      width: 30px;
      height: 30px;
      font-size: 15px;
      cursor: pointer;
      margin-left: 20px;
    }
    .time {
      margin: 0 25px;
      color: #ffffff;
      font-size: 15px;
    }
    .jin {
      width: 475px;
      height: 10px;
      border-radius: 5px;
      background-color: #43567f;
      //   position: relative;
      cursor: pointer;
      display: flex;
      align-items: center;
      .hua {
        width: 0;
        height: 10px;
        border-radius: 5px;
        background-color: #f05636;
        transition: 0.1s;
        // position: absolute;
        // left: 0;
      }
      .point {
        width: 15px;
        height: 15px;
        border-radius: 50%;
        background-color: #fff;
        margin-left: -10px;
      }
    }
    .yin {
      width: 30px;
      height: 30px;
      font-size: 15px;
      cursor: pointer;
      margin-left: 15px;
    }
    .full {
      width: 30px;
      height: 30px;
      font-size: 15px;
      cursor: pointer;
    }
  }
  .videocontent {
    position: absolute;
    left: 0;
    top: 0;
    width: 272px;
    height: 395px;
    background: rgba(0, 11, 46, 0.5);
    box-sizing: border-box;
    padding: 0 15px;
    .title {
      height: 32px;
      background: linear-gradient(
        270deg,
        rgba(76, 59, 255, 0) 0%,
        #899eff 48%,
        rgba(76, 59, 255, 0) 100%
      );
      filter: blur(0px);
      font-size: 17px;
      font-weight: 600;
      color: #ffffff;
      line-height: 32px;
    }
    .title2 {
      display: flex;
      align-items: center;
      font-size: 14px;
      font-weight: 400;
      color: #c2cde7;
      .span1 {
        margin: 5px 10px 0 0;
      }
      .span2 {
        max-width: 175px;
        font-size: 28px;
        color: #00d3ff;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        .span3 {
          font-size: 14px;
        }
      }
    }
    .content {
      width: 180px;
      height: 90px;
      margin: 0 auto;
      // background-color: cadetblue;
    }
    .content2 {
      height: 50px;
      display: flex;
      justify-content: space-between;
      margin-top: 10px;
      .text {
        width: 90px;
        height: 100%;
        color: #c2cde7;
        font-size: 14px;
        div {
          color: #00d3ff;
          font-size: 20px;
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
          span {
            font-size: 12px;
          }
        }
      }
    }
    .content3 {
      height: 165px;
      .project {
        font-size: 14px;
        color: #ffffff;
        margin: 10px 0 5px 0;
        display: flex;
        align-items: center;
        cursor: pointer;
      }
      .projectcontent {
        height: 90px;
        font-size: 12px;
        color: #c2cde7;
      }
    }
  }
}
.icon-xiangxiajiantou {
  height: 14px;
  width: 14px;
  font-size: 14px !important;
  color: #00d3ff !important;
  margin-left: 5px;
  // margin: 2px 0 0 5px;
  // transition: 0.3s;
  // transform: rotateZ(90deg);
}
@font-face {
  font-family: 'iconfont'; /* Project id 3274792 */
  src: url('//at.alicdn.com/t/font_3274792_4l5ykunhnm5.woff2?t=1648171585990')
      format('woff2'), url('//at.alicdn.com/t/font_3274792_4l5ykunhnm5.woff?t=1648171585990')
      format('woff'),
    url('//at.alicdn.com/t/font_3274792_4l5ykunhnm5.ttf?t=1648171585990') format('truetype');
}

.iconfont {
  font-family: 'iconfont' !important;
  font-size: 28px;
  font-style: normal;
  color: #fff;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.icon-xiangxiajiantou:before {
  content: '\e689';
}

.icon-quanping:before {
  content: '\e61f';
}

.icon-mn_shengyinwu_fill:before {
  content: '\e600';
}

.icon-24gf-pause2:before {
  content: '\ea81';
}

.icon-24gf-play:before {
  content: '\ea82';
}

.icon-shengyin:before {
  content: '\e637';
}
</style>

在 vue 中使用 ECharts

  • 先在 main.js 中引入
js
import * as echarts5 from 'echarts5'
import * as echarts4 from 'echarts4'
Vue.use(echarts4)
Vue.use(echarts5)
  • 在组件中使用
vue
<div class="right_content">
    <div class="ChartsBox2" ref="ChartsBox2"></div>
</div>
<script>
export default {
  data() {
    //这里存放数据
    return {
      // 环状图数据
      option2: {
        grid: {
          left: "10%",
          right: "10",
          containLabel: true
        },
        series: [
          {
            type: "pie",
            center: ["50%", "50%"],
            radius: [30, 45],
            selectedMode: "single",
            data: [],
            label: {
              formatter: "{name|{b}}{val|{d}}{name|%}\n",
              minMargin: 15,
              lineHeight: 25,
              padding: [0, -45],
              rich: {
                val: {
                  fontSize: 14
                },
                name: {
                  fontSize: 10,
                  color: "#FFFFFF"
                }
              }
            },
            labelLine: {
              length: 20,
              length2: 50,
              maxSurfaceAngle: 80
            }
          }
        ],
        color: ["#FFCF29", "#DB4537"]
      }
    };
  },
  //监听属性 类似于data概念
  computed: {},
  created() {},
  mounted() {
    let data2 = [
      { value: 55, name: "巡听" },
      { value: 45, name: "旁听" }
    ];
    this.initCharts2(data2);
  },
  //监控data中的数据变化
  watch: {},
  //方法集合
  methods: {
    // 环状图
    initCharts2(data) {
      let param = $.extend(true, {}, this.option2, {
        series: [
          {
            data: data
          }
        ]
      });
      let $dom = this.$refs["ChartsBox2"];
      this.chartTrend = this.$echarts.init($dom);
      this.chartTrend.resize();
      this.chartTrend.clear();
      this.option2 && this.chartTrend.setOption(param);
    }
  }
};
</script>

ECharts 配置

js
theme = {
  // 全图默认背景
  // backgroundColor: 'rgba(0,0,0,0)',

  // 默认色板
  color: [
    '#ff7f50',
    '#87cefa',
    '#da70d6',
    '#32cd32',
    '#6495ed',
    '#ff69b4',
    '#ba55d3',
    '#cd5c5c',
    '#ffa500',
    '#40e0d0',
    '#1e90ff',
    '#ff6347',
    '#7b68ee',
    '#00fa9a',
    '#ffd700',
    '#6699FF',
    '#ff6666',
    '#3cb371',
    '#b8860b',
    '#30e0e0'
  ],

  // 图表标题
  title: {
    x: 'left', // 水平安放位置,默认为左对齐,可选为:
    // 'center' ¦ 'left' ¦ 'right'
    // ¦ {number}(x坐标,单位px)
    y: 'top', // 垂直安放位置,默认为全图顶端,可选为:
    // 'top' ¦ 'bottom' ¦ 'center'
    // ¦ {number}(y坐标,单位px)
    //textAlign: null          // 水平对齐方式,默认根据x设置自动调整
    backgroundColor: 'rgba(0,0,0,0)',
    borderColor: '#ccc', // 标题边框颜色
    borderWidth: 0, // 标题边框线宽,单位px,默认为0(无边框)
    padding: 5, // 标题内边距,单位px,默认各方向内边距为5,
    // 接受数组分别设定上右下左边距,同css
    itemGap: 10, // 主副标题纵向间隔,单位px,默认为10,
    textStyle: {
      fontSize: 18,
      fontWeight: 'bolder',
      color: '#333' // 主标题文字颜色
    },
    subtextStyle: {
      color: '#aaa' // 副标题文字颜色
    }
  },

  // 图例
  legend: {
    orient: 'horizontal', // 布局方式,默认为水平布局,可选为:
    // 'horizontal' ¦ 'vertical'
    x: 'center', // 水平安放位置,默认为全图居中,可选为:
    // 'center' ¦ 'left' ¦ 'right'
    // ¦ {number}(x坐标,单位px)
    y: 'top', // 垂直安放位置,默认为全图顶端,可选为:
    // 'top' ¦ 'bottom' ¦ 'center'
    // ¦ {number}(y坐标,单位px)
    backgroundColor: 'rgba(0,0,0,0)',
    borderColor: '#ccc', // 图例边框颜色
    borderWidth: 0, // 图例边框线宽,单位px,默认为0(无边框)
    padding: 5, // 图例内边距,单位px,默认各方向内边距为5,
    // 接受数组分别设定上右下左边距,同css
    itemGap: 10, // 各个item之间的间隔,单位px,默认为10,
    // 横向布局时为水平间隔,纵向布局时为纵向间隔
    itemWidth: 20, // 图例图形宽度
    itemHeight: 14, // 图例图形高度
    textStyle: {
      color: '#333' // 图例文字颜色
    }
  },

  // 值域
  dataRange: {
    orient: 'vertical', // 布局方式,默认为垂直布局,可选为:
    // 'horizontal' ¦ 'vertical'
    x: 'left', // 水平安放位置,默认为全图左对齐,可选为:
    // 'center' ¦ 'left' ¦ 'right'
    // ¦ {number}(x坐标,单位px)
    y: 'bottom', // 垂直安放位置,默认为全图底部,可选为:
    // 'top' ¦ 'bottom' ¦ 'center'
    // ¦ {number}(y坐标,单位px)
    backgroundColor: 'rgba(0,0,0,0)',
    borderColor: '#ccc', // 值域边框颜色
    borderWidth: 0, // 值域边框线宽,单位px,默认为0(无边框)
    padding: 5, // 值域内边距,单位px,默认各方向内边距为5,
    // 接受数组分别设定上右下左边距,同css
    itemGap: 10, // 各个item之间的间隔,单位px,默认为10,
    // 横向布局时为水平间隔,纵向布局时为纵向间隔
    itemWidth: 20, // 值域图形宽度,线性渐变水平布局宽度为该值 * 10
    itemHeight: 14, // 值域图形高度,线性渐变垂直布局高度为该值 * 10
    splitNumber: 5, // 分割段数,默认为5,为0时为线性渐变
    color: ['#1e90ff', '#f0ffff'], //颜色
    //text:['高','低'],         // 文本,默认为数值文本
    textStyle: {
      color: '#333' // 值域文字颜色
    }
  },

  toolbox: {
    orient: 'horizontal', // 布局方式,默认为水平布局,可选为:
    // 'horizontal' ¦ 'vertical'
    x: 'right', // 水平安放位置,默认为全图右对齐,可选为:
    // 'center' ¦ 'left' ¦ 'right'
    // ¦ {number}(x坐标,单位px)
    y: 'top', // 垂直安放位置,默认为全图顶端,可选为:
    // 'top' ¦ 'bottom' ¦ 'center'
    // ¦ {number}(y坐标,单位px)
    color: ['#1e90ff', '#22bb22', '#4b0082', '#d2691e'],
    backgroundColor: 'rgba(0,0,0,0)', // 工具箱背景颜色
    borderColor: '#ccc', // 工具箱边框颜色
    borderWidth: 0, // 工具箱边框线宽,单位px,默认为0(无边框)
    padding: 5, // 工具箱内边距,单位px,默认各方向内边距为5,
    // 接受数组分别设定上右下左边距,同css
    itemGap: 10, // 各个item之间的间隔,单位px,默认为10,
    // 横向布局时为水平间隔,纵向布局时为纵向间隔
    itemSize: 16, // 工具箱图形宽度
    featureImageIcon: {}, // 自定义图片icon
    featureTitle: {
      mark: '辅助线开关',
      markUndo: '删除辅助线',
      markClear: '清空辅助线',
      dataZoom: '区域缩放',
      dataZoomReset: '区域缩放后退',
      dataView: '数据视图',
      lineChart: '折线图切换',
      barChart: '柱形图切换',
      restore: '还原',
      saveAsImage: '保存为图片'
    }
  },

  // 提示框
  tooltip: {
    trigger: 'item', // 触发类型,默认数据触发,见下图,可选为:'item' ¦ 'axis'
    showDelay: 20, // 显示延迟,添加显示延迟可以避免频繁切换,单位ms
    hideDelay: 100, // 隐藏延迟,单位ms
    transitionDuration: 0.4, // 动画变换时间,单位s
    backgroundColor: 'rgba(0,0,0,0.7)', // 提示背景颜色,默认为透明度为0.7的黑色
    borderColor: '#333', // 提示边框颜色
    borderRadius: 4, // 提示边框圆角,单位px,默认为4
    borderWidth: 0, // 提示边框线宽,单位px,默认为0(无边框)
    padding: 5, // 提示内边距,单位px,默认各方向内边距为5,
    // 接受数组分别设定上右下左边距,同css
    axisPointer: {
      // 坐标轴指示器,坐标轴触发有效
      type: 'line', // 默认为直线,可选为:'line' | 'shadow'
      lineStyle: {
        // 直线指示器样式设置
        color: '#48b',
        width: 2,
        type: 'solid'
      },
      shadowStyle: {
        // 阴影指示器样式设置
        width: 'auto', // 阴影大小
        color: 'rgba(150,150,150,0.3)' // 阴影颜色
      }
    },
    textStyle: {
      color: '#fff'
    }
  },

  // 区域缩放控制器
  dataZoom: {
    orient: 'horizontal', // 布局方式,默认为水平布局,可选为:
    // 'horizontal' ¦ 'vertical'
    // x: {number},            // 水平安放位置,默认为根据grid参数适配,可选为:
    // {number}(x坐标,单位px)
    // y: {number},            // 垂直安放位置,默认为根据grid参数适配,可选为:
    // {number}(y坐标,单位px)
    // width: {number},        // 指定宽度,横向布局时默认为根据grid参数适配
    // height: {number},       // 指定高度,纵向布局时默认为根据grid参数适配
    backgroundColor: 'rgba(0,0,0,0)', // 背景颜色
    dataBackgroundColor: '#eee', // 数据背景颜色
    fillerColor: 'rgba(144,197,237,0.2)', // 填充颜色
    handleColor: 'rgba(70,130,180,0.8)' // 手柄颜色
  },

  // 网格
  grid: {
    x: 80,
    y: 60,
    x2: 80,
    y2: 60,
    // width: {totalWidth} - x - x2,
    // height: {totalHeight} - y - y2,
    backgroundColor: 'rgba(0,0,0,0)',
    borderWidth: 1,
    borderColor: '#ccc'
  },

  // 类目轴
  categoryAxis: {
    position: 'bottom', // 位置
    nameLocation: 'end', // 坐标轴名字位置,支持'start' | 'end'
    boundaryGap: true, // 类目起始和结束两端空白策略
    axisLine: {
      // 坐标轴线
      show: true, // 默认显示,属性show控制显示与否
      lineStyle: {
        // 属性lineStyle控制线条样式
        color: '#48b',
        width: 2,
        type: 'solid'
      }
    },
    axisTick: {
      // 坐标轴小标记
      show: true, // 属性show控制显示与否,默认不显示
      interval: 'auto',
      // onGap: null,
      inside: false, // 控制小标记是否在grid里
      length: 5, // 属性length控制线长
      lineStyle: {
        // 属性lineStyle控制线条样式
        color: '#333',
        width: 1
      }
    },
    axisLabel: {
      // 坐标轴文本标签,详见axis.axisLabel
      show: true,
      interval: 'auto',
      rotate: 0,
      margin: 8,
      // formatter: null,
      textStyle: {
        // 其余属性默认使用全局文本样式,详见TEXTSTYLE
        color: '#333'
      }
    },
    splitLine: {
      // 分隔线
      show: true, // 默认显示,属性show控制显示与否
      // onGap: null,
      lineStyle: {
        // 属性lineStyle(详见lineStyle)控制线条样式
        color: ['#ccc'],
        width: 1,
        type: 'solid'
      }
    },
    splitArea: {
      // 分隔区域
      show: false, // 默认不显示,属性show控制显示与否
      // onGap: null,
      areaStyle: {
        // 属性areaStyle(详见areaStyle)控制区域样式
        color: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)']
      }
    }
  },

  // 数值型坐标轴默认参数
  valueAxis: {
    position: 'left', // 位置
    nameLocation: 'end', // 坐标轴名字位置,支持'start' | 'end'
    nameTextStyle: {}, // 坐标轴文字样式,默认取全局样式
    boundaryGap: [0, 0], // 数值起始和结束两端空白策略
    splitNumber: 5, // 分割段数,默认为5
    axisLine: {
      // 坐标轴线
      show: true, // 默认显示,属性show控制显示与否
      lineStyle: {
        // 属性lineStyle控制线条样式
        color: '#48b',
        width: 2,
        type: 'solid'
      }
    },
    axisTick: {
      // 坐标轴小标记
      show: false, // 属性show控制显示与否,默认不显示
      inside: false, // 控制小标记是否在grid里
      length: 5, // 属性length控制线长
      lineStyle: {
        // 属性lineStyle控制线条样式
        color: '#333',
        width: 1
      }
    },
    axisLabel: {
      // 坐标轴文本标签,详见axis.axisLabel
      show: true,
      rotate: 0,
      margin: 8,
      // formatter: null,
      textStyle: {
        // 其余属性默认使用全局文本样式,详见TEXTSTYLE
        color: '#333'
      }
    },
    splitLine: {
      // 分隔线
      show: true, // 默认显示,属性show控制显示与否
      lineStyle: {
        // 属性lineStyle(详见lineStyle)控制线条样式
        color: ['#ccc'],
        width: 1,
        type: 'solid'
      }
    },
    splitArea: {
      // 分隔区域
      show: false, // 默认不显示,属性show控制显示与否
      areaStyle: {
        // 属性areaStyle(详见areaStyle)控制区域样式
        color: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)']
      }
    }
  },

  polar: {
    center: ['50%', '50%'], // 默认全局居中
    radius: '75%',
    startAngle: 90,
    splitNumber: 5,
    name: {
      show: true,
      textStyle: {
        // 其余属性默认使用全局文本样式,详见TEXTSTYLE
        color: '#333'
      }
    },
    axisLine: {
      // 坐标轴线
      show: true, // 默认显示,属性show控制显示与否
      lineStyle: {
        // 属性lineStyle控制线条样式
        color: '#ccc',
        width: 1,
        type: 'solid'
      }
    },
    axisLabel: {
      // 坐标轴文本标签,详见axis.axisLabel
      show: false,
      textStyle: {
        // 其余属性默认使用全局文本样式,详见TEXTSTYLE
        color: '#333'
      }
    },
    splitArea: {
      show: true,
      areaStyle: {
        color: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)']
      }
    },
    splitLine: {
      show: true,
      lineStyle: {
        width: 1,
        color: '#ccc'
      }
    }
  },

  // 柱形图默认参数
  bar: {
    barMinHeight: 0, // 最小高度改为0
    // barWidth: null,        // 默认自适应
    barGap: '30%', // 柱间距离,默认为柱形宽度的30%,可设固定值
    barCategoryGap: '20%', // 类目间柱形距离,默认为类目间距的20%,可设固定值
    itemStyle: {
      normal: {
        // color: '各异',
        barBorderColor: '#fff', // 柱条边线
        barBorderRadius: 0, // 柱条边线圆角,单位px,默认为0
        barBorderWidth: 1, // 柱条边线线宽,单位px,默认为1
        label: {
          show: false
          // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
          //           'inside'|'left'|'right'|'top'|'bottom'
          // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
        }
      },
      emphasis: {
        // color: '各异',
        barBorderColor: 'rgba(0,0,0,0)', // 柱条边线
        barBorderRadius: 0, // 柱条边线圆角,单位px,默认为0
        barBorderWidth: 1, // 柱条边线线宽,单位px,默认为1
        label: {
          show: false
          // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
          //           'inside'|'left'|'right'|'top'|'bottom'
          // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
        }
      }
    }
  },

  // 折线图默认参数
  line: {
    itemStyle: {
      normal: {
        // color: 各异,
        label: {
          show: false
          // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
          //           'inside'|'left'|'right'|'top'|'bottom'
          // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
        },
        lineStyle: {
          width: 2,
          type: 'solid',
          shadowColor: 'rgba(0,0,0,0)', //默认透明
          shadowBlur: 5,
          shadowOffsetX: 3,
          shadowOffsetY: 3
        }
      },
      emphasis: {
        // color: 各异,
        label: {
          show: false
          // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
          //           'inside'|'left'|'right'|'top'|'bottom'
          // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
        }
      }
    },
    //smooth : false,
    //symbol: null,         // 拐点图形类型
    symbolSize: 2, // 拐点图形大小
    //symbolRotate : null,  // 拐点图形旋转控制
    showAllSymbol: false // 标志图形默认只有主轴显示(随主轴标签间隔隐藏策略)
  },

  // K线图默认参数
  k: {
    // barWidth : null          // 默认自适应
    // barMaxWidth : null       // 默认自适应
    itemStyle: {
      normal: {
        color: '#fff', // 阳线填充颜色
        color0: '#00aa11', // 阴线填充颜色
        lineStyle: {
          width: 1,
          color: '#ff3200', // 阳线边框颜色
          color0: '#00aa11' // 阴线边框颜色
        }
      },
      emphasis: {
        // color: 各异,
        // color0: 各异
      }
    }
  },

  // 散点图默认参数
  scatter: {
    //symbol: null,      // 图形类型
    symbolSize: 4, // 图形大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2
    //symbolRotate : null,  // 图形旋转控制
    large: false, // 大规模散点图
    largeThreshold: 2000, // 大规模阀值,large为true且数据量>largeThreshold才启用大规模模式
    itemStyle: {
      normal: {
        // color: 各异,
        label: {
          show: false
          // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
          //           'inside'|'left'|'right'|'top'|'bottom'
          // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
        }
      },
      emphasis: {
        // color: '各异'
        label: {
          show: false
          // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
          //           'inside'|'left'|'right'|'top'|'bottom'
          // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
        }
      }
    }
  },

  // 雷达图默认参数
  radar: {
    itemStyle: {
      normal: {
        // color: 各异,
        label: {
          show: false
        },
        lineStyle: {
          width: 2,
          type: 'solid'
        }
      },
      emphasis: {
        // color: 各异,
        label: {
          show: false
        }
      }
    },
    //symbol: null,         // 拐点图形类型
    symbolSize: 2 // 可计算特性参数,空数据拖拽提示图形大小
    //symbolRotate : null,  // 图形旋转控制
  },

  // 饼图默认参数
  pie: {
    center: ['50%', '50%'], // 默认全局居中
    radius: [0, '75%'],
    clockWise: false, // 默认逆时针
    startAngle: 90,
    minAngle: 0, // 最小角度改为0
    selectedOffset: 10, // 选中是扇区偏移量
    itemStyle: {
      normal: {
        // color: 各异,
        borderColor: '#fff',
        borderWidth: 1,
        label: {
          show: true,
          position: 'outer'
          // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
        },
        labelLine: {
          show: true,
          length: 20,
          lineStyle: {
            // color: 各异,
            width: 1,
            type: 'solid'
          }
        }
      },
      emphasis: {
        // color: 各异,
        borderColor: 'rgba(0,0,0,0)',
        borderWidth: 1,
        label: {
          show: false
          // position: 'outer'
          // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
        },
        labelLine: {
          show: false,
          length: 20,
          lineStyle: {
            // color: 各异,
            width: 1,
            type: 'solid'
          }
        }
      }
    }
  },

  map: {
    mapType: 'china', // 各省的mapType暂时都用中文
    mapLocation: {
      x: 'center',
      y: 'center'
      // width    // 自适应
      // height   // 自适应
    },
    showLegendSymbol: true, // 显示图例颜色标识(系列标识的小圆点),存在legend时生效
    itemStyle: {
      normal: {
        // color: 各异,
        borderColor: '#fff',
        borderWidth: 1,
        areaStyle: {
          color: '#ccc' //rgba(135,206,250,0.8)
        },
        label: {
          show: false,
          textStyle: {
            color: 'rgba(139,69,19,1)'
          }
        }
      },
      emphasis: {
        // 也是选中样式
        // color: 各异,
        borderColor: 'rgba(0,0,0,0)',
        borderWidth: 1,
        areaStyle: {
          color: 'rgba(255,215,0,0.8)'
        },
        label: {
          show: false,
          textStyle: {
            color: 'rgba(139,69,19,1)'
          }
        }
      }
    }
  },

  force: {
    // 数据map到圆的半径的最小值和最大值
    minRadius: 10,
    maxRadius: 20,
    density: 1.0,
    attractiveness: 1.0,
    // 初始化的随机大小位置
    initSize: 300,
    // 向心力因子,越大向心力越大
    centripetal: 1,
    // 冷却因子
    coolDown: 0.99,
    // 分类里如果有样式会覆盖节点默认样式
    itemStyle: {
      normal: {
        // color: 各异,
        label: {
          show: false
          // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
        },
        nodeStyle: {
          brushType: 'both',
          color: '#f08c2e',
          strokeColor: '#5182ab'
        },
        linkStyle: {
          strokeColor: '#5182ab'
        }
      },
      emphasis: {
        // color: 各异,
        label: {
          show: false
          // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
        },
        nodeStyle: {},
        linkStyle: {}
      }
    }
  },

  chord: {
    radius: ['65%', '75%'],
    center: ['50%', '50%'],
    padding: 2,
    sort: 'none', // can be 'none', 'ascending', 'descending'
    sortSub: 'none', // can be 'none', 'ascending', 'descending'
    startAngle: 90,
    clockWise: false,
    showScale: false,
    showScaleText: false,
    itemStyle: {
      normal: {
        label: {
          show: true
          // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
        },
        lineStyle: {
          width: 0,
          color: '#000'
        },
        chordStyle: {
          lineStyle: {
            width: 1,
            color: '#666'
          }
        }
      },
      emphasis: {
        lineStyle: {
          width: 0,
          color: '#000'
        },
        chordStyle: {
          lineStyle: {
            width: 2,
            color: '#333'
          }
        }
      }
    }
  },

  island: {
    r: 15,
    calculateStep: 0.1 // 滚轮可计算步长 0.1 = 10%
  },

  markPoint: {
    symbol: 'pin', // 标注类型
    symbolSize: 10, // 标注大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2
    //symbolRotate : null, // 标注旋转控制
    itemStyle: {
      normal: {
        // color: 各异,
        // borderColor: 各异,     // 标注边线颜色,优先于color
        borderWidth: 2, // 标注边线线宽,单位px,默认为1
        label: {
          show: true,
          position: 'inside' // 可选为'left'|'right'|'top'|'bottom'
          // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
        }
      },
      emphasis: {
        // color: 各异
        label: {
          show: true
          // position: 'inside'  // 'left'|'right'|'top'|'bottom'
          // textStyle: null     // 默认使用全局文本样式,详见TEXTSTYLE
        }
      }
    }
  },

  markLine: {
    // 标线起始和结束的symbol介绍类型,如果都一样,可以直接传string
    symbol: ['circle', 'arrow'],
    // 标线起始和结束的symbol大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2
    symbolSize: [2, 4],
    // 标线起始和结束的symbol旋转控制
    //symbolRotate : null,
    itemStyle: {
      normal: {
        // color: 各异,           // 标线主色,线色,symbol主色
        // borderColor: 随color,     // 标线symbol边框颜色,优先于color
        borderWidth: 2, // 标线symbol边框线宽,单位px,默认为2
        label: {
          show: false,
          // 可选为 'start'|'end'|'left'|'right'|'top'|'bottom'
          position: 'inside',
          textStyle: {
            // 默认使用全局文本样式,详见TEXTSTYLE
            color: '#333'
          }
        },
        lineStyle: {
          // color: 随borderColor, // 主色,线色,优先级高于borderColor和color
          // width: 随borderWidth, // 优先于borderWidth
          type: 'solid',
          shadowColor: 'rgba(0,0,0,0)', //默认透明
          shadowBlur: 5,
          shadowOffsetX: 3,
          shadowOffsetY: 3
        }
      },
      emphasis: {
        // color: 各异
        label: {
          show: false
          // position: 'inside' // 'left'|'right'|'top'|'bottom'
          // textStyle: null    // 默认使用全局文本样式,详见TEXTSTYLE
        },
        lineStyle: {}
      }
    }
  },

  textStyle: {
    decoration: 'none',
    fontFamily: 'Arial, Verdana, sans-serif',
    fontFamily2: '微软雅黑', // IE8- 字体模糊并且不支持不同字体混排,额外指定一份
    fontSize: 12,
    fontStyle: 'normal',
    fontWeight: 'normal'
  },

  // 默认标志图形类型列表
  symbolList: [
    'circle',
    'rectangle',
    'triangle',
    'diamond',
    'emptyCircle',
    'emptyRectangle',
    'emptyTriangle',
    'emptyDiamond'
  ],
  loadingText: 'Loading...',
  // 可计算特性配置,孤岛,提示颜色
  calculable: false, // 默认关闭可计算特性
  calculableColor: 'rgba(255,165,0,0.6)', // 拖拽提示边框颜色
  calculableHolderColor: '#ccc', // 可计算占位提示颜色
  nameConnector: ' & ',
  valueConnector: ' : ',
  animation: true,
  animationThreshold: 2500, // 动画元素阀值,产生的图形原素超过2500不出动画
  addDataAnimation: true, // 动态数据接口是否开启动画效果
  animationDuration: 2000,
  animationEasing: 'ExponentialOut' //BounceOut
}

ECharts 折线与柱状图结合双 y 轴

vue
<!-- 责任追究处理情形分析 -->
<template>
  <div class="dynamic">
    <div class="left">
      <h3>违规经营投资资产损失趋势分析</h3>
      <div>
        <div class="lineChartBox" ref="lineChartBox"></div>
      </div>
    </div>
  </div>
</template>

<script>
import * as echarts from 'echarts4'
export default {
  //import引入的组件需要注入到对象中才能使用
  components: {},
  data() {
    //这里存放数据
    return {
      yesterday: 561.22,
      lastMonth: '13,467.15',
      lineOptNum: {
        grid: {
          left: '2%',
          top: '18%',
          right: '8%',
          bottom: '0%',
          containLabel: true
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            // 坐标轴指示器,坐标轴触发有效
            type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
          }
        },
        legend: {
          data: ['违规资产损失金额(万元)', '重大', '较大', '一般'],
          textStyle: {
            color: '#fff', // 图例文字颜色
            fontSize: '10'
          }
        },
        xAxis: {
          type: 'category',
            // axisLabel:{
           // interval:0  x 轴信息全部展示
        //}
          data: [],
          axisLabel: {
            interval: 0,
            textStyle: {
              color: '#fff',
              fontSize: 8,
              width: 50
            }
          }
        },
        yAxis: [
          //这里两个坐标轴,因为下面用的数据有柱状图和折线图,而他们的一个是数值,一个是百分比因此数的范围不一样,因此这里要加入id来定义坐标轴的标记下面 yAxisIndex 相对应其标记号就可以取这个坐标轴线了
          {
            type: 'value',
            id: 0,
            interval:400 // 设置 y 轴间隔值大小
            axisLabel: {
              show: true,
              textStyle: {
                color: '#fff'
              }
            },
            splitLine: {
              //网格线
              lineStyle: {
                type: 'dashed', //设置网格线类型 dotted:虚线   solid:实线
                color: '#44AAFF'
              },
              show: true //隐藏或显示
            }
          },
          {
            nameLocation: 'end',
            id: 1,
            type: 'value',
            axisLabel: {
              show: true,
              textStyle: {
                color: '#fff'
              }
            },
            splitLine: {
              //网格线
              lineStyle: {
                type: 'dashed', //设置网格线类型 dotted:虚线   solid:实线
                color: '#44AAFF'
              },
              show: true //隐藏或显示
            }
          }
        ],
        series: [
          {
            name: '违规资产损失金额(万元)',
            yAxisIndex: 0, //对应y轴的那一组坐标
            data: [],
            type: 'bar',
            itemStyle: {
              normal: {
                color: new echarts.graphic.LinearGradient(
                  0,
                  1,
                  0,
                  0,
                  [
                    {
                      offset: 0,
                      color: '#1DB4FF' // 0% 处的颜色
                    },
                    {
                      offset: 1,
                      color: '#3EDBFF' // 100% 处的颜色
                    }
                  ],
                  false
                )
              }
            },
            barWidth: 24 //柱图宽度
          },
          {
            name: '重大',
            type: 'line',
            yAxisIndex: 1,
            itemStyle: {
              /*设置折线颜色*/
              normal: {
                color: '#DB4537'
              }
            },
            data: [9, 5, 3, 4, 4, 2, 1, 0]
          },
          {
            name: '较大',
            type: 'line',
            yAxisIndex: 1,
            itemStyle: {
              /*设置折线颜色*/
              normal: {
                color: '#FBDB00'
              }
            },
            data: [6, 7, 6, 8, 5, 3, 5, 2]
          },
          {
            name: '一般',
            type: 'line',
            yAxisIndex: 1,
            itemStyle: {
              /*设置折线颜色*/
              normal: {
                color: '#00B091'
              }
            },
            data: [12, 13, 9, 6, 7, 5, 4, 5]
          }
        ]
      }
    }
  },
  //监听属性 类似于data概念
  computed: {},
  created() {},
  mounted() {
    let name = ['2014', '2015', '2016', '2017', '2018', '2019', '2020', '2021']
    let data = [13, 12, 11, 8, 7, 6, 6, 6]
    this.initCharts(data, name)
  },
  //监控data中的数据变化
  watch: {},
  //方法集合
  methods: {
    initCharts(data, time) {
      let param = $.extend(true, {}, this.lineOptNum, {
        xAxis: {
          data: time
        },
        series: [
          {
            data: data
          }
        ]
      })

      let $dom = this.$refs['lineChartBox']
      this.chartTrend = this.$echarts.init($dom)
      this.chartTrend.resize()
      this.chartTrend.clear()
      this.chartTrend.setOption(param)
    }
  }
}
</script>
<style scoped lang="less">
.dynamic {
  width: 100%;
  height: 100%;
  & > div {
    width: 100%;
    height: 100%;
    float: left;
    background-image: url(../../../static/images/finance.png);
    background-size: 100% 100%;
    background-repeat: no-repeat;
    h3 {
      height: 32px;
      font-size: 20px;
      font-weight: 400;
      color: #ffffff;
      opacity: 0.8;
      line-height: 32px;
      text-indent: 34px;
      text-shadow: 0px 0px 5px #2cc5ff;
    }
    div {
      width: 100%;
      height: calc(100% - 32px);
      .lineChartBox {
        margin-left: 3%;
        width: 100%;
        height: 100%;
      }
    }
  }
}
</style>

地图图表(中国)

  • 代码中所需文件可在本目录下 ditu(中国)文件夹找到
vue
<template>
  <div>
    <div
      id="myChart1"
      :style="{ width: width + 'px', height: height + 'px' }"
    ></div>
  </div>
</template>

<script>
import { MapData } from '@/api'
// import { mapState } from 'vuex'
// import geoCoordMap from '@/assets/geoCoordMap.js'
// let geoCoordMap = {
//   新疆玛纳斯基地: [86.22, 44.3],
//   九江: [116.0, 29.7],
//   新乡: [116.402217, 35.311657],
//   若羌县: [88.17, 39.02],
//   上海: [121.4648, 31.2891],
//   东莞: [113.8953, 22.901],
//   东营: [118.7073, 37.5513],
//   中山: [113.4229, 22.478],
//   临汾: [111.4783, 36.1615],
//   临沂: [118.3118, 35.2936],
//   丹东: [124.541, 40.4242],
//   丽水: [119.5642, 28.1854],
//   乌鲁木齐: [87.9236, 43.5883],
//   佛山: [112.8955, 23.1097],
//   保定: [115.0488, 39.0948],
//   兰州: [103.5901, 36.3043],
//   包头: [110.3467, 41.4899],
//   北京: [116.4551, 40.2539],
//   北海: [109.314, 21.6211],
//   南京: [118.8062, 31.9208],
//   南宁: [108.479, 23.1152],
//   南昌: [116.0046, 28.6633],
//   南通: [121.1023, 32.1625],
//   厦门: [118.1689, 24.6478],
//   台州: [121.1353, 28.6688],
//   合肥: [117.29, 32.0581],
//   呼和浩特: [111.4124, 40.4901],
//   咸阳: [108.4131, 34.8706],
//   哈尔滨: [127.9688, 45.368],
//   唐山: [118.4766, 39.6826],
//   嘉兴: [120.9155, 30.6354],
//   大同: [113.7854, 39.8035],
//   大连: [122.2229, 39.4409],
//   天津: [117.4219, 39.4189],
//   太原: [112.3352, 37.9413],
//   威海: [121.9482, 37.1393],
//   宁波: [121.5967, 29.6466],
//   宝鸡: [107.1826, 34.3433],
//   宿迁: [118.5535, 33.7775],
//   常州: [119.4543, 31.5582],
//   广州: [113.5107, 23.2196],
//   廊坊: [116.521, 39.0509],
//   延安: [109.1052, 36.4252],
//   张家口: [115.1477, 40.8527],
//   徐州: [117.5208, 34.3268],
//   德州: [116.6858, 37.2107],
//   惠州: [114.6204, 23.1647],
//   成都: [103.9526, 30.7617],
//   扬州: [119.4653, 32.8162],
//   承德: [117.5757, 41.4075],
//   拉萨: [91.1865, 30.1465],
//   无锡: [120.3442, 31.5527],
//   日照: [119.2786, 35.5023],
//   昆明: [102.9199, 25.4663],
//   杭州: [119.5313, 29.8773],
//   枣庄: [117.323, 34.8926],
//   柳州: [109.3799, 24.9774],
//   株洲: [113.5327, 27.0319],
//   武汉: [114.3896, 30.6628],
//   汕头: [117.1692, 23.3405],
//   江门: [112.6318, 22.1484],
//   沈阳: [123.1238, 42.1216],
//   沧州: [116.8286, 38.2104],
//   河源: [114.917, 23.9722],
//   泉州: [118.3228, 25.1147],
//   泰安: [117.0264, 36.0516],
//   泰州: [120.0586, 32.5525],
//   济南: [117.1582, 36.8701],
//   济宁: [116.8286, 35.3375],
//   海口: [110.3893, 19.8516],
//   淄博: [118.0371, 36.6064],
//   淮安: [118.927, 33.4039],
//   深圳: [114.5435, 22.5439],
//   清远: [112.9175, 24.3292],
//   温州: [120.498, 27.8119],
//   渭南: [109.7864, 35.0299],
//   湖州: [119.8608, 30.7782],
//   湘潭: [112.5439, 27.7075],
//   滨州: [117.8174, 37.4963],
//   潍坊: [119.0918, 36.524],
//   烟台: [120.7397, 37.5128],
//   玉溪: [101.9312, 23.8898],
//   珠海: [113.7305, 22.1155],
//   盐城: [120.2234, 33.5577],
//   盘锦: [121.9482, 41.0449],
//   石家庄: [114.4995, 38.1006],
//   福州: [119.4543, 25.9222],
//   秦皇岛: [119.2126, 40.0232],
//   绍兴: [120.564, 29.7565],
//   聊城: [115.9167, 36.4032],
//   肇庆: [112.1265, 23.5822],
//   舟山: [122.2559, 30.2234],
//   苏州: [120.6519, 31.3989],
//   莱芜: [117.6526, 36.2714],
//   菏泽: [115.6201, 35.2057],
//   营口: [122.4316, 40.4297],
//   葫芦岛: [120.1575, 40.578],
//   衡水: [115.8838, 37.7161],
//   衢州: [118.6853, 28.8666],
//   西宁: [101.4038, 36.8207],
//   西安: [109.1162, 34.2004],
//   贵阳: [106.6992, 26.7682],
//   连云港: [119.1248, 34.552],
//   邢台: [114.8071, 37.2821],
//   邯郸: [114.4775, 36.535],
//   郑州: [113.4668, 34.6234],
//   鄂尔多斯: [108.9734, 39.2487],
//   重庆: [107.7539, 30.1904],
//   金华: [120.0037, 29.1028],
//   铜川: [109.0393, 35.1947],
//   银川: [106.3586, 38.1775],
//   镇江: [119.4763, 31.9702],
//   长春: [125.8154, 44.2584],
//   长沙: [113.0823, 28.2568],
//   长治: [112.8625, 36.4746],
//   阳泉: [113.4778, 38.0951],
//   青岛: [120.4651, 36.3373],
//   韶关: [113.7964, 24.7028],
//   浙江: [120.5313, 29.0773]
// }
let china = require('@/assets/china.json')
export default {
  name: 'hello',
  data() {
    return {
      // 数据流出
      GZData: [
        [
          {
            name: '浙江'
          },
          {
            name: '浙江',
            value: 200
          }
        ],
        [
          {
            name: '浙江'
          },
          {
            name: '呼和浩特',
            value: 90
          }
        ],
        [
          {
            name: '浙江'
          },
          {
            name: '昆明',
            value: 40
          }
        ],
        [
          {
            name: '浙江'
          },
          {
            name: '成都',
            value: 10
          }
        ],
        [
          {
            name: '浙江'
          },
          {
            name: '兰州',
            value: 95
          }
        ],
        [
          {
            name: '浙江'
          },
          {
            name: '银川',
            value: 90
          }
        ],
        [
          {
            name: '浙江'
          },
          {
            name: '西宁',
            value: 80
          }
        ]
      ],
      // 数据流入
      ZJData: [
        [
          {
            name: '郑州',
            value: 90
          },
          {
            name: '浙江'
          }
        ],
        [
          {
            name: '连云港',
            value: 100
          },
          {
            name: '浙江'
          }
        ],
        [
          {
            name: '贵阳',
            value: 10
          },
          {
            name: '浙江'
          }
        ],
        [
          {
            name: '营口',
            value: 90
          },
          {
            name: '浙江'
          }
        ],
        [
          {
            name: '石家庄',
            value: 80
          },
          {
            name: '浙江'
          }
        ]
      ]
    }
  },
  props: {
    width: Number,
    height: Number,
    mapStyle: Object
  },
  computed: {
    // ...mapState(['MapData']) // 读取 vuex 中保存的地图信息
  },
  created() {
    this.MapData() // 获取 大额资金大额资金省内地图
    this.$echarts5.registerMap('china', china)
  },
  mounted() {
    // this.drawMap()
  },
  methods: {
    // 获取 大额资金大额资金省内地图
    async MapData() {
      const { data } = await MapData({
        payFlag: '1'
      })
      if (data.result === 401 && data.result !== 0) {
        if (data.result === 401) {
          this.$router.push('/')
        }
        return this.$message.error(data.msg)
      }
      let geoCoordMap = {} // 准备地区经纬度
      let outData = [] // 准备数据流出地区
      let inData = [] // 准备数据流入地区
      data.data.rows.forEach(item => {
        geoCoordMap[item.from_province] = item.from_info.split(',')
        geoCoordMap[item.to_province] = item.to_info.split(',')
        // 1 为支出,0 为收入
        if (item.pay_flag == 1) {
          outData.push([
            { name: item.from_province },
            { name: item.to_province, value: 120 }
          ])
        } else {
          inData.push([
            { name: item.to_province, value: 120 },
            { name: item.from_province }
          ])
        }
      })
      this.GZData = outData
      this.ZJData = inData
      this.drawMap(geoCoordMap)
      // console.log(geoCoordMap)
      // this.$store.commit('setMapData', data.data.rows) // 将获取到的数据存入 vuex 中
    },
    drawMap(geoCoordMap) {
      // 基于准备好的dom,初始化echarts实例
      let myChart1 = this.$echarts5.init(document.getElementById('myChart1'))
      var convertData = function (data) {
        var res = []
        for (var i = 0; i < data.length; i++) {
          var dataItem = data[i]
          var fromCoord = geoCoordMap[dataItem[0].name]
          var toCoord = geoCoordMap[dataItem[1].name]
          if (fromCoord && toCoord) {
            res.push([
              {
                coord: fromCoord
              },
              {
                coord: toCoord
              }
            ])
          }
        }
        return res
      }
      var color = ['#00E686', '#fb4e4d']
      var series = []
      ;[
        ['数据流出', this.GZData],
        ['数据流入', this.ZJData]
      ].forEach(function (item, i) {
        series.push(
          {
            name: item[0],
            type: 'lines',
            zlevel: 1,
            effect: {
              show: true,
              period: 5,
              trailLength: 0.5,
              color: '#fff',
              symbolSize: 1,
              borderColor: color[i],
              borderWidth: 4,
              shadowBlur: 1,
              shadowColor: color[i],
              shadowOffsetX: 0,
              shadowOffsetY: 0,
              delay: function () {
                return Math.random() * 5000
              }
            },
            lineStyle: {
              normal: {
                color: color[i],
                width: 1,
                curveness: -0.2
              }
            },
            data: convertData(item[1])
          },
          {
            name: item[0],
            type: 'effectScatter',
            coordinateSystem: 'geo',
            zlevel: 2,
            rippleEffect: {
              brushType: 'stroke'
            },
            label: {
              normal: {
                show: true,
                position: 'right',
                formatter: '{b}',
                color: '#fff',
                fontSize: 10
              }
            },
            symbolSize: function (val) {
              return val[2] / 8
            },
            itemStyle: {
              normal: {
                color: color[i]
              }
            },
            // 当鼠标移入地区时显示弹框信息
            tooltip: {
              formatter: res => {
                const _html = `<div>${res.seriesName}</div>
                ${res.marker}
                ${res.name}
                <b style="padding-left:10px">${res.data.value[2]}</b>`
                return _html
              }
            },
            data: item[1].map(function (dataItem) {
              let name, value
              if (dataItem[0].value) {
                name = dataItem[0].name
                value = geoCoordMap[dataItem[0].name].concat([
                  dataItem[0].value
                ])
              } else {
                name = dataItem[1].name
                value = geoCoordMap[dataItem[1].name].concat([
                  dataItem[1].value
                ])
              }
              return {
                name: name,
                value: value
              }
            })
          }
        )
      })
      // 绘制图表
      let option = {
        // backgroundColor: "#031439",
        backgroundColor: 'rgba(0,0,0,0)',
        title: {
          left: 'left',
          textStyle: {
            color: '#fff'
          }
        },
        tooltip: {
          trigger: 'item'
        },
        geo: {
          map: 'china',
          zoom: 1.2,
          label: {
            emphasis: {
              show: false
            }
          },
          roam: false,
          itemStyle: {
            normal: {
              areaColor: 'rgba(35, 95, 157, 1)',
              borderColor: '#18cdfe',
              borderWidth: 1,
              shadowBlur: 0,
              shadowColor: '#18cdfe',
              shadowOffsetX: 0.5,
              shadowOffsetY: 1
            },
            emphasis: {
              label: {
                show: false
              },
              areaColor: 'rgba(0, 255, 255, .1)'
            }
          }
        },
        center: [109, 29],
        series: series
      }
      myChart1.setOption(option)
    }
  }
}
</script>

<style>
#myChart1 {
  margin: 0 auto;
  left: -30px;
  top: -16px;
}
</style>

地图图表(浙江)

  • 代码中所需文件可在本目录下 ditu(浙江)文件夹找到
vue
<template>
  <div>
    <div
      id="myChartProvince"
      :style="{ width: width + 'px', height: height + 'px' }"
    ></div>
  </div>
</template>

<script>
let zhejiang = require('@/assets/zhejiang.json')
let geoCoordMap = {
  杭州: [120.206886, 30.271798],
  淳安县: [119.039233, 29.63997],
  慈溪: [121.272205, 30.173936],
  桐庐县: [119.676239, 29.793543],
  衢州: [118.866758, 28.971757],
  丽水: [119.930352, 28.477114],
  舟山: [122.217366, 30.004943],
  台州市: [121.429732, 28.657811],
  绍兴市: [120.586905, 30.053971],
  嘉兴市: [120.754781, 30.749698],
  温州市: [120.716836, 27.992368],
  宁波市: [121.559662, 29.888779]
}
export default {
  name: 'hello',
  data() {
    return {
      GZData: [
        [
          {
            name: '杭州'
          },
          {
            name: '杭州',
            value: 200
          }
        ],
        [
          {
            name: '杭州'
          },
          {
            name: '淳安县',
            value: 90
          }
        ],
        [
          {
            name: '杭州'
          },
          {
            name: '慈溪',
            value: 40
          }
        ],
        [
          {
            name: '杭州'
          },
          {
            name: '桐庐县',
            value: 10
          }
        ],
        [
          {
            name: '杭州'
          },
          {
            name: '衢州',
            value: 95
          }
        ],
        [
          {
            name: '杭州'
          },
          {
            name: '丽水',
            value: 90
          }
        ],
        [
          {
            name: '杭州'
          },
          {
            name: '舟山',
            value: 80
          }
        ]
      ],
      ZJData: [
        [
          {
            name: '台州市',
            value: 90
          },
          {
            name: '杭州'
          }
        ],
        [
          {
            name: '绍兴市',
            value: 100
          },
          {
            name: '杭州'
          }
        ],
        [
          {
            name: '嘉兴市',
            value: 10
          },
          {
            name: '杭州'
          }
        ],
        [
          {
            name: '温州市',
            value: 90
          },
          {
            name: '杭州'
          }
        ],
        [
          {
            name: '宁波市',
            value: 80
          },
          {
            name: '杭州'
          }
        ]
      ]
    }
  },
  props: {
    width: Number,
    height: Number
  },
  created() {
    this.$echarts5.registerMap('zhejiang', zhejiang)
  },
  mounted() {
    this.drawMap()
  },
  methods: {
    drawMap() {
      // 基于准备好的dom,初始化echarts实例
      let myChart = this.$echarts5.init(
        document.getElementById('myChartProvince')
      )
      var convertData = function (data) {
        var res = []
        for (var i = 0; i < data.length; i++) {
          var dataItem = data[i]
          var fromCoord = geoCoordMap[dataItem[0].name]
          var toCoord = geoCoordMap[dataItem[1].name]
          if (fromCoord && toCoord) {
            res.push([
              {
                coord: fromCoord
              },
              {
                coord: toCoord
              }
            ])
          }
        }
        return res
      }
      var color = ['#00E686', '#fb4e4d']
      var series = []
      ;[
        ['数据流出', this.GZData],
        ['数据流入', this.ZJData]
      ].forEach(function (item, i) {
        series.push(
          {
            name: item[0],
            type: 'lines',
            zlevel: 1,
            effect: {
              show: true,
              period: 5,
              trailLength: 0.5,
              color: '#fff',
              symbolSize: 1,
              borderColor: color[i],
              borderWidth: 4,
              shadowBlur: 1,
              shadowColor: color[i],
              shadowOffsetX: 0,
              shadowOffsetY: 0,
              delay: function () {
                return Math.random() * 5000
              }
            },
            lineStyle: {
              normal: {
                color: color[i],
                width: 1,
                curveness: -0.2
              }
            },
            data: convertData(item[1])
          },
          {
            name: item[0],
            type: 'effectScatter',
            coordinateSystem: 'geo',
            zlevel: 2,
            rippleEffect: {
              brushType: 'stroke'
            },
            label: {
              normal: {
                show: true,
                position: 'right',
                formatter: '{b}',
                color: '#fff',
                fontSize: 10
              }
            },
            symbolSize: function (val) {
              return val[2] / 8
            },
            itemStyle: {
              normal: {
                color: color[i]
              }
            },
            data: item[1].map(function (dataItem) {
              let name, value
              if (dataItem[0].value) {
                name = dataItem[0].name
                value = geoCoordMap[dataItem[0].name].concat([
                  dataItem[0].value
                ])
              } else {
                name = dataItem[1].name
                value = geoCoordMap[dataItem[1].name].concat([
                  dataItem[1].value
                ])
              }
              return {
                name: name,
                value: value
              }
            })
          }
        )
      })
      // 绘制图表
      let option = {
        // backgroundColor: "#031439",
        backgroundColor: 'rgba(0,0,0,0)',
        title: {
          left: 'left',
          textStyle: {
            color: '#fff'
          }
        },
        tooltip: {
          trigger: 'item'
        },
        geo: {
          map: 'zhejiang',
          zoom: 1.2,
          label: {
            emphasis: {
              show: false
            }
          },
          roam: false,
          aspectScale: 0.88,
          itemStyle: {
            normal: {
              areaColor: 'rgba(35, 95, 157, 1)',
              borderColor: '#18cdfe',
              borderWidth: 1,
              shadowBlur: 0,
              shadowColor: '#18cdfe',
              shadowOffsetX: 0.5,
              shadowOffsetY: 1
            },
            emphasis: {
              label: {
                show: false
              },
              areaColor: 'rgba(0, 255, 255, .1)'
            }
          }
        },
        series: series
      }
      myChart.setOption(option)
    }
  }
}
</script>

<style>
#myChartProvince {
  left: 75px;
}
</style>

地图自定义文字

vue
<template>
  <div>
    <div
      id="myChart"
      :style="{ width: width + 'px', height: height + 'px' }"
    ></div>
  </div>
</template>

<script>
let zhejiang = require('@/assets/zhejiang.json')
export default {
  data() {
    return {
      // 地图各省数据
      dataArr: [
        { name: '杭州市', value: 12 },
        { name: '湖州市', value: 3 },
        { name: '嘉兴市', value: 0 },
        { name: '绍兴市', value: 2 },
        { name: '宁波市', value: 2 },
        { name: '金华市', value: 0 },
        { name: '台州市', value: 0 },
        { name: '丽水市', value: 2 },
        { name: '温州市', value: 2 },
        { name: '舟山市', value: 2 },
        { name: '衢州市', value: 6 }
      ]
    }
  },
  props: {
    width: {
      type: Number,
      default: 1200
    },
    height: {
      type: Number,
      default: 600
    },
    mapData: {
      type: Array,
      default() {
        return [
          {
            name: '浙江省国有资本运营有限公司',
            adress: '杭州市求是路'
          }
        ]
      }
    }
  },
  created() {
    this.$echarts5.registerMap('china', zhejiang)
  },
  mounted() {
    this.$nextTick(() => {
      this.drawMap()
    })
  },
  methods: {
    drawMap() {
      // console.log(this.dataArr)
      // 基于准备好的dom,初始化echarts实例
      let myChart = this.$echarts5.init(document.getElementById('myChart'))
      // 绘制图表
      let option = {
        // backgroundColor: 'rgba(1, 20, 57, 1)', // 编辑地图背景
        grid: {
          // top: '30%'
        },
        // 控制地图图例样式
        visualMap: {
          show: false,
          type: 'piecewise',
          right: '100',
          top: 'bottom',
          // orient: 'vertical',
          orient: 'horizontal',
          color: '#fff',
          itemGap: 10,
          align: 'left',
          pieces: [
            { gt: 10, lte: 100, label: '10以上' },
            { gt: 1, lte: 10, label: '1到10以内' },
            { gt: -1, lte: 1, label: '1以内' }
          ],
          inRange: {
            color: ['#64bfff', '#00b5ff', '#266bff'],
            symbol: 'rect'
          },
          textStyle: {
            color: '#fff',
            fontSize: '15'
          }
        },
        // 当鼠标移动到对应地区时会显示提示框
        // tooltip: {
        //   padding: 0,
        //   enterable: true,
        //   transitionDuration: 1,
        //   textStyle: {
        //     color: '#000',
        //     decoration: 'none'
        //   },
        //   position: 'top',
        //   className: 'tooltips',
        //   formatter: function(params) {
        //     var tipHtml = ''
        //     if (!params.data) {
        //       return tipHtml
        //     }
        //     tipHtml = `<div class="tooltip">
        //               <span class="name">${params.data.name}</span>
        //               <span class="value">${params.data.value}家</span>
        //             </div>`

        //     return tipHtml
        //   }
        // },
        series: [
          {
            name: '',
            type: 'map',
            mapType: 'china',
            // top: '25%',
            center: [120, 29.1], // 控制地图对齐位置
            zoom: 3.5,
            label: {
              normal: {
                show: true,
                color: '#ffffff',
                fontSize: 18,
                /////////////////////////////// 控制地区自定义文字
                formatter(params) {
                  return `${params.data.name}\n${params.data.value}家`
                }
              }
              ///////////////////////////////////////////////// 控制地区自定义文字
              // emphasis: {
              //   show: false,
              //   color: '#ffffff',
              //   fontSize: 25,
              //   // 控制地区自定义文字
              //   formatter(params) {
              //     return `${params.data.name}\n${params.data.value}家`
              //   }
              // }
            },
            itemStyle: {
              normal: {
                label: {
                  show: false
                },
                borderWidth: 2,
                borderColor: '#5c97ff'
              },
              emphasis: {
                label: {
                  show: true
                },
                areaColor: '#18cdfe',
                color: '#fff'
              }
            },
            data: this.dataArr
          }
        ]
      }
      myChart.setOption(option)
      // function showTooltip() {
      //   myChart.dispatchAction({
      //     type: 'showTip',
      //     seriesIndex: 0,
      //     dataIndex: 0
      //   })
      // }
      // showTooltip()
    }
  }
}
</script>

<style lang="less" scoped>
// 控制提示框样式
// /deep/ .tooltipbg {
//   background-color: rgba(250, 87, 87, 0) !important;
//   border: none !important;
//   padding: 0 !important;
//   box-shadow: none !important;
// }
// /deep/ .tooltipLine {
//   position: absolute;
//   top: 0;
//   left: 0;
//   width: 109px;
//   height: 52px;
//   background: url(../../assets/img/tooltipLine.png) no-repeat;
// }
// /deep/ .tooltipBox {
//   border: 1px solid #3793de;
//   font-size: 10px;
//   color: #ffffff;
//   padding: 10px;
//   margin: 25px 0 0 89px;
//   background: rgba(7, 34, 76, 0.5);
//   box-shadow: -2px -2px 20px #3793de inset;
//   border-radius: 5px;
//   .tooltipName {
//     padding: 0 10px 0 20px;
//     font-size: 16px;
//     line-height: 30px;
//     border-bottom: 1px solid #3793de;
//     margin-bottom: 10px;
//   }
//   .tooltipItem {
//     border-left: 3px solid #3793de;
//     line-height: 30px;
//     padding-left: 5%;
//     span {
//       display: inline-block;
//       text-align: left;
//     }
//     span:nth-child(1) {
//       width: 25%;
//     }
//     span:nth-child(2) {
//       width: 40%;
//     }
//     span:nth-child(3) {
//       width: 30%;
//       color: #00a58b;
//     }
//   }
//   .companyName {
//     display: flex;
//     justify-content: space-between;
//     font-size: 14px;
//     line-height: 25px;
//     margin: 10px 0 10px 0;
//     border-bottom: 1px solid #3793de;
//     span:nth-child(1) {
//       margin-right: 20px;
//     }
//     span:nth-child(2) {
//       width: calc(50% - 20px);
//       margin-right: 20px;
//       text-align: left;
//     }
//   }
//   .companyList {
//     height: 115px;
//     overflow: auto;
//   }
//   ::-webkit-scrollbar {
//     width: 0;
//   }
//   .companyItme {
//     display: flex;
//     justify-content: space-between;
//     line-height: 28px;
//     span:nth-child(1) {
//       margin-right: 20px;
//     }
//     span:nth-child(2) {
//       width: calc(50% - 20px);
//       margin-right: 20px;
//       text-align: left;
//     }
//   }
// }
// /deep/ .tooltips {
//   height: 100px;
//   width: 200px;
//   background: url(../../assets/img/tooltip2.png) no-repeat center transparent !important;
//   border: none !important;
//   box-shadow: none !important;
//   div {
//     display: none;
//   }
//   .tooltip {
//     display: block;
//     color: #ffffff;
//     padding: 28px 0 28px 75px;
//     span {
//       display: block;
//     }
//     .name {
//       font-size: 24px;
//       padding-bottom: 20px;
//     }
//     .value {
//       font-size: 18px;
//     }
//   }
// }
</style>

实现图例两端排列

vue
<!-- 省国资财务动态统计 -->
<template>
  <div>
    <div class="organization">
      <div class="checkbtn">
        <div
          :style="{
            backgroundImage:
              type == 1
                ? clickStyle.style
                : 'url(../../../static/images/select_left.png)'
          }"
          @click="handelClick(1)"
        >
          组织概况
        </div>
        <div
          :style="{
            backgroundImage:
              type == 2
                ? clickStyle.style
                : 'url(../../../static/images/select_content.png)'
          }"
          @click="handelClick(2)"
        >
          星级组织
        </div>
        <div
          :style="{
            backgroundImage:
              type == 3
                ? clickStyle.style
                : 'url(../../../static/images/select_right.png)'
          }"
          @click="handelClick(3)"
        >
          预警列表
        </div>
      </div>
      <div v-if="type == 1">
        <div class="ChartsBox" ref="ChartsBox"></div>
      </div>
      <div v-if="type == 2">
        <div class="ChartsRing" ref="ChartsRing1"></div>
      </div>
      <div v-if="type == 3">
        <div class="ChartsBox" ref="ChartsBox2"></div>
      </div>
    </div>
  </div>
</template>

<script>
//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
//例如:import 《组件名称》 from '《组件路径》';
import { mapState } from 'vuex'
import * as echarts from 'echarts4'
export default {
  //import引入的组件需要注入到对象中才能使用
  components: {},
  data() {
    //这里存放数据
    return {
      Clcik_Style: {
        1: {
          style: 'url(../../../static/images/checked.png)'
        },
        2: {
          style: 'url(../../../static/images/checked_center.png)'
        },
        3: {
          style: 'url(../../../static/images/checked_right.png)'
        }
      },
      type: 1,

      option: {
        textStyle: {
          color: 'white'
        },
        grid: {
          left: '5%',
          right: '10%',
          bottom: '-20%',
          top: '5%',
          containLabel: true
        },
        xAxis: [
          {
            type: 'value',
            show: false
          }
        ],
        yAxis: {
          type: 'category',
          data: []
        },
        series: [
          {
            type: 'bar',
            data: [],
            barWidth: 15,
            itemStyle: {
              //通常情况下:
              normal: {
                //每个柱子的颜色即为colorList数组里的每一项,如果柱子数目多于colorList的长度,则柱子颜色循环使用该数组
                color: function (params) {
                  var colorList = [
                    ['#00B091', '#00D8C4'],
                    ['#D85700', '#EE9000'],
                    ['#DB4537', '#EF7B68']
                  ]
                  var index = params.dataIndex
                  if (params.dataIndex >= colorList.length) {
                    index = params.dataIndex - colorList.length
                  }
                  return new echarts.graphic.LinearGradient(0, 0, 1, 0, [
                    {
                      offset: 0,
                      color: colorList[index][0]
                    },
                    {
                      offset: 1,
                      color: colorList[index][1]
                    }
                  ])
                },
                label: {
                  show: true, //开启显示
                  position: 'right', //在上方显示
                  formatter: '{c}人',
                  textStyle: {
                    //数值样式
                    color: '#FFFFFF',
                    fontSize: 12
                  }
                }
              }
            }
          }
        ]
      },

      option2: {
        legend: {
          icon: 'circle',
          orient: 'vertical',
          y: 'center', //延Y轴居中
          x: '50%', //居右显示
          align: 'left',
          itemHeight: 8
        },
        series: [
          {
            name: '访问来源',
            type: 'pie',
            radius: ['40%', '70%'],
            center: ['50%', '50%'],
            avoidLabelOverlap: false,
            hoverAnimation: false,
            itemStyle: {
              borderRadius: 10,
              borderColor: '#010a1e',
              borderWidth: 3
            },
            label: {
              show: false,
              position: 'center'
            },
            emphasis: {
              label: {
                show: false,
                fontSize: '40',
                fontWeight: 'bold'
              }
            },
            labelLine: {
              show: false
            },
            data: [],
            color: [
              '#00ACD8',
              '#FEC825',
              '#FC4D4C',
              '#FEA413',
              '#39C3AB',
              '#72DA80'
            ]
          }
        ]
      },

      option3: {
        textStyle: {
          color: 'white'
        },
        grid: {
          left: '-5%',
          right: '5',
          bottom: '-10%',
          top: '30%',
          containLabel: true
        },
        xAxis: {
          type: 'category',
          show: false
        },
        yAxis: {
          type: 'value',
          show: false,
          data: []
        },
        series: [
          {
            type: 'bar',
            data: [],
            barWidth: 30,
            itemStyle: {
              normal: {
                label: {
                  show: true,
                  position: 'top',
                  formatter: '{b}\n{c}个'
                },
                color: function (params) {
                  var colorlist = [
                    '#00ACD8',
                    '#FEC825',
                    '#FC4D4C',
                    '#FEA413',
                    '#39C3AB'
                  ]
                  return colorlist[params.dataIndex]
                }
              }
            }
          }
        ],
        color: ['#D85700', '#1DB4FF', '#FEA212', '#39C3AB']
      }
    }
  },
  //监听属性 类似于data概念
  computed: {
    ...mapState(['PartyInfo']), // 获取最新的页面右上角公司数据
    clickStyle() {
      return this.Clcik_Style[this.type]
    }
  },
  created() {
    console.log(echarts)
  },
  mounted() {
    // let name = ['党务工作者', '班子成员', '政治宣传员']
    // let data = [11, 14, 18]
    // this.initCharts(name, data)
  },
  //监控data中的数据变化
  watch: {
    PartyInfo(val) {
      // 组织概况
      let name = ['党务工作者', '班子成员', '政治宣传员']
      let data = [val[0].worker, val[0].teamMember, val[0].propagandist]
      this.initCharts(name, data)
      // 组织概况
      // 星级组织
      let dataRing1 = [
        { value: val[0].zeroStar, name: '无星' },
        { value: val[0].oneStar, name: '一星' },
        { value: val[0].twoStar, name: '二星' },
        { value: val[0].threeStar, name: '三星' },
        { value: val[0].fourStar, name: '四星' },
        { value: val[0].fiveStar, name: '五星' }
      ]
      this.initChartsRing(dataRing1)
      // 星级组织
      // 预警列表
      let name2 = [
        '逾期未换届的标黄预警',
        '联合支部预警的标黄预警',
        '组织不健全预警',
        '支部超员预警'
      ]
      let data2 = [
        this.val[0].overdueBranch,
        this.val[0].unionYellowBranch,
        this.val[0].incompleteBranch,
        this.val[0].overcrowdBranch
      ]
      this.initCharts2(name2, data2)
      // 预警列表
    }
  },
  //方法集合
  methods: {
    handelClick(type) {
      this.type = type
      setTimeout(() => {
        if (type == 1) {
          let name = ['党务工作者', '班子成员', '政治宣传员']
          let data = [
            this.PartyInfo[0].worker,
            this.PartyInfo[0].teamMember,
            this.PartyInfo[0].propagandist
          ]
          this.initCharts(name, data)
        } else if (type == 2) {
          let dataRing1 = [
            { value: this.PartyInfo[0].zeroStar, name: '无星' },
            { value: this.PartyInfo[0].oneStar, name: '一星' },
            { value: this.PartyInfo[0].twoStar, name: '二星' },
            { value: this.PartyInfo[0].threeStar, name: '三星' },
            { value: this.PartyInfo[0].fourStar, name: '四星' },
            { value: this.PartyInfo[0].fiveStar, name: '五星' }
          ]
          this.initChartsRing(dataRing1)
        } else if (type == 3) {
          let name = [
            '逾期未换届的标黄预警',
            '联合支部预警的标黄预警',
            '组织不健全预警',
            '支部超员预警'
          ]
          let data = [
            this.PartyInfo[0].overdueBranch,
            this.PartyInfo[0].unionYellowBranch,
            this.PartyInfo[0].incompleteBranch,
            this.PartyInfo[0].overcrowdBranch
          ]
          this.initCharts2(name, data)
        }
      })
    },

    initCharts(name, data) {
      let param = $.extend(true, {}, this.option, {
        yAxis: {
          data: name
        },
        series: [
          {
            data: data
          }
        ]
      })
      let $dom = this.$refs['ChartsBox']
      this.chartTrend = this.$echarts.init($dom)
      this.chartTrend.resize()
      this.chartTrend.clear()
      this.option && this.chartTrend.setOption(param)
    },

    ////////////////////////////////////////////////////////////////
    // 将需要分开的数据定义样式和数据 data
    initChartsRing(data) {
      let param = $.extend(true, {}, this.option2, {
        // 定义图例
        legend: [
          {
            icon: 'circle',
            orient: 'vertical',
            y: 'center', //延Y轴居中
            // x: '50%', //居右显示
            left: '1%',
            itemHeight: 8,
            data: data.slice(0, 3),

            // textStyle: {
            //   color: '#ffffff',
            //   fontSize: 8
            // },
            textStyle: {
              rich: {
                a: {
                  verticalAlign: 'right',
                  fontSize: 15,
                  align: 'left',
                  color: '#ffffff',
                  // padding:[0,28,0,0],
                  width: 30
                },
                b: {
                  fontSize: 15,
                  align: 'left',
                  color: '#ffffff',
                  // padding:[0,28,0,0],
                  width: 50
                },
                c: {
                  fontSize: 15,
                  align: 'left',
                  color: '#ffffff',
                  width: 30
                }
              }
            },
            formatter: name => {
              let total = 0
              let target
              for (let i = 0; i < data.length; i++) {
                total += parseFloat(data[i].value)
                if (data[i].name === name) {
                  target = parseFloat(data[i].value)
                }
              }
              let arr = [
                '{a|' +
                  name +
                  '}{b|' +
                  target +
                  '个}{c|' +
                  ((target / total) * 100).toFixed(2) +
                  '%}'
              ]

              return arr.join('\n')
            }
          },
          {
            icon: 'circle',
            orient: 'vertical',
            y: 'center', //延Y轴居中
            // x: '50%', //居右显示
            right: '5%',
            itemHeight: 8,
            data: data.slice(3, 6),
            // textStyle: {
            //   color: '#ffffff',
            //   fontSize: 8
            // },
            textStyle: {
              rich: {
                a: {
                  verticalAlign: 'right',
                  fontSize: 15,
                  align: 'left',
                  color: '#ffffff',
                  // padding:[0,28,0,0],
                  width: 30
                },
                b: {
                  fontSize: 15,
                  align: 'left',
                  color: '#ffffff',
                  // padding:[0,28,0,0],
                  width: 50
                },
                c: {
                  fontSize: 15,
                  align: 'left',
                  color: '#ffffff',
                  width: 30
                }
              }
            },
            formatter: name => {
              let total = 0
              let target
              for (let i = 0; i < data.length; i++) {
                total += parseFloat(data[i].value)
                if (data[i].name === name) {
                  target = parseFloat(data[i].value)
                }
              }
              let arr = [
                '{a|' +
                  name +
                  '}{b|' +
                  target +
                  '个}{c|' +
                  ((target / total) * 100).toFixed(2) +
                  '%}'
              ]

              return arr.join('\n')
            }
          }
        ],
        ////////////////////////////////////////////////////////////////

        series: [
          {
            data: data
          }
        ]
      })
      let $dom = this.$refs['ChartsRing1']
      this.chartTrend = this.$echarts.init($dom)
      this.chartTrend.resize()
      this.chartTrend.clear()
      this.option2 && this.chartTrend.setOption(param, true)
    },

    initCharts2(name, data) {
      let param = $.extend(true, {}, this.option3, {
        xAxis: {
          data: name
        },
        series: [
          {
            data: data
          }
        ]
      })
      let $dom = this.$refs['ChartsBox2']
      this.chartTrend = this.$echarts.init($dom)
      this.chartTrend.resize()
      this.chartTrend.clear()
      this.option3 && this.chartTrend.setOption(param)
    }
  }
}
</script>
<style scoped lang="less">
.organization {
  width: 100%;
  height: 150px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  box-sizing: border-box;
  .checkbtn {
    height: 21px;
    display: flex;
    margin-top: 20px;
    justify-content: space-evenly;
    div {
      cursor: pointer;
      width: 30%;
      text-align: center;
      background-image: url(../../../static/images/select_content.png);
      background-size: 136px 21px;
      background-repeat: no-repeat;
      pointer-events: auto;
    }
  }
  & > div:last-child {
    width: 100%;
    height: 100%;

    // .organization_right{
    //     width:50%;
    //     height: 100%;
    //     float: left;
    // }
  }

  .ChartsBox {
    height: 108px;
    width: 100%;
    margin: 0 auto;
    overflow: hidden;
  }
  .ChartsRing {
    height: 108px;
    width: 100%;
    float: left;
    overflow: hidden;
  }
}
</style>

地图飞线效果修改数值

vue
<template>
  <div>
    <div
      id="myChart1"
      :style="{ width: width + 'px', height: height + 'px' }"
    ></div>
  </div>
</template>

<script>
import { MapData, provinceMap2 } from '@/api'
import { mapState } from 'vuex'
// import geoCoordMap from '@/assets/geoCoordMap.js'
// let geoCoordMap = {
//   新疆玛纳斯基地: [86.22, 44.3],
//   九江: [116.0, 29.7],
//   新乡: [116.402217, 35.311657],
//   若羌县: [88.17, 39.02],
//   上海: [121.4648, 31.2891],
//   东莞: [113.8953, 22.901],
//   东营: [118.7073, 37.5513],
//   中山: [113.4229, 22.478],
//   临汾: [111.4783, 36.1615],
//   临沂: [118.3118, 35.2936],
//   丹东: [124.541, 40.4242],
//   丽水: [119.5642, 28.1854],
//   乌鲁木齐: [87.9236, 43.5883],
//   佛山: [112.8955, 23.1097],
//   保定: [115.0488, 39.0948],
//   兰州: [103.5901, 36.3043],
//   包头: [110.3467, 41.4899],
//   北京: [116.4551, 40.2539],
//   北海: [109.314, 21.6211],
//   南京: [118.8062, 31.9208],
//   南宁: [108.479, 23.1152],
//   南昌: [116.0046, 28.6633],
//   南通: [121.1023, 32.1625],
//   厦门: [118.1689, 24.6478],
//   台州: [121.1353, 28.6688],
//   合肥: [117.29, 32.0581],
//   呼和浩特: [111.4124, 40.4901],
//   咸阳: [108.4131, 34.8706],
//   哈尔滨: [127.9688, 45.368],
//   唐山: [118.4766, 39.6826],
//   嘉兴: [120.9155, 30.6354],
//   大同: [113.7854, 39.8035],
//   大连: [122.2229, 39.4409],
//   天津: [117.4219, 39.4189],
//   太原: [112.3352, 37.9413],
//   威海: [121.9482, 37.1393],
//   宁波: [121.5967, 29.6466],
//   宝鸡: [107.1826, 34.3433],
//   宿迁: [118.5535, 33.7775],
//   常州: [119.4543, 31.5582],
//   广州: [113.5107, 23.2196],
//   廊坊: [116.521, 39.0509],
//   延安: [109.1052, 36.4252],
//   张家口: [115.1477, 40.8527],
//   徐州: [117.5208, 34.3268],
//   德州: [116.6858, 37.2107],
//   惠州: [114.6204, 23.1647],
//   成都: [103.9526, 30.7617],
//   扬州: [119.4653, 32.8162],
//   承德: [117.5757, 41.4075],
//   拉萨: [91.1865, 30.1465],
//   无锡: [120.3442, 31.5527],
//   日照: [119.2786, 35.5023],
//   昆明: [102.9199, 25.4663],
//   杭州: [119.5313, 29.8773],
//   枣庄: [117.323, 34.8926],
//   柳州: [109.3799, 24.9774],
//   株洲: [113.5327, 27.0319],
//   武汉: [114.3896, 30.6628],
//   汕头: [117.1692, 23.3405],
//   江门: [112.6318, 22.1484],
//   沈阳: [123.1238, 42.1216],
//   沧州: [116.8286, 38.2104],
//   河源: [114.917, 23.9722],
//   泉州: [118.3228, 25.1147],
//   泰安: [117.0264, 36.0516],
//   泰州: [120.0586, 32.5525],
//   济南: [117.1582, 36.8701],
//   济宁: [116.8286, 35.3375],
//   海口: [110.3893, 19.8516],
//   淄博: [118.0371, 36.6064],
//   淮安: [118.927, 33.4039],
//   深圳: [114.5435, 22.5439],
//   清远: [112.9175, 24.3292],
//   温州: [120.498, 27.8119],
//   渭南: [109.7864, 35.0299],
//   湖州: [119.8608, 30.7782],
//   湘潭: [112.5439, 27.7075],
//   滨州: [117.8174, 37.4963],
//   潍坊: [119.0918, 36.524],
//   烟台: [120.7397, 37.5128],
//   玉溪: [101.9312, 23.8898],
//   珠海: [113.7305, 22.1155],
//   盐城: [120.2234, 33.5577],
//   盘锦: [121.9482, 41.0449],
//   石家庄: [114.4995, 38.1006],
//   福州: [119.4543, 25.9222],
//   秦皇岛: [119.2126, 40.0232],
//   绍兴: [120.564, 29.7565],
//   聊城: [115.9167, 36.4032],
//   肇庆: [112.1265, 23.5822],
//   舟山: [122.2559, 30.2234],
//   苏州: [120.6519, 31.3989],
//   莱芜: [117.6526, 36.2714],
//   菏泽: [115.6201, 35.2057],
//   营口: [122.4316, 40.4297],
//   葫芦岛: [120.1575, 40.578],
//   衡水: [115.8838, 37.7161],
//   衢州: [118.6853, 28.8666],
//   西宁: [101.4038, 36.8207],
//   西安: [109.1162, 34.2004],
//   贵阳: [106.6992, 26.7682],
//   连云港: [119.1248, 34.552],
//   邢台: [114.8071, 37.2821],
//   邯郸: [114.4775, 36.535],
//   郑州: [113.4668, 34.6234],
//   鄂尔多斯: [108.9734, 39.2487],
//   重庆: [107.7539, 30.1904],
//   金华: [120.0037, 29.1028],
//   铜川: [109.0393, 35.1947],
//   银川: [106.3586, 38.1775],
//   镇江: [119.4763, 31.9702],
//   长春: [125.8154, 44.2584],
//   长沙: [113.0823, 28.2568],
//   长治: [112.8625, 36.4746],
//   阳泉: [113.4778, 38.0951],
//   青岛: [120.4651, 36.3373],
//   韶关: [113.7964, 24.7028],
//   浙江: [120.5313, 29.0773]
// }
let china = require('@/assets/china.json')
export default {
  name: 'hello',
  data() {
    return {
      panyName: {
        省国资委: '浙江省人民政府国有资产监督管理委员会',
        省国资运营公司: '浙江省国有资本运营有限公司',
        物产中大: '物产中大集团股份有限公司',
        省建设集团: '浙江省建设投资集团股份有限公司',
        省机电集团: '浙江省机电集团有限公司',
        省国贸集团: '浙江省国际贸易集团有限公司',
        省旅投集团: '浙江省旅游投资集团有限公司',
        杭钢集团: '杭州钢铁集团有限公司',
        巨化集团: '巨化集团有限公司',
        省能源集团: '浙江省能源集团有限公司',
        省交投集团: '浙江省交通投资集团有限公司',
        省农发集团: '浙江省农村发展集团有限公司',
        省机场集团: '浙江省机场集团有限公司',
        省海港集团: '浙江省海港投资运营集团有限公司',
        省二轻集团: '浙江省二轻集团有限责任公司',
        安邦护卫集团: '安邦护卫集团股份有限公司',
        浙大控股: '浙江大学控股集团有限公司'
      },
      // 数据流出
      GZData: [
        [
          {
            name: '浙江'
          },
          {
            name: '浙江',
            value: 200
          }
        ],
        [
          {
            name: '浙江'
          },
          {
            name: '呼和浩特',
            value: 90
          }
        ],
        [
          {
            name: '浙江'
          },
          {
            name: '昆明',
            value: 40
          }
        ],
        [
          {
            name: '浙江'
          },
          {
            name: '成都',
            value: 10
          }
        ],
        [
          {
            name: '浙江'
          },
          {
            name: '兰州',
            value: 95
          }
        ],
        [
          {
            name: '浙江'
          },
          {
            name: '银川',
            value: 90
          }
        ],
        [
          {
            name: '浙江'
          },
          {
            name: '西宁',
            value: 80
          }
        ]
      ],
      // 数据流入
      ZJData: [
        [
          {
            name: '郑州',
            value: 90
          },
          {
            name: '浙江'
          }
        ],
        [
          {
            name: '连云港',
            value: 100
          },
          {
            name: '浙江'
          }
        ],
        [
          {
            name: '贵阳',
            value: 10
          },
          {
            name: '浙江'
          }
        ],
        [
          {
            name: '营口',
            value: 90
          },
          {
            name: '浙江'
          }
        ],
        [
          {
            name: '石家庄',
            value: 80
          },
          {
            name: '浙江'
          }
        ]
      ]
    }
  },
  props: {
    width: Number,
    height: Number,
    mapStyle: Object
  },
  computed: {
    // ...mapState(['MapData']) // 读取 vuex 中保存的地图信息
    ...mapState(['headerData']) // 获取最新的页面右上角公司数据
  },
  watch: {
    // 监听页面右上角公司名称变化,动态修改标题
    headerData(val) {
      this.MapData() // 获取 大额资金大额资金省内地图
      this.$echarts5.registerMap('china', china)
    }
  },
  created() {
    this.MapData() // 获取 大额资金大额资金省内地图
    this.$echarts5.registerMap('china', china)
  },
  mounted() {
    // this.drawMap()
  },
  methods: {
    // 获取 大额资金大额资金省内地图
    async MapData() {
      if (this.headerData == '省国资委') {
        const { data } = await MapData({
          payFlag: '1'
        })
        if (data.result === 401 && data.result !== 0) {
          if (data.result === 401) {
            this.$router.push('/')
          }
          return this.$message.error(data.msg)
        }
        console.log(data.data.rows)
        let geoCoordMap = {} // 准备地区经纬度
        let outData = [] // 准备数据流出地区
        let inData = [] // 准备数据流入地区
        data.data.rows.forEach(item => {
          geoCoordMap[item.from_province] = item.from_info.split(',')
          geoCoordMap[item.to_province] = item.to_info.split(',')
          // 1 为支出,0 为收入
          if (item.pay_flag == 1) {
            outData.push([
              { name: item.from_province },
              //////////////////////////在这里准备数据
              { name: item.to_province, value: 120, num: item.amt_cny }
            ])
          } else {
            inData.push([
              //////////////////////////在这里准备数据
              { name: item.to_province, value: 120, num: item.amt_cny },
              { name: item.from_province }
            ])
          }
        })
        this.GZData = outData
        this.ZJData = inData
        this.drawMap(geoCoordMap)
      } else {
        const { data } = await provinceMap2({
          pay_flag: '1',
          corp_name: this.panyName[this.headerData]
        })
        if (data.result === 401 && data.result !== 0) {
          if (data.result === 401) {
            this.$router.push('/')
          }
          return this.$message.error(data.msg)
        }
        let geoCoordMap = {} // 准备地区经纬度
        let outData = [] // 准备数据流出地区
        let inData = [] // 准备数据流入地区
        data.data.rows.forEach(item => {
          geoCoordMap[item.from_province] = item.from_info.split(',')
          geoCoordMap[item.to_province] = item.to_info.split(',')
          // 1 为支出,0 为收入
          if (item.pay_flag == 1) {
            outData.push([
              { name: item.from_province },
              //////////////////////////在这里准备数据
              { name: item.to_province, value: 120, num: item.amt_cny }
            ])
          } else {
            inData.push([
              //////////////////////////在这里准备数据
              { name: item.to_province, value: 120, num: item.amt_cny },
              { name: item.from_province }
            ])
          }
        })
        this.GZData = outData
        this.ZJData = inData
        this.drawMap(geoCoordMap)
      }

      // console.log(geoCoordMap)
      // this.$store.commit('setMapData', data.data.rows) // 将获取到的数据存入 vuex 中
    },
    drawMap(geoCoordMap) {
      // 基于准备好的dom,初始化echarts实例
      let myChart1 = this.$echarts5.init(document.getElementById('myChart1'))
      var convertData = function (data) {
        var res = []
        for (var i = 0; i < data.length; i++) {
          var dataItem = data[i]
          var fromCoord = geoCoordMap[dataItem[0].name]
          var toCoord = geoCoordMap[dataItem[1].name]
          if (fromCoord && toCoord) {
            res.push([
              {
                coord: fromCoord
              },
              {
                coord: toCoord
              }
            ])
          }
        }
        return res
      }
      var color = ['#00E686', '#fb4e4d']
      var series = []
      ;[
        ['数据流出', this.GZData],
        ['数据流入', this.ZJData]
      ].forEach(function (item, i) {
        series.push(
          {
            name: item[0],
            type: 'lines',
            zlevel: 1,
            effect: {
              show: true,
              period: 5,
              trailLength: 0.5,
              color: '#fff',
              symbolSize: 1,
              borderColor: color[i],
              borderWidth: 4,
              shadowBlur: 1,
              shadowColor: color[i],
              shadowOffsetX: 0,
              shadowOffsetY: 0,
              delay: function () {
                return Math.random() * 5000
              }
            },
            lineStyle: {
              normal: {
                color: color[i],
                width: 1,
                curveness: -0.2
              }
            },
            data: convertData(item[1])
          },
          {
            name: item[0],
            type: 'effectScatter',
            coordinateSystem: 'geo',
            zlevel: 2,
            rippleEffect: {
              brushType: 'stroke'
            },
            label: {
              normal: {
                show: true,
                position: 'right',
                formatter: '{b}',
                color: '#fff',
                fontSize: 10
              }
            },
            symbolSize: function (val) {
              return val[2] / 8
            },
            itemStyle: {
              normal: {
                color: color[i]
              }
            },
            // 当鼠标移入地区时显示弹框信息
            tooltip: {
              formatter: res => {
                // 在这里就可以拿到下面准备的数值///////////////////////////////////////
                const _html = `<div>${res.seriesName}</div>
                ${res.marker}
                ${res.name}
                <b style="padding-left:10px">${res.data.num}</b>`
                return _html
              }
            },
            data: item[1].map(function (dataItem) {
              // 在这里准备需要展示的数据 num 需要展示的值 //////////////////////////
              let name, value, num
              if (dataItem[0].value) {
                name = dataItem[0].name
                value = geoCoordMap[dataItem[0].name].concat([
                  dataItem[0].value
                ])
                num = dataItem[0].num
              } else {
                name = dataItem[1].name
                value = geoCoordMap[dataItem[1].name].concat([
                  dataItem[1].value
                ])
                num = dataItem[1].num
              }
              return {
                name: name,
                value: value,
                // 在这里返回////////////////////////////////////////////////////
                num: num
              }
            })
          }
        )
      })
      // 绘制图表
      let option = {
        // backgroundColor: "#031439",
        backgroundColor: 'rgba(0,0,0,0)',
        title: {
          left: 'left',
          textStyle: {
            color: '#fff'
          }
        },
        tooltip: {
          trigger: 'item'
        },
        geo: {
          map: 'china',
          zoom: 1.2,
          label: {
            emphasis: {
              show: false
            }
          },
          roam: false,
          itemStyle: {
            normal: {
              areaColor: 'rgba(35, 95, 157, 1)',
              borderColor: '#18cdfe',
              borderWidth: 1,
              shadowBlur: 0,
              shadowColor: '#18cdfe',
              shadowOffsetX: 0.5,
              shadowOffsetY: 1
            },
            emphasis: {
              label: {
                show: false
              },
              areaColor: 'rgba(0, 255, 255, .1)'
            }
          }
        },
        center: [109, 29],
        series: series
      }
      myChart1.setOption(option)
    }
  }
}
</script>

<style>
#myChart1 {
  margin: 0 auto;
  left: -30px;
  top: -16px;
}
</style>

自定义 tooltip

vue
<template>
  <div class="page">
    <div class="content">
      <p class="legend">
        <span class="rect"></span>
        <span>完成数量</span>
      </p>
      <h3>任务完成情况</h3>
      <div>
        <div class="radarChartBox" ref="radarChartBox"></div>
      </div>
    </div>
  </div>
</template>
<script>
import { TaskCompletion } from '@/api'
import { mapState } from 'vuex'
export default {
  data() {
    return {
      TaskData: [], // 保存获取到的数据
      radarOption: {
        radar: {
          indicator: [],
          radius: 65
        },
        tooltip: {
          show: true,
          position: [0, 0],
          ////////////////////////////////////////////////////////////////////////////////自定义显示数据
          formatter: series => {
            let DataName = ''
            series.data.name2.forEach((item, index) => {
              DataName += `${item}:${series.data.value[index]}%<br>`
            })
            return DataName
          }
          ////////////////////////////////////////////////////////////////////////////////自定义显示数据
        },
        series: [
          {
            name: '完成情况',
            type: 'radar',
            data: [],
            axisLabel: {
              show: true,
              textStyle: { fontSize: 8, color: '#333' }
            }
          }
        ]
      }
    }
  },
  computed: {
    ...mapState(['headerData']), // 获取最新的页面右上角公司数据
    ...mapState(['setheaderId']) // 获取最新的页面右上角公司数据
  },
  watch: {
    headerData(val) {
      this.TaskCompletion()
    }
  },
  created() {
    this.TaskCompletion() // 获取企业改革页面主要任务完成情况概览数据
  },
  methods: {
    // 获取企业改革页面主要任务完成情况概览数据
    async TaskCompletion() {
      const { data } = await TaskCompletion({
        // id: this.setheaderId
        id: -1
      })
      // if (!data.success)
      //   return this.$message.error('当前公司无数据或者请求公司数据失败!')
      if (data.result === 401 && data.result !== 0) {
        if (data.result === 401) {
          this.$router.push('/')
        }
        return this.$message.error(data.msg)
      }
      this.TaskData = data.data.rows
      let data2 = [{ value: [], name2: [] }]
      let time2 = []
      this.TaskData.forEach(item => {
        ////////////////////////////////////////////////////////////////////////////////添加数据
        data2[0].value.push(item.wcbl)
        data2[0].name2.push(item.flmc)
        ////////////////////////////////////////////////////////////////////////////////添加数据
        time2.push({ name: item.flmc })
      })
      this.initCharts(data2, time2)
    },
    initCharts(data, time) {
      let param = $.extend(true, {}, this.radarOption, {
        radar: {
          name: {
            textStyle: {
              color: '#FFF',
              fontSize: '10'
            }
            // lineHeight: 8,
            // padding: [-10, -5, -10, -10]
          },
          indicator: time,
          axisLabel: {
            // 坐标轴文本标签,详见axis.axisLabel
            show: true,
            textStyle: {
              color: 'white', // 坐标轴刻度文字的样式
              fontSize: '5'
            }
          }
        },
        series: [
          {
            symbol: 'none',
            axisLabel: {
              show: true,
              textStyle: { fontSize: 12, color: '#333' }
            },
            data: data,
            areaStyle: {
              color: '#1890FF'
            },
            lineStyle: {
              color: '#1890FF',
              type: 'solid'
            }
          }
        ]
      })
      let $dom = this.$refs['radarChartBox']
      let chartTrend = this.$echarts.init($dom)
      chartTrend.resize()
      chartTrend.clear()
      chartTrend.setOption(param)
    }
  },
  mounted() {
    // let data = [{ value: [5, 10, 15, 20, 25, 30, 35, 40, 45, 50] }]
    // let time = [
    //   { name: '落实一批重大项目', max: 100 },
    //   { name: '长三角一体化发展', max: 100, axisLabel: { show: false } },
    //   { name: '自贸试验区', max: 100, axisLabel: { show: false } },
    //   { name: '业合作发展', max: 100, axisLabel: { show: false } },
    //   { name: '控股公司章程建设', max: 100, axisLabel: { show: false } },
    //   { name: '企业改革发展', max: 100, axisLabel: { show: false } },
    //   { name: '建立董事会向总经理授权', max: 100, axisLabel: { show: false } },
    //   { name: '管理提升运动', max: 100, axisLabel: { show: false } },
    //   { name: '深入参与一带一路', max: 100, axisLabel: { show: false } },
    //   { name: '推进项目开工和建设', max: 100, axisLabel: { show: false } }
    // ]
    // this.initCharts(data, time)
  }
}
</script>
<style lang="less" scoped>
.page {
  width: 100%;
  height: 100%;
  .content {
    width: 100%;
    height: 100%;
    float: left;
    // background-image: url(../../../static/images/finance@2x.png);
    background-image: url(../../../static/images/left2@.png);
    // background-image: url(../../../static/images/dangjianghbbg.png);
    background-size: 100% 105%;
    background-repeat: no-repeat;
    position: relative;
    .legend {
      position: absolute;
      top: 20%;
      right: 5%;
      font-size: 10px;
      .rect {
        display: inline-block;
        width: 15px;
        height: 9px;
        background: #1890ff;
      }
      span:nth-of-type(2) {
        opacity: 0.5;
      }
    }
    h3 {
      height: 32px;
      font-size: 20px;
      font-weight: 400;
      color: #ffffff;
      opacity: 0.8;
      line-height: 25px;
      text-indent: 34px;
      text-shadow: 0px 0px 5px #2cc5ff;
      padding-top: 5px;
    }
    & > div {
      margin-top: 10px;
      width: 100%;
      height: calc(100% - 40px);
      .radarChartBox {
        margin: 0 auto;
        width: 100%;
        height: 100%;
      }
    }
  }
}
</style>

地图下载

http://datav.aliyun.com/tools/atlas/#&lat=31.840232667909365&lng=104.2822265625&zoom=4

地图默认选中与取消选中以及复杂地图

vue
<template>
  <div>
    <div class="map2" id="myChart2"></div>
    <div
      id="myChart"
      :style="{ width: width + 'px', height: height + 'px' }"
    ></div>
  </div>
</template>

<script>
import { enterprisesNum } from '@/api'
import { mapState } from 'vuex'
let zhejiang = require('@/assets/zhejiang.json')
let yiwu = require('@/assets/yiwu.json')
export default {
  data() {
    return {
      mapname: '' // 保存当前点击的地区
    }
  },
  props: {
    width: {
      type: Number,
      default: 1200
    },
    height: {
      type: Number,
      default: 600
    },
    mapData: {
      type: Array,
      default() {
        return [
          {
            name: '浙江省国有资本运营有限公司',
            adress: '杭州市求是路'
          }
        ]
      }
    }
  },
  watch: {
    headerData(val) {},
    mapname(val) {
      // console.log(val)
    }
  },
  computed: {
    ...mapState(['headerData']), // 获取最新的页面右上角公司名称
    ...mapState(['setheaderId']) // 获取最新的页面右上角公司id
  },
  created() {
    // this.enterprisesNum()
    this.$echarts5.registerMap('浙江', zhejiang)
    this.$echarts5.registerMap('义乌', yiwu)
  },
  mounted() {
    this.$nextTick(() => {
      this.drawMap()
      this.drawMap2()
    })
  },
  methods: {
    drawMap() {
      // console.log(this.dataArr)
      // 基于准备好的dom,初始化echarts实例
      let myChart = this.$echarts5.init(document.getElementById('myChart'))
      let myChart2 = this.$echarts5.init(document.getElementById('myChart2'))
      // 监听地图点击事件获取当前点击地区名称
      myChart.on('click', params => {
        if (params.componentType === 'series') {
          this.mapname = params.name
          myChart2.dispatchAction({
            type: 'unselect', // 取消默认选中////////////////////////////
            name: '义乌市'
          })
          console.log(this.mapname)
        }
      })
      // 绘制图表
      let option = {
        // backgroundColor: 'rgba(1, 20, 57, 1)',
        grid: {
          // top: '30%'
        },
        // 控制地图图例样式
        visualMap: {
          show: false,
          type: 'piecewise',
          right: '100',
          top: 'bottom',
          // orient: 'vertical',
          orient: 'horizontal',
          color: '#fff',
          itemGap: 10,
          align: 'left',
          pieces: [
            { gt: 21, lte: 30, label: '1到10以内' },
            { gt: 0, lte: 20, label: '1以内' }
          ],
          inRange: {
            color: '#18cdfe',
            symbol: 'rect'
          },
          textStyle: {
            color: '#fff',
            fontSize: '15'
          }
        },
        // tooltip: {
        //   padding: 0,
        //   enterable: true,
        //   transitionDuration: 1,
        //   textStyle: {
        //     color: '#000',
        //     decoration: 'none'
        //   },
        //   position: 'top',
        //   className: 'tooltips',
        //   formatter: function(params) {
        //     var tipHtml = ''
        //     if (!params.data) {
        //       return tipHtml
        //     }
        //     tipHtml = `<div class="tooltip">
        //               <span class="name">${params.data.name}</span>
        //               <span class="value">${params.data.value}家</span>
        //             </div>`

        //     return tipHtml
        //   }
        // },
        series: [
          {
            name: '',
            type: 'map',
            mapType: '浙江',
            // top: '25%',
            center: [119.5, 29],
            zoom: 1.1,
            select: {
              label: {
                fontSize: 12,
                color: '#ffffff' //设置地图点击后的文字颜色
              },
              itemStyle: {
                borderColor: '#18cdfe',
                borderWidth: '1',
                areaColor: '#18cdfe' //设置地图点击后的颜色
              }
            },
            label: {
              // 控制常态默认情况下地图板块样式
              normal: {
                show: true,
                color: '#ffffff', // 文字颜色
                fontSize: 12
                // 控制地区自定义文字
                // formatter(params) {
                //   return `${params.data.name}\n${params.data.value}家`
                // }
              },
              // 控制鼠标经过时地图板块样式
              emphasis: {
                show: true,
                color: '#ffffff',
                fontSize: 12
                // 控制地区自定义文字
                // formatter(params) {
                //   return `${params.data.name}\n${params.data.value}家`
                // }
              }
            },
            itemStyle: {
              normal: {
                label: {
                  show: false
                },
                areaColor: 'rgba(35, 95, 157, 1)',
                borderColor: '#18cdfe',
                borderWidth: 0.5,
                shadowBlur: 0,
                shadowColor: '#18cdfe',
                shadowOffsetX: 0.5,
                shadowOffsetY: 1
              },
              emphasis: {
                label: {
                  show: true
                },
                areaColor: '#18cdfe',
                color: '#fff'
              }
            }
            // data: this.dataArr
          }
        ]
      }

      myChart.setOption(option)
      // myChart.dispatchAction({
      //   type: 'highlight',
      //   name: '杭州市'
      // })
      // function showTooltip() {
      //   myChart.dispatchAction({
      //     type: 'showTip',
      //     seriesIndex: 0,
      //     dataIndex: 0
      //   })
      // }
      // showTooltip()
    },
    drawMap2() {
      // console.log(this.dataArr)

      // 基于准备好的dom,初始化echarts实例
      let myChart = this.$echarts5.init(document.getElementById('myChart2'))
      let myChart2 = this.$echarts5.init(document.getElementById('myChart'))

      // 绘制图表
      let option = {
        // backgroundColor: 'rgba(1, 20, 57, 1)',
        grid: {
          // top: '30%'
        },
        // 控制地图图例样式
        visualMap: {
          show: false,
          type: 'piecewise',
          right: '100',
          top: 'bottom',
          // orient: 'vertical',
          orient: 'horizontal',
          color: '#fff',
          itemGap: 10,
          align: 'left',
          // pieces: [
          //   { gt: 21, lte: 30, label: '1到10以内' },
          //   { gt: 0, lte: 20, label: '1以内' }
          // ],
          inRange: {
            color: '#0089ff',
            symbol: 'rect'
          },
          textStyle: {
            color: '#fff',
            fontSize: '15'
          }
        },
        series: [
          {
            name: '',
            type: 'map',
            mapType: '义乌',
            // top: '25%',
            center: [120, 29.3],
            zoom: 1.1,
            select: {
              label: {
                fontSize: 12,
                color: '#ffffff' //设置地图点击后的文字颜色
              },
              itemStyle: {
                borderColor: '#18cdfe',
                borderWidth: '1',
                areaColor: '#18cdfe' //设置地图点击后的颜色
              }
            },
            label: {
              // 控制常态默认情况下地图板块样式
              normal: {
                show: true,
                color: '#ffffff', // 文字颜色
                fontSize: 12
                // 控制地区自定义文字
                // formatter(params) {
                //   return `${params.data.name}\n${params.data.value}家`
                // }
              },
              // 控制鼠标经过时地图板块样式
              emphasis: {
                show: true,
                color: '#ffffff',
                fontSize: 12
                // 控制地区自定义文字
                // formatter(params) {
                //   return `${params.data.name}\n${params.data.value}家`
                // }
              }
            },
            itemStyle: {
              normal: {
                label: {
                  show: false
                },
                areaColor: 'rgba(35, 95, 157, 1)',
                borderColor: '#18cdfe',
                borderWidth: 0.5,
                shadowBlur: 0,
                shadowColor: '#18cdfe',
                shadowOffsetX: 0.5,
                shadowOffsetY: 1
              },
              emphasis: {
                label: {
                  show: true
                },
                areaColor: '#18cdfe',
                color: '#fff'
              }
            }
            // data: this.dataArr
          }
        ]
      }

      myChart.setOption(option)
      // 监听地图点击事件获取当前点击地区名称
      myChart.on('click', params => {
        if (params.componentType === 'series') {
          // this.mapname = params.name
          myChart2.dispatchAction({
            type: 'unselect', // 取消选中效果////////////////////////////
            dataIndex: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
          })
          console.log(params.name)
        }
      })
      myChart.dispatchAction({
        type: 'select', // 选中////////////////////////////////////////////////////////
        name: '义乌市'
      })
    }
  }
}
</script>

<style lang="less" scoped>
.map2 {
  width: 70px;
  height: 70px;
  z-index: 2;
  left: 439px;
  top: 211px;
  position: absolute;
  // background-color: red;
}
/deep/ .tooltipbg {
  background-color: rgba(250, 87, 87, 0) !important;
  border: none !important;
  padding: 0 !important;
  box-shadow: none !important;
}
</style>

实现打点地图背景色

vue
<script>
echarts.registerMap('浙江', zhejiang)
let myChartMap = echarts.init(this.$refs.myEchart)
// 地图弹框数据(浙江)
// 地图弹框数据(浙江)
let data = [
  {
    name: '杭州市',
    // itemStyle: {
    //   areaColor: '#56b1da'
    // },
    value: [
      '16308.12',
      '6082.47',
      '6840.45',
      '8349.82',
      '473.8',
      '422.38',
      '364.34',
      '950.0'
    ],
    name2: [
      '资产总额',
      '国有资产',
      '净资产',
      '营业收入',
      '利润总额',
      '净利润',
      '工业生产总值',
      '企业数量'
    ],
    unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
  },
  {
    name: '宁波市',
    // itemStyle: {
    //   areaColor: '#56b1da'
    // },
    value: [
      '2764.58',
      '1460.79',
      '1535.75',
      '2136.53',
      '124.42',
      '102.27',
      '312.49',
      '252.0'
    ],
    name2: [
      '资产总额',
      '国有资产',
      '净资产',
      '营业收入',
      '利润总额',
      '净利润',
      '工业生产总值',
      '企业数量'
    ],
    unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
  },
  {
    name: '温州市',
    // itemStyle: {
    //   areaColor: '#56b1da'
    // },
    value: [
      '735.66',
      '305.67',
      '308.68',
      '176.72',
      '-2.56',
      '-4.14',
      '69.47',
      '75.0'
    ],
    name2: [
      '资产总额',
      '国有资产',
      '净资产',
      '营业收入',
      '利润总额',
      '净利润',
      '工业生产总值',
      '企业数量'
    ],
    unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
  },
  {
    name: '嘉兴市',
    // itemStyle: {
    //   areaColor: '#56b1da'
    // },
    value: [
      '453.94',
      '231.15',
      '241.87',
      '170.85',
      '19.25',
      '15.12',
      '31.62',
      '83.0'
    ],
    name2: [
      '资产总额',
      '国有资产',
      '净资产',
      '营业收入',
      '利润总额',
      '净利润',
      '工业生产总值',
      '企业数量'
    ],
    unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
  },
  {
    name: '湖州市',
    // itemStyle: {
    //   areaColor: '#56b1da'
    // },
    value: [
      '382.39',
      '158.66',
      '162.29',
      '196.68',
      '13.43',
      '10.43',
      '54.83',
      '79.0'
    ],
    name2: [
      '资产总额',
      '国有资产',
      '净资产',
      '营业收入',
      '利润总额',
      '净利润',
      '工业生产总值',
      '企业数量'
    ],
    unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
  },
  {
    name: '绍兴市',
    // itemStyle: {
    //   areaColor: '#56b1da'
    // },
    value: [
      '313.19',
      '101.98',
      '118.91',
      '188.14',
      '14.48',
      '11.54',
      '105.01',
      '89.0'
    ],
    name2: [
      '资产总额',
      '国有资产',
      '净资产',
      '营业收入',
      '利润总额',
      '净利润',
      '工业生产总值',
      '企业数量'
    ],
    unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
  },
  {
    name: '金华市',
    // itemStyle: {
    //   areaColor: '#56b1da'
    // },
    value: [
      '338.9',
      '174.83',
      '178.43',
      '183.16',
      '12.49',
      '9.15',
      '65.52',
      '96.0'
    ],
    name2: [
      '资产总额',
      '国有资产',
      '净资产',
      '营业收入',
      '利润总额',
      '净利润',
      '工业生产总值',
      '企业数量'
    ],
    unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
  },
  {
    name: '衢州市',
    // itemStyle: {
    //   areaColor: '#56b1da'
    // },
    value: [
      '940.43',
      '374.97',
      '440.13',
      '429.0',
      '5.99',
      '4.49',
      '295.17',
      '123.0'
    ],
    name2: [
      '资产总额',
      '国有资产',
      '净资产',
      '营业收入',
      '利润总额',
      '净利润',
      '工业生产总值',
      '企业数量'
    ],
    unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
  },
  {
    name: '舟山市',
    // itemStyle: {
    //   areaColor: '#56b1da'
    // },
    value: [
      '1444.14',
      '909.83',
      '928.27',
      '345.35',
      '26.74',
      '24.22',
      '33.35',
      '97.0'
    ],
    name2: [
      '资产总额',
      '国有资产',
      '净资产',
      '营业收入',
      '利润总额',
      '净利润',
      '工业生产总值',
      '企业数量'
    ],
    unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
  },
  {
    name: '台州市',
    // itemStyle: {
    //   areaColor: '#56b1da'
    // },
    value: [
      '684.87',
      '232.04',
      '243.89',
      '148.56',
      '2.97',
      '1.05',
      '46.51',
      '87.0'
    ],
    name2: [
      '资产总额',
      '国有资产',
      '净资产',
      '营业收入',
      '利润总额',
      '净利润',
      '工业生产总值',
      '企业数量'
    ],
    unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
  },
  {
    name: '丽水市',
    // itemStyle: {
    //   areaColor: '#56b1da'
    // },
    value: [
      '164.34',
      '67.39',
      '70.43',
      '53.88',
      '5.62',
      '4.39',
      '20.56',
      '66.0'
    ],
    name2: [
      '资产总额',
      '国有资产',
      '净资产',
      '营业收入',
      '利润总额',
      '净利润',
      '工业生产总值',
      '企业数量'
    ],
    unit: ['亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '亿元', '个']
  }
]
// 浙江省打点位置数据
let markPoint = [
  {
    name: '杭州市',
    value: '0',
    coord: [119.39, 29.8]
  },
  {
    name: '湖州市',
    value: '0',
    coord: [120, 30.8]
  },
  {
    name: '嘉兴市',
    value: '0',
    coord: [121.05, 30.6]
  },
  {
    name: '衢州市',
    value: '0',
    coord: [119, 28.75]
  },
  {
    name: '绍兴市',
    value: '0',
    coord: [120.88, 29.65]
  },
  {
    name: '宁波市',
    value: '0',
    coord: [121.86, 29.59]
  },
  {
    name: '金华市',
    value: '0',
    coord: [120.28, 29]
  },
  {
    name: '丽水市',
    value: '0',
    coord: [119.62, 27.95]
  },
  {
    name: '温州市',
    value: '0',
    coord: [120.75, 27.77]
  },
  {
    name: '台州市',
    value: '0',
    coord: [121.33, 28.78]
  },
  {
    name: '舟山市',
    value: '0',
    coord: [122.55, 30.15]
  }
]
const options = {
  tooltip: {
    backgroundColor: null,
    formatter: function (params) {
      let str2 = ''
      let animaTime = 'animation-duration: 0s;'
      if (params.data !== undefined && params.data.name2) {
        params.data.name2.forEach((item, i) => {
          str2 += `
<div class="IndustrialLayout22item">
<span>${item}</span>
<p>
<span style="color: #FFFFFF;">${params.data.value[i]}</span><span> ${params.data.unit[i]}</span>
    </p>
    </div>
`
        })
        if (params.data.name2.length > 5) {
          str2 += str2
          animaTime = `animation-duration: ${params.data.name2.length * 2}s;`
        }
      }
      let str1 = `
<div class="IndustrialLayout22div">
<p class="IndustrialLayout22p">${params.name}</p>
<div class="IndustrialLayout22div1">
<div class="IndustrialLayout22div2" style="${animaTime}">
${str2}
    </div>
    </div>
    </div>
`
      return str1
    }
  },
  geo: [
    {
      map: '浙江',
      aspectScale: 1,
      show: false,
      roam: false, //是否允许缩放
      layoutSize: `95%`,
      layoutCenter: [`55%`, `57%`],
      label: {
        // 地图默认常态样式
        show: false,
        color: `#EEEEEE`,
        // 鼠标划入样式
        emphasis: {
          show: false,
          areaColor: `#fff`,
          color: `#EEEEEE`
        }
      },
      emphasis: {
        label: {
          show: false,
          color: `#fff`
        }
      },
      itemStyle: {
        areaColor: `transparent`,
        borderColor: `#d1e7f8`,
        borderWidth: 1,
        shadowBlur: 6,
        shadowOffsetY: 0,
        shadowOffsetX: 0,
        shadowColor: `#d1e7f8`,
        // 鼠标移入时板块样式
        emphasis: {
          areaColor: `rgba(103, 96, 158, 0.2)`,
          label: {
            color: `#fff`
          }
        }
      },
      z: 4
    },
    {
      map: '浙江',
      aspectScale: 1,
      roam: false, //是否允许缩放
      //zoom: 1.1, //默认显示级别
      layoutSize: `95%`,
      layoutCenter: [`55%`, `57%`],
      itemStyle: {
        // normal: {
        areaColor: {
          image: '', //配置图片
          repeat: 'no-repeat' //可选值repeat、no-repeat、repeat-x、repeat-y
        },
        // color: {
        //   image: '', // 支持为 HTMLImageElement, HTMLCanvasElement,不支持路径字符串
        //   repeat: `repeat` // 是否平铺,可以是 'repeat-x', 'repeat-y', 'no-repeat'
        // },
        borderColor: `#37C1FD`,
        borderWidth: 2
      },
      z: 3,
      silent: true
    },
    {
      map: '浙江',
      aspectScale: 1,
      roam: false, //是否允许缩放
      //zoom: 1.1, //默认显示级别
      layoutSize: `97%`,
      layoutCenter: [`55.1%`, `59.8%`],
      itemStyle: {
        areaColor: `#233c83`,
        borderColor: `#233c83`
      },
      z: 2,
      silent: true
    }
  ],
  series: [
    {
      type: 'map',
      // selectedMode: 'multiple',
      mapType: '浙江',
      aspectScale: 1,
      roam: false, //是否允许缩放
      layoutSize: `95%`,
      layoutCenter: [`55%`, `57%`],
      label: {
        // 地图默认常态样式
        show: true,
        color: `#EEEEEE`,
        // 鼠标划入样式
        emphasis: {
          show: false,
          areaColor: `#fff`,
          color: `#EEEEEE`
        }
      },
      emphasis: {
        label: {
          show: false,
          color: `#fff`
        }
      },
      itemStyle: {
        areaColor: `transparent`,
        borderColor: `#d1e7f8`,
        borderWidth: 0.5,
        shadowBlur: 6,
        shadowOffsetY: 0,
        shadowOffsetX: 0,
        shadowColor: `#d1e7f8`,
        // 鼠标移入时板块样式
        emphasis: {
          areaColor: `rgba(103, 96, 158, 0.2)`,
          label: {
            color: `#fff`
          }
        }
      },
      data: data,
      z: 10,
      // 地图打点
      markPoint: {
        symbol: 'image://' + require('../../../static/images/c@2x.png'), // 自定义图片路径
        //数据全是markPoint
        symbolSize: [120, 52], // 标注大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2
        itemStyle: {
          normal: {
            borderColor: '#FFFFFF',
            borderWidth: 1, // 标注边线线宽,单位px,默认为1
            label: {
              show: true,
              position: ['40%', '8%'],
              color: '#fff'
            }
          },
          emphasis: {
            borderColor: 'red',
            borderWidth: 5,
            label: {
              show: false
            }
          }
        },
        effect: {
          show: true,
          shadowBlur: 0
        },
        // 此数据源为定位点数据
        data: markPoint
      } //end markPoint
    },
    {
      name: 'Top 5',
      type: 'scatter',
      coordinateSystem: 'geo',
      //   symbol: 'image://http://ssq168.shupf.cn/data/biaoji.png',
      // symbolSize: [30,120],
      // symbolOffset:[0, '-40%'] ,
      label: {
        normal: {
          show: false
        }
      },
      itemStyle: {
        normal: {
          color: '#D8BC37' //标志颜色
        }
      },
      data: data,
      showEffectOn: 'render',
      rippleEffect: {
        brushType: 'stroke'
      },
      hoverAnimation: true,
      zlevel: 10
    }
  ]
}
// 记录各省份打点对应数据位置(浙江)
let obj = {
  杭州市: 0,
  湖州市: 1,
  嘉兴市: 2,
  衢州市: 3,
  绍兴市: 4,
  宁波市: 5,
  金华市: 6,
  丽水市: 7,
  温州市: 8,
  台州市: 9,
  舟山市: 10
}
// 引入地图背景图
let domImg = document.createElement('img')
domImg.src = './../../../static/images/zhejiangmap_1@2x.png'
options.geo[1].itemStyle.areaColor.image = domImg
// 引入地图背景图
// 产业布局 地图 浙江省
const { data: data2 } = await zjsMap({
  statDate: this.chanyeyear,
  indexName: this.panytype,
  distName: '%'
})
if (!data2.success) return ''
data2.data.rows.forEach(item => {
  if (obj[item.distName]) {
    markPoint[obj[item.distName]].value = `${item.indexValue.split('.')[0]}${
      item.indexUnit
    }`
  }
})
myChartMap.setOption(options, true)
</script>

按需加载

新建 src/utils/echarts.js

js
// 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口
import * as echarts from 'echarts/core'

// 引入各种图表,图表后缀都为 Chart
import { BarChart, PieChart } from 'echarts/charts'

// 引入提示框,标题,直角坐标系等组件,组件后缀都为 Component
import {
  //   TitleComponent,
  TooltipComponent,
  //   ToolboxComponent,
  GridComponent,
  LegendComponent
  //   AxisPointerComponent,
  //   DatasetComponent,
  //   GraphicComponent
} from 'echarts/components'

// 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
import { SVGRenderer } from 'echarts/renderers'

// 注册必须的组件
echarts.use([
  BarChart,
  //   LineChart,
  PieChart,

  //   TitleComponent,
  TooltipComponent,
  //   ToolboxComponent,
  GridComponent,
  LegendComponent,
  //   AxisPointerComponent,
  //   DatasetComponent,
  //   GraphicComponent,
  SVGRenderer
])

export default echarts

在 main.js 中引入并挂载

在组件中使用

js
initCharts2(info) {
    let charts = this.$echarts.init(document.getElementById('charts2'))
    let option = {}
    charts.resize()
    charts.clear()
    charts.setOption(option)
},

社区示例

http:www.ppchart.com/#/

https://www.isqqw.com/homepage#/homepage

js 实用写法

axios 全局捕获错误

js
import axios from 'axios'
axios.interceptors.response.use(
  response => {
    return response
  },
  error => {
    // 这里可以提示用户,如:网络错误
    console.log(error)
    // 这种种写法可以在任何请求出错(如网络原因)时让该请求相关代码不再往下执行也可以捕获错误,简化代码省略 catch 或者 try、catch
    return new Promise(() => {})
    // return Promise.reject(error) 这种写法需要在对应请求代码中写入 catch 或者 try、catch
  }
)

await 中简化 try catch

js
function getUserInfo() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject('请求异常')
    }, 1000)
  })
}
// 不需要中断代码执行时可以这么写
async function logined() {
  let userInfo = await getUserInfo().catch(e => console.warn(e))
  // 执行没有中断,userInfo 为 undefined
  if (!userInfo) return // 需要做非空校验
  let pageInfo = await getPageInfo(userInfo?.userId)
}

// 需要中断代码执行时这么写
async function logined() {
  let userInfo = await getUserInfo().catch(e => {
    console.warn(e)
    return Promise.reject(e) // 会导致控制台出现 uncaught (in promise) 报错信息
  })
  // 执行中断
  let pageInfo = await getPageInfo(userInfo?.userId)
}

logined()

从 url 获取参数并转为对象

js
const getParameters = URL =>
  JSON.parse(
    `{"${decodeURI(URL.split('?')[1])
      .replace(/"/g, '\\"')
      .replace(/&/g, '","')
      .replace(/=/g, '":"')}"}`
  )

getParameters('https://www.google.com.hk/search?q=js+md&newwindow=1')
// {q: 'js+md', neww}

两日期之间相差的天数

js
const dayDiff = (date1, date2) =>
  Math.ceil(Math.abs(date1.getTime() - date2.getTime()) / 86400000)

dayDiff(new Date('2021-10-21'), new Date('2022-02-12'))
// Result:144

高德地图使用

vue
<template>
  <div class="GDwarp">
    <div id="GDcontainer"></div>
    <a-input
      placeholder="如需修改位置请先搜索地址"
      v-model="amap.searchAddress"
      class="amap-search"
      id="GDsearch"
      :disabled="type === 2"
    />
    <!-- 搜索结果 -->
    <div id="amap-panel" v-show="amap.searchNearBy"></div>
    <div ref="infoWindow" v-show="infoWindowShow" class="infoWindow">
      <span>名称: {{ addressName }}</span>
      <span>地址: {{ amap.formattedAddress }}</span>
      <div class="triangle"></div>
    </div>
  </div>
</template>

<script>
import AMapLoader from '@amap/amap-jsapi-loader'
window._AMapSecurityConfig = {
  securityJsCode: '9aab3b0492ae2e3a138d95f4259b85f8'
}
export default {
  // 记录当前状态 1:新增 2:查看 3:编辑
  props: ['type'],
  data() {
    return {
      map: null,
      // 保存自定义弹框
      infoWindow: null,
      infoWindowShow: false,
      addressName: '',
      amap: {
        // 用户选择地址的经纬度
        lonlat: '',
        position: undefined,
        // 用户选择的详细地址
        formattedAddress: '',
        searchNearBy: false,
        placeSearch: null,
        searchAddress: ''
      }
    }
  },
  methods: {
    // 初始化
    initMap() {
      AMapLoader.load({
        key: '81921971980445dc8138d38ea50b1fb9', // 申请好的Web端开发者Key,首次调用 load 时必填
        plugins: ['AMap.PlaceSearch', 'AMap.Autocomplete', 'AMap.InfoWindow'],
        AMapUI: {
          plugins: ['misc/PositionPicker']
        }
      })
        .then(AMap => {
          this.amap.searchAddress = ''
          this.map = new AMap.Map('GDcontainer', {
            //设置地图容器id
            zoom: 15, //初始化地图级别
            center: [120.435702, 30.238782] //初始化地图中心点位置
          })
          // 地图点击事件
          this.map.on('click', () => {
            // 关闭信息弹框
            this.map.clearInfoWindow()
            this.infoWindowShow = false
          })
          // 初始化搜索框
          this.addKeywordSearch()
        })
        .catch(e => {
          console.log(e)
        })
    },
    // 初始化搜索框
    addKeywordSearch() {
      const auto = new AMap.Autocomplete({
        input: 'GDsearch'
      })
      this.amap.placeSearch = new AMap.PlaceSearch({
        map: this.map,
        panel: 'amap-panel', // 结果列表将在此容器中进行展示。
        autoFitView: true, // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
        extensions: 'base' //返回基本地址信息
      })
      if (this.type === 2) return
      auto.on('select', this.select)
      // 点击地图覆盖物
      AMap.event.addListener(this.amap.placeSearch, 'markerClick', e => {
        this.openInfo(e.data, e.event)
        this.amap.position = e.data.location
        this.amap.lonlat = e.data.location.lng + ',' + e.data.location.lat
        this.fullLonlat = this.amap.lonlat
        this.amap.formattedAddress =
          e.data.pname +
          e.data.cityname +
          e.data.adname +
          e.data.address +
          e.data.name
        this.$emit('getMapInfo', this.amap)
      })
    },
    // 地图选择事件(点击搜索项)
    select(e) {
      this.amap.placeSearch.setCity(e.poi.adcode)
      this.amap.placeSearch.search(e.poi.name) //关键字查询查询
      this.amap.position = e.poi.location
      if (e.poi.location) {
        this.amap.lonlat = e.poi.location.lng + ',' + e.poi.location.lat
      }
      this.fullLonlat = this.amap.lonlat
      this.amap.formattedAddress = e.poi.district + e.poi.address + e.poi.name
      this.$emit('getMapInfo', this.amap)
    },
    // 自定义信息框
    openInfo({ name }, { lnglat }) {
      this.addressName = name
      this.infoWindowShow = true
      this.infoWindow = new AMap.InfoWindow({
        isCustom: true,
        content: this.$refs.infoWindow,
        offset: new AMap.Pixel(0, -25)
      })
      this.infoWindow.open(this.map, lnglat)
    }
  }
}
</script>

<style lang="less" scoped>
#GDcontainer {
  width: 100%;
  height: 300px;
}
.GDwarp {
  position: relative;
  .amap-search {
    position: absolute;
    width: 50%;
    top: 10px;
    left: 10px;
  }
  #amap-panel {
    position: absolute;
    background-color: white;
    max-height: 90%;
    margin: 10px 0 10px 0;
    overflow-y: auto;
    top: 10px;
    right: 10px;
    width: 280px;
    height: 300px;
    border-bottom: solid 1px silver;
  }
  .infoWindow {
    background-color: #fff;
    box-shadow: 0px 4px 12px 0px rgba(0, 0, 0, 0.15);
    border-radius: 2px;
    line-height: 30px;
    padding: 10px;
    display: flex;
    flex-direction: column;
    position: relative;
    .triangle {
      position: absolute;
      border-color: #fff transparent transparent transparent;
      border-style: solid;
      border-width: 15px 15px 15px 15px;
      bottom: -30px;
      left: 50%;
      transform: translateX(-50%);
    }
  }
}
</style>

css 实现高度不固定过渡动画

css
/* 可以通过 max-height来实现 */
.div1 {
  max-height: 0;
  trabsition: 0.3s;
}
.div1:hover {
  max-height: 800px;
}

还可以通过 grid 来实现,可参考 juejin.cn/post/7196843994030342200

html
<style>
  .warp {
    width: 200px;
  }
  .grid {
    display: grid;
    grid-template-columns: 0fr;
    transition: 0.3s;
    overflow: hidden;
    background-color: aqua;
  }
  .grid > div {
    min-height: 0;
  }
  .warp:hover .grid {
    grid-template-columns: 1fr;
  }
</style>

<div class="wrap">
  <button class="trigger">鼠标移入</button>
  <div class="grid">
    <div>很多内容具体有多少不确定所以此 div 最终有多高不知道</div>
  </div>
</div>

在 vue3 中使用 jsx

基本使用

由于 tsx 直接就是运行时了,无法在编译期做一些优化,导致性能比不过模板的写法

安装依赖

base
npm i @vitejs/plugin-vue-jsx -D

在 vite.config.js 文件中的 plugins 字段中添加 jsx 支持

js
import vueJsx from '@vitejs/plugin-vue-jsx'
export default defineConfig({
  plugins: [vueJsx()]
})

新建 jsx 文件

jsx
import HelloWorld from './HelloWorld.vue'
export default {
  setup() {
    return () => <HelloWorld msg="11" />
  }
}

也可以使用另一种写法

jsx
import { defineComponent, ref } from "vue";

export default defineComponent({
  name: "TsxDemo",
  props: {
    msg: {
      type: String,
      required: true,
      default: "hello wrold",
    },
  },
  setup(props) {
    const count = ref(0);
    return () => (
      <div>
        <header>{props.msg}</header>
        <main>{count.value}</main>
      </div>
    );
  },
});

template 和 jsx 混用

vue
<template>
  <el-tabs v-model="activeName" @tab-click="handleClick">
    <!-- 使用 jsx 编写的组件 -->
    <reuseP />
    <el-tab-pane label="热门主题" name="hot">热门主题</el-tab-pane>
  </el-tabs>
</template>

<script setup lang="tsx">
import { ref } from 'vue'
import type { TabsPaneContext } from 'element-plus'
const activeName = ref('new')
const arr = [1, 2, 3]
// 创建 jsx 编写的组件
const reuseP = () => arr.map((item: any) => <p key={item}>xxx</p>)

function handleClick(tab: TabsPaneContext) {
  console.log(tab.paneName)
}
</script>

也可以使用这种写法

vue
<template>
  <el-tabs v-model="activeName" @tab-click="handleClick">
    <!-- 使用 jsx 编写的组件 -->
    <Demo msg="hello world" />
    <el-tab-pane label="热门主题" name="hot">热门主题</el-tab-pane>
  </el-tabs>
</template>

<script setup lang="tsx">
import { ref,defineComponent } from 'vue'
import type { TabsPaneContext } from 'element-plus'
const activeName = ref('new')

// 创建 jsx 编写的组件
const Demo = defineComponent({
  props: {
    msg: String,
  },
  setup(props) {
    return () => (
      <div>
        <div>msg is {props.msg}</div>
      </div>
    );
  },
});
</script>

css 方案

.vue 文件中支持 css modulecss scoped 方案

css module

vue
<template>
  <div>
    <Demo msg="hello world" />
  </div>
</template>

<script lang="tsx" setup>
import { defineComponent, useCssModule } from "vue";

const styles = useCssModule();

const Demo = defineComponent({
  props: {
    msg: String,
  },
  setup(props) {
    return () => (
      <div class={styles.wrapper}>
        <div class={styles.inner}>msg is {props.msg}</div>
      </div>
    );
  },
});
</script>

<style lang="less" module>
.wrapper {
  .inner {
    color: red;
  }
}
</style>

css scoped

vue
<template>
  <div>
    <Demo msg="hello world" />
  </div>
</template>

<script lang="tsx" setup>
import { defineComponent } from "vue";

const Demo = defineComponent({
  props: {
    msg: String,
  },
  setup(props) {
    return () => (
      <div class="wrapper">
        <div class="inner">msg is {props.msg}</div>
      </div>
    );
  },
});
</script>

<style lang="less" scoped>
// 由于 Demo 是一个子组件,而 scoped 方案不会透传到子组件中dom中,所以这里我们得用:deep处理
:deep(.wrapper) {
  .inner {
    color: red;
  }
}
</style>

如果想在混合且使用 scoped 的情况下,不写 deep 样式穿透可以使用如下写法

vue
<template>
  <div>
    <component :is="renderDemo('hello world')"></component>
  </div>
</template>

<script lang="tsx" setup>
const renderDemo = (msg: string) => (
  <div class="wrapper">
    <div class="inner"> msg is {msg}</div>
  </div>
);
</script>

<style lang="less" scoped>
.wrapper {
  .inner {
    color: red;
  }
}
</style>