|
|
@ -4,73 +4,169 @@ |
|
|
@ 备注: 性格色彩 |
|
|
@ 备注: 性格色彩 |
|
|
--> |
|
|
--> |
|
|
<script lang="ts" setup> |
|
|
<script lang="ts" setup> |
|
|
import { ref } from "vue"; |
|
|
import { ref, onMounted, onUnmounted, nextTick } from 'vue'; |
|
|
import * as echarts from "echarts"; |
|
|
import * as echarts from 'echarts'; |
|
|
|
|
|
import { getCharacterColor } from '@/api/hr/people'; |
|
|
// 定义一个ref用于存储占比最高的两种性格色彩 |
|
|
const props = defineProps({ |
|
|
const topTwoColours = ref<string[]>([]); |
|
|
tabsid: { |
|
|
const option = { |
|
|
type: String, |
|
|
tooltip: { |
|
|
default: "1", |
|
|
trigger: "axis", |
|
|
|
|
|
}, |
|
|
}, |
|
|
radar: [ |
|
|
usercont:{ |
|
|
{ |
|
|
type:Object, |
|
|
indicator: [ |
|
|
default(){ |
|
|
{ name: "红色", max: 100 }, |
|
|
return {} |
|
|
{ name: "蓝色", max: 100 }, |
|
|
} |
|
|
{ name: "黄色", max: 100 }, |
|
|
} |
|
|
{ name: "绿色", max: 100 }, |
|
|
}); |
|
|
], |
|
|
// 定义数据和方法 |
|
|
center: ["50%", "50%"], |
|
|
const chartContainer = ref<HTMLDivElement | null>(null); |
|
|
radius: 90, |
|
|
let chartInstance: echarts.ECharts | null = null; |
|
|
|
|
|
// 添加对ColourNameList的响应式引用 |
|
|
|
|
|
const ColourNameList = ref<string[]>([]); |
|
|
|
|
|
const error = ref<string | null>(null); |
|
|
|
|
|
//添加了一个新的变量用来处理尺寸变化 |
|
|
|
|
|
let resizeObserver: ResizeObserver | null = null; |
|
|
|
|
|
// 使用计算属性确保number存在且非空字符串再初始化 |
|
|
|
|
|
const isReadyToInit = computed(() => { |
|
|
|
|
|
return props.usercont.number !== undefined && props.usercont.number.trim() !== ''; |
|
|
|
|
|
}); |
|
|
|
|
|
// 处理数据和初始化ECharts |
|
|
|
|
|
const initChart = async () => { |
|
|
|
|
|
// console.log(chartContainer.value) |
|
|
|
|
|
// 检查并销毁已有实例 |
|
|
|
|
|
if (chartInstance) { |
|
|
|
|
|
chartInstance.dispose(); |
|
|
|
|
|
chartInstance = null; |
|
|
|
|
|
} |
|
|
|
|
|
//确保chartContainer关联的DOM元素存在 |
|
|
|
|
|
if (!chartContainer.value) { |
|
|
|
|
|
console.warn('DOM元素未找到,无法初始化图表'); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
try { |
|
|
|
|
|
// 确保usercont.number存在再发起请求 |
|
|
|
|
|
if (!isReadyToInit.value) { |
|
|
|
|
|
throw new Error("员工信息未准备好,无法初始化图表"); |
|
|
|
|
|
} |
|
|
|
|
|
// 调用接口获取性格色彩数据 |
|
|
|
|
|
const response = await getCharacterColor({ number: props.usercont.number }); |
|
|
|
|
|
// 初始化图表实例 |
|
|
|
|
|
chartInstance = echarts.init(chartContainer.value); |
|
|
|
|
|
// console.log('Response:', response, chartInstance); |
|
|
|
|
|
if (response.code === 0) { |
|
|
|
|
|
// 处理返回的数据,得到颜色列表和雷达图颜色数据,解构数据 |
|
|
|
|
|
const { ColourNameList: apiColourNameList, RadarColour } = response.data; |
|
|
|
|
|
ColourNameList.value = apiColourNameList; // 更新响应式数组 |
|
|
|
|
|
// 确保所有颜色都在雷达图中显示,即使ColourNameList中没有提及 |
|
|
|
|
|
const allColours = ["红色", "蓝色", "黄色", "绿色"]; |
|
|
|
|
|
// 更新雷达图 |
|
|
|
|
|
updateRadarChart(chartInstance, RadarColour, allColours); |
|
|
|
|
|
} else { |
|
|
|
|
|
ElMessage.error(response.data.msg || '系统出错'); |
|
|
|
|
|
} |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
console.error(e); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
// 更新雷达图 |
|
|
|
|
|
const updateRadarChart = (chart: echarts.ECharts, radarColour: any[], colourNameList: string[]) => { |
|
|
|
|
|
const radarOptions = createRadarOptions(radarColour, colourNameList); |
|
|
|
|
|
chart.setOption(radarOptions); |
|
|
|
|
|
chart.resize(); |
|
|
|
|
|
// 将colourNameList赋值给ColourNameList,以便在模板中使用 |
|
|
|
|
|
// ColourNameList.value = colourNameList; |
|
|
|
|
|
} |
|
|
|
|
|
// 创建雷达图配置项 |
|
|
|
|
|
const createRadarOptions = (radarColour: any[], colourNameList: string[]) => { |
|
|
|
|
|
let maxVal = Math.max(...radarColour); |
|
|
|
|
|
return { |
|
|
|
|
|
tooltip: { trigger: "item" }, |
|
|
|
|
|
radar: { |
|
|
|
|
|
indicator: colourNameList.map((color, index) => ({ |
|
|
|
|
|
name: color, |
|
|
|
|
|
max: maxVal + 2, |
|
|
|
|
|
min: 0 , |
|
|
|
|
|
})), |
|
|
|
|
|
shape: "circle", |
|
|
|
|
|
splitNumber: 4, |
|
|
}, |
|
|
}, |
|
|
], |
|
|
|
|
|
series: [ |
|
|
series: [ |
|
|
{ |
|
|
{ |
|
|
|
|
|
name: "个人性格色彩", |
|
|
type: "radar", |
|
|
type: "radar", |
|
|
tooltip: { |
|
|
areaStyle: { |
|
|
trigger: "item", |
|
|
// 填充区颜色 |
|
|
|
|
|
color: '#a0c3f8', |
|
|
}, |
|
|
}, |
|
|
areaStyle: {}, |
|
|
data: [{ value: radarColour, |
|
|
data: [ |
|
|
name: "个人色彩分布" |
|
|
{ |
|
|
}], |
|
|
value: [77, 55, 66, 33], |
|
|
itemStyle: { color: "#3c96ff" }, // 示例颜色 |
|
|
name: "性格色彩", |
|
|
|
|
|
}, |
|
|
|
|
|
], |
|
|
|
|
|
}, |
|
|
}, |
|
|
], |
|
|
], |
|
|
}; |
|
|
}; |
|
|
onMounted(() => { |
|
|
} |
|
|
// 计算四种色彩的占比并找出最高的两种 |
|
|
onMounted(async () => { |
|
|
const values = option.series[0].data[0].value; |
|
|
//在DOM就绪后初始化echarts实例 |
|
|
const colors = ["红色", "蓝色", "黄色", "绿色"]; |
|
|
await nextTick(); |
|
|
const percentages = values.map((val) => val / 100); |
|
|
// console.log(chartContainer.value); |
|
|
const sortedColors = colors.sort( |
|
|
// 初始化ResizeObserver |
|
|
(a, b) => percentages[colors.indexOf(b)] - percentages[colors.indexOf(a)] |
|
|
resizeObserver = new ResizeObserver(() => { |
|
|
); |
|
|
if (chartInstance) { |
|
|
topTwoColours.value = sortedColors.slice(0, 2); |
|
|
chartInstance.resize(); |
|
|
// 初始化echarts实例 |
|
|
} |
|
|
Promise.resolve().then(() => { |
|
|
|
|
|
const dom = document.getElementById("myChart"); |
|
|
|
|
|
const myChart = echarts.init(dom); |
|
|
|
|
|
window.addEventListener("resize", () => { |
|
|
|
|
|
myChart.resize(); // 大小自适应 |
|
|
|
|
|
}); |
|
|
}); |
|
|
|
|
|
resizeObserver.observe(chartContainer.value!); // 监听chartContainer尺寸变化 |
|
|
myChart.setOption(option); |
|
|
|
|
|
}); |
|
|
}); |
|
|
|
|
|
// 监听员工信息变化 |
|
|
|
|
|
watch( |
|
|
|
|
|
() => ({ |
|
|
|
|
|
usercont: props.usercont, |
|
|
|
|
|
tabsid: props.tabsid |
|
|
|
|
|
}), |
|
|
|
|
|
async (newValues) => { |
|
|
|
|
|
const { usercont, tabsid } = newValues; |
|
|
|
|
|
// 如果tabsid为'2'且usercont.number准备好了 |
|
|
|
|
|
if (tabsid === '2' && usercont.number) { |
|
|
|
|
|
error.value = null; |
|
|
|
|
|
await nextTick(); |
|
|
|
|
|
await initChart(); |
|
|
|
|
|
} else if (usercont.number) { |
|
|
|
|
|
// 如果只是usercont.number变化了 |
|
|
|
|
|
error.value = null; |
|
|
|
|
|
await nextTick(); |
|
|
|
|
|
await initChart(); |
|
|
|
|
|
} else { |
|
|
|
|
|
error.value = "员工信息未准备好"; |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
{ immediate: true, deep: true } |
|
|
|
|
|
); |
|
|
|
|
|
// 组件卸载时清理ECharts实例 |
|
|
|
|
|
onUnmounted(() => { |
|
|
|
|
|
if (chartInstance) { |
|
|
|
|
|
chartInstance.dispose(); |
|
|
|
|
|
chartInstance = null; |
|
|
|
|
|
} |
|
|
|
|
|
// 清理ResizeObserver |
|
|
|
|
|
if (resizeObserver) { |
|
|
|
|
|
resizeObserver.disconnect(); |
|
|
|
|
|
resizeObserver = null; |
|
|
|
|
|
} |
|
|
}); |
|
|
}); |
|
|
|
|
|
//监听tabsid变化(点击性格色彩选项) |
|
|
|
|
|
// watch(()=>props.tabsid,(val:string)=>{ |
|
|
|
|
|
// if(val == '2'){ |
|
|
|
|
|
// initChart(); |
|
|
|
|
|
// } |
|
|
|
|
|
// }) |
|
|
</script> |
|
|
</script> |
|
|
<template> |
|
|
<template> |
|
|
<div> |
|
|
<!-- 在模板中根据loading状态显示加载提示 --> |
|
|
<div class="title">性格色彩特质</div> |
|
|
<div class="chart-container"> |
|
|
<!-- 雷达图 --> |
|
|
<div ref="chartContainer" class="chart"></div> |
|
|
<div id="myChart" class="chart"></div> |
|
|
<div v-for="(item, index) in ColourNameList" :key="index"> |
|
|
<!-- 文字部分 --> |
|
|
|
|
|
<div class="text-content"> |
|
|
|
|
|
<el-row> |
|
|
|
|
|
<el-col v-for="(item, index) in topTwoColours" :key="index" :span="24"> |
|
|
|
|
|
<div v-if="item == '红色'"> |
|
|
<div v-if="item == '红色'"> |
|
|
<el-text type="info" class="color-title">{{ item }}:<br/></el-text> |
|
|
<el-text type="info" class="color-title">{{ item }}:<br/></el-text> |
|
|
<el-text type="info">——他们的优势是:<br /></el-text> |
|
|
<el-text type="info">——他们的优势是:<br /></el-text> |
|
|
@ -123,13 +219,14 @@ onMounted(() => { |
|
|
<el-text type="info">没有主见,</el-text> |
|
|
<el-text type="info">没有主见,</el-text> |
|
|
<el-text type="info">缺乏创意。<br /></el-text> |
|
|
<el-text type="info">缺乏创意。<br /></el-text> |
|
|
</div> |
|
|
</div> |
|
|
</el-col> |
|
|
|
|
|
</el-row> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</template> |
|
|
</template> |
|
|
<style scoped> |
|
|
<style scoped> |
|
|
|
|
|
.chart-container { |
|
|
|
|
|
width: 100%; |
|
|
|
|
|
height: 100%; |
|
|
|
|
|
} |
|
|
.title { |
|
|
.title { |
|
|
font-size: 18px; |
|
|
font-size: 18px; |
|
|
font-weight: bold; |
|
|
font-weight: bold; |
|
|
|