go-viee-fetch-Demo/src/packages/components/Charts/HazardousChemicalsSpace/TopAlarmsHaz/index.vue
gaohaifeng bec142aff1 feat(Charts): 修改危险化学品空间组件以支持API数据
- 将静态数据替换为从API获取的动态数据
- 新增fetchCorpsData方法处理API请求
- 修改calculateWidth逻辑以适应新数据结构
- 添加组件挂载时的数据初始化
- 调整SmallBorder组件样式确保SVG宽度适配
2025-08-28 10:11:48 +08:00

276 lines
6.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<SmallBorder class="SmallBorder">
<div class="go-top-alarms">
<CustomSelect
:options="option.dateTime.dataset"
:selectedValue="option.dateTime.selectValue"
@change="handleSelectChange"
class="top-select"
/>
<div class="header">
<div class="title">
<div class="title-text">
<span :style="{
color: option.titleColor,
fontSize: option.titleSize + 'px',
marginTop: option.paddingY + 'px',
marginLeft: option.paddingX + 'px',
letterSpacing: option.letterSpacing + 'px'
}">{{ option.title }}</span>
</div>
</div>
<n-dropdown v-if='option.isShowButton' trigger="hover" :options="dropdownOptions" @select="handleSelect">
<div class="dropdown-button">
{{ selectedOption }}
<svg-icon icon-class="arrow-down" class="arrow-down-icon" />
</div>
</n-dropdown>
</div>
<div class="content">
<ul>
<li v-for="(item, index) in displayData" :key="index" class="alarm-item">
<div class="item-info">
<span class="rank" :style="{ color: option.rankColor }">
<span class="rank-icon"></span>
{{ index + 1 }}
</span>
<span class="name" :style="{ color: option.nameColor }">{{ item.enterpriseName }}</span>
</div>
<div class="item-value">
<span class="value" :style="{ color: option.valueColor }">{{ item.alarmCount }}</span>
</div>
<div class="progress-bar-wrapper">
<div class="progress-bar">
<div class="progress" :style="{
width: calculateWidth(item.alarmCount),
background: `linear-gradient(to right, ${option.barColorStart}, ${option.barColorEnd})`
}"></div>
</div>
</div>
</li>
</ul>
</div>
</div>
</SmallBorder>
</template>
<script setup lang="ts">
import { ref, computed, PropType, onMounted } from 'vue'
import { option as configOption } from './config'
import SmallBorder from '../SmallBorder/index.vue'
import CustomSelect from './select.vue'
import axios from 'axios'
const props = defineProps({
chartConfig: {
type: Object as PropType<{ option: typeof configOption }>,
required: true
}
})
const option = computed(() => props.chartConfig.option)
const selectedOption = ref(props.chartConfig.option.dropdownDefault)
// 新增存储API返回的数据
const displayData = ref([])
const dropdownOptions = computed(() => {
return props.chartConfig.option.dropdownOptions.map(opt => ({
label: opt,
key: opt
}))
})
// 修改基于API数据计算进度条宽度
const calculateWidth = (value: number) => {
if (displayData.value.length === 0 || displayData.value[0].alarmCount === 0) {
return '0%'
}
const firstRowValue = displayData.value[0].alarmCount
return `${(value / firstRowValue) * 100}%` // 当前行的alarmCount/第一行的alarmCount值
}
// 新增API调用函数
const fetchCorpsData = async (option: string) => {
try {
const response = await axios.get(`/screen/corpsFive/${option}`)
if (response.data.state === true) {
displayData.value = response.data.value || []
} else {
console.error('API调用失败:', response.data)
displayData.value = []
}
} catch (error) {
console.error('获取企业数据失败:', error)
displayData.value = []
}
}
const handleSelect = (key: string) => {
selectedOption.value = key
}
// 修改处理下拉选择器变化调用API
const handleSelectChange = async (value: any) => {
props.chartConfig.option.dateTime.selectValue = value
await fetchCorpsData(value)
}
// 新增:组件挂载时初始化数据
onMounted(async () => {
const initialValue = props.chartConfig.option.dateTime.selectValue || 'day'
await fetchCorpsData(initialValue)
})
</script>
<style lang="scss" scoped>
.SmallBorder {
position: relative;
}
.go-top-alarms {
position: absolute;
top: 0;
right: 0;
width: 100%;
height: 100%;
margin-top: -10px;
// background-color: #0a162b;
padding: 15px;
box-sizing: border-box;
display: flex;
flex-direction: column;
color: #fff;
.top-select {
top:20px;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
.title {
display: flex;
align-items: center;
.title-text {
height: 35px;
display: flex;
align-items: center;
padding: 0 20px 0 20px;
margin-left: 0px;
clip-path: polygon(10% 0, 100% 0, 100% 100%, 0% 100%);
}
}
.dropdown-button {
height: 30px;
padding: 0 15px;
background-color: #034a4b;
border: 1px solid #00e5ff;
border-radius: 15px;
display: flex;
align-items: center;
cursor: pointer;
color: #fff;
.arrow-down-icon {
margin-left: 8px;
font-size: 14px;
}
}
}
.content {
flex: 1;
margin-top: -15px;
padding-right: 10px;
font-size: 12.5px;
ul {
list-style: none;
padding: 0;
margin: 0;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-around;
}
}
.alarm-item {
display: grid;
grid-template-columns: 1fr auto;
grid-template-rows: auto auto;
grid-template-areas:
'info value'
'bar bar';
align-items: center;
padding: 0 10px;
gap: 6px 15px;
.item-info {
grid-area: info;
display: flex;
align-items: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
.rank {
font-weight: normal;
margin-right: 10px;
display: flex;
align-items: center;
.rank-icon {
display: inline-block;
width: 4px;
height: 4px;
border-radius: 50%;
background-color: #00e5ff;
margin-right: 8px;
margin-left: 6px;
box-shadow: 0 0 6px #00e5ff;
}
}
.name {
overflow: hidden;
text-overflow: ellipsis;
flex-grow: 1;
}
}
.item-value {
grid-area: value;
text-align: right;
// font-size: 16px;
font-weight: normal;
}
.progress-bar-wrapper {
grid-area: bar;
width: calc(100% - 60px);
position: relative;
left: 20px;
}
.progress-bar {
width: 100%;
height: 5px;
border-radius: 1px;
overflow: hidden;
.progress {
height: 100%;
border-radius: 1px;
}
}
}
}
</style>