Newer
Older
xc-business-system / src / views / dataManagement / components / data / customChart.vue
lyg on 23 May 2024 6 KB 自定义图表-折线图
<script lang="ts" setup name="CustomChart">
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, '需要填充的数据')
    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 {
    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: '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')
}
const saveData = () => {
  dataFormRef.value.validate((valid: any) => {
    if (valid) {
      // 整理数据
      const data = {
        type: dataForm.value.type,
        name: dataForm.value.name,
        source: 'custom',
      } as any
      // 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(','),
      }))

      dialogFormVisible.value = false
      emits('confirm', data)
    }
  })
}
// 填充示例数据
const fillData = () => {
  if (!dataForm.value.type) {
    ElMessage.warning('请先选择')
  }
  dataForm.value.name = '测试'
  // 填充数据
  // 1.折线图
  const name1 = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
  const name2 = ['在用', '停用', '禁用']
  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('|')
}
</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'" :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轴数据的个数" />
            <!-- <precision-input-number v-model.trim="dataForm.data" :precision="3" placeholder="" /> -->
          </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>