Newer
Older
xc-business-system / src / views / dataManagement / components / data / customChart.vue
dutingting on 2 Dec 11 KB 临时提交
<script lang="ts" setup name="CustomChart">
import dayjs from 'dayjs'
import type { FormRules } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
const emits = defineEmits(['confirm'])
const dialogFormVisible = ref(false) // 对话框是否显示
const dataFormRef = ref()
const dataForm = ref({
  type: '',
  name: '',
  xAxisData: '',
  data: '',
  dataName: '',
})
const rules: FormRules = {
  type: [{ required: true, message: '图表类型必选', trigger: ['blur', 'change'] }],
  name: [{ required: true, message: '图表名称必选', trigger: ['blur', 'change'] }],
  xAxisData: [{ required: true, message: '数据必填', trigger: ['blur', 'change'] }],
  data: [{ required: true, message: '数据必填', trigger: ['blur', 'change'] }],
  dataName: [{ required: true, message: '数据必填', trigger: ['blur', 'change'] }],
} // 前端校验规则

// 重置表单
const resetForm = () => {
  dataForm.value = {
    type: '',
    name: '',
    xAxisData: '',
    data: '',
    dataName: '',
  }
}

const initDialog = (data: any) => {
  dialogFormVisible.value = true
  if (data.name) {
    // 填充数据
    // 1.折线图
    console.log(data, '需要填充的数据')
    if (dataForm.value.type === 'line' || dataForm.value.type === 'bar-horizontal' || dataForm.value.type === 'bar-vertical') {
      dataForm.value.xAxisData = data.xAxisData.join(',')
      dataForm.value.dataName = data.data.map((item: any) => item.name).join(',')
      dataForm.value.data = data.data.map((item: any) => item.data.join(',')).join('|')
      dataForm.value.type = data.type
      dataForm.value.name = data.name
    }
    else if (dataForm.value.type === 'pie' || dataForm.value.type === 'ring') {
      dataForm.value.dataName = data.data.map(item => item.name).join(',')
      dataForm.value.data = data.data.map(item => item.value).join(',')
      if (data.showTotal) {
        dataForm.value.type = 'ring'
      }
    }
    else if (dataForm.value.type === 'rank-table') {
      dataForm.value.dataName = data.columns.map((item: any) => item.text)
      dataForm.value.data = data.data.map((item) => {
        const arr = []
        for (const i in item) {
          arr.push(item[i])
        }
        return arr
      }).join('|')
    }
  }
  else {
    resetForm()
  }
}
defineExpose({
  initDialog,
})

const cancel = () => {
  dialogFormVisible.value = false
}

const chartList = ref([
  {
    type: 'line',
    icon: 'icon-set-line',
    name: '折线图',
  },
  {
    type: 'pie',
    icon: 'icon-set-pie',
    name: '饼图',
  },
  {
    type: 'ring',
    icon: 'icon-set-ring',
    name: '环图',
  },
  {
    type: 'bar-vertical',
    icon: 'icon-set-bar-vertical',
    name: '柱状图-水平',
  },
  {
    type: 'bar-horizontal',
    icon: 'icon-set-bar-horizontal',
    name: '柱状图-垂直',
  },
  {
    type: 'rank-table',
    icon: 'icon-set-table',
    name: '表格',
  },
  // {
  //   type: 'rank',
  //   icon: 'icon-set-rank',
  //   name: '排行榜',
  // },
])
const selectChart = (item: any) => {
  dataForm.value.type = item.type
  dataFormRef.value.clearValidate('type')
  dataForm.value.data = ''
  dataForm.value.xAxisData = ''
  dataForm.value.dataName = ''
}
const saveData = () => {
  dataFormRef.value.validate((valid: any) => {
    if (valid) {
      // 整理数据
      const data = {
        type: dataForm.value.type,
        name: dataForm.value.name,
        source: 'custom',
      } as any
      if (dataForm.value.type === 'line' || dataForm.value.type === 'bar-horizontal' || dataForm.value.type === 'bar-vertical') {
        // 1.折线图数据
        data.smooth = false
        data.gradient = true
        data.xAxisData = dataForm.value.xAxisData.split(',')
        data.data = dataForm.value.dataName.split(',').map((item: string, index: number) => ({
          name: item,
          data: dataForm.value.data.split('|')[index].split(','),
        }))
      }
      else if (dataForm.value.type === 'pie' || dataForm.value.type === 'ring') {
        if (dataForm.value.type === 'pie') {
          data.center = ['50%', '60%']
          data.radius = '70%'
        }
        else {
          data.radius = ['60%', '45%']
          data.title = ' '
          data.showTotal = true
        }
        data.type = 'pie'
        data.labelPosition = 'outside'
        data.data = dataForm.value.data.split(',').map((item, index) => ({
          name: dataForm.value.dataName.split(',')[index],
          value: item,
        }))
      }
      else if (dataForm.value.type === 'rank-table') {
        data.columns = dataForm.value.dataName.split(',').map(item => ({

          text: item,
          value: item,
          align: 'center',
        }
        ))
        data.data = dataForm.value.data.split('|').map((item) => {
          const data1 = item.split(',')
          const object = {}
          data.columns.forEach((element, index) => {
            object[element.value] = data1[index]
          })
          return object
        })
      }
      dialogFormVisible.value = false
      emits('confirm', data)
    }
  })
}
// 填充示例数据
const fillData = () => {
  if (!dataForm.value.type) {
    ElMessage.warning('请先选择')
  }
  dataForm.value.name = '测试'
  // 填充数据
  // 1.折线图
  const name1 = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
  const name2 = ['在用', '停用', '禁用', '限用']
  const name3 = ['电学电源组', '无线脉冲组', '热工力学组']
  if (dataForm.value.type === 'line') {
    dataForm.value.xAxisData = name1.join(',')
    dataForm.value.dataName = name2.join(',')
    dataForm.value.data = name2.map((item: string) => (name1.map((citem: string) => (Math.floor(Math.random() * 100) + 1)))).join('|')
  }
  else if (dataForm.value.type === 'pie' || dataForm.value.type === 'ring') {
    // 2,3 饼图,环图
    dataForm.value.dataName = name2.join(',')
    dataForm.value.data = name2.map(item => Math.floor(Math.random() * 100) + 1).join(',')
  }
  else if (dataForm.value.type === 'bar-horizontal' || dataForm.value.type === 'bar-vertical') {
    dataForm.value.xAxisData = name3.join(',')
    dataForm.value.dataName = name2.join(',')
    dataForm.value.data = name2.map((item: string) => (name2.map((citem: string) => (Math.floor(Math.random() * 100) + 1)))).join('|')
  }
  else if (dataForm.value.type === 'rank-table') {
    dataForm.value.dataName = ['标准装置名称', '创建人', '创建时间'].join(',')
    const name = ['直流稳压电源', '多功能校准源', '多功能电气安全', '安全阀', '微波衰减', '信号发生器', '频谱分析仪', '频率短期稳定度', '失真度', '低频信号源', '0.02级活塞式压力计', 'E2等砝码', '失真度', '低频信号源', '0.02级活塞式压力计', 'E2等砝码', '失真度', '低频信号源', '0.02级活塞式压力计', 'E2等砝码']
    const name4 = ['李响', '张超', '王立勇', '张浩', '孙子涵', '楚瑜', '张月月', '刘涵', '李渊', '王瑞', '张超', '王立勇', '张浩', '孙子涵', '楚瑜', '张月月', '刘涵', '李渊', '王瑞']
    const data = []
    for (let i = 0; i < 15; i++) {
      data.push(`${name[i]},${name4[i]},${dayjs().subtract(Math.floor(Math.random() * 30) + 1, 'day').format('YYYY-MM-DD')}`)
    }
    dataForm.value.data = data.join('|')
  }
}
</script>

<template>
  <el-dialog v-model="dialogFormVisible" title="自定义数据" append-to-body>
    <el-form ref="dataFormRef" :rules="rules" :model="dataForm" label-position="right" label-width="80px">
      <el-row :gutter="20">
        <el-col :span="20">
          <el-form-item label="图表类型" prop="type">
            <div class="type-container">
              <div v-for="item in chartList" :key="item.type">
                <el-tooltip
                  class="box-item"
                  effect="dark"
                  :content="item.name"
                  placement="top"
                >
                  <svg-icon :class="dataForm.type === item.type ? 'border' : ''" :name="item.icon" class="icon-button-icon" @click="selectChart(item)" />
                </el-tooltip>
              </div>
            </div>
          </el-form-item>
        </el-col>
        <el-row />
      </el-row>
      <el-row :gutter="20">
        <el-col :span="20">
          <el-form-item label="图表名称" prop="name">
            <el-input v-model.trim="dataForm.name" type="text" placeholder="必填" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row v-if="dataForm.type === 'line' || dataForm.type === 'bar-vertical' || dataForm.type === 'bar-horizontal'" :gutter="20">
        <el-col :span="20">
          <el-form-item label="x轴数据" prop="xAxisData">
            <el-input v-model.trim="dataForm.xAxisData" type="text" placeholder="多个数据用,分割。示例: 周一,周二" />
          </el-form-item>
        </el-col>
        <el-col :span="20">
          <el-form-item label="数据名称" prop="dataName">
            <el-input v-model.trim="dataForm.dataName" type="text" placeholder="多个数据用,分割。示例: 在用,禁用,停用" />
          </el-form-item>
        </el-col>
        <el-col :span="20">
          <el-form-item label="数据" prop="data">
            <el-input v-model.trim="dataForm.data" type="text" placeholder="多个数据用,每组数据用|分割。示例: 5,3 | 2,6 注意每组数字数量需等于x轴数据的个数" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row v-if="dataForm.type === 'pie' || dataForm.type === 'ring'" :gutter="20">
        <el-col :span="20">
          <el-form-item label="数据名称" prop="dataName">
            <el-input v-model.trim="dataForm.dataName" type="text" placeholder="多个数据用,分割。示例: 在用,禁用,停用" />
          </el-form-item>
        </el-col>
        <el-col :span="20">
          <el-form-item label="数据" prop="data">
            <el-input v-model.trim="dataForm.data" type="text" placeholder="多个数据用,。示例: 5,3,7" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row v-if="dataForm.type === 'rank-table'" :gutter="20">
        <el-col :span="20">
          <el-form-item label="表头数据" prop="dataName">
            <el-input v-model.trim="dataForm.dataName" type="text" placeholder="多个数据用,分割。示例: 标准装置名称,创建人,创建时间" />
          </el-form-item>
        </el-col>
        <el-col :span="20">
          <el-form-item label="表格数据" prop="data">
            <el-input v-model.trim="dataForm.data" type="text" placeholder="多个数据用,每组数据用|分割。示例: 频谱分析仪,张三,2024-05-01|直流稳压电源,张三,2024-05-16" />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" @click="fillData">
          填充示例数据
        </el-button>
        <el-button type="primary" @click="saveData">
          保存
        </el-button>
        <el-button @click="cancel">
          取消
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<style lang="scss" scoped>
.border {
  border: 2px solid #000;
}

.type-container {
  width: 100%;
  display: flex;
  justify-content: space-around;
}

.el-dialog {
  width: 700px;
}

.el-select {
  width: 100%;
}

.icon-button-icon {
  width: 44px;
  height: 44px;
  margin: 0 auto;
  // border: 1px solid #000;

  &:hover {
    cursor: pointer;
    // width: 45px;
    // height: 45px;
    box-shadow: 4px 4px 15px #666;
  }
}
</style>