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